요즘 추천시스템이랑 텍스트분석쪽에 관심이 생겨서 책을 찾아보았다.
사실 이미 한번 프로젝트(?)로 수행했지만 훑어보고 간단하게 넘어간것 같아서..
다시한번 짚어보는 목적! 튼튼한 기본이 단단한 기초가 중요하니까!
아래의 내용은 파이썬 머신러닝 완벽가이드의 책의 [8.텍스트분석] 읽고 정리한 내용입니다
이전에 살펴본 텍스트분석 프로세스에 따라 두번째 단계인 피쳐 벡터화 작업! 를 살펴본다.
- 텍스트 사전준비 (텍스트 전처리) : 텍스트를 벡터로 만들기 전에 토큰화작업
- 피쳐 벡터화/추출 : 가공된 텍스트에서 피쳐를 추출하고, 여기에 벡터값을 할당하는 작업
- ML모델 수립 및 학습/예측/평가 : 피쳐 벡터화된 데이터세트에 ML모델을 적용해 학습/예측/평가 수행
BOW (Bag of Words) 모델이란?
문서가 가지는 모든 단어를 문맥이나 순서를 무시하고
일괄적으로 단어에 대해 빈도값을 부여해 피쳐값을 추출하는 모델
문서내 모든 단어를 한꺼번에 bag에 넣은 뒤 흔들어 섞는다는 의미.
장점
- 쉽고 빠른 구축 -> 단순히 단어의 발생횟수에 기반을 하고 있지만 문서의 특징을 잘 나타낼 수 있는 모델
단점
- 문맥의미 반영부족 : 단어의 순서를 고려하지 않기 떄문에 문장내에서 단어의 문맥적인 의미가 무시된다.
- 희소행렬문제 : 나타나지 않은 단어들이 다 0으로 채워져서 ML알고리즘의 수행시간과 예측성능 떨어뜨린다.
- 희소행렬 : 대규모 컬럼으로 구성된 행렬에서 대부분의 값이 0으로 채워지는 행렬
- 밀집행렬 : 반대로 대부분의 값이 0이 아닌 의미있는 값으로 채워지는 행렬
BOW로 피쳐벡터화를 수행하면 희소행렬 형태의 데이터세트(각 단어가 컬럼이 된 형태)가 만들어진다.
그런데 문서마다 서로 다른단어로 구성되서, 나타나지 않은 단어들은 0으로 다 채워지는 희소행렬이 생기는 단점
BOW 피쳐 벡터화
일반적으로 머신러닝 알고리즘은 숫자형 피쳐를 데이터로 입력받아 동작한다.
그래서 피쳐벡터화(피쳐추출) 작업이 필요하다.
즉, 텍스트 데이터를 머신러닝에 입력하기 위해 특정의미를 가지는 숫자형값인 벡터값으로 변환하는 작업.
예를 들어, 각 문서의 텍스트를 단어로 추출해 피처로 할당,
각 단어의 발생빈도와 같은 값을 피처에 값으로 부여해 피쳐의 발생빈도 값으로 구성된 벡터로 만드는 작업.
BOW 피쳐 벡터화 방법1 - 카운트기반의 벡터화
단어에 피쳐값을 부여할때 각 문서에서 해당단어가 나타난 횟수, 즉 COUNT를 부여하는 방식.
카운트 값이 높을수록 중요한 단어로 인식된다.
그러나 문서의 특징을 나타내기보다는 언어의 특성상 문장에서 자주 사용될 수 밖에 없는 단어까지 높은값을 부여한다.
Sklearn의 CountVectorizer로 구현
from sklearn.feature_extraction.text import CountVectorizer
corpus = [
'This is the first document.',
'This is the second second document.',
'And the third one.',
'Is this the first document?',
'The last document?',
]
vector = CountVectorizer()
print(vector.fit_transform(corpus).toarray()) # count기반 벡터화
'''
[[0 1 1 1 0 0 0 1 0 1]
[0 1 0 1 0 0 2 1 0 1]
[1 0 0 0 0 1 0 1 1 0]
[0 1 1 1 0 0 0 1 0 1]
[0 1 0 0 1 0 0 1 0 0]]
'''
print(vector.vocabulary_) # 각 단어의 인덱스 (기본 token화)
'''
{'this': 9, 'is': 3, 'the': 7, 'first': 2, 'document': 1, 'second': 6, 'and': 0, 'third': 8, 'one': 5, 'last': 4}
'''
이해하기 쉽게 데이터프레임으로 변환하면 아래와 같다.
각 문장마다 각각의 단어들이 전체 몇번 등장했는지 알 수 있다.
# CountVectorizer -> DataFrame
countvect_df = pd.DataFrame(vector.fit_transform(corpus).toarray(), columns = sorted(vector.vocabulary_))
print(countvect_df)
'''
and document first is last one second the third this
0 0 1 1 1 0 0 0 1 0 1
1 0 1 0 1 0 0 2 1 0 1
2 1 0 0 0 0 1 0 1 1 0
3 0 1 1 1 0 0 0 1 0 1
4 0 1 0 0 1 0 0 1 0 0
'''
CountVectorizer 파라미터
추가로 CounterVectorizer()를 생성할때 몇가지 파라미터를 받아서 생성할 수 있다.
- stop_words : 제거할 불용어 (보통 영어의 관사,접속사 등) 지정가능
# 불용어를 직접 지정할경우
vect = CountVectorizer(stop_words=["and", "is", "the", "this"]).fit(corpus)
vect.vocabulary_
# {'first': 1, 'document': 0, 'second': 4, 'third': 5, 'one': 3, 'last': 2}
# 영어용 stop_words를 적용할 경우(한국어는 지원불가)
vect = CountVectorizer(stop_words="english").fit(corpus)
vect.vocabulary_
- 토큰생성시 선택 : analyzer, tokenizer, token_pattern 등의 인수로 토큰화 지정가능
# analyzer : 문자열 {‘word’, ‘char’, ‘char_wb’} 또는 함수 사용
vect = CountVectorizer(analyzer="char").fit(corpus)
vect.vocabulary_
# token_pattern : 토큰정의용 정규표현식
vect = CountVectorizer(token_pattern="t\w+").fit(corpus)
vect.vocabulary_
# tokenizer : 직접 정의한 토큰생성 함수 또는 None (디폴트)
import nltk
vectorizer = CountVectorizer(tokenizer=nltk.word_tokenize).fit(corpus)
vectorizer.vocabulary_
- 빈도수 선택 : 단어 피쳐를 빈도수 기준으로 지정가능
max_df : 전체문서에 걸쳐 너무 높은 빈도수를 가지는 단어 피쳐를 제외
min_df : 전체문서에 걸쳐 너무 낮은 빈도수를 가지는 단어 피쳐를 제외
- max_features: 추출할 단어 피쳐의 개수를 제한 가능
추출하는 피쳐가 너무 많을때 가장 높은 빈도를 가지는 단어순으로 피쳐를 추출한다.
# max_df, min_df : 토큰의 빈도수가 max_df,min_df를 초과하면 무시
vect = CountVectorizer(max_df=4, min_df=2).fit(corpus)
# max_features : 추출하는 피쳐의 개수 지정
vect = CountVectorizer(max_features1=100).fit(corpus)
참고
'🌿 Data Engineering > Data Analysis' 카테고리의 다른 글
[텍스트분석3.2] BOW피쳐 벡터화 - TfidfVectorizer (0) | 2021.09.05 |
---|---|
[텍스트분석] 02. 텍스트 사전준비 (텍스트 전처리) (0) | 2021.09.04 |
[텍스트분석] 01.텍스트 분석 수행 프로세스 (0) | 2021.09.04 |
추천시스템04. 잠재요인 협업필터링(latent factor collaborative filtering) 구현 (0) | 2021.08.27 |
추천시스템03. 아이템 기반 협업 필터링 (collaborative filtering) 구현 (1) | 2021.08.27 |
추천시스템02. 콘텐츠기반 필터링(content based filtering) 구현 (0) | 2021.08.26 |