神经网络机器翻译的实现
2017-01-07 23:01
501 查看
本文主要讲解以recurrent neural network为主,以及使用Chainer和自然语言处理其中的encoder-decoder翻译模型。
并将英中机器翻译用代码实现。
最基本的recurrent neural network(RNN),像下面的图一样,最典型的是追加3层神经网络隐含层的反馈。
这是非常简单的模型,本文接下来介绍的翻译模型就是由RNN作成。RNN是比以前的N - gram模型精度性能更加优越的模型。
上图写成式子的话就是
在chainer(本次实现所使用的程序库)中,我们就使用上面的式子。
在这里暂且先是考虑“输入单词ID,预测下一个单词ID”的RNN语言模式吧。
首先定义模型。模式是学习可能的参数的集合,上图的W∗∗就是这个意思。这个场合W∗∗是全部线性算子(矩阵),所以使用chainer . functions内的Linear吗EmbedID。EmbedID是输入方面在one-hot向量的Linear,代替vector。
然后,定义实际的解析函数forward。在这里基本是按照上图的网络结构来再现模型的定义和实际的输入数据,最终进行求值计算。语言模型的情况下,是用下面的式表示句子的结合概率。
[/code]
以下是代码的例子。
这样就可以求出句子的概率了。但是,上面并没有计算损失函数。所以我们使用softmax函数来进行计算。
也就是用chainer.functions.softmax_cross_entropy
现在就可以进行学习了。
那么基本上chainer的RNN代码就是这样实现的了。
和过去的方法相比也能够达到很高精度,现在深受NLP研究者们喜爱的翻译模型。
encoder-decoder有很多种,以下是我在本文中实现的模型。
很简单的想法,准备输入方面(encoder)和输出方面(decoder)的2个RNN,在中间节点上连接。
这个模型的有趣之处在于,为了在输出方面一起生成终端符号,翻译的结束是由模型自己决定的。但是反过来讲,为了不生成无限的单词死循环,实际处理的时候,做一些限制还是有必要的。
i和j是embedding(词向量)层。
整个模型的计算式如下
对隐藏层p和q的位移,使用了LSTM神经网络。但是encoder方面实质的损失的计算位置y的距离很远,一般的传递函数很难进行学习。
所以LSTM神经网络的长距离时序依存关系的优点就能够体现出来。
上式的位移W∗∗一共有8种。用以下的代码来定义。
接下来是forward函数。
因为LSTM带有内部结构,注意p和q的计算需要多一个
稍微有点长,这段代码和之前的图结合起来读就会明白了。
最终结果如下:
第一次epoch的结果。
第100次epoch的结果。
src是英文原文。trg是正确译文。hyp是预测译文。
因为现在手头只有笔记本电脑,内存不足,所以把参数都调低了,不然无法执行。你们懂的。
看起来还不赖吧。参数调高必然能取得更好的效果。
Have fun!
Ps:过阵子回学校再把代码整理下发布。
并将英中机器翻译用代码实现。
Recurrent Neural Network
最基本的recurrent neural network(RNN),像下面的图一样,最典型的是追加3层神经网络隐含层的反馈。这是非常简单的模型,本文接下来介绍的翻译模型就是由RNN作成。RNN是比以前的N - gram模型精度性能更加优越的模型。
上图写成式子的话就是
在chainer(本次实现所使用的程序库)中,我们就使用上面的式子。
在这里暂且先是考虑“输入单词ID,预测下一个单词ID”的RNN语言模式吧。
首先定义模型。模式是学习可能的参数的集合,上图的W∗∗就是这个意思。这个场合W∗∗是全部线性算子(矩阵),所以使用chainer . functions内的Linear吗EmbedID。EmbedID是输入方面在one-hot向量的Linear,代替vector。
from chainer import FunctionSet from chainer.functions import * model = FunctionSet( w_xh = EmbedID(VOCAB_SIZE, HIDDEN_SIZE), # 输入层(one-hot) -> 隐藏层 w_hh = Linear(HIDDEN_SIZE, HIDDEN_SIZE), # 隐藏层 -> 隐藏层 w_hy = Linear(HIDDEN_SIZE, VOCAB_SIZE), # 隐藏层 -> 输出层 )
VOCAB_SIZE是单词的数量、
HIDDEN_SIZE是隐藏层的维数。
然后,定义实际的解析函数forward。在这里基本是按照上图的网络结构来再现模型的定义和实际的输入数据,最终进行求值计算。语言模型的情况下,是用下面的式表示句子的结合概率。
[/code]
以下是代码的例子。
import math import numpy as np from chainer import Variable from chainer.functions import * def forward(sentence, model): # sentence是strの排列结果。 sentence = [convert_to_your_word_id(word) for word in sentence] # 单词转换为ID h = Variable(np.zeros((1, HIDDEN_SIZE), dtype=np.float32)) # 隐藏层的初值 log_joint_prob = float(0) # 句子的结合概率 for word in sentence: x = Variable(np.array([[word]], dtype=np.int32)) # 下一次的输入层 y = softmax(model.w_hy(h)) # 下一个单词的概率分布 log_joint_prob += math.log(y.data[0][word]) #结合概率的分布 h = tanh(model.w_xh(x) + model.w_hh(h)) #隐藏层的更新 return log_joint_prob #返回结合概率的计算结果
这样就可以求出句子的概率了。但是,上面并没有计算损失函数。所以我们使用softmax函数来进行计算。
也就是用chainer.functions.softmax_cross_entropy
def forward(sentence, model): ... accum_loss = Variable(np.zeros((), dtype=np.float32)) # 累计损失的初値 ... for word in sentence: x = Variable(np.array([[word]], dtype=np.int32)) #下次的输入 (=现在的正确值) u = model.w_hy(h) accum_loss += softmax_cross_entropy(u, x) # 累计损失 y = softmax(u) ... return log_joint_prob, accum_loss # 累计损失全部返回
现在就可以进行学习了。
from chainer.optimizers import * ... def train(sentence_set, model): opt = SGD() # 使用梯度下降法 opt.setup(model) # 学习初期化 for sentence in sentence_set: opt.zero_grad(); # 勾配の初期化 log_joint_prob, accum_loss = forward(sentence, model) # 损失的计算 accum_loss.backward() # 误差反向传播 opt.clip_grads(10) # 剔除过大的梯度 opt.update() # 参数更新
那么基本上chainer的RNN代码就是这样实现的了。
Encoder-decode翻译模型
encoder-decoder是现在广泛使用的利用神经网络的翻译模型。和过去的方法相比也能够达到很高精度,现在深受NLP研究者们喜爱的翻译模型。
encoder-decoder有很多种,以下是我在本文中实现的模型。
很简单的想法,准备输入方面(encoder)和输出方面(decoder)的2个RNN,在中间节点上连接。
这个模型的有趣之处在于,为了在输出方面一起生成终端符号,翻译的结束是由模型自己决定的。但是反过来讲,为了不生成无限的单词死循环,实际处理的时候,做一些限制还是有必要的。
i和j是embedding(词向量)层。
整个模型的计算式如下
对隐藏层p和q的位移,使用了LSTM神经网络。但是encoder方面实质的损失的计算位置y的距离很远,一般的传递函数很难进行学习。
所以LSTM神经网络的长距离时序依存关系的优点就能够体现出来。
上式的位移W∗∗一共有8种。用以下的代码来定义。
model = FunctionSet( w_xi = EmbedID(SRC_VOCAB_SIZE, SRC_EMBED_SIZE), #输入层(one-hot) -> 输入词向量层 w_ip = Linear(SRC_EMBED_SIZE, 4 * HIDDEN_SIZE), # 输入词向量层-> 输入隐藏层 w_pp = Linear(HIDDEN_SIZE, 4 * HIDDEN_SIZE), # 输入隐藏层 -> 输入隐藏层 w_pq = Linear(HIDDEN_SIZE, 4 * HIDDEN_SIZE), # 输入隐藏层-> 输出隐藏层 w_yq = EmbedID(TRG_VOCAB_SIZE, 4 * HIDDEN_SIZE), #输出层(one-hot) -> 输出隐藏层 w_qq = Linear(HIDDEN_SIZE, 4 * HIDDEN_SIZE), #输出隐藏层 -> 输出隐藏层 w_qj = Linear(HIDDEN_SIZE, TRG_EMBED_SIZE), # 输出隐藏层 -> 输出词向量层 w_jy = Linear(TRG_EMBED_SIZE, TRG_VOCAB_SIZE), # 输出隐藏层 -> 输出隐藏层 )
接下来是forward函数。
因为LSTM带有内部结构,注意p和q的计算需要多一个
Variable。
# src_sentence: 需要翻译的句子 e.g. ['他', '在', '走'] # trg_sentence: 正解的翻译句子 e.g. ['he', 'runs'] # training: 机械学习的预测。 def forward(src_sentence, trg_sentence, model, training): # 转换单词I a2f2 D # 对正解的翻訳追加终端符号 src_sentence = [convert_to_your_src_id(word) for word in src_sentence] trg_sentence = [convert_to_your_trg_id(word) for wprd in trg_sentence] + [END_OF_SENTENCE] # LSTM内部状态的初期値 c = Variable(np.zeros((1, HIDDEN_SIZE), dtype=np.float32)) # encoder for word in reversed(src_sentence): x = Variable(np.array([[word]], dtype=np.int32)) i = tanh(model.w_xi(x)) c, p = lstm(c, model.w_ip(i) + model.w_pp(p)) # encoder -> decoder c, q = lstm(c, model.w_pq(p)) # decoder if training: # 学习时使用y作为正解的翻译、forward结果作为累计损失来返回 accum_loss = np.zeros((), dtype=np.float32) for word in trg_sentence: j = tanh(model.w_qj(q)) y = model.w_jy(j) t = Variable(np.array([[word]], dtype=np.int32)) accum_loss += softmax_cross_entropy(y, t) c, q = lstm(c, model.w_yq(t), model.w_qq(q)) return accum_loss else: # 预测时翻译器生成的y作为下次的输入,forward的结果作为生成了的单词句子 # 选择y中最大概率的单词、没必要用softmax。 hyp_sentence = [] while len(hyp_sentence) < 100: # 剔除生成100个单词以上的句子 j = tanh(model.w_qj(q)) y = model.w_jy(j) word = y.data.argmax(1)[0] if word == END_OF_SENTENCE: break # 生成了终端符号,结束。 hyp_sentence.append(convert_to_your_trg_str(word)) c, q = lstm(c, model.w_yq(y), model.w_qq(q)) return hyp_sentence
稍微有点长,这段代码和之前的图结合起来读就会明白了。
最终结果如下:
第一次epoch的结果。
第100次epoch的结果。
src是英文原文。trg是正确译文。hyp是预测译文。
因为现在手头只有笔记本电脑,内存不足,所以把参数都调低了,不然无法执行。你们懂的。
看起来还不赖吧。参数调高必然能取得更好的效果。
Have fun!
Ps:过阵子回学校再把代码整理下发布。
相关文章推荐
- 谷歌翻译整合神经网络:机器翻译实现颠覆性突破
- 机器学习之基于matlab的神经网络粒子群优化算法的实现
- 神经网络机器翻译模型介绍-GNMT
- 机器学习之 神经网络的实现(二)-->手写识别
- 神经网络机器翻译Neural Machine Translation: Attention Mechanism
- 谷歌神经网络机器翻译NMT:人人可利用TensorFlow快速建立翻译模型
- 干货 | NIPS 2017线上分享:利用价值网络改进神经机器翻译
- 神经网络机器翻译Neural Machine Translation(1): Encoder-Decoder Architecture
- 神经网络机器翻译模型介绍
- 一个基于Tensorflow的神经网络机器翻译系统
- 融合统计机器翻译特征的蒙汉神经网络机器翻译技术
- 神经网络机器翻译总结
- 神经网络机器翻译模型介绍-总结
- Seq2Seq非常好的代码(机器翻译、对话生成等):漫谈四种神经网络序列解码模型【附示例代码】
- 神经网络机器翻译Neural Machine Translation(2): Attention Mechanism
- 神经记忆网络、神经机器翻译和神经图灵机的初步探讨
- 神经网络python 实现
- 最简单的三层神经网络Matlab实现
- ANN 人工神经前馈网络BP实现
- R语言实现神经网络