机器翻译及相关技术

机器翻译(MT)是将一种语言转换成另一种语言,语言之间表达一个含义用的词汇量是不同的,之前讲到的RNN、LSTM、GRU【人工智能学习】【十一】循环神经网络进阶里的输出要么是多对多、要么多对一。参考【人工智能学习】【六】循环神经网络里的图。比如翻译“我我是中国人”——>“I am Chinese”,就会把5个字符翻译成3个词,这种前后不等长的问题是机器翻译要解决的问题。下面介绍Encoder-Decoder模型,在NLP中是一个非常基础的模型。

Encoder-Decoder模型


“Any problem in computer science can be solved by anther layer of indirection.”
“既然RNN那种神经网络模型无法解决这类问题,那就加一层。”
这个模型分为三部分,左侧是Encoder,从名字上看是一个编码作用,编码成中间的语义编码c,作为输入输入到右侧的Decoder中。
这个模型是一个框架思想,Encoder和Decoder可以用CNN、RNN来实现,比如【人工智能学习】【十】卷积神经网络进阶中的AlexNet、VGG、NiN、GoogLeNet,再比如【人工智能学习】【十一】循环神经网络进阶中的LSTM,GRU,Bi-LSTM,深度循环神经网络来做。所以Encoder-Decoder模型更像一种思想。
输入的序列 X t X_t Xt经过Encoder后,最终输出一个隐含层状态,这个状态我们可以在经过一个权重矩阵 W W W来进行一个线性变换,得到语义语义编码 c c c(context vector)。

语义编码

c = f ( H 1 , H 2 , H 3 … … H t , ) c=f(H_1,H_2,H_3……H_t,) c=f(H1,H2,H3Ht,)
也可以直接使用
C = f ( H t , ) C=f(H_t,) C=f(Ht,)
学习机器学习要有抽象能力,模型产生的数据都看看哪些可以当做信息,可以拿来用一些就用。

Decoder

decoder过程是使用encoder计算出来的隐藏状态 H t H_t Ht,经过一个 W W W矩阵变换出来的序列 c c c作为输出,来预测当前的输出符号 y t y_t yt,这里的 y t y_t yt和decoder里隐藏状态 y h t y_{ht} yht都与 c c c和前一个输出有关。
y 1 = f ( C ) y_1=f(C) y1=f(C)
y 2 = f ( C , H y − 1 , y 1 ) y_2=f(C,H_{y-1},y_1) y2=f(C,Hy1,y1)
y 3 = f ( C , H y − 1 , y 2 ) y_3=f(C,H_{y-1},y_2) y3=f(C,Hy1,y2)
… … ……

当遇到终止字符时 < E O S > <EOS> <EOS>就认为输出结束了。
这里有几种模式,请参考NLP(3)——seq to seq
总结:

  1. 处理变长序列问题。
  2. 数据降维

代码

定义Encoder

class Encoder(nn.Module):def __init__(self, **kwargs):super(Encoder, self).__init__(**kwargs)def forward(self, X, *args):raise NotImplementedError

定义Decoder

class Decoder(nn.Module):def __init__(self, **kwargs):super(Decoder, self).__init__(**kwargs)# decoder的state初始值是encoder的最后一个神经元的statedef init_state(self, enc_outputs, *args):raise NotImplementedErrordef forward(self, X, state):raise NotImplementedError

定义模型

class EncoderDecoder(nn.Module):def __init__(self, encoder, decoder, **kwargs):super(EncoderDecoder, self).__init__(**kwargs)self.encoder = encoderself.decoder = decoderdef forward(self, enc_X, dec_X, *args):enc_outputs = self.encoder(enc_X, *args)dec_state = self.decoder.init_state(enc_outputs, *args)return self.decoder(dec_X, dec_state)

Sequence to Sequence模型

在机器翻译中,用的是基于Encoder-Decoder模型思想的Sequence to Sequence模型模型。

训练结构:


首先来看

模型分Encoder和Decoder两部分,Encoder模型的初始化state为0,Decoder初始化state为Encoder的hidden state。Encoder顺序输入待翻译序列hello world,Decoder里它的法语翻译作为标签。
Decoder的第一个输入是 < b o s > <bos> <bos>,代表句子的开始字符,输出一个翻译结果bonjour,然后bonjour输入,得到下一个字符le(这个就类似之前【人工智能学习】【六】循环神经网络)的那个例子。直到网络遇到了 < e o s > <eos> <eos>,翻译结束。

