working_helen
[모델링] CountVectorizer/ TfidfVectorizer / 한글 형태소 분석기 KoNLPy 본문
[모델링] CountVectorizer/ TfidfVectorizer / 한글 형태소 분석기 KoNLPy
HaeWon_Seo 2023. 8. 10. 15:59추천시스템 모델링 과정에서 접한 CountVectorizer와 TfidfVectorizer, KoNLPy에 대해 공부해본다.
1. 문서-단어 행렬
2. CountVectorizer 문서 벡터화
3. TfidfVectorizer 문서 벡터화
4. 문서 벡터화에서 한국어 처리
1) tokenizer 설정
2) 한국어 형태소 분석기 KoNLPy
1. 문서-단어 행렬 (document-term matrix)
(위키백과) 문서 -용어 매트릭스는 문서 모음에서 발생하는 용어의 빈도를 설명하는 수학적 매트릭스 입니다. 문서 용어 행렬에서 행은 컬렉션의 문서에 해당하고 열은 용어에 해당합니다. 각 ij 셀은 문서 i 에서 단어 j가 나타나는 횟수입니다 . 따라서 각 행은 해당 행에 해당하는 문서의 내용을 나타내는 용어 수의 벡터입니다. 어떤 문서에 어떤 용어가 포함되어 있고 몇 번이나 나타나는지 보여줍니다.
- 각각의 문서에서 각각의 단어가 몇 번 등장했는지 출현 빈도(frequency)를 카운트하여 행렬로 표현한 것이다.
- 자연어 처리에 문서를 벡터화하는 방법 중 하나로, 단어의 count로 문서를 벡터화한다.
행렬의 행 = 각각의 문서
행렬의 열 = 각각의 단어
행렬의 (i, j)성분 = i번째 문서에 j번째 단어가 몇번 등장하는지 카운트한 빈도값
행렬의 크기 = 문서의 개수 X 단어의 개수
2. CountVectorizer 문서 벡터화
- 사이킷런 sklearn.feature_extraction 항목에서 제공하는 문서 벡터화 패키지
- CountVectorizer는 주어진 문서에 각각의 단어가 몇 번 등장했는지를 count하여 document-term matrix를 만든다.
- 단어를 토큰나이징 + 문서에 대하여 단어의 count로 벡터화
- 모든 단어를 소문자로 변환한 상태에서 구분하기 때문에 Apple과 apple은 같은 단어로 인식된다.
from sklearn.feature_extraction.text import CountVectorizer
# CountVectorizer 객체 생성
count_vec = CountVectorizer()
# 문서 list의 문서들로 document-term matrix 생성
mat = count_vec.fit_transform(문서 list)
# document-term matrix 출력
mat.toarray()
# document-term matrix에서 각 단어가 몇번째 열인지 출력
count_vec.vocabulary_
- CountVectorizer 객체 fit : 단어 사전을 구축하는 기능, 주어진 문서 속 단어들에 대해 각 단어가 몇번째 열에 올 것인지 index를 지정한다.
- CountVectorizer 객체 transform : 구축한 단어 사전을 기반으로 주어진 문서를 벡터로 변환하는 기능, 단어 사전에 없는 단어가 문서에 포함된 경우 이를 무시해버린다.
- fit_transform : 문서 list를 이용해 단어 사전을 구축하고, 각 문서를 벡터화하여 document-term matrix으로 변환한다.
- count_vec.vocabulary_는 document-term matrix에서 각 단어가 몇번째 열인지 출력한다. 즉 'love'가 2라는 것은 `mat`의 2열이 'love' 단어가 각 문서에 등장하는 빈도를 의미하는 것으로 (1, 0, 0)임을 확인할 수 있다.
- 'love'와 'loves'가 같은 단어임을 구분하지 못한다 => 문서에 적절한 전처리가 필요하다.
3. TfidfVectorizer 문서 벡터화
- 사이킷런 sklearn.feature_extraction 항목에서 제공하는 문서 벡터화 패키지
- TfidfVectorizer 클래스는 주어진 문서에 각각의 단어의 TF-IDF를 계산하여 document-term matrix를 만든다.
- 단어를 토큰나이징 + 문서에 대하여 단어의 TF-IDF 값으로 벡터화
- CountVectorizer와 마찬가지로 모든 단어를 소문자로 변환한 상태에서 구분하며 I, a 등 한 글자 단어는 제외한다.
- TfidfVectorizer는 CountVectorize의 문제를 보완한다.
TF(t, d) = 특정 단어 t가 특정 문서 d에 나온 빈도
DF(t, D) = df = 특정 단어 t가 나타난 문서의 수 D (값이 클수록 여러문장에 쓰이는 범용적인 단어)
IDF(t) = 전체 문서 수 N을 해당 단어의 DF+1로 나눈 뒤 로그를 취한 값 (분모가 0이 되는 것을 방지하기 위해 1을 더함)
=> TF-IDF(t, d) = TF(t, d)와 IDF(t)의 곱
: IDF값은 모든 문서에 등장하는 범용적인 단어의 중요도를 낮춘다. CountVectorizer로 벡터화하는 경우 중요하진 않지만 대부분의 문서에서 자주 사용되는 단어의 가중치가 높아지는 문제가 발생할 수 있다. 따라서 TfidfVectorizer를 통해 TF-IDF 값을 사용하는 경우 IDF을 통해 CountVectorizer가 가지는 위와 같은 문제를 해소할 수 있다.
- 본 프로젝트의 경우 EDA 과정에서 '책소개’ 텍스트에서 추출한 '책소개 키워드 수정본의 경우 ‘것’, ‘하는’, ‘있다’, ‘저자’와 같이 대부분의 책소개 텍스트에 들어가 있는 일반적인 단어가 많이 추출되었음을 확인했다. 이에 따라 단순히 단어의 등장 여부를 기준으로 하는 인코딩 기반보단 TF-IDF 기반 추천 시스템이 더욱 적절할 것이라고 예상했다.
from sklearn.feature_extraction.text import TfidfVectorizer
# CountVectorizer 객체 생성
tfidf_vec = TfidfVectorizer()
# 문서 list의 문서들로 document-term matrix 생성
mat = tfidf_vec.fit_transform(문서 list)
# document-term matrix 출력
mat.toarray()
# document-term matrix에서 각 단어가 몇번째 열인지 출력
tfidf_vec.vocabulary_
- TfidfVectorizer 객체 fit : 단어 사전을 구축하는 기능, 주어진 문서 속 단어들에 대해 각 단어가 몇번째 열에 올 것인지 index를 지정한다.
- TfidfVectorizer 객체 transform : 구축한 단어 사전을 기반으로 주어진 문서를 벡터로 변환하는 기능, 특정 문서에서 각 단어의 TF-IDF 값을 계산한다. 문서에 등장하지 않는 단어에 대해선 0을 부여한다.
- fit_transform : fit과 transform 과정을 동시에 진행하여 각 문서를 벡터화하여 document-term matrix으로 변환한다.
- CountVectorizer와 마찬가지로 'love'와 'loves'가 같은 단어임을 구분하지 못한다 => 문서에 적절한 전처리가 필요하다.
4. 문서 벡터화에서 한국어 처리
- CountVectorizer에서 토크나이징의 defualt는 영어에 맞춰져 있다.
- 영어에서는 띄어쓰기를 기준으로 단어를 토크나이징하기 때문에 '조사', '어간'과 같이 다른 단어에 붙혀서 사용하는 의존 형태소가 존재하는 한국어의 경우 띄어쓰기만을 기준으로 토크나이징하기 적합하지 않다.
- 위 사진에서 보듯 '그녀도'와 '그녀는'을 서로 다른 단어로 인식하고 있다.
1) tokenizer 설정
CountVectorizer의 tokenizer 속성에 한국어 형태소 분석기를 설정하여 한국어를 적절히 토크나이징할 수 있다.
# 적절한 형태소 분석기 객체 생성
from konlpy.tag import Komoran
komoran = Komoran()
# 한국어 tokenizer로 지정
count_vec = CountVectorizer(tokenizer=komoran.nouns)
mat = count_vec.fit_transform(text)
mat.toarray()
count_vec.vocabulary_
2) 한국어 형태소 분석기 KoNLPy
- KoNLPy(코엔엘파이) python 패키지를 통해 한국어 형태소 분석기를 import할 수 있다.
- KoNLPy 제공 한국어 형태소 분석기 5가지
- Okt(Open Korea Text)
- Komoran(코모란)
- Hannanum(한나눔)
- Kkma
- Mecab (Mecab은 윈도우에서 작동이 불가능)
- 한국어 형태소 분석기 객체를 생성 > 분석할 text + 분석할 단위 method 설정
from konlpy.tag import Kkma, Komoran, Okt, Hannanum
# 형태소 분석기 객체 생성
hannanum = Hannanum()
hannanum.nouns(text)
hannanum.morphs(text)
hannanum.pos(text, stem = True)
# CountVectorizer에 적용
count_vec_kr = CountVectorizer(tokenizer=hannanum.nouns)
mat_kr = count_vec_kr_1.fit_transform(text_kr)
mat_kr.toarray()
count_vec_kr.vocabulary_
- .nouns : 명사 기준 추출
- .phrases : 어절 기준 추출
- .morphs : 형태소 단위로 추출
- .pos : 품사를 함께 태깅해서 추출
.pos에서 stem = True 속성 : 어간을 복원해주는 기능 (예 : '하는' 대신에 '하다'로 바꾸어서 추출)
Jupyter Notebook
CountVectorizer 실행 예시¶
from sklearn.feature_extraction.text import CountVectorizer
text = ["I love banana.",
"She loves BANANA.",
"she also loves orange!"]
count_vec = CountVectorizer()
mat = count_vec.fit_transform(text)
mat.toarray()
array([[0, 1, 1, 0, 0, 0],
[0, 1, 0, 1, 0, 1],
[1, 0, 0, 1, 1, 1]], dtype=int64)
count_vec.vocabulary_
{'love': 2, 'banana': 1, 'she': 5, 'loves': 3, 'also': 0, 'orange': 4}
TfidfVectorizer 실행 예시¶
from sklearn.feature_extraction.text import TfidfVectorizer
text = ["I love banana.",
"She loves BANANA.",
"she also loves orange!"]
tfidf_vec = TfidfVectorizer()
mat_2 = tfidf_vec.fit_transform(text)
print(mat_2.toarray())
[[0. 0.60534851 0.79596054 0. 0. 0. ]
[0. 0.57735027 0. 0.57735027 0. 0.57735027]
[0.5628291 0. 0. 0.42804604 0.5628291 0.42804604]]
tfidf_vec.vocabulary_
{'love': 2, 'banana': 1, 'she': 5, 'loves': 3, 'also': 0, 'orange': 4}
한글 실행 예시¶
text_kr = ["나는 바나나를 좋아해",
"그녀도 바나나를 좋아해.",
"그녀는 오렌지도 좋아해!"]
count_vec_kr = CountVectorizer()
mat_kr = count_vec_kr.fit_transform(text_kr)
mat_kr.toarray()
array([[0, 0, 1, 1, 0, 1],
[0, 1, 0, 1, 0, 1],
[1, 0, 0, 0, 1, 1]], dtype=int64)
count_vec_kr.vocabulary_
{'나는': 2, '바나나를': 3, '좋아해': 5, '그녀도': 1, '그녀는': 0, '오렌지도': 4}
한글 토크나이징을 이용한 CountVectorizer¶
from konlpy.tag import Kkma, Komoran, Okt, Hannanum #Mecab은 윈도우에서 작동 불가능
Hannanum 분석기
hannanum = Hannanum()
count_vec_kr_1 = CountVectorizer(tokenizer=hannanum.nouns)
mat_kr_1 = count_vec_kr_1.fit_transform(text_kr)
mat_kr_1.toarray()
array([[0, 1, 1, 0],
[1, 0, 1, 0],
[1, 0, 0, 1]], dtype=int64)
count_vec_kr_1.vocabulary_
{'나': 1, '바나나': 2, '그녀': 0, '오렌지': 3}
Komoran 분석기
komoran = Komoran()
count_vec_kr_2 = CountVectorizer(tokenizer=komoran.nouns)
mat_kr_2 = count_vec_kr_2.fit_transform(text_kr)
mat_kr_2.toarray()
array([[1, 0],
[1, 0],
[0, 1]], dtype=int64)
count_vec_kr_2.vocabulary_
{'바나나': 0, '오렌지': 1}
Kkma 분석기
kkma = Kkma()
count_vec_kr_3 = CountVectorizer(tokenizer=kkma.nouns)
mat_kr_3 = count_vec_kr_3.fit_transform(text_kr)
mat_kr_3.toarray()
array([[0, 1, 1, 0],
[1, 0, 1, 0],
[1, 0, 0, 1]], dtype=int64)
count_vec_kr_3.vocabulary_
{'나': 1, '바나나': 2, '그녀': 0, '오렌지': 3}
Okt 분석기
okt = Okt()
count_vec_kr_4 = CountVectorizer(tokenizer=okt.nouns)
mat_kr_4 = count_vec_kr_4.fit_transform(text_kr)
mat_kr_4.toarray()
array([[0, 1, 1, 0],
[1, 0, 1, 0],
[1, 0, 0, 1]], dtype=int64)
count_vec_kr_4.vocabulary_
{'나': 1, '바나나': 2, '그녀': 0, '오렌지': 3}
Konlpy 한글 형태소 분석기 비교¶
hannanum = Hannanum()
komoran = Komoran()
kkma = Kkma()
okt = Okt()
text = "지금부터 한글 형태소를 분석해봅시다."
text
'지금부터 한글 형태소를 분석해봅시다.'
.nouns : 명사 추출¶
print("Hannanum")
print(hannanum.nouns(text))
print("Komoran")
print(komoran.nouns(text))
print("Kkma")
print(kkma.nouns(text))
print("Okt")
print(okt.nouns(text))
Hannanum
['지금', '한글', '형태소', '분석']
Komoran
['지금', '한글', '형태소', '분석']
Kkma
['지금', '한글', '형태소', '분석']
Okt
['지금', '한글', '형태소', '분석']
.morphs 형태소 추출¶
print("Hannanum")
print(hannanum.morphs(text))
print("Komoran")
print(komoran.morphs(text))
print("Kkma")
print(kkma.morphs(text))
print("Okt")
print(okt.morphs(text))
Hannanum
['지금', '부터', '한글', '형태소', '를', '분석', '하', '어', '보', 'ㅂ시다', '.']
Komoran
['지금', '부터', '한글', '형태소', '를', '분석', '하', '아', '보', 'ㅂ시다', '.']
Kkma
['지금', '부터', '한글', '형태소', '를', '분석', '하', '어', '보', 'ㅂ시다', '.']
Okt
['지금', '부터', '한글', '형태소', '를', '분석', '해봅시다', '.']
.phrases 어절 추출¶
print("Okt")
print(okt.phrases(text))
Okt
['지금', '한글', '한글 형태소', '분석', '형태소']
.pos 품사 태깅¶
print("Hannanum")
print(hannanum.pos(text))
print("Komoran")
print(komoran.pos(text))
print("Kkma")
print(kkma.pos(text))
print("Okt")
print(okt.pos(text))
Hannanum
[('지금', 'N'), ('부터', 'J'), ('한글', 'N'), ('형태소', 'N'), ('를', 'J'), ('분석', 'N'), ('하', 'X'), ('어', 'E'), ('보', 'P'), ('ㅂ시다', 'E'), ('.', 'S')]
Komoran
[('지금', 'NNG'), ('부터', 'JX'), ('한글', 'NNP'), ('형태소', 'NNP'), ('를', 'JKO'), ('분석', 'NNG'), ('하', 'XSV'), ('아', 'EC'), ('보', 'VX'), ('ㅂ시다', 'EF'), ('.', 'SF')]
Kkma
[('지금', 'NNG'), ('부터', 'JX'), ('한글', 'NNG'), ('형태소', 'NNG'), ('를', 'JKO'), ('분석', 'NNG'), ('하', 'XSV'), ('어', 'ECS'), ('보', 'VV'), ('ㅂ시다', 'EFA'), ('.', 'SF')]
Okt
[('지금', 'Noun'), ('부터', 'Josa'), ('한글', 'Noun'), ('형태소', 'Noun'), ('를', 'Josa'), ('분석', 'Noun'), ('해봅시다', 'Verb'), ('.', 'Punctuation')]
Reference
https://en.wikipedia.org/wiki/Document-term_matrix
https://radish-greens.tistory.com/3
https://wikidocs.net/33661
https://m.blog.naver.com/myincizor/221643794025
https://han-py.tistory.com/283
https://kaya-dev.tistory.com/20
https://mingchin.tistory.com/7
https://wiserloner.tistory.com/917
'deep daiv. > 추천시스템 toy project' 카테고리의 다른 글
[모델링] 인코딩 기반 추천 시스템 (0) | 2023.08.10 |
---|---|
[데이터 전처리] EDA (0) | 2023.08.10 |
[데이터 수집] 데이터 수집 Workflow (0) | 2023.08.07 |