将词嵌入应用于整个文档,以获得特征向量

机器算法验证 分类 自然语言 监督学习 word2vec 词嵌入
2022-02-06 05:30:09

如何使用词嵌入将文档映射到特征向量,适用于监督学习?

词嵌入映射到向量,其中是一些不太大的数字(例如,500)。流行的词嵌入包括word2vecGlovewvRdd

我想应用监督学习对文档进行分类。我目前正在使用词袋表示将每个文档映射到特征向量,然后应用现成的分类器。我想用基于现有预训练词嵌入的东西替换词袋特征向量,以利用词嵌入中包含的语义知识。有没有标准的方法来做到这一点?

我可以想象一些可能性,但我不知道是否有最有意义的事情。我考虑过的候选方法:

  • 我可以计算文档中每个单词的向量,并对它们进行平均。但是,这似乎可能会丢失很多信息。例如,对于词袋表示,如果有几个词与分类任务高度相关,而大多数词不相关,分类器可以很容易地学习到;如果我平均文档中所有单词的向量,分类器就没有机会了。

  • 连接所有单词的向量不起作用,因为它不会导致固定大小的特征向量。这似乎也是一个坏主意,因为它对单词的特定位置过于敏感。

  • 我可以使用词嵌入将所有单词的词汇表聚集到一组固定的集群中,比如 1000 个集群,我在向量上使用余弦相似度作为词相似度的度量。然后,我可以有一个词袋,而不是词袋:我提供给分类器的特征向量可以是一个 1000 向量,其中第个组件计算文档中的单词数是集群的一部分。ii

  • 给定一个词,这些词嵌入让我计算出一组前 20 个最相似的词及其相似度得分我可以使用它来调整类似词袋的特征向量。当我看到单词时,除了将单词对应的元素增加之外,我还可以将单词w_1 对应的元素增加,将单词 w_2 对应的元素s_2ww1,,w20s1,,s20ww1w1s1w2s2

是否有任何特定方法可能适用于文档分类?


我不是在寻找paragraph2vec 或doc2vec;那些需要对大数据语料库进行培训,而我没有大数据语料库。相反,我想使用现有的词嵌入。

4个回答

一种似乎对短文本(例如,句子或推文)相当有效的简单技术是计算文档中每个单词的向量,然后使用坐标均值、最小值或最大值聚合它们。

根据最近一篇论文的结果,使用最小值和最大值似乎效果很好。它不是最佳的,但它很简单,并且与其他简单技术一样好或更好。特别是,如果单词的向量是,那么你计算这里我们取坐标最小值,即最小值是一个向量使得,同样对于最大值。特征向量就是这两个向量的串联,所以我们在nv1,v2,,vnRdmin(v1,,vn)max(v1,,vn)uui=min(vi1,,vin)R2d. 我不知道这是否比词袋表示更好或更差,但对于短文档,我怀疑它可能比词袋表现更好,并且它允许使用预训练的词嵌入。

TL;DR:令人惊讶的是,最小值和最大值的串联工作得相当好。

参考:

使用加权词嵌入聚合对非常短的文本进行表示学习。Cedric De Boom、Steven Van Canneyt、Thomas Demeester、Bart Dhoedt。模式识别字母;arxiv:1607.00570。 摘要pdf尤其参见表 1 和表 2。

致谢:感谢@user115202 让我注意到这篇论文。

您可以使用类似于 word2vec 的 doc2vec,并使用来自大型语料库的预训练模型。然后使用类似.infer_vector()gensim 的东西来构造一个文档向量。doc2vec 训练不需要来自训练集。

另一种方法是使用 RNN、CNN 或前馈网络进行分类。这有效地将词向量组合成文档向量。

您还可以将稀疏特征(词)与密集(词向量)特征结合起来,相互补充。因此,您的特征矩阵将是稀疏词袋矩阵与词向量平均值的串联。https://research.googleblog.com/2016/06/wide-deep-learning-better-together-with.html

另一种有趣的方法是使用与 word2vec 类似的算法,但您可以预测目标标签,而不是预测目标词。这直接将词向量调整为分类任务。http://arxiv.org/pdf/1607.01759v2.pdf

对于更多临时方法,您可以尝试根据语法对单词进行不同的加权。例如,您可以比限定词更强烈地衡量动词。

如果您正在使用英文文本并希望从预训练的词嵌入开始,请参阅:https ://code.google.com/archive/p/word2vec/

