자연어 처리(Natural Language Processing, NLP)의 하위 분야인 감성 분석(sentiment analysis)에 대해서 알아보는 장이다.
영화 리뷰를 읽고 각 리뷰가 긍정인지 부정인지 구별하는 예측기를 구축하자.
데이터 전처리
모델에 데이터를 주기 전에 모델이 잘 학습할 수 있도록 preprocessing을 해줘야 한다. 다음과 같은 개념을 알고 활용해보자.
BoW 모델을 사용하여 범주형 데이터를 수치로 변경해주겠다.
BoW의 과정은 다음과 같다.
- 단어를 토큰 단위로 나누기
- 중복을 제거해 단어 사전 생성
- 문서에 포함된 단어의 개수를 나타내는 행렬 생성
아래의 내용들은 BoW 모델에 대한 지식들이다.
tf(t,d)
텍스트나 단어 같은 범주형 데이터는 수치 형태로 인코딩해줘야 한다. BoW(Bag-of-Word)를 사용하자.
수로 이루어진 특성 벡터로 나타냄
행: 문서 d, 열: 단어 t -> 값: 문서 d에 단어 t가 몇 개 있는가 = tf(t,d)
즉 tf(t,d)의 행렬을 생성함.
- 1-gram or unigram: 하나의 단어만 저장, BoW의 경우가 그러하다.
- n-gram: 여러 개의 단어를 이어서 저장.
예를 들면, the sun is shining.이라는 문장을 the sun, sun is, is shining으로 저장
tf-idf(t,d)
tf-idf(Term Frequency - Inverse Document Frequency)
문서마다 자주 나오는 단어는 중요하지 않을 가능성이 높다. 해당 단어의 가중치를 낮춰주자.
가중치를 낮추는 방법은 아래 처럼 를 곱해주는 것이다.
- df(d,t): 단어 t가 포함된 문서 d의 개수
- : 전 체 문서 개수
1을 더해주거나 log를 취해주는 이유는 값을 원하는 범위로 맞추고 싶기 때문이다.
원래는 정규화를 한 후에 idf를 계산해야 하지만 사이킷런의 TfidfTransformer에서는 tf-idf 자체를 L2 정규화한다.
텍스트 데이터 정제
이모티콘을 제외하고 구두점 같은 필요없는 문자를 제거해준다.
여기서는 정규표현식으로 했으나 파이썬의 HTML 파서 모델이 더 다양한 기능을 제공한다.
문서를 토큰으로 나누기
문서를 토큰 즉, 단어로 나누는 가장 간단한 방법은 공백이지만 너무 대충이라 다른 방법을 찾아보자.
어간 추출 방법인 Porter stemmer 알고리즘을 사용할 수 있다. nlkt라이브러리에 구현되어 있다. 어간은 핵심 단어요소로 running에서 어간은 run이 된다.
어간 추출 알고리즘은 초기 알고리즘인 Porter 말고도 발전된 Snowball, Lancaster 등이 있다.
다만 어간 추출은 약간의 오류가 있는데, thus -> thu를 추출하는 경우가 그러하다. 이러한 오류를 없애고 정확하게 추출하는 알고리즘을 표제어 추출이라고 하는데 이는 계산이 어렵고 비용이 많이 든다.
실전에서는 어 간추출과 표제어추출의 성능 차이가 크지 않기 때문에 어간추출을 많이 사용한다. (한글은 조사와 어미가 발달되어 있어 표제어 추출방식이 적합하다)
문장의 구조에 중요한 역할을 하지만 의미는 크지 않는 불용어(stop-word)를 제거할 때가 있다. 예시로는 is, and, has, like가 있다. 이미 tf-idf를 통해 가중치 값이 많이 낮았지만 이를 미리 제공된 불용어 리스트를 적용시켜 해결한다.
모델링
데이터 전처리를 끝냈으니, 이제 모델링을 해보자.
문서 분류를 위한 로지스틱 회귀 모델 훈련
이제 전처리(빈도 수 가중치 조절, 텍스트 정제, 토큰 나누기 등)을 마쳤으니 로지스틱 회귀 모델에 넣어 훈련시키자.
(각 단어의 값) -> (주로 긍정/부정 결과이더라)
대용량 데이터 처리
NLP는 계산비용이 많고 그로 인한 하드웨어적 한계를 극복하기 위해 외부 메모리 학습(out-of-core learning)을 사용한다.