预测


区别在于Decoder部分

在预测时,Decoder的输入变成上一个神经元的输出。

Encoder实现

Encoder用LSTM实现的

class Seq2SeqEncoder(d2l.Encoder):def __init__(self, vocab_size, embed_size, num_hiddens, num_layers,dropout=0, **kwargs):super(Seq2SeqEncoder, self).__init__(**kwargs)self.num_hiddens=num_hiddensself.num_layers=num_layersself.embedding = nn.Embedding(vocab_size, embed_size)self.rnn = nn.LSTM(embed_size,num_hiddens, num_layers, dropout=dropout)def begin_state(self, batch_size, device):return [torch.zeros(size=(self.num_layers, batch_size, self.num_hiddens),  device=device),torch.zeros(size=(self.num_layers, batch_size, self.num_hiddens),  device=device)]def forward(self, X, *args):X = self.embedding(X) # X shape: (batch_size, seq_len, embed_size)X = X.transpose(0, 1)  # RNN needs first axes to be time# state = self.begin_state(X.shape[1], device=X.device)out, state = self.rnn(X)# The shape of out is (seq_len, batch_size, num_hiddens).# state contains the hidden state and the memory cell# of the last time step, the shape is (num_layers, batch_size, num_hiddens)return out, state

做一个输出

encoder = Seq2SeqEncoder(vocab_size=10, embed_size=8,num_hiddens=16, num_layers=2)
X = torch.zeros((4, 7),dtype=torch.long)
output, state = encoder(X)
output.shape, len(state), state[0].shape, state[1].shape

(torch.Size([7, 4, 16]), 2, torch.Size([2, 4, 16]), torch.Size([2, 4, 16]))
\

Decoder

class Seq2SeqDecoder(d2l.Decoder):def __init__(self, vocab_size, embed_size, num_hiddens, num_layers,dropout=0, **kwargs):super(Seq2SeqDecoder, self).__init__(**kwargs)self.embedding = nn.Embedding(vocab_size, embed_size)self.rnn = nn.LSTM(embed_size,num_hiddens, num_layers, dropout=dropout)# 输出层self.dense = nn.Linear(num_hiddens,vocab_size)def init_state(self, enc_outputs, *args):return enc_outputs[1]def forward(self, X, state):X = self.embedding(X).transpose(0, 1)out, state = self.rnn(X, state)# Make the batch to be the first dimension to simplify loss computation.out = self.dense(out).transpose(0, 1)return out, state

输出测试

decoder = Seq2SeqDecoder(vocab_size=10, embed_size=8,num_hiddens=16, num_layers=2)
state = decoder.init_state(encoder(X))
out, state = decoder(X, state)
out.shape, len(state), state[0].shape, state[1].shape

(torch.Size([4, 7, 10]), 2, torch.Size([2, 4, 16]), torch.Size([2, 4, 16]))

损失函数

def SequenceMask(X, X_len,value=0):maxlen = X.size(1)mask = torch.arange(maxlen)[None, :].to(X_len.device) < X_len[:, None]   X[~mask]=valuereturn X
X = torch.tensor([[1,2,3], [4,5,6]])
SequenceMask(X,torch.tensor([1,2]))

tensor([[1, 0, 0],
[4, 5, 0]])

因为句子向量输入到RNN中,要保证是长度一致,所以短的句子要做padding,这时候padding的0是无效的损失,这部分损失不需要计算,所以需要SequenceMask函数来指定哪些向量的梯度是有效的。

class MaskedSoftmaxCELoss(nn.CrossEntropyLoss):# pred shape: (batch_size, seq_len, vocab_size)# label shape: (batch_size, seq_len)# valid_length shape: (batch_size, )def forward(self, pred, label, valid_length):# the sample weights shape should be (batch_size, seq_len)weights = torch.ones_like(label)weights = SequenceMask(weights, valid_length).float()self.reduction='none'output=super(MaskedSoftmaxCELoss, self).forward(pred.transpose(1,2), label)return (output*weights).mean(dim=1)

训练

