링크한 곳에서 다음 코드를 해석해보자
def getAnalogy(s, model):
qry = model.transform(s[0]) - model.transform(s[1]) - model.transform(s[2])
res = model.findSynonyms((-1)*qry,5) # return 5 "synonyms"
res = [x[0] for x in res]
for k in range(0,3):
if s[k] in res:
res.remove(s[k])
return res[0]
s = ('france', 'paris', 'portugal')
getAnalogy(s, model)
# u'lisbon'
벡터를 빼면 다음과 같이 유추할 수 있다.
프랑스 - 파리 = 도시
포르투갈 - ? = 도시
-(프랑스 - 파리 - 포르투갈) = ?
이제 ?와 벡터 거리가 가장 가까운 워드를 추출하면 어떻게 되나. 리스본이라고 예상되는 가상의 벡터 ?와 가장 가까운 벡터를 찾으니까 리스본이 나온다. 그런데 가까운 벡터에 프랑스, 파리, 도시가 있는 경우는 결과 셋에서 제거한다. 결과 셋에 중복으로 출현할 수 있는 이유는 아직 잘 이해가 안 가는데, "도시"라고 가정한 벡터의 차에는 사실 "도시" 외에도 이들 지명과 관련한 다른 성분이 들어있을 수 있고, 이에 따라 상위 랭크에 이들 단어가 포함될 가능성이 높기 때문이 아닐까 유추만 하고 있다.
벡터의 길이를 충분히 늘려서 학습시키면 어쩌면 res[0]만 이용해도 되지 않을까?
스파크의 word2vec은 ml 패키지와 mlib 패키지 둘 다 제공한다. mlib 패키지가 더 기저패키지다. ml은 데이터프레임을 인터페이스로 사용하며 경험 상 더 빠르게도 해주고 그러는 것 같다. 이 두 차이를 모르고 뚝딱뚝딱 하다가 시간만 날렸다.
1문장을 1문서로 보고 word2vec의 모델을 구했을 때, 이 모델에 원래 데이터를 넣으면 문장(문서) 단위로 벡터가 나온다.
getvectors()를 해보면 단어 별로 벡터 값이 존재하는 것을 알 수 있다.
문장 단위로 나온 벡터값은 사실 각각의 토큰의 벡터를 모두 합해서 갯수로 나눈, 즉 평균 값이다. 이것이 의미하는 것은 벡터의 평균만으로 문장, 문단, 책의 주요 피쳐를 추정할 수 있다는 것이다.