原文出处:Embeddings 原作者:Microsoft · 许可证:MIT License 中文译本由诸葛AI学院整理,仅供学习参考,版权归原作者与微软所有。
课前测验
训练基于词袋(bag of words)或 TF/IDF 的分类器时,我们操作的是高维的词袋向量(vector),长度等于 vocab_size,还要把低维的位置表示向量显式转换成稀疏的 one-hot 表示。这种 one-hot 表示不省内存。每个词也被当成跟别的词彼此独立:one-hot 编码的向量表达不出词与词之间的语义相似性。
嵌入(embedding)的想法是:用维度更低的稠密向量来表示词,让它多少反映出词的语义。怎么构造有意义的词嵌入,后面会讨论;眼下先把嵌入看作给词向量降维的一种办法。
嵌入层接收一个词作为输入,产出一个指定 embedding_size 的输出向量。某种意义上它很像 Linear 层,区别在于它不用吃 one-hot 编码向量,而是可以直接拿词的编号当输入,省掉了构造庞大 one-hot 向量这一步。
把嵌入层当成分类器网络的第一层,我们就能从词袋模型切换到嵌入袋(embedding bag)模型:先把文本里的每个词换成对应的嵌入,再对这些嵌入算某个聚合函数,比如 sum、average 或 max。原文此处有一张图,画的是五个词的序列各自经过嵌入层、再汇总送进分类器的过程(图为原文作者所绘)。
练习:嵌入
继续在下面的 notebook 里学习:
语义嵌入:Word2Vec
嵌入层虽然学会了把词映射成向量表示,但这种表示未必带多少语义。理想情况是学出这样一种向量表示:相似的词或同义词,对应的向量在某种向量距离(比如欧氏距离)下也彼此靠近。
要做到这一点,得用特定的方式在大规模文本集合上预训练嵌入模型。训练语义嵌入的一种方法叫 Word2Vec。它基于两种主要架构,都用来产生词的分布式表示:
- 连续词袋(Continuous bag-of-words,CBoW):这种架构下,我们训练模型根据周围的上下文预测一个词。给定 ngram $(W_{-2},W_{-1},W_0,W_1,W_2)$,模型的目标是从 $(W_{-2},W_{-1},W_1,W_2)$ 预测 $W_0$。
- 连续跳词(Continuous skip-gram):与 CBoW 相反,模型用当前词去预测周围窗口内的上下文词。
CBoW 更快,skip-gram 更慢,但低频词表示得更好。
原文此处有一张图,把 CBoW 和 Skip-Gram 两种"词转向量"的算法摆在一起做对比(图来自这篇论文)。
Word2Vec 预训练好的嵌入(以及 GloVe 这类相似模型)也可以替代神经网络里的嵌入层直接使用。词汇表是个麻烦:预训练 Word2Vec/GloVe 用的词汇表,很可能跟我们文本库里的词汇表对不上。这个问题怎么解决,可以看上面那几个 notebook。
上下文嵌入
Word2Vec 这类传统预训练表示有一个关键局限:词义消歧(word sense disambiguation)。预训练嵌入能捕捉到词在上下文中的部分含义,但一个词的每一种含义都编码在同一个嵌入里。这会给下游模型带来麻烦,因为像 play 这样的词,意思随上下文而变。
比如下面两个句子里的 play,含义差别不小:
- I went to a play at the theatre.(我去剧院看了一出戏。)
- John wants to play with his friends.(约翰想和朋友们玩。)
前面说的预训练嵌入,会把 play 的这两个意思塞进同一个向量。要迈过这道坎,嵌入得建立在语言模型(language model)之上:它在大规模文本上训练,知道词语在不同上下文里可以怎样组合。上下文嵌入的讨论超出本篇教程的范围,课程后面讲语言模型时会回到这个话题。
小结
这节课学了怎么在 TensorFlow 和 PyTorch 里搭建、使用嵌入层,让向量更贴合词的语义。
挑战
Word2Vec 有过一些有意思的应用,包括生成歌词和诗歌。可以读读这篇文章,作者一步步讲了他怎么用 Word2Vec 写诗;再看 Dan Shiffman 的这个视频,是另一种讲法。然后试着把这些手法用到你自己的文本库上,素材不妨从 Kaggle 找。
课后测验
复习与自学
读一读这篇 Word2Vec 论文:Efficient Estimation of Word Representations in Vector Space。