def train_ch7(model, data_iter, lr, num_epochs, device):  # Saved in d2lmodel.to(device)optimizer = optim.Adam(model.parameters(), lr=lr)loss = MaskedSoftmaxCELoss()tic = time.time()for epoch in range(1, num_epochs+1):l_sum, num_tokens_sum = 0.0, 0.0for batch in data_iter:optimizer.zero_grad()X, X_vlen, Y, Y_vlen = [x.to(device) for x in batch]Y_input, Y_label, Y_vlen = Y[:,:-1], Y[:,1:], Y_vlen-1Y_hat, _ = model(X, Y_input, X_vlen, Y_vlen)l = loss(Y_hat, Y_label, Y_vlen).sum()l.backward()with torch.no_grad():d2l.grad_clipping_nn(model, 5, device)num_tokens = Y_vlen.sum().item()optimizer.step()l_sum += l.sum().item()num_tokens_sum += num_tokensif epoch % 50 == 0:print("epoch {0:4d},loss {1:.3f}, time {2:.1f} sec".format( epoch, (l_sum/num_tokens_sum), time.time()-tic))tic = time.time()
embed_size, num_hiddens, num_layers, dropout = 32, 32, 2, 0.0
batch_size, num_examples, max_len = 64, 1e3, 10
lr, num_epochs, ctx = 0.005, 300, d2l.try_gpu()
src_vocab, tgt_vocab, train_iter = d2l.load_data_nmt(batch_size, max_len,num_examples)
encoder = Seq2SeqEncoder(len(src_vocab), embed_size, num_hiddens, num_layers, dropout)
decoder = Seq2SeqDecoder(len(tgt_vocab), embed_size, num_hiddens, num_layers, dropout)
model = d2l.EncoderDecoder(encoder, decoder)
train_ch7(model, train_iter, lr, num_epochs, ctx)

测试

def translate_ch7(model, src_sentence, src_vocab, tgt_vocab, max_len, device):src_tokens = src_vocab[src_sentence.lower().split(' ')]src_len = len(src_tokens)if src_len < max_len:src_tokens += [src_vocab.pad] * (max_len - src_len)enc_X = torch.tensor(src_tokens, device=device)enc_valid_length = torch.tensor([src_len], device=device)# use expand_dim to add the batch_size dimension.enc_outputs = model.encoder(enc_X.unsqueeze(dim=0), enc_valid_length)dec_state = model.decoder.init_state(enc_outputs, enc_valid_length)dec_X = torch.tensor([tgt_vocab.bos], device=device).unsqueeze(dim=0)predict_tokens = []for _ in range(max_len):Y, dec_state = model.decoder(dec_X, dec_state)# The token with highest score is used as the next time step input.dec_X = Y.argmax(dim=2)py = dec_X.squeeze(dim=0).int().item()if py == tgt_vocab.eos:breakpredict_tokens.append(py)return ' '.join(tgt_vocab.to_tokens(predict_tokens))

Beam Search(集束搜索)

在测试中,Decoder输出的是所有词的词向量的概率向量,我们如何知道该把哪个词输入到下一个呢?直观上一定是概率最大的那个。这样是一个贪心算法原理。

但是这样只考虑一个局部最优了,并没有考虑上下文之间是否最优,句子是否通顺。Beam Search(集束搜索)可以来缓解这个问题。Beam Search有一个超参数阈值 n n n。在第一步的时候,我们通过模型计算得到 y t y_t yt的分布概率,选择前 n n n个作为候选结果,将这 n n n个候选结果在输入到Decoder中,会继续得到单词的分布概率,取最好的,然后将第一次和第二次的词组合起来再输入到Decoder中,重复操作。

本质是一个条件概率。