这是 word2vec 的原始 C 版本。除了这个版本,他们还发布了一个模型,训练了从谷歌新闻文章中提取的 1000 亿个单词(参见标题为“预训练的单词和短语向量”的小节)。

在我从事词嵌入工作的经验和经验中,对于文档分类,像 doc2vec(带有 CBOW)这样的模型比词袋效果好得多。

因为,你有一个小的语料库,我建议你通过上面提到的预训练嵌入来初始化你的词嵌入矩阵。然后在 doc2vec 代码中训练段落向量。如果你对 python 很熟悉,你可以查看它的 gensim 版本,它很容易修改。

另请查看详细介绍 word2vec/doc2vec 内部工作原理的这篇论文:http: //arxiv.org/abs/1411.2738这将使理解 gensim 代码变得非常容易。

没有人提到它给我留下了深刻的印象,但其他最佳实践是将句子填充到固定大小,使用 Word2Vec 的权重初始化嵌入层并将其输入 LSTM。所以它基本上是 OP 在这里提到的,但包括处理不同长度的填充:

连接所有单词的向量不起作用,因为它不会导致固定大小的特征向量。

例子

考虑以下句子(取自有毒评论分类挑战):

“解释为什么我的用户名 Hardcore Metallica Fan 下的编辑被还原了?他们不是故意破坏,只是在我在纽约娃娃 FAC 投票后关闭了一些 GA。请不要从讨论页面中删除模板,因为我'我现在退休了。89.205.38.27"

首先,我们清理这样的句子:

“解释为什么我的用户名 hardcore metalica fan 下所做的编辑被还原了?他们不是故意破坏,只是在我在纽约娃娃 fac 投票后关闭了一些气体。请不要从讨论页面中删除模板,因为我 '我现在退休了。ipaddress"

接下来,我们将他们的单词编码成整数:

776 92 2 161 153 24964 2492 10 29 75 24 3 2 2 2 2 2 2 2 2 2 75 2730 29 29 23 67 73 10 29 29 2 3 9 10 81 10 81 4030 107 1 216

最后,如果我们执行长度为 200 的填充,它看起来像这样:

array([    0,     0,     0,     0,     0,     0,     0,     0,     0,
           0,     0,     0,     0,     0,     0,     0,     0,     0,
           0,     0,     0,     0,     0,     0,     0,     0,     0,
           0,     0,     0,     0,     0,     0,     0,     0,     0,
           0,     0,     0,     0,     0,     0,     0,     0,     0,
           0,     0,     0,     0,     0,     0,     0,     0,     0,
           0,     0,     0,     0,     0,     0,     0,     0,     0,
           0,     0,     0,     0,     0,     0,     0,     0,     0,
           0,     0,     0,     0,     0,     0,     0,     0,     0,
           0,     0,     0,     0,     0,     0,     0,     0,     0,
           0,     0,     0,     0,     0,     0,     0,     0,     0,
           0,     0,     0,     0,     0,     0,     0,     0,     0,
           0,     0,     0,     0,     0,     0,     0,     0,     0,
           0,     0,     0,     0,     0,     0,     0,     0,     0,
           0,     0,     0,     0,     0,     0,     0,     0,     0,
           0,     0,     0,     0,     0,     0,     0,     0,     0,
           0,     0,   776,    92,     2,   161,   153,   212,    44,
         754,  4597,  9964,  1290,   104,   399,    34,    57,  2292,
          10,    29, 14515,     3,    66,  6964,    22,    75,  2730,
         173,     5,  2952,    47,   136,  1298, 16686,  2615,     1,
           8,    67,    73,    10,    29,   290,     2,   398,    45,
           2,    60,    43,   164,     5,    10,    81,  4030,   107,
           1,   216], dtype=int32)

我们可以强制所有句子最多包含 200 个单词,如果少则用零填充,如果多的话则删去后面的单词。

接下来,我们使用 word2vec 的权重初始化一个嵌入模型,这是一个使用 Keras 的示例:

model.add(Embedding(nb_words, WV_DIM, weights=[wv_matrix], input_length=MAX_SEQUENCE_LENGTH, trainable=False))

wv_matrix包含一个形状为的矩阵(唯一词的数量与嵌入维度的关系)。nd

最后我们在这之后添加一个 LSTM 层,例如:

embedded_sequences = SpatialDropout1D(0.2)(embedded_sequences)
x = Bidirectional(CuDNNLSTM(64, return_sequences=False))(embedded_sequences)

参考