自然语言识别、分析原理

大多数自然语言处理应用都是(至少部分)基于RNN的,诸如机器翻译、自动总结、语法分析、观点分析等。
在本章的最后部分,我们将要看看机器翻译模型是如何工作的。TensorFlow的Word2Vec和Seq2Seq教程详细地介绍了这部分内容,你应该认真学习一下。

单词嵌入:
在开始之前,我们需要选择一个单词代表。一个选择是使用一个one-hot向量来代表每个单词。
假设单词表有50000个单词,那么第n个单词要使用一个50000向量代替,除了第n位是1外,其他位都是0。
然而,这么大的词汇量使用这种稀疏表示方式不是很高效。
理想情况下,我们希望相似的单词使用相似的表示,这样模型就可以很容易地推此即彼,将学习到的单词概括为所有相似的单词。
例如,如果告知模型“I drink milk”是一个合法的句子,并且知道“milk”和“water”比较相似,但是和“shoes”差得很远,
那么它就会知道“I drink water”应该是一个合法的句子,而“I drink shoes”不是合法的。
但是怎样才能得到一个如此有意义的表示方式呢?

最常见的方案是,将词汇表中的每个单词用小且密集的向量代表(例如150维),此方法称被为嵌入(下面的embeddings)。
然后只需要让神经网络在训练期间对每个单词学习一个好的嵌入即可。
在训练刚开始的时候,嵌入是简单的随机选择,但是随着训练的进行,反向传播会自动移动嵌入,以帮助神经网络执行其任务。
这就意味着,相似的单词会逐渐地集中在彼此之间,甚至最终会以最有意义的方式组织起来。
例如,嵌入最终可能会沿着表示性别、单数/复数、形容词/名词等各种轴放置。结果确实相当惊人。

在TensorFlow中,首先需要为词汇表中的每个单词创建一个表示嵌入的变量(随机初始化):
vocabulary_size = 50000
embedding_size = 150
embeddings = tf.Variable(tf.random_uniform([vocabulary_size, embedding_size], -1.0, 1.0))
# 这个变量表示了全部词汇表的嵌入权重50000*150,通过不断学习嵌入来更新权重150维

现在,假设要将句子“I drink milk”传入网络。首先,应该将句子分解为一系列已知的单词。
例如,可以删除不必要的字符,用预定义的令牌替换未知的单词,如用“[NUM]”替换数字,用“[URL]”替换URL等。
一旦有一个已知的单词列表,可以查找每个单词在字典中的数字标识符(从0到49999),例如[72,3335,288]。
此时,使用占位符将这些标识符提供给TensorFlow,并且应用embedding_lookup()函数来得到相应的嵌入:
train_inputs = tf.placeholder(tf.int32, shape=[None]) # 输入的一句单词分解成的列表
embed = tf.nn.embedding_lookup(embeddings, train_inputs) # 输入与嵌入的结果,tf.nn.nce_loss计算loss
# 得到loss函数后,基于良好的样本对嵌入进行训练,以用于机器翻译
# 两个输入,一个是表示源上下文字词的整数批次,另一个是表示目标字词的整数批次。如the quick brown fox jumped over the lazy dog
# 那么训练样本为(quick, the), (quick, brown), (brown, quick), (brown, fox)。。。根据源来预测目标(还要转数字)
# 根据一篇文章,不断输入句子,那么嵌入就会不断更新。最终根据这个嵌入变量来求出要翻译的每个单词的嵌入向量,用于翻译训练
# 单词有原本的50000维稀稀疏变量,变为了150维的相似变量。用相似的组合解决了稀疏。
# 这个相似不单是指词性或,更多的是性别、单数/复数、形容词/名词等各种轴
Word2vec 是一种计算效率特别高的预测模型,用于学习原始文本中的字词嵌入。
它分为两种类型:连续词袋模型 (CBOW) 和 Skip-Gram 模型。
从算法上看,这些模型比较相似,只是 CBOW 从源上下文字词(“the cat sits on the”)中预测目标字词(例如“mat”),
而 skip-gram 则逆向而行,从目标字词中预测源上下文字词。这种调换似乎是一种随意的选择,
但从统计学上来看,它有助于 CBOW 整理很多分布信息(通过将整个上下文视为一个观察对象)。
在大多数情况下,这对于小型数据集来说是很有用的。
但是,skip-gram 将每个上下文-目标对视为一个新的观察对象,当我们使用大型数据集时,skip-gram 似乎能发挥更好的效果。
在本教程接下来的部分,我们将重点介绍 skip-gram 模型。

该模型的数学原理是最大似然率 (ML) 原则,为实际字词分配高概率,并为噪声字词分配低概率时,此目标被最大化。
实际上,我们会利用非常相似的噪声对比估算 (NCE) 损失,TensorFlow 为此提供了一个方便的辅助函数 tf.nn.nce_loss()。
loss = tf.reduce_mean(tf.nn.nce_loss(nce_weights, nce_biases, train_labels, embed,num_sampled, vocabulary_size))

一旦模型学习了良好的单词植入,那么它们实际上可以在任何NLP应用中发挥作用:
毕竟,无论是什么应用,“milk”仍然比较接近“water”,而和“shoes”差距较大。事实上,你可能希望下载预训练的单词嵌入,而不是训练自己的。
正如在重用预训练层一样(参见第11章),可以选择冻结预训练嵌入(例如,创建嵌入变量),或者让反向传播调整应用程序。
第一种选择将会加快培训,第二种可能会提高性能。

嵌入对于代表可能占用大量不同值的分类属性也很有用处,特别是当值之间存在复杂的相似性时,例如,考虑职业、爱好、菜肴、品种、品牌,等等。

我们已经拥有了实现一个机器翻译系统的所有工具。现在一起看看如何实现吧。

posted @ 2019-10-19 20:40  心平万物顺  阅读(977)  评论(0编辑  收藏  举报