본문 바로가기
AI/자연어처리

[생활속의 IT] 자연어 처리#6 - 직방 부동산 평가데이터 전처리(1/2)

by 생활속의 IT램프 2020. 3. 26.

[이전 글 보기]

2020/03/22 - [AI/자연어처리] - [생활속의 IT] 자연어 처리#1 - 아나콘다 설치하기

2020/03/22 - [AI/자연어처리] - [생활속의 IT] 자연어 처리 - 참고) Jupyter의 개념

2020/03/23 - [AI/자연어처리] - [생활속의 IT] 자연어 처리#2 - 크롤러 만들기

2020/03/23 - [AI/자연어처리] - [생활속의 IT] 자연어 처리#3 - 직방의 지리정보 Geohash 이해하기

2020/03/24 - [AI/자연어처리] - [생활속의 IT] 자연어 처리#4 - 직방 아파트ID 얻기

2020/03/24 - [AI/자연어처리] - [생활속의 IT] 자연어 처리#5 - 직방 부동산 평가 크롤링하기

 

 

이제 raw 데이터는 수집을 하였으므로 본격 전처리를 해보도록 하겠습니다.

빅데이터 처리에서 전처리는 가장 손이 많이 가는 작업입니다.

가장 노가다이기도 하구요. 천천히 보도록 하겠습니다. 

 

 

1. 전처리 이해하기

 

2. 긍정/부정 정의 및 구조 변경

 

 

---------------------------------------------------------------------------------------------------------------------------------

 

1. 전처리 이해하기

우선 텍스트 마이닝에 있어 전처리가 무엇인지 이해해보도록 하겠습니다.

 

최근 부각되는 딥러닝이 인간을 뛰어넘었다니 그런 얘기가 나오고

딥러닝이 완전 사람을 대체할 것만 같은 느낌이 들지만, 딥러닝을 하기 위해선 사람이 개입할 것이 무지 많습니다.

알고리즘 자체는 사람 뇌 속 뉴런과 시냅스를 본따 만들어 훌륭한 인지 능력을 지녔지만

학습 데이터 구조가 잘못되었다거나 무슨 변수 하나 빠지면 에러를 뱉으며 

돌아가지 않는 게 어쩔 수 없는 프로그래밍의 현실이죠.

 

그래서 딥러닝을 수행하기 전 에러를 뱉지 않도록 데이터를 "잘" 준비해놔야 합니다.

알고리즘에 데이터가 잘 입력되고 성능을 높이기 위해 수집한 데이터를 처리하는 과정을 전처리 과정이라고 하는데 

데이터 분석에서 어떤 알고리즘을 쓰냐에 따라 필요한 전처리 내용이 조금씩 다릅니다.

 

자연어 분석에서는 대체적으로 아래와 같은 순서를 따릅니다.

 

(1) 중복 데이터 제거: 우리가 분석할 리뷰 데이터에 중복 데이터가 있으면 제거합니다.

 

(2) 긍정/부정 정의

  - "바퀴벌레가 자주 나오고 너무 노후화 됐어요" --> 부정

  - "역이 가깝고 공세원이라 완전 좋습니다" --> 긍정

 

  우리가 수집한 직방 데이터에는 1~5 점의 점수를 주도록 되어 있습니다.

  그런데 딥러닝, 자연어 처리에서는 1~5 점으로 분류하는것보다 긍정/부정, 단 2개의 카테고리로 분류하는것이

  더 정확한 결과를 도출합니다. 즉 분류할 카테고리가 적을수록 더 정확합니다.

  그래서 우리는 1~2점은 부정, 4~5점은 긍정으로 분류하여 라벨링할 예정입니다.

 

(3) RawData 구조변경

  - 우리의 수집 데이터는 성별, 자가 여부, 나이 등의 컬럼이 포함되어 있습니다.

    자연어 처리를 위해선 학습할 텍스트, 1개의 컬럼만 필요합니다.  

    이 컬럼만 가진 데이터를 만드는 과정입니다.

 

(4) 불용어 정의  

  - 분석하지 않을 사전을 정하는 과정입니다. 

    큰 의미를 가지지 않은 데이터는 분석대상에서 빼면 정확도가 더 증가하기 때문입니다.

    영어의 경우 i, the, a, an 등이 있지만 한글은 생각보다 쉽지 않습니다.

    은/는/이/가 같은 부사도 당연히 포함되지만 분석할 데이터에 따라 직접 정의해야할 필요성도 있습니다.

    이 부분은 뒤에 다시 설명하도록 하겠습니다.

 

(5) 형태소 분석/토큰화

  - 형태소란 언어에서 의미를 가지면서 분해할 수 없는 가장 작은 단위라고 정의하고 있습니다.

    (마치 데이터베이스에서 트랜잭션의 정의와 비슷하군요)
 

    한국어의 경우 영어와 달리 형태소 분석 과정이 포함됩니다.

    왜일까요? 

  

    한국어는 영어와 다르게 단어의 형태가 수없이 다양하기 때문입니다.

    되다. 되었다. 되었지만. 되어서. 될 것. 

 

    이런 경우 형태소 분석을 통해 명사/동사/조사/형용사 등을 구분하고 원형을 찾아주게 됩니다.

    위의 경우 "되다" 하나로 변형시키는 것이죠.

    그러면 학습할 단어가 줄어드는 효과가 있습니다.

 

    결국 토큰화란 분석한 형태소를 토대로 단어를 자르는 겁니다.

    날씨가 너무 좋다 --> 날씨 / 가 / 너무 / 좋다

 

