使用 doc2vec 的余弦相似度 doc 向量和词向量用于局部流行

cosine similarity doc vectors and word vectors for topical prevalence using doc2vec

我有一个包含 2010-2020 年 25 万篇荷兰新闻文章的语料库,我在其中应用了 word2vec 模型来揭示中性词组和维度(例如好-坏)之间的关系。由于我的目标也是分析某些主题随时间的流行程度,因此我考虑使用 doc2vec 来同时学习单词和文档嵌入。然后可以将文档中的 'prevalence' 主题计算为文档向量和词嵌入(或词向量的组合)之间的余弦相似度。通过这种方式,我可以计算语料库中的年度主题流行度,并查看是否随时间发生任何变化。可以在 here.

中找到这种方法的示例

我的问题是平均。年度余弦相似性会产生非常奇怪的结果。例如,文档向量与与 covid-19/coronavirus 相关的关键字混合之间的余弦相似性表明自 2016 年以来主题流行度有所下降(显然情况并非如此)。

我的问题是我遵循的方法是否真的有效。或者也许我缺少某些东西。一个250k的文档和100k+的词汇量应该够了吧?

下面是我写的代码:

# Doc2Vec model 
from gensim.models.doc2vec import Doc2Vec, TaggedDocument
docs = [TaggedDocument(doc, [i]) for i, doc in enumerate(tokenized_docs)]
d2vmodel = Doc2Vec(docs, min_count = 5, vector_size = 200, window = 10, dm = 1)
docvecs = d2vmodel.docvecs
wordvecs = d2vmodel.wv
    
# normalize vector 
from numpy.linalg import norm
def nrm(x):
  return x/norm(x)

# topical prevalence per doc
def topicalprevalence(topic, docvecs, wordvecs):
  proj_lst = []
  for i in range(0, len(docvecs)):
    topic_lst = []
    for j in topic: 
      cossim =  nrm(docvecs[i]) @ nrm(wordvecs[j])
      topic_lst.append(cossim)
    topic_avg = sum(topic_lst) / len(topic_lst)
    proj_lst.append(topic_avg)
  topicsyrs = { 
      'topic': proj_lst,
      'year': df['datetime'].dt.year
  }
  return pd.DataFrame(topicsyrs)

# avg topic prevalence per year
def avgtopicyear(topic, docvecs, wordvecs):
  docs = topicalprevalence(topic, docvecs, wordvecs)
  return pd.DataFrame(docs.groupby("year")["topic"].mean())

# run 
covid = ['corona', 'coronapandemie', 'coronacrisis', 'covid', 'pandemie']
covid_scores = topicalprevalence(covid, docvecs, wordvecs)

事实证明,将参数设置为 dm=0, dbow_words=1 允许在同一 space 中训练文档和单词,现在产生有效结果。

训练两者的模式中的 word-vec-to-doc-vec 关系很有趣,但很难描述它们的真正含义。在某种意义上,dm=1(PV-DM)的类 CBOW 模式在训练预测 'target' 词时将文档向量混合为整个 window 中的一个相等词。但是在 skip-gram-mixed 模式 dm=0, dbow_words=1 中,每 1 个 doc-vec-to-target-word 就会有 window count context-word-vec-to-target-word 对循环配对循环,改变相对权重。

因此,如果您在 dm=0, dbow_words=1 中看到很大的改进,也可能是因为这使得模型相对更容易接受单词到单词的训练。在普通 dm=1 模式下,改变 window 是改变平衡或增加 epochs 的另一种方式——这也应该导致 doc/word 兼容训练,尽管可能不一样rate/balance.

一整年的单个 topicalprevalence() 均值向量是否实际上反映了一个主要主题的单个单词出现次数可能是也可能不是一个有效的猜想,这取决于训练数据中可能发生的其他变化。语料库中其他主要类别的相对组合的差异甚至可能淹没一个巨大的新新闻主题。 (例如:如果在 2020 年推出一些具有不同重点的新部分或子公司,如娱乐,会怎样?它 可能 淹没其他词的影响,特别是当压缩到 单个一些特定维度的向量。)

有点像当年文章的聚类,以及与目标词最接近的 1 或 N 个聚类的识别,以及它们的相似性,即使文章数量在变化,也可能更具反映性。或者,将每年的整套文章作为与目标词的相似性直方图的图表 - 这可能显示 'lump' 个别文章(不失去全年平均值的独特性)发展,随着时间的推移,越来越接近新现象。