使用 word2vec 嵌入句子

Sentences embedding using word2vec

我想比较不同句子中提到的同一个词的区别,例如“旅行”。 我想做的是:

我知道 word2vec 需要的不仅仅是几个句子来训练可靠的向量。官网推荐了几十亿字的数据集,但是我的数据集里没有这个数字(我有几千字)。

我试图用以下几句话测试模型:

    Sentences
    Hawaii makes a move to boost domestic travel and support local tourism
    Honolulu makes a move to boost travel and support local tourism
    Hawaii wants tourists to return so much it's offering to pay for half of their travel expenses

我构建向量的方法是:

from gensim.models import Word2Vec

vocab = df['Sentences']))
model = Word2Vec(sentences=vocab, size=100, window=10, min_count=3, workers=4, sg=0)
df['Sentences'].apply(model.vectorize)

但是我不知道如何将结果可视化以查看它们的相似性并获得一些有用的见解。 欢迎任何帮助和建议。

更新:我会使用主成分分析算法来可视化 3 维 space 中的嵌入。我知道如何对每个单词做,但我不知道如何做句子。

有趣的 word2vec 模型,您可以使用向量的 T-SNE 嵌入并将维数减少到 3,并使用任何绘图库(如 matplotlib 或 dash)将它们可视化。我还发现这个工具在可视化词嵌入时很有用:https://projector.tensorflow.org/

学习不同上下文中的词的不同词嵌入的想法是 ELMO(https://allennlp.org/elmo) 的前提,但你需要一个巨大的训练集来训练它。幸运的是,如果您的应用不是很具体,您可以使用 pre-trained 模型。

请注意,word2vec 本身并不是一种建模句子的方法,它只是单词。所以没有单一的、正式的方法来使用 word2vec 来表示句子。

一种快速粗略的方法是通过将所有 word-vectors 平均在一起来为句子(或其他 multi-word 文本)创建一个向量。它很快,它是 better-than-nothing,并且在一些简单的 (broadly-topical) 任务上表现不错——但不会很好地捕捉文本的全部含义,尤其是任何依赖于语法的含义,多义词,或复杂的上下文提示。

不过,您可以使用它为每个短文本获取一个 fixed-size 向量,并计算这些向量之间的成对 similarities/distances,并将结果输入 dimensionality-reduction 算法以进行可视化或其他用途。

其他算法实际上为较长的文本创建向量。与 word2vec 密切相关的浅层算法是 'paragraph vectors',在 Gensim 中可用 Doc2Vec class。但它仍然不是很复杂,仍然不是 grammar-aware。许多 deeper-network 文本模型,如 BERT、ELMo 等可能都是可能的。

Word2vec 和相关算法非常 data-hungry:它们的所有优点都来自于同一单词的许多不同用法示例之间的 tug-of-war。因此,如果您有一个 toy-sized 数据集,您将不会得到一组具有有用相互关系的向量。

而且,较大数据集中的稀有词不会获得好的向量。在训练中,通常会丢弃出现频​​率低于 min_count 的单词,就好像它们根本不存在一样——因为不仅它们的向量很差,仅来自一个或几个特殊的样本使用,而且因为总共有很多这样的未被充分代表的词,保留它们往往会使 other word-vectors 变得更糟。他们是噪音。

因此,您提出的采用 travel 个实例并将其替换为 single-appearance 标记的想法很可能会产生有趣的结果。将你的 min_count 降低到 1 将为你获得每个变体的向量 - 但它们的质量会比你的其他 word-vectors 差得多(& more-random),相比之下接受的训练注意力相对较少换句话说,每个人都完全受到周围几个词的影响(而不是所有周围环境的整个范围都可以帮助有助于统一 travel 标记的有用定位)。

(您可以通过 (1) 保留句子的原始版本,这样您仍然可以得到一个 travel 向量;(2) 重复您的 token-mangled 句子多次,并将它们改组以出现在整个语料库中,以在某种程度上模拟合成上下文中更真实的出现。但如果没有真正的多样性,此类 single-context 向量的大部分问题将仍然存在。)

另一种比较 travel_sent_Atravel_sent_B 等的可能方法是完全忽略 traveltravel_sent_X 的确切向量,而是编译一个摘要向量对于单词周围的 N 个单词。例如,如果您有 100 个单词 travel 的示例,请创建 100 个向量,每个向量都是 around 旅行的 N 个单词。这些向量可能会显示一些模糊的 clusters/neighborhoods,尤其是在单词具有 very-different 替代含义的情况下。 (一些采用 word2vec 来解释多义词的研究使用这种 context vector 方法在替代 word-senses 中 influence/choose。)

您可能还会发现这项关于将单词建模为从替代 'atoms' 话语中提取的研究很有趣:Linear algebraic structure of word meanings

如果您的 headline-like 文本很短,并且只有 word-vectors(没有数据或算法来进行更深入的建模),您可能还想查看“Word Mover's Distance”用于比较文本的计算。它不是将单个文本简化为单个向量,而是将其建模为“word-vectors 包”。然后,它定义了一个 cost-to-transform 一个包到另一个包的距离。 (更多相似的词比 less-similar 个词更容易相互转化,因此非常相似的表达,只替换了几个同义词,报告为非常接近。)

对较长的文本进行计算可能会非常昂贵,但对于短短语和 headlines/tweets/etc 的小集合可能效果很好。它在 Gensim KeyedVector classes 上可用 wmdistance(). An example of the kinds of correlations it may be useful in discovering is in this article: Navigating themes in restaurant reviews with Word Mover’s Distance

如果你对比较句子感兴趣,Word2Vec 不是最好的选择。结果表明,使用它来创建句子嵌入会产生比专用句子嵌入算法更差的结果。如果您的数据集不大,则无法使用自己的数据创建(训练新的)嵌入 space。这迫使您对句子使用预训练的嵌入。幸运的是,现在已经有足够多的了。我相信 Universal Sentence Encoder(作者 Google)最能满足您的需求。

获得句子的向量表示后,您可以采用两种方式:

  1. 创建成对比较矩阵并将其可视化为热图。当你对句子有多接近有一些先验知识并且你想检查你的假设时,这种表示很有用。你甚至可以try it online
  2. 运行 t-SNE 在矢量表示上。这将创建句子的 2D 投影,以保持句子之间的相对距离。它呈现的数据比 PCA 好得多。你可以很容易地找到某个句子的邻居:

您可以从 this and this

了解更多