(6) 불용어 제거

    토큰화 후에는 앞서 정의했던 불용어 사전을 통해 불필요한 단어는 제외하게 됩니다.

    날씨 / 가 / 너무 / 좋다 --> 날씨 / 너무 / 좋다

 

    조사인 "가"는 분석에 의미가 없으므로 제외하는 겁니다.

    저는 4~6 단계를 몇 번 거치면서 불용어 사전을 지속적으로 추가해나갔습니다.

    

  

(7) 벡터화

    위 과정이 끝나면 전처리는 90% 끝납니다.

    마지막 벡터화는 각 단어를 숫자로 매핑하는 단계입니다.

    즉 컴퓨터는 단어를 단어 그 자체로 인식하지 않고 일종의 ID로 인식합니다.

    날씨: 1, 너무: 134, 좋다: 732  이라면

 

    [1/ 134 / 732] 값을 자연어 처리 알고리즘에 입력시키는 것이죠.

    그러면 학습이 진행됩니다. 학습 알고리즘도 여러가지인데

    학습 알고리즘에 대해선 전처리 포스트 이후에 별도로 설명드리겠습니다.

 

 

전처리 코드 작성에 앞서 전처리 과정에 대한 대략적인 과정을 보겠습니다.

 

2. 긍정/부정 정의 및 구조변경

 

이전 포스트(2020/03/24 - [AI/자연어처리] - [생활속의 IT] 자연어 처리#5 - 직방 부동산 평가 크롤링하기)

에서 전국 아파트의 리뷰데이터를 수집하였는데

사실 이렇게 수집한 형태로는 감성분석에 이용할수는 없습니다.

모델 훈련을 위해선 한글 데이터만 담긴 컬럼 1개와 점수 1컬럼만 있으면 됩니다.

 

직방의 리뷰 데이터는 1~5까지 점수를 매길 수 있는데 4~5점이면 긍정이라 보고 1로

1~2점이면 부정으로 보고 0으로 매길 예정입니다.

 

그리고 직방 리뷰데이터는 교통점수, 주변점수 등 여러 평가 유형이 있는데

이런 유형을 구분하지 않고 같은 데이터로 취급하여 활용할 예정입니다.

 

(1) 함수 구현하기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import pandas as pd
import os
 
 
def getRawData(inputDF):
 
    # 중복 행 삭제
    cnt = len(inputDF)
    dupCnt=inputDF['totalDesc'].nunique()
    inputDF.drop_duplicates(subset=['totalDesc'], inplace=True)
    printstr(cnt - dupCnt) + " of duplicated item has been deleted.")
 
    # 필요없는 컬럼은 삭제
    inputDF.drop(["danji_id""danji_name""age""sex""residenceType""married"], axis='columns', inplace=True)
    resultDF = pd.DataFrame()
 
    # 교통평가(3,4열) / 주변평가(5,6열) / 관리평가(7,8열), 주거평가(9,10열) 을 concat 하여 합침
    for i in range(0102):
           inputDF.columns.values[i] = "score"
           inputDF.columns.values[i + 1= "desc"
           resultDF = pd.concat([resultDF, inputDF.iloc[:, i:i + 2]])
 
    # 인덱스 재생성
    resultDF.reset_index(drop=True, inplace=True)
 
    # 긍정/부정 분류
    idx_nm = resultDF[resultDF['score'== 3].index
    resultDF = resultDF.drop(idx_nm)
    resultDF["score"= resultDF["score"].apply(lambda x: 1 if x >= 4 else 0)
 
    # resultDF.to_csv("resultDF.csv", mode='w')
    return resultDF
 
 
def getConcatData(inputList):
    returnDF = pd.DataFrame()
    for i in inputList:
        tmp_data = pd.read_csv('junkook/'+i)
        tmp_data = getRawData(tmp_data)
        returnDF = pd.concat([returnDF, tmp_data])
    returnDF.reset_index(drop=True, inplace=True)
    return returnDF
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter
 

두 개의 함수를 정의했는데 getRawData는 리뷰데이터로 이루어진 데이터프레임 하나를 입력받으며

네 가지 평가 데이터를 동일하게 취급하여 row 기준 concat하여 합친 후

3점 데이터는 삭제하였고 4~5점은 1로 매핑하고 1~2점은 0으로 매핑한 결과를 리턴합니다.

컬럼은 index, score, desc 로 3개로 변환됩니다.

 

getConcatData 함수는 getRawData로 변환된 데이터를 raw 단위로 이어붙이는 역할을 합니다. 

 

 

(2) 메인 구현하기

 

그리고 메인은 아래와 같이 작성했습니다.

참고로 수집했던 csv 데이터는 junkook 폴더에 넣어놓은 상태입니다. 

1
2
3
4
5
dirName = 'C:\\Users\\kalwr\\PycharmProjects\\realState\\junkook'
filename = os.listdir(dirName)
 
allData = getConcatData(filename)
allData.to_csv("refinedData.csv", mode='w')

junkook 폴더를 읽어 거기 있는 csv 파일을 변환 후 이어붙이는 역할을 하며

결과를 refinedData.csv 파일로 저장합니다. 

결과는 아래와 같습니다. 

 

 

이제 모든 리뷰데이터가 0 또는 1의 점수를 가지는 형태가 되었습니다.

다음은 형태소 분석을 통해 토큰화 후 불용어를 제거할 단계입니다.

댓글