희소 표현(sparse representation)
- 대부분이 0으로 표현되는 방법
예) 나는 배가 고프다 → [ 1 0 0 1 0 0 0 1 0 0 ]- BoW(Bag of Words)
- 단어들의 문맥이나 순서를 무시
- 단어들의 출현 빈도수를 카운트(count)하여 단어를 수치화, 문장을 수치화하는 방법 => 대부분이 0(데이터로 가치없는 부분)으로 표현됨
- 문맥과 순서를 무시하고 빈도수만 수치화함
(ex - sklearn.~~.CountVectorizer)- 사전에 텍스트 데이터를 입력하여 단어사전을 생성 > 임베딩 할 문장 입력 > 단어사전에 있는 단어들의 출현 빈도수로 위치벡터를 만듬 (주객전도)
- 임베딩한 배열이 표준화가 됨(임베딩되는 형식을 통일할 수 있다): 단어사전 기준으로 임베딩되기 때문에 임베딩할 문장이 매우 길어도 단어사전 길이로 임베딩됨
- BoW으로 제대로 임베딩하려면 단어 사전이 풍부해야함 but, 메모리 소모가 매우 커짐(데이터의 밀집도가 낮다) => 단점이자 한계
- 모델 : CountVectorizer
CountVectorizer 클래스 함수를 이용한 BoW(Bag of Words) 구현
- 개념 : 단어들의 순서는 고려하지 않고, 단어들의 출현 빈도로만 표현하는 수치화 방법
- 구현 방법
① 텍스트 데이터(말뭉치, corpus) → 단어 사전{‘단어’:인덱스} 생성
② 임베딩 할 문장(sentence) : 단어 사전에 있는 각 단어들의 출현 빈도수로 표현
③ sklearn.feature_extraction.text.CountVectorizer 사용
CountVectorizer 클래스 함수를 이용한 BoW 구현 예시
sklearn.feature_extraction.text.CountVectorizer 1.3.2 method
- fit(raw_documents, y=None)
- raw_documents = 반복가능한 텍스트 데이터, y는 무시
- 결과를 자기자신에게 저장하기 때문에 추가적인 변수에 저장X
- 토큰화(어절 단위) > 토큰별 단어사전 생성
- vocabulary_ : 만들어진 단어 사전
- transform(raw_documents)
- 임베딩할 단어를 숫자화(임베딩) 해주는 함수
- raw_documents = 반복가능한 데이터
- 결과 : 희소행렬(행, 열)로 리턴함
- 2차원 배열로 데이터프레임을 만들어줌 (매우 중요)
- CountVectorizer의 기본 token_pattern
- r"(?u)\b\w\w+\b” - \b는 단어 경계를 의미하고, \w\w+는 두 글자 이상의 단어를 의미 : len > 1만 단어사전으로 생성함
- 변경하기 위해서는 token_pattern=r"(?u)\b\w+\b” > \w 제거
- CountVectorizer를 활용할 경우 단어 사전과 임베딩할 문장은 모두 list형식으로 만들어서 입력해야함
# 클래스 함수 임폴트
from sklearn.feature_extraction.text import CountVectorizer
# 함수 호출, 임베딩 모델 생성
ko_cv = CountVectorizer(token_pattern=r"(?u)\b\w+\b")
en_cv = CountVectorizer(stop_words='english')
##########################################################
# 한글 텍스트 데이터 생성 및 단어 사전 생성
ko_text = ['나는 배가 고프다', '내일 점심 뭐먹지', '내일 공부 해야겠다', '점심 먹고 공부해야지'] #텍스트 데이터 생성
ko_cv.fit(ko_text) #함수호출 > 토큰화(어절 단위) > 토큰별 단어 사전 생성
ko_voca = ko_cv.vocabulary_ #생성된 단어 사전 확인
# 0번부터 재배치된 새로운 단어 사전 생성
sorted_voca = sorted(ko_voca.items(), key=lambda item: item[1])
ko_voca = {word: index for index, (word, _) in enumerate(sorted_voca)}
print(ko_voca)
##########################################################
# 한글 text데이터 임베딩 > 임베딩 행렬 생성
# 임베딩 할 text 생성
ko_sentences1 = ['나는 배가 고프다 내일 점심 먹고 공부 해야겠다']
ko_sentences2 = [ko_text[0], ko_text[1], ko_text[2]]
# transform 함수 호출 (toarray() == 배열로 변환)
ko_matrix1 = ko_cv.transform(ko_sentences1).toarray()
ko_matrix2 = ko_cv.transform(ko_sentences2).toarray()
print(ko_matrix1)
print(f'\n{"-"*80}\n')
print(ko_matrix2)
Q) BoW에서 단어사전과 임베딩할 문장을 잘 조절하면 0의 개수를 적게 만들 수 있는데 이러해도 희소표현이라고 하는가?
- 알고리즘 ‘모델’이라 함은 하나의 데이터만 적용되는 것이 아닌 범용성이 중요함 즉, 몇개에 문장에 대해 0이 안나오게 할 수 있지만, 그외 대부분의 문장에 대해는 0을 더 많이 띄우기 때문에 희소표현이라고 할 수 있음
!pip install kiwipiepy #kiwi 라이브러리 설치
##########################################################
import kiwipiepy
kw = kiwipiepy. Kiwi() #함수 호출
stopword = kiwipiepy.utils.Stopwords() #불용어 함수 호출
##########################################################
sentence_list = [] #전체 결과를 저장할 리스트
for sent in ko_text:
sentence = [] #각 1개마다 결과를 저장할 리스트
morphs_list = kw.tokenize(sent, stopwords=stopword) #한 문장에 대한 형태소 분석 및 불용어 제거
for morph, _, _, _ in morphs_list: #형태소만 추출
sentence.append(morph)
string = ' '.join(sentence)
sentence_list.append(string)
print(sentence_list)
# 보충 - join함수
sample = ['나는','배가','고프다']
string = ' '.join(sample)
print(string)
# 영어 텍스트 데이터 생성 및 단어 사전 생성
en_text = ['You already know what The Present is',
'You already know where to find it',
'And you already know how it can make you happy and successful',
'You knew it best when you were younger',
'You have simply forgotten']
en_lower = []
for sent in en_text:
en_lower.append(sent.lower())
en_cv.fit(en_lower)
en_voca = en_cv.vocabulary_ #단어 사전 생성
#단어 사전 순서 재배치
sorted_voca = sorted(en_voca.items(), key=lambda item: item[1])
en_voca = {word: index for index, (word, _) in enumerate(sorted_voca)}
print(en_voca)
##########################################################
# 영어 문장 임베딩
# 임베딩 할 텍스트 데이터 소문자로 생성
en_sentences1 = en_lower[:1]
en_sentences2 = en_lower[:]
print(en_sentences1)
print(en_sentences2)
print(f'\n{"-"*80}\n')
# transform 함수 호출
en_matrix1 = en_cv.transform(en_sentences1).toarray()
en_matrix2 = en_cv.transform(en_sentences2).toarray()
print(en_matrix1)
print(f'\n{"-"*80}\n')
print(en_matrix2)
참고자료
CountVectorizer - scikit-learn 공식문서
scikit-learn/sklearn/feature_extraction/_stop_words.py (불용어 리스트)