doc2vec 예제 분석
오래전부터 doc2vec 예제를 좀 찾아봤습니다. 적당한 예제도 없고 자세한 설명이 부족한것 같아서 정리해 봅니다.
준비
기본 예제는 아래 링크에서 출발합니다.python3 로 시작 합니다.
https://medium.com/@mishra.thedeepak/doc2vec-simple-implementation-example-df2afbbfbad5
시작하기전에 import 에러나는 것은 없는지 확인해봅시다.
#Import all the dependencies
from gensim.models.doc2vec import Doc2Vec, TaggedDocument
from nltk.tokenize import word_tokenize
만약 아래와 같은 에러가 난다면 nltk를 설치해 줍니다.
python doc2vectut.py Traceback (most recent call last): File "doc2vectut.py", line 3, in <module> from nltk.tokenize import word_tokenize ModuleNotFoundError: No module named 'nltk'
https://stackoverflow.com/questions/40361488/importerror-no-module-named-nltk-tokenize-nltk-is-not-a-package
pip install nltk
입력 데이터
학습 모델의 기본은 입력 데이터 형태부터 파악 하는것입니다. 여기 train을 위해서 입력하는 데이터를 가공 하는 소스 입니다. word2vec에서는 list의 list형태로 데이터를 넣었다면, 여기에서는 words=['i', 'love', 'machine', 'learning', '.', 'its', 'awesome', '.'], tags=['0'] 이런 형태의 데이터의 list들을 만들어서 입력으로 사용합니다.
여기에서 tags는 label이 되기를 원하는 값=목표값으로 (분류를 원하는 값) 입니다. 예를 들어보자면 영화 평점 리뷰 게시판이 있고 댓글과 평점이 있을때 학습을 하는경우 댓글 내용이 words가 되고 평점은 tags가 됩니다. 학습이 되고 나면 댓글 (words)내용을 가지고 (tags)평점이 얼마나 될지 예측이 가능하게 됩니다.
평점이 높을수록 좋은 의미를 지니므로 이것은 영화뿐 아니라 다른곳에서 사용가능한 데이터에도 응용할 수 있습니다. 영화 평점은 이런면에서 좋은 학습 데이터가 되게 됩니다.
여기 비슷하게 처리한 내용이 있네요, 한번 읽어보는것도 좋을것 같습니다.
http://hero4earth.com/blog/projects/2018/01/21/naver_movie_review/
Let’s prepare data for training our doc2vec model
data = ["I love machine learning. Its awesome.",
"I love coding in python",
"I love building chatbots",
"they chat amagingly well"]
tagged_data = [TaggedDocument(words=word_tokenize(_d.lower()), tags=[str(i)]) for i, _d in enumerate(data
위 코드를 실행했을때 nltk 아래와 같은 오류가 난다면 데이터를 다운로드 받도록 합니다.
LookupError: ********************************************************************** Resource [93mpunkt [0m not found. Please use the NLTK Downloader to obtain the resource: [31m>>> import nltk >>> nltk.download('punkt') [0m For more information see: https://www.nltk.org/data.html Attempted to load [93mtokenizers/punkt/english.pickle [0m Searched in: - 'C:\\Users\\USER/nltk_data' - 'C:\\Users\\USER\\AppData\\Local\\Programs\\Python\\Python37\\nltk_data' - 'C:\\Users\\USER\\AppData\\Local\\Programs\\Python\\Python37\\share\\nltk_data' - 'C:\\Users\\USER\\AppData\\Local\\Programs\\Python\\Python37\\lib\\nltk_data' - 'C:\\Users\\USER\\AppData\\Roaming\\nltk_data' - 'C:\\nltk_data' - 'D:\\nltk_data' - 'E:\\nltk_data' - '' **********************************************************************
nltk 데이터 다운로드 받기
http://www.nltk.org/nltk_data/
Punkt Tokenizer Models
python 실행 후 아래와 같이 실행합니다.
>>> import nltk
>>> nltk.download('punkt')
지금까지 소스와 실행한 결과입니다.
#Import all the dependencies from gensim.models.doc2vec import Doc2Vec, TaggedDocument from nltk.tokenize import word_tokenize data = ["I love machine learning. Its awesome.", "I love coding in python", "I love building chatbots", "they chat amagingly well"] tagged_data = [TaggedDocument(words=word_tokenize(_d.lower()), tags=[str(i)]) for i, _d in enumerate(data)] print(tagged_data)
실행 결과
C:\Users\USER\Documents\python\doc2vec>python doc2vectut.py [TaggedDocument(words=['i', 'love', 'machine', 'learning', '.', 'its', 'awesome', '.'], tags=['0']), TaggedDocument(words=['i', 'love', 'coding', 'in', 'python'], tags=['1']), TaggedDocument(words=['i', 'love', 'building', 'chatbots'], tags=['2']), TaggedDocument(words=['they', 'chat', 'amagingly', 'well'], tags=['3'])]
코드가 복잡한데 좀 더 쉽게 풀어서 구현한 코드는 아래와 같습니다.
tagged_data = [] for i, _d in enumerate(data): tagged_data.append(TaggedDocument(words=word_tokenize(_d.lower()), tags=[str(i)]))
python enumerate 는 index와 data를 분리하게 됩니다. 아래 링크 참조
https://dpdpwl.tistory.com/43
학습시키기
학습하는 데이터의 parameter는 데이터들마다 다르기 때문에 값을 바꿔가면서 이것저것 변경해봐야 합니다. 이것을 hyper parameter라고 하는데 여기 원본 문서를 참고해 가면서 의미를 파악 하시면 됩니다.https://radimrehurek.com/gensim/models/doc2vec.html
학습의 기본은 epoch과 learning rate입니다. 여기 예제에서 max_epochs로 나온 부분이 학습을 얼마나 할것인지 결정합니다. 전체 데이터를 이용해서 1번 학습하는것을 1 epoch라고합니다.
여기 예제에서는 model.alpha -= 0.0002 를 이용하여 learning rate를 조절 하고 있습니다. 학습을 거듭할수록 error값이 줄어드는데 learning rate가 올라가면 발진할 수 있으므로 학습 할수록 작아지도록 예제를 만들어 놓은것으로 판단됩니다.
max_epochs = 100
vec_size = 20
alpha = 0.025
model = Doc2Vec(size=vec_size,
alpha=alpha,
min_alpha=0.00025,
min_count=1,
dm =1)
model.build_vocab(tagged_data)
for epoch in range(max_epochs):
print('iteration {0}'.format(epoch))
model.train(tagged_data,
total_examples=model.corpus_count,
epochs=model.iter)
# decrease the learning rate
model.alpha -= 0.0002
# fix the learning rate, no decay
model.min_alpha = model.alpha
model.save("d2v.model")
print("Model Saved")
지금까지 소스외에 model save / load하는 소스까지 하여 실행 시켜 봤습니다.
전체 소스
#Import all the dependencies from gensim.models.doc2vec import Doc2Vec, TaggedDocument from nltk.tokenize import word_tokenize #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ data = ["I love machine learning. Its awesome.", "I love coding in python", "I love building chatbots", "they chat amagingly well"] tagged_data = [] for i, _d in enumerate(data): tagged_data.append(TaggedDocument(words=word_tokenize(_d.lower()), tags=[str(i)])) print(tagged_data) #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ max_epochs = 100 vec_size = 20 alpha = 0.025 model = Doc2Vec(size=vec_size, alpha=alpha, min_alpha=0.00025, min_count=1, dm =1) model.build_vocab(tagged_data) for epoch in range(max_epochs): print('iteration {0}'.format(epoch)) model.train(tagged_data, total_examples=model.corpus_count, epochs=model.iter) # decrease the learning rate model.alpha -= 0.0002 # fix the learning rate, no decay model.min_alpha = model.alpha model.save("d2v.model") print("Model Saved") #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ from gensim.models.doc2vec import Doc2Vec model= Doc2Vec.load("d2v.model") #to find the vector of a document which is not in training data test_data = word_tokenize("I love chatbots".lower()) v1 = model.infer_vector(test_data) print("V1_infer", v1) # to find most similar doc using tags similar_doc = model.docvecs.most_similar('1') print(similar_doc)
결과
C:\Users\USER\Documents\python\doc2vec>python doc2vectut.py [TaggedDocument(words=['i', 'love', 'machine', 'learning', '.', 'its', 'awesome', '.'], tags=['0']), TaggedDocument(words=['i', 'love', 'coding', 'in', 'python'], tags=['1']), TaggedDocument(words=['i', 'love', 'building', 'chatbots'], tags=['2']), TaggedDocument(words=['they', 'chat', 'amagingly', 'well'], tags=['3'])] C:\Users\USER\AppData\Local\Programs\Python\Python37\lib\site-packages\gensim\models\doc2vec.py:574: UserWarning: The parameter `size` is deprecated, will be removed in 4.0.0, use `vector_size` instead. warnings.warn("The parameter `size` is deprecated, will be removed in 4.0.0, use `vector_size` instead.") iteration 0 doc2vectut.py:37: DeprecationWarning: Call to deprecated `iter` (Attribute will be removed in 4.0.0, use self.epochs instead). epochs=model.iter) iteration 1 iteration 2 iteration 3 iteration 4 iteration 5 iteration 6 iteration 7 iteration 8 iteration 9 iteration 10 iteration 11 iteration 12 iteration 13 iteration 14 iteration 15 iteration 16 iteration 17 iteration 18 iteration 19 iteration 20 iteration 21 iteration 22 iteration 23 iteration 24 iteration 25 iteration 26 iteration 27 iteration 28 iteration 29 iteration 30 iteration 31 iteration 32 iteration 33 iteration 34 iteration 35 iteration 36 iteration 37 iteration 38 iteration 39 iteration 40 iteration 41 iteration 42 iteration 43 iteration 44 iteration 45 iteration 46 iteration 47 iteration 48 iteration 49 iteration 50 iteration 51 iteration 52 iteration 53 iteration 54 iteration 55 iteration 56 iteration 57 iteration 58 iteration 59 iteration 60 iteration 61 iteration 62 iteration 63 iteration 64 iteration 65 iteration 66 iteration 67 iteration 68 iteration 69 iteration 70 iteration 71 iteration 72 iteration 73 iteration 74 iteration 75 iteration 76 iteration 77 iteration 78 iteration 79 iteration 80 iteration 81 iteration 82 iteration 83 iteration 84 iteration 85 iteration 86 iteration 87 iteration 88 iteration 89 iteration 90 iteration 91 iteration 92 iteration 93 iteration 94 iteration 95 iteration 96 iteration 97 iteration 98 iteration 99 Model Saved V1_infer [-0.0109304 0.01453446 -0.02796343 0.01905919 0.0186462 0.01566897 0.01792961 0.00705164 0.01424597 0.00248461 0.02653115 0.02868732 -0.01172108 0.00585754 -0.01540187 -0.01015471 0.0146137 0.00021682 0.01906102 -0.01555774] [('0', 0.9923108816146851), ('3', 0.9911640882492065), ('2', 0.9911146759986877)]
소스 분석
test_data = word_tokenize("I love chatbots".lower())위 코드는 test_data를 토큰화 해서 vector를 만드는 과정입니다.
v1 = model.infer_vector(test_data)
위 예제에서는 결과로서 아래와 같은 vector가 출력되었습니다. 위에서 vector size를 20으로 했기 때문에 20개가 되는것 입니다. 크기가 클수록 더 정확해질 수 있으나 더 많은 메모리와 더많은 데이터로 더 많은 훈련이 필요합니다.
[-0.0109304 0.01453446 -0.02796343 0.01905919 0.0186462 0.01566897
0.01792961 0.00705164 0.01424597 0.00248461 0.02653115 0.02868732
-0.01172108 0.00585754 -0.01540187 -0.01015471 0.0146137 0.00021682
0.01906102 -0.01555774]
similar_doc = model.docvecs.most_similar('1')이 예제는 "1" 번 문장과 가장 비슷한 문장이 어떤것인지 나타납니다. 결과를 보자면 "0"이 0.9923% 수준으로 제일 근접 합니다. "0" 번 문장인데 전혀 비슷하지 않지만....
[('0', 0.9923108816146851), ('3', 0.9911640882492065), ('2', 0.9911146759986877)]
문제점
여러번 실행시키면 아래와 같이 값이 다릅니다. 이때 결과가 "2" 두번째 문장인 경우도 나옵니다.Model Saved V1_infer [-0.02121443 -0.00848201 -0.00763245 0.00745193 0.00415829 -0.01217643 0.01441886 0.01548216 -0.00765178 -0.02253398 -0.0081254 -0.00448609 -0.0034246 -0.01841096 0.02063655 -0.01921302 0.01506925 0.0162458 0.01329079 -0.0103074 ] [('2', 0.9906354546546936), ('0', 0.9863607883453369), ('3', 0.9810261726379395)]
Model Saved V1_infer [ 0.00368929 0.00579063 -0.00694244 -0.01026715 -0.00822515 0.01120392 -0.00292197 0.00318307 -0.00821392 0.003614 -0.02230442 -0.01828359 0.01888582 0.01448112 0.00215786 0.00533434 0.01083726 -0.00696347 -0.00343927 -0.02374181] [('0', 0.9902483224868774), ('3', 0.9879346489906311), ('2', 0.9857644438743591)]
앞으로 해결할 주제
위 문제점은 어디에서 잘못되었을까?원하는 문장이 있을때 어떤 문장과 비슷한가?
댓글 없음:
댓글 쓰기