FastText에 document를 학습시킬 때, itertools.cycle 사용하기.

1 분 소요

Intro

  • 요즘 저는 FastText를 이용해서 단어의 의미를 학습시키고 있습니다. word2vec도 doc2vec도 있습니다만, fasttext의 경우는 vocabulary에 없는 단어들이라도 형태적인 유사성을 고려해서, 의미를 파악할 수 있다는 강점이 있죠. 따라서, 꽤 많은 경우 복합어에 대해서도 어느 정도 유추해준다는, 강점이 있습니다.
  • 다만, 슬프게도 제 맥북은 램이 4GB입니다. 좋은 컴퓨터를 가지신 분들은 좋겠지만, 저는 그래서, 일정 량을 넘치는 데이터의 경우 한번에 list로 변환하여 memory에 올릴 수 없어요. 즉, 저는, 한번에 올리지 못하고 generator로 변환해서 올려야 합니다.

Problem: couldn’t train model by list

  • 예를 들면 다음과 같습니다. generator를 만들어서 train시킵니다.
from gensim.models.fasttext import FastText

docs = ["i am a boy", "you are a girl"]
# 따라서, docs라는 corpus를 generator로 만들도록 하죠. 
# 즉, generator로 만들었으니까, 필요할 때 하나씩 읽는 형태로 변경된 것이죠.
docs = (s.lower().split(" ") for s in docs)
print(f"type of docs: {type(docs)}")

FTmodel = FastText(min_count=1, size=10)
# build_vocab: 우선 vocab을 만들고요. 
FTmodel.build_vocab(docs)
# train: 학습을 시켜줍니다.
FTmodel.train(sentences=docs, total_examples=FTmodel.corpus_count, epochs=10)
  • 어떤가요? 잘 되는 것처럼 보이죠? 실제로 실행을 해보면, 아무 문제없이 잘 수행되는 것을 알 수 있습니다. 하지만, 실제로는 전혀 학습이 안되었죠.

왜 학습이 안되었는가?

  • 이는 결국 generator의 속성과 닿아 았습니다. generator는 한번 읽고 나면 비어 있습니다.
  • 다음 코드를 보시면, 처음에는 잘 출력해주지만, 그 다음에는 아무것도 없는 빈 리스트가 출력되죠.
# generator를 만들었습니다. 
test_generator = (i for i in range(0, 3))
# 여기서는 잘 실행이 되지만, 
print(list(test_generator))
print("----------------")
# 여기서는 비어 있는 리스트가 그냥 출력됩니다.
print(list(test_generator))
  • 두번째 출력할때는 아무것도 출력되지 않ㅎ습니다. 즉, 비어있는 generator에서 그냥 긁어온 것이니까요.
[0, 1, 2]
----------------
[]

Solution: 매번 새로운 generator를 넘긴다

  • 따라서, 매번 새로운 generator를 생성해서 넘겨주는 식으로 진행해야 합니다.
  • 그리고 매번 새로 generator를 넘겨서 학습해준다고 생각해야 하죠.
def RETURN_docs_generator():
    # 새로운 generator를 생성해서 RETURN해준다.
    docs = ["i am a boy", "you are a girl"]
    docs = ( s.lower().split(" ") for s in docs )
    return docs

FTmodel = FastText(min_count=1, size=10)
FTmodel.build_vocab(RETURN_docs_generator())
print("buile vocab done")
for epoch in range(0, 10):
    # epochs를 1로 설정해서 새롭게 매번 넘겨준다고 생각하고 접근해야함.
    FTmodel.train(sentences=RETURN_docs_generator(), total_examples=FTmodel.corpus_count, epochs=1)
    print(f"-- EPOCH: {epoch}")
print("== complete")
  • 혹은 generator를 반복하는 itertools.repeatitertools.chain.from_iterable를 사용해서 한번에 더 많은 자료를 넘겨서 학습시킬 수도 있습니다.
  • 즉, corpus 자체를
def RETURN_docs_generator():
    # 새로운 generator를 생성해서 RETURN해준다.
    docs = ["i am a boy", "you are a girl"]
    docs = ( s.lower().split(" ") for s in docs )
    return docs

FTmodel = FastText(min_count=1, size=10)
FTmodel.build_vocab(RETURN_docs_generator())
print("buile vocab done")
FTmodel.train(
    sentences=itertools.chain.from_iterable(itertools.repeat(RETURN_docs_generator(), 3)), 
    total_examples=FTmodel.corpus_count, 
    epochs=1)
print(f"-- EPOCH: {epoch}")
print("== complete")

댓글남기기