자연어처리: 문서임베딩 - Doc2Vec

Dec2vec

natural language processing
document embedding
doc2vec
Author

Cheonghyo Cho

문서 임베딩

  • Doc2Vec(Paragraph Vector)은 문서(단락, 문장 등) 전체를 고정 길이 벡터로 변환하는 기법
  • 기본 아이디어는 문서 자체를 하나의 벡터로 학습하고, 단어 벡터와 함께 학습된 문서 벡터를 활용하여 단어 예측을 수행

Doc2Vec의 주요 개념

Doc2Vec은 두 가지 학습 방식을 사용

  • Distributed Memory Model of Paragraph Vectors (PV-DM)
    • 문서 벡터 + 단어 벡터를 사용하여 다음 단어를 예측하는 방식
    • Word2Vec의 CBOW(Continuous Bag of Words)와 유사
  • Distributed Bag of Words Model of Paragraph Vectors (PV-DBOW)
    • 문서 벡터를 사용하여 문서 내에서 임의의 단어를 예측하는 방식
    • Word2Vec의 Skip-gram과 유사

Doc2Vec의 학습 과정

  • Doc2Vec은 주어진 문서에서 각 단어를 예측하는 방식으로 학습
  • 이를 위해 문서 ID를 나타내는 벡터와 단어 벡터를 함께 학습하는 방식으로 동작

PV-DM (Distributed Memory) 모델

  • 목표: 문서 벡터와 주변 단어 벡터를 기반으로 다음 단어를 예측
  • 방법: 특정 윈도우 크기(예: 3~5) 내의 단어들을 입력으로 받아, 다음 단어를 예측
  • 구성 요소:
    • 문서 벡터 (D) → 해당 문서의 문맥을 저장하는 역할
    • 단어 벡터 (W) → 문서 내 등장하는 개별 단어의 의미 저장
  • 학습 과정:
    • 주어진 문서에서 연속된 여러 단어(컨텍스트 단어)를 선택
    • 문서 벡터(D)와 선택된 단어 벡터(W)를 결합
    • 이를 통해 다음 단어를 예측하는 신경망을 학습
    • 문서 벡터와 단어 벡터를 동시에 업데이트
  • 예제:
    • 문서: “The cat sat on the mat.”
    • 컨텍스트: [“The”, “cat”, “sat”]
    • 다음 단어 예측: “on”
    • → (D + “The” + “cat” + “sat”) → “on” 예측
  • 장점:
    • 문서 벡터가 문맥을 유지하기 때문에 문서 전체의 의미를 잘 반영
    • 단어 순서를 일부 반영하여 BoW보다 향상된 표현 학습 가능

PV-DBOW (Distributed Bag of Words) 모델

  • 목표: 문서 벡터를 이용해 문서 내 랜덤 단어를 예측

  • 방법: 문서 벡터만을 입력으로 사용하고, 문서에 포함된 단어 중 하나를 무작위로 선택하여 예측

  • 구성 요소:

    • 문서 벡터 (D) → 문서의 전체적인 의미 저장
    • 단어 벡터는 따로 사용하지 않음
  • 학습 과정:

    • 특정 문서에서 하나의 단어를 랜덤하게 선택
    • 문서 벡터만을 입력으로 사용하여 해당 단어를 예측
    • 문서 벡터를 업데이트하여 해당 문서의 의미를 반영
  • 예제

    • 문서: “The cat sat on the mat.”
    • 랜덤 단어: “cat”
    • → (D) → “cat” 예측
  • 장점:

    • 단어 벡터 없이 문서 벡터만을 학습하여 메모리 효율성이 높음
    • Word2Vec의 Skip-gram 방식과 유사하며, 강력한 표현력을 가짐
from gensim.models.doc2vec import Doc2Vec, TaggedDocument
from nltk.tokenize import word_tokenize

# 학습 데이터 준비
documents = [
    TaggedDocument(words=word_tokenize("The cat sat on the mat."), tags=["DOC_1"]),
    TaggedDocument(words=word_tokenize("Dogs are great pets."), tags=["DOC_2"]),
    TaggedDocument(words=word_tokenize("Cats and dogs can be friends."), tags=["DOC_3"])
]

# Doc2Vec 모델 학습 (PV-DM 방식)
model = Doc2Vec(documents, vector_size=50, window=2, min_count=1, workers=4, dm=1)

# 학습된 문서 벡터 출력
print(model.dv["DOC_1"])  # 첫 번째 문서 벡터
[-0.01051783 -0.01200203 -0.01984816  0.01716449  0.00712801  0.00053357
 -0.01982716 -0.01033127 -0.01949057  0.00405696  0.00568871  0.00931222
 -0.00861875 -0.00632861 -0.00614419 -0.01753384  0.0043392   0.01851678
 -0.01906662 -0.00693029 -0.00754504  0.00525124 -0.01144489  0.00526968
  0.01160711 -0.01626217 -0.01673745 -0.01998021  0.0099023  -0.01832683
  0.01174006  0.01364959 -0.01306674 -0.00905344 -0.00252451  0.00329995
 -0.00295675 -0.01713611 -0.00724468  0.00345583 -0.00412142 -0.01448993
  0.0083869  -0.0172424   0.00543042 -0.00923537  0.00130436 -0.00409975
  0.01087504 -0.01606338]
# 새로운 문서를 벡터화하고 유사 문서 찾기
new_doc = word_tokenize("Dogs are friendly animals.")
new_vector = model.infer_vector(new_doc)
similar_docs = model.dv.most_similar([new_vector], topn=3)

print(similar_docs)
[('DOC_2', 0.05467547848820686), ('DOC_1', 0.037136662751436234), ('DOC_3', -0.2144276350736618)]