【人工智能学习】【十二】机器翻译及相关技术
机器翻译及相关技术
机器翻译(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,H3……Ht,)
也可以直接使用
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,Hy−1,y1)
y 3 = f ( C , H y − 1 , y 2 ) y_3=f(C,H_{y-1},y_2) y3=f(C,Hy−1,y2)
… … …… ……
当遇到终止字符时 < E O S > <EOS> <EOS>就认为输出结束了。
这里有几种模式,请参考NLP(3)——seq to seq
总结:
- 处理变长序列问题。
- 数据降维
代码
定义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中,重复操作。
本质是一个条件概率。
【人工智能学习】【十二】机器翻译及相关技术相关推荐
- PyTorch框架学习十二——损失函数
PyTorch框架学习十二--损失函数 一.损失函数的作用 二.18种常见损失函数简述 1.L1Loss(MAE) 2.MSELoss 3.SmoothL1Loss 4.交叉熵CrossEntropy ...
- (转)SpringMVC学习(十二)——SpringMVC中的拦截器
http://blog.csdn.net/yerenyuan_pku/article/details/72567761 SpringMVC的处理器拦截器类似于Servlet开发中的过滤器Filter, ...
- IT职场人生系列之十二:语言与技术I
本文是IT职场人生系列的第十二篇. 最近移动互联网很流行,很多人都在学习IOS.Android编程.这也引起一个入行.改行的潮流. 那么,作为新手.老手,应该怎样选择自己学习的语言和技术呢? 本人从早 ...
- AI之机器翻译及相关技术
AI之机器翻译及相关技术 机器翻译和数据集 载入需要的包 数据预处理 分词 建立词典 载入数据集 Encoder-Decoder Sequence to Sequence模型 模型: 训练 预测 具体 ...
- OpenCV与图像处理学习十二——图像形状特征之HOG特征
OpenCV与图像处理学习十二--图像形状特征之HOG特征 一.图像特征理解 1.1 颜色特征 1.2 纹理特征 1.3 形状特征 1.4 空间关系特征 二.形状特征描述 2.1 HOG特征 2.1. ...
- 【FastAPI 学习十二】定时任务篇 (移步博客园或个人网站 无广告,界面清爽整洁)
声明 目前个人放弃CSDN平台,文章只发布于个人网站和博客园 博客园地址 [FastAPI 学习十二]定时任务篇
- C1认证学习十二(网络拓扑)
C1认证学习十二(网络拓扑) 任务背景 互联网是一个广义的概念,它泛指是一切通过网路连接在一起的计算机的集合,所以,若果只是局部观察,那就不能再说互联网是一个互联的了,那么,如果说对于一个公司来说,具 ...
- Js高级程序设计第三版学习(十二章)
Js高级程序设计第三版学习(十二章) 第十二章 DOM2和DOM3 1.样式: 访问样式属性 任何支持style特性的HTML元素都有一 ...
- linux中ftp的工作原理,Linux系统学习 十二、VSFTP服务—简介与原理
1.简介与原理 互联网诞生之初就存在三大服务:WWW.FTP.邮件 FTP主要针对企业级,可以设置权限,对不同等级的资料针对不同权限人员显示. 但是像网盘这样的基本没有权限划分. 简介: FTP(Fi ...
最新文章
- Matlab的曲线拟合工具箱CFtool使用简介
- 走近算法:受众行为分析与人群定向
- java实现视频加密_JAVA实现视频加密
- QQ恶搞 - 让艾特你的人语无伦次
- 用VC6.0实现上位机串口通信
- 解决启动eureka报错Unable to start web ... nested exception is org.springframework.boot.web.server.WebS
- java 实现session的退出登录
- vue中监听enter键触发事件
- 已解决在向有外键表插入数据提示“foreign key constraint fails”
- Error Some file crunching failed, see logs for details 解决方案
- CSS:怎么样给背景图加透明度 opacity ?
- 行业网站十年改变了什么 电商网 -《电子商务世界》打造电子商务大社区
- 判断给出的秒数是几天几小时几分几秒
- 一个“追跌卖涨”的股票筛选程序
- mkv转mp4,mkv转换mp4格式方法
- C语言文件操作超详解(万字解读,细致入微)
- 网络技术(十一)加强MSTP 、STP、VRRP协议理论理解,进一步深究相关协议的实验
- 人民币汇率--中国经济大赌局
- java定义接口的方法_java定义接口的方法
- 用计算机打出iloveyou,ILOVEYOU病毒是什么
热门文章
- sanic学习踩坑记录:第一坑——sanic_jinja2应用报错ModuleNotFoundError: No module named ‘AppName‘
- Linux服务器各应用版本信息查看总结
- 相机标定:现实到虚拟世界的映射关系
- 入职滴滴和头条后的开发工作感悟,希望对你有所帮助!
- hmi服务器在宽限期下运行,通过HMI/SCADA 系统(如 WinCC)中的 SNMP OPC服务器,使用 ActiveX控件监测SIMATIC NET系列的SNMP兼容设备...
- python图像拼接_python numpy 和 opencv 图像拼接
- freeswitch获取手机号码状态
- 表面粗糙度的基本评定参数是_表面粗糙度评定粗糙度三个评定参数的含义是什么...
- 预备内容:---软件安装篇(2)
- 联通取消漫游费损失63亿;ATT宣布2018年底推出5G行动服务 | IoT黑板报