【人工智能学习】【十二】机器翻译及相关技术相关推荐

  1. PyTorch框架学习十二——损失函数

    PyTorch框架学习十二--损失函数 一.损失函数的作用 二.18种常见损失函数简述 1.L1Loss(MAE) 2.MSELoss 3.SmoothL1Loss 4.交叉熵CrossEntropy ...

  2. (转)SpringMVC学习(十二)——SpringMVC中的拦截器

    http://blog.csdn.net/yerenyuan_pku/article/details/72567761 SpringMVC的处理器拦截器类似于Servlet开发中的过滤器Filter, ...

  3. IT职场人生系列之十二:语言与技术I

    本文是IT职场人生系列的第十二篇. 最近移动互联网很流行,很多人都在学习IOS.Android编程.这也引起一个入行.改行的潮流. 那么,作为新手.老手,应该怎样选择自己学习的语言和技术呢? 本人从早 ...

  4. AI之机器翻译及相关技术

    AI之机器翻译及相关技术 机器翻译和数据集 载入需要的包 数据预处理 分词 建立词典 载入数据集 Encoder-Decoder Sequence to Sequence模型 模型: 训练 预测 具体 ...

  5. OpenCV与图像处理学习十二——图像形状特征之HOG特征

    OpenCV与图像处理学习十二--图像形状特征之HOG特征 一.图像特征理解 1.1 颜色特征 1.2 纹理特征 1.3 形状特征 1.4 空间关系特征 二.形状特征描述 2.1 HOG特征 2.1. ...

  6. 【FastAPI 学习十二】定时任务篇 (移步博客园或个人网站 无广告,界面清爽整洁)

    声明 目前个人放弃CSDN平台,文章只发布于个人网站和博客园 博客园地址 [FastAPI 学习十二]定时任务篇

  7. C1认证学习十二(网络拓扑)

    C1认证学习十二(网络拓扑) 任务背景 互联网是一个广义的概念,它泛指是一切通过网路连接在一起的计算机的集合,所以,若果只是局部观察,那就不能再说互联网是一个互联的了,那么,如果说对于一个公司来说,具 ...

  8. Js高级程序设计第三版学习(十二章)

                                  Js高级程序设计第三版学习(十二章) 第十二章 DOM2和DOM3   1.样式: 访问样式属性 任何支持style特性的HTML元素都有一 ...

  9. linux中ftp的工作原理,Linux系统学习 十二、VSFTP服务—简介与原理

    1.简介与原理 互联网诞生之初就存在三大服务:WWW.FTP.邮件 FTP主要针对企业级,可以设置权限,对不同等级的资料针对不同权限人员显示. 但是像网盘这样的基本没有权限划分. 简介: FTP(Fi ...

最新文章

  1. Matlab的曲线拟合工具箱CFtool使用简介
  2. 走近算法:受众行为分析与人群定向
  3. java实现视频加密_JAVA实现视频加密
  4. QQ恶搞 - 让艾特你的人语无伦次
  5. 用VC6.0实现上位机串口通信
  6. 解决启动eureka报错Unable to start web ... nested exception is org.springframework.boot.web.server.WebS
  7. java 实现session的退出登录
  8. vue中监听enter键触发事件
  9. 已解决在向有外键表插入数据提示“foreign key constraint fails”
  10. Error Some file crunching failed, see logs for details 解决方案
  11. CSS:怎么样给背景图加透明度 opacity ?
  12. 行业网站十年改变了什么 电商网 -《电子商务世界》打造电子商务大社区
  13. 判断给出的秒数是几天几小时几分几秒
  14. 一个“追跌卖涨”的股票筛选程序
  15. mkv转mp4,mkv转换mp4格式方法
  16. C语言文件操作超详解(万字解读,细致入微)
  17. 网络技术(十一)加强MSTP 、STP、VRRP协议理论理解,进一步深究相关协议的实验
  18. 人民币汇率--中国经济大赌局
  19. java定义接口的方法_java定义接口的方法
  20. 用计算机打出iloveyou,ILOVEYOU病毒是什么

热门文章

  1. sanic学习踩坑记录:第一坑——sanic_jinja2应用报错ModuleNotFoundError: No module named ‘AppName‘
  2. Linux服务器各应用版本信息查看总结
  3. 相机标定:现实到虚拟世界的映射关系
  4. 入职滴滴和头条后的开发工作感悟,希望对你有所帮助!
  5. hmi服务器在宽限期下运行,通过HMI/SCADA 系统(如 WinCC)中的 SNMP OPC服务器,使用 ActiveX控件监测SIMATIC NET系列的SNMP兼容设备...
  6. python图像拼接_python numpy 和 opencv 图像拼接
  7. freeswitch获取手机号码状态
  8. 表面粗糙度的基本评定参数是_表面粗糙度评定粗糙度三个评定参数的含义是什么...
  9. 预备内容:---软件安装篇(2)
  10. 联通取消漫游费损失63亿;ATT宣布2018年底推出5G行动服务 | IoT黑板报