* 이 글은 태생이 문과생인 글쓴이 본인을 이해시키기 위해 초등학생도 이해할 수 있는 쉬운 언어로 바꾸어 작성했습니다. 혹시라도 틀린 부분이 있다면 저보다 멋지신 많은 디지털 노마드님들의 조언 또는 지적 감사히 받겠습니다
오늘은 단어를 벡터화하는 임베딩 방법론 중 하나인 Glove 에 대해 알아보겠다.
1. 등장 배경 (word2vec 너 좀 별로다)
우선 Glove 는 Word2vec, Fasttext 와 함께 임베딩 방법론의 삼대장으로 자주 거론되는 라이브러리라고 한다. 세 가지 방법론은 각기 다르나 핵심적인 원리는 비슷하다. 임베딩 방식의 이 nlp 방법론들을 공부하는 사람이라면, "CBOW" 와 "skip-gram" 정도는 들어봤을 것이다. CBOW 는 어떤 문장의 중심 단어를 보고 주변 단어를 예측하는 방법이고, skip-gram 은 반대로 주변 단어를 보고 중심 단어를 예측하는 방법이다.
예를 들어,
" 녹차 초콜릿 프라푸치노" (글쓴이의 최애 메뉴) 라는 단어를 학습시키면,
CBOW 의 경우
__ 초콜릿 ________
의 방식으로 학습을, skip- gram 의 경우
녹차 ____ 프라푸치노
의 방식으로 학습을 진행하게 된다. 이 과정으로 학습할 말뭉치 전체를 돌면서, 쉽게 설명하자면 "어떤 단어 앞뒤에 어떤 단어가 많이 왔는가" 를 학습하고, 함께 출현한 빈도가 높은 단어들을 "비슷한 단어" 취급을 한다는 방법론을 쓴다고 이해하면 되겠다.
그러니까 저런 말뭉치들을 다양하게 학습시키면, 임베딩 방식의 학습법은 기본적으로 "녹차" 와 "초콜릿" 과 "프라푸치노" 를 비슷한 단어라고 학습하게 된다.
그런데 말이지.. Word2Vec 은 기본적으로 임베딩 벡터가 윈도우 크기 내에서만 학습을 진행한다. 이게 무슨 말이냐면 학습을 하는 탐색 범위가 엄청 좁다는거다. 이해를 위해 글쓴이의 개발새발 그림을 첨부하겠다
그림을 보자 (...) 왼쪽은 Word2vec 이 문서를 학습하는 방법이다. 지정된 window의 크기만큼을 고려하여 문서를 학습하고, 또 그 다음 단어로 넘어가 학습하고.. 이 방법을 이용한다. 그렇기 때문에 탐색 범위도 좁고 시간도 엄청 오래 걸린다. 반면Glove 는 한 번 학습에서 문서를 처음부터 끝까지 돌며 학습하고, 그 다음 학습때도 마찬가지다. 그래서 말뭉치의 전체적인 통계 정보를 학습할 수 있다는 엄청난 장점이 있다
2. 구현 원리
다른 분들 블로그 가서 보세요!
엄청난 수식들과 함수들...
3. 그래서 장단점
따라서 출현 빈도가 적은 단어에 대해 부정확해지는 단점을 보완할 수 있다. (왜냐면 학습 범위가 전체니까! ) 또 앞서 언급했듯 학습 시간이 빠르다! 이전에는 각 단어별로 좁은 탐지 범위 내에서 학습하고, 다음 단어의 다음 범위를 학습하는 방법을 썼는데, 이 방법은 전체 코퍼스에 대해 단어별로 학습을 진행하기 때문이다.
4. 이제 한 번 써볼까?
그러면 이제 한번 Glove 를 써보도록 하겠다. 다른 분들의 블로그를 보니까 사전학습 모델을 많이 쓰는 것 같던데, 기본적으로 당연히 코퍼스는 많을수록 좋고 사전학습은 많이 되면 좋으나, 특수한 상황에 놓인 nlp 를 할 때는 우리의 데이터를 가지고 훈련을 시켜야 한다.. 필자는 지난 시간에 이어 계속 사용하던 카페 메뉴 데이터를 가지고 학습시켜 보도록 하겠다.
필자는 카페 메뉴 데이터 500여개를 가지고 학습시켰다. 1번의 예제에서 살펴본 것 처럼 어떤 메뉴명이나 어떤 메뉴명의 요소 단어를 입력했을 때 어떤 단어가 가장 유사한지 알고 싶다.
4.1 필요 라이브러리 import
fasttext 를 쓸 때는 따로 토큰화를 안 해줘도 알아서 자기가 했으나 얘는 따로 해줘야 한다. 한국어 형태소 분석기인 Konlpy 를 이용해서 먼저 토큰화해주자.
pip install glove_python_binary
pip install konlpy
from glove import Corpus, Glove
from konlpy.tag import Okt
이 때! 단어를 토큰화한다는건 이런 뜻이다..
"녹차 초콜릿 프라푸치노" -> ["녹차", "초콜릿", "프라푸치노"]
기계는 전자와 같은str 형태로 입력시키면 단 한 건의 학습도 안 해 준 채로 빠꾸를 먹일 것이다.. 형태소 단위나 음절 단위나 뭐 상황에 따라 괜찮은 단위로 잘 잘라서 리스트 형태로 담아서 넣어주자
4.2. 토큰화
제거할 불용어를 리스트에 담아주고 포문을 돌려서 불용어를 제거한 뒤 토큰화를 해 주면 된다. 나의 예제 데이터에는 쓸모없는 (only).. 같은게 들어있어서 저 아이들을 제거하고 토큰화했다
# 불용어 정의
stopwords = ['(only)', "인분"]
# 형태소 분석기 OKT를 사용한 토큰화 작업 (다소 시간 소요)
okt = Okt()
tokenized_data = []
for i in df['MENU_FULL_NM']:
tokenized_sentence = okt.morphs(i, stem=True) # 토큰화
stopwords_removed_sentence = [word for word in tokenized_sentence if not word in stopwords] # 불용어 제거
tokenized_data.append(stopwords_removed_sentence)
토큰화를 하면 이런식으로 나온다
아 다시 보니까 & 같은 특수문자도 빼주는게 좋겠다. 제대로 토큰화 된 것들도 있고 아닌 것들도 눈에 보인다.
틀린 것들을 보니까 주로 스위트, 프라페와 같이 영어인데 한국어로 쓰여진 것들인 것 같다.
4.3. Corpus 생성
말뭉치를 생성하자. 나의 학습 데이터는 매우 작기 때문에 저렇게 했는데, 학습 데이터가 문장이라면 window 를 100 단위로 늘려도 될 것 같다
# corpus 생성
corpus = Corpus()
corpus.fit(tokenized_data, window=10)
4.4. 학습
no_components 파라미터는 를, learning_rate 파라미터는 를 뜻한다.
fit 앞쪽에 매직메서드 %time 을 붙이면 학습시키는데 걸린 시간을 볼 수 있다. 생략해도 됨. 근데 필자는 1초가 걸려서 약간 민망했다.
# model
glove = Glove(no_components=100, learning_rate=0.05)
%time glove.fit(corpus.matrix, epochs=50, no_threads=4, verbose=False)
glove.add_dictionary(corpus.dictionary)
4.5 유사한 단어 찾기
most_similar 메서드를 쓰면 비슷한 단어를 찾아준다.
흐음.. 기대하던 성능보다 훨씬 떨어지는건 아니지만 아직 뭔가 말뭉치가 적어서 그런지 불용어 제거가 덜 되어 그런건지 만족스럽진 않은 결과가 나와줬다. 비슷하긴 한데 저게 과연 최선일까? 하는 단어들. 나는 아메리카노를 치면 "카페라떼" 라던가, "버블티" 라던가가 반환될것을 기대했는데, 아무래도 단어 단위 학습이었기 때문에 이 방법은 한계가 있었던 듯 하다.
print(glove.most_similar("아메리카노"))
[('월넛', 0.34037335247101097), ('소', 0.32296872365935664), ('아몬드', 0.2771482643417035), ('이다', 0.2542079146708588)]
print(glove.most_similar("라떼"))
[('버블', 0.5284820655650415), ('(', 0.5077608382037931), ('크림', 0.5077576053444117)]
print(glove.most_similar("녹차"))
[('토스트', 0.32370878549981585), ('생강', 0.2800209826023582), ('카츠', 0.27208754828746967), ('미니', 0.2498923434252674)]
참고자료
다른 분을 보니까 이걸로 k-means 써서 비슷한 문장끼리 묶는 실습도 하신 듯!
[NLP] 단어부터 문장까지 GloVe Embedding / Clustering
[NLP] 단어부터 문장까지 GloVe Embedding 하기 / Clustering 까지 워드 임베딩 방법론 중 하나인 GloVe에 대해서 직접 임베딩하는 과정을 알아보겠습니다. 단어 단위로 임베딩하고 문장 단위의 임베딩으로
jxnjxn.tistory.com
'데이터 과학 Data Science > 자연어처리 NLP' 카테고리의 다른 글
[nlp] 자연어처리에서 숫자를 학습시킬 수 있을까? (0) | 2023.01.26 |
---|---|
[NLP] Fasttext 한국어에서 써보고 하이퍼파라미터 튜닝까지! (2) | 2023.01.17 |
[nlp] subword 분절 (0) | 2023.01.02 |
[NLP] Tokenization (0) | 2022.12.29 |
[NLP] 정규표현식 re 간단한 예제 (0) | 2022.12.29 |