【问题标题】:cosine similarity doc vectors and word vectors for topical prevalence using doc2vec余弦相似度文档向量和词向量使用 doc2vec 进行局部流行
【发布时间】:2021-11-20 11:48:40
【问题描述】:

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

我的问题是平均值。每年的余弦相似度会产生非常奇怪的结果。例如,文档向量和与 covid-19/冠状病毒相关的关键字混合之间的余弦相似性表明,自 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)

【问题讨论】:

    标签: python gensim word2vec doc2vec


    【解决方案1】:

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

    因此,如果您看到 dm=0, dbow_words=1 有很大改进,也可能是因为这使得模型相对而言更容易接受逐字训练。改变window 是另一种改变这种平衡的方法,或者增加epochs,在普通的dm=1 模式下——这也应该导致文档/单词兼容的培训,尽管可能不是相同的速率/平衡。

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

    类似于年度文章的聚类,以及与目标词最近的 1 个或 N 个聚类的识别,以及它们的相似性,即使文章的数量在变化,也可能更具反映性。或者,将每年的全套文章绘制为与目标词的相似性直方图——这可能显示随着时间的推移,单个文章的“块”(不会失去其与全年平均值相比的独特性) ,更接近新现象。

    【讨论】:

    • 感谢您的广泛回答。使用 'dm=0, dbow_words=1' 训练确实花费了至少三倍的时间。从定性的角度来看,结果似乎是有效的。例如,冠状病毒主题的流行率在 2020 年确实达到峰值。此外,仔细检查多年来得分最高的文件也很有意义。
    • 关于topicalprevalence功能,我会试试你的建议。您认为逐月更改会更容易解决问题吗?
    • 每月进行可能会有所帮助,也可能会造成伤害 - 取决于每个时期数据的相对数量/质量/平衡。更多的是假设一个时期内所有文档的平均值必然会接近某些单词 - 我怀疑它可以,有足够的数据和良好的 moel 参数,但我可以想象某些类型的数据不足或不平衡,或模型弱点, mgith 压倒了预期/期望的效果。这些类型的“密集嵌入”本质上是一种压缩,会丢弃大量基础数据 - 但希望(如果调整/使用得当)揭示重要/更深层次的模式。
    • 我想我也可以围绕每个月/年的平均值绘制一个箱线图来说明方差?我认为我分析的主要论点将围绕词嵌入,但人们(在社会科学领域)总是想看看事情是如何随着时间的推移而演变的。所以我认为我可以通过使用dm=0, dbow_words=1 在同一空间中训练文档和单词来克服这个问题。我想另一种选择是像某些人一样在不同的时间段训练不同的 word2vec 模型,但老实说,我认为 doc2vec 解决方案会产生更可靠的结果。
    • 这些年来数据本身相当平衡。它们也都来自一个荷兰新闻来源。
    【解决方案2】:

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

    【讨论】:

    • 请注意,普通的dm=1 模式(又名“PV-DM”)也应该成功地将单词和文档训练为向量,并具有兼容的向量空间。只有dm=0(没有dbow_words=1)使用纯“PV-DBOW”模式,它根本不训练词向量,使它们随机初始化(未经训练)。所以,我不希望从dm=1dm=0, dbow_words=1 的切换器可以解决一个主要问题——除非它可能会导致一些更多网络训练(并且风格略有不同) .增加dm=1 训练的强度(好像增加epochs 等)可能会产生相同的效果。
    猜你喜欢
    • 2021-07-25
    • 2019-05-31
    • 1970-01-01
    • 2019-10-25
    • 2017-09-27
    • 1970-01-01
    • 2011-03-08
    • 2018-11-14
    • 2017-01-10
    相关资源
    最近更新 更多