热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

神经网络机器翻译的实现

本文系qitta的文章翻译而成,由renzhe0009实现。转载请注明以上信息,谢谢合作。本文主要讲解以recurrentneuralnetwork为主,以及使用Chainer和自
本文系qitta的文章翻译而成,由renzhe0009实现。转载请注明以上信息,谢谢合作。

本文主要讲解以recurrent neural network为主,以及使用Chainer和自然语言处理其中的encoder-decoder翻译模型。

并将英中机器翻译用代码实现。

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。在这里基本是按照上图的网络结构来再现模型的定义和实际的输入数据,最终进行求值计算。语言模型的情况下,是用下面的式表示句子的结合概率。

《神经网络机器翻译的实现》

 

以下是代码的例子。

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):
# 转换单词ID
# 对正解的翻訳追加终端符号
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:过阵子回学校再把代码整理下发布。

 

 

 

 


推荐阅读
  • 不同优化算法的比较分析及实验验证
    本文介绍了神经网络优化中常用的优化方法,包括学习率调整和梯度估计修正,并通过实验验证了不同优化算法的效果。实验结果表明,Adam算法在综合考虑学习率调整和梯度估计修正方面表现较好。该研究对于优化神经网络的训练过程具有指导意义。 ... [详细]
  • 生成式对抗网络模型综述摘要生成式对抗网络模型(GAN)是基于深度学习的一种强大的生成模型,可以应用于计算机视觉、自然语言处理、半监督学习等重要领域。生成式对抗网络 ... [详细]
  • 浏览器中的异常检测算法及其在深度学习中的应用
    本文介绍了在浏览器中进行异常检测的算法,包括统计学方法和机器学习方法,并探讨了异常检测在深度学习中的应用。异常检测在金融领域的信用卡欺诈、企业安全领域的非法入侵、IT运维中的设备维护时间点预测等方面具有广泛的应用。通过使用TensorFlow.js进行异常检测,可以实现对单变量和多变量异常的检测。统计学方法通过估计数据的分布概率来计算数据点的异常概率,而机器学习方法则通过训练数据来建立异常检测模型。 ... [详细]
  • Learning to Paint with Model-based Deep Reinforcement Learning
    本文介绍了一种基于模型的深度强化学习方法,通过结合神经渲染器,教机器像人类画家一样进行绘画。该方法能够生成笔画的坐标点、半径、透明度、颜色值等,以生成类似于给定目标图像的绘画。文章还讨论了该方法面临的挑战,包括绘制纹理丰富的图像等。通过对比实验的结果,作者证明了基于模型的深度强化学习方法相对于基于模型的DDPG和模型无关的DDPG方法的优势。该研究对于深度强化学习在绘画领域的应用具有重要意义。 ... [详细]
  • 超级简单加解密工具的方案和功能
    本文介绍了一个超级简单的加解密工具的方案和功能。该工具可以读取文件头,并根据特定长度进行加密,加密后将加密部分写入源文件。同时,该工具也支持解密操作。加密和解密过程是可逆的。本文还提到了一些相关的功能和使用方法,并给出了Python代码示例。 ... [详细]
  • 从批量eml文件中提取附件的Python代码实现方法
    本文介绍了使用Python代码从批量eml文件中提取附件的实现方法,包括获取eml附件信息、递归文件夹下所有文件、创建目的文件夹等步骤。通过该方法可以方便地提取eml文件中的附件,并保存到指定的文件夹中。 ... [详细]
  • 第七课主要内容:多进程多线程FIFO,LIFO,优先队列线程局部变量进程与线程的选择线程池异步IO概念及twisted案例股票数据抓取 ... [详细]
  • 本博文基于《Amalgamationofproteinsequence,structureandtextualinformationforimprovingprote ... [详细]
  • 【论文】ICLR 2020 九篇满分论文!!!
    点击上方,选择星标或置顶,每天给你送干货!阅读大概需要11分钟跟随小博主,每天进步一丢丢来自:深度学习技术前沿 ... [详细]
  • 如何使用Java获取服务器硬件信息和磁盘负载率
    本文介绍了使用Java编程语言获取服务器硬件信息和磁盘负载率的方法。首先在远程服务器上搭建一个支持服务端语言的HTTP服务,并获取服务器的磁盘信息,并将结果输出。然后在本地使用JS编写一个AJAX脚本,远程请求服务端的程序,得到结果并展示给用户。其中还介绍了如何提取硬盘序列号的方法。 ... [详细]
  • javascript  – 概述在Firefox上无法正常工作
    我试图提出一些自定义大纲,以达到一些Web可访问性建议.但我不能用Firefox制作.这就是它在Chrome上的外观:而那个图标实际上是一个锚点.在Firefox上,它只概述了整个 ... [详细]
  • 安卓select模态框样式改变_微软Office风格的多端(Web、安卓、iOS)组件库——Fabric UI...
    介绍FabricUI是微软开源的一套Office风格的多端组件库,共有三套针对性的组件,分别适用于web、android以及iOS,Fab ... [详细]
  • 从零学Java(10)之方法详解,喷打野你真的没我6!
    本文介绍了从零学Java系列中的第10篇文章,详解了Java中的方法。同时讨论了打野过程中喷打野的影响,以及金色打野刀对经济的增加和线上队友经济的影响。指出喷打野会导致线上经济的消减和影响队伍的团结。 ... [详细]
  • 闭包一直是Java社区中争论不断的话题,很多语言都支持闭包这个语言特性,闭包定义了一个依赖于外部环境的自由变量的函数,这个函数能够访问外部环境的变量。本文以JavaScript的一个闭包为例,介绍了闭包的定义和特性。 ... [详细]
  • java drools5_Java Drools5.1 规则流基础【示例】(中)
    五、规则文件及规则流EduInfoRule.drl:packagemyrules;importsample.Employ;ruleBachelorruleflow-group ... [详细]
author-avatar
小帅
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有