nodevectors 不返回所有节点

nodevectors not returning all nodes

我正在尝试使用 nodevectorNode2Vec class 为我的图表获取嵌入。我无法展示完整的代码,但基本上这就是我正在做的:

import networkx as nx
import pandas as pd
import nodevectors

n2v = nodevectors.Node2Vec(n_components=128,
                           walklen=80,
                           epochs=3,
                           return_weight=1,
                           neighbor_weight=1,
                           threads=4)
G = nx.from_pandas_edgelist(df, 'customer', 'item', edge_attr='weight', create_using=nx.Graph)
n2v.fit(G)
model = n2v.model
shape = model.ww.vectors.shape

我知道 G 拥有我范围内的所有节点。然后,我拟合模型,但 model.ww.vectors 的行数小于我的节点数。

我没有成功找到为什么 model.ww.vectors 在我的嵌入中表示的节点数低于我在 G 中的实际节点数。

有人知道为什么会这样吗?

TL;DR:您的 non-default epochs=3 可能导致某些节点仅出现 3 次——但内部 Word2Vec 模型默认忽略出现次数少于 5 次的标记。提高到 epochs=5 可能是一个快速修复 - 但请继续阅读原因和权衡各种默认值。

--

如果您使用 nodevectors 描述的包 here,它似乎是建立在 Gensim 的 Word2Vec 之上的——它使用默认的 min_count=5.

这意味着出现次数少于 5 次的任何标记(在本例中为节点)都将被忽略。尤其是在 Word2Vec 开创的 natural-language 语境中,完全丢弃这些不常见的词通常有很多好处:

  • 仅从几个特殊的例子中,这些罕见的词本身就有特殊的向量 less-likely 以推广到下游使用(其他文本)
  • 与其他常用词相比,每个词总体上得到的训练工作量很少,因此仅对共享模型权重提供了一点回推(基于它们的特殊示例)-因此向量较弱并保留了更多来自[的任意影响=85=] & 在语料库中的相对定位。 (More-frequent 单词提供了更多样的例子来提取其独特的含义。)
  • 由于自然语言中 word-frequencies 的 Zipfian 分布,有 很多 这样的 low-frequency 词——通常甚至是拼写错误——而且它们一共占用大量模型的内存&training-time。但它们 不会 单独获得非常好的向量,或者对共享模型具有普遍的有益影响。因此,它们最终会像噪声一样服务,也会削弱 more-frequent 单词的其他向量。

因此通常在 Word2Vec 中,丢弃稀有词只会放弃 low-value 个向量,同时加快训练速度、减少内存需求并提高剩余向量的质量:一个巨大的胜利。

虽然图 random-walks 中 node-names 的分布可能与 natural-language word-frequencies 有很大不同,但一些相同的问题仍然适用于很少出现的节点。另一方面,如果一个节点真的只出现在一长串节点的末尾,那么每次往返它都会包含完全相同的邻居 - 并且可能在更多的行走中额外出现不会增加新的 variety-of-information (至少在 Word2Vec window 分析的内部)。

您可以通过使用 Node2Vec keep_walks 参数来存储生成的行走,然后检查:是否正是节点'missing' 在散步中出现的次数是否少于 min_count 次?

如果是这样,几个选项可能是:

  • 使用 Node2Vec w2vparams 选项将 min_count 覆盖为 min_count=1 之类的东西。如上所述,这在传统的 natural-language Word2Vec 中始终是一个坏主意 - 但在图形应用程序中可能并不是那么糟糕,对于 rare/outer-edge 个节点来说,一次行走就足够了,然后在至少你有任何 strange/noisy 最小训练的矢量结果。
  • 尝试影响游走以确保所有节点出现足够的次数。我想 Node2Vec walklen, return_weight, & neighbor_weight 的一些值可以提高覆盖率——但我认为它们不能保证所有节点至少出现在 N (比如,5,以匹配默认的 min_count) 不同的步行。但看起来 Node2Vec epochs 参数控制多少次 每个 节点被用作起点 - 所以 epochs=5 将保证每个节点出现至少 5 次,作为 5 次独立步行的开始。 (值得注意的是:Node2Vec 默认值是 epochs=20 - 它永远不会触发与内部 Word2Vec min_count=5 的不良交互。但是设置你的 non-default epochs=3 冒着让一些节点只出现 3 次的风险。)