目录

一、前言

二、Simple RNN基本概念

三、关键代码解释

四、Simple RNN的缺陷

五、代码实现

从零开始实现

简洁实现

六、总结

七、参考连接


一、前言

现在RNN没有以前流行,由于在自然语言处理问题上,RNN已经有点过时了,如果训练数据足够多,RNN训练效果不如Transformer,但是在小规模数据集上,RNN还是非常有用的。

机器学习经常用语音、文本等一些时序数据,我们如何对时序数据进行建模

上一次我们把一段文字整体输入一个logistics regression【线性回归】模型,让模型来做二分类,这属于one to one,一个输入对应一个输出模型,全连接神经网络和卷积神经网络都属于one to one模型,但是人脑并不用one to one 模型来处理数据,人类并不会把整一段文字,输入大脑,我们阅读的时候从左到右阅读一段文字,阅读时,不断在大脑里面积累文本的信息,阅读一段话之后,我们大脑便积累了整段文字的大意。

1 to 1要求一个输入对应一个输出,比如输入一张图片,输出每一类的概率值,1to1很适合图片的问题,但是不太适合文本问题,对于文本问题,输入和输出的长度并不固定,一句话可长可短,所以输入的长度并不固定,输出的长度也不固定,比如,把英语翻译成为汉语,一句英语10个单词,翻译成汉语可能有四字成语,8个字的句子等,输出的汉语字数并不固定,由于输入和输出的长度都不固定,1to1模型便不太适合,对于时序数据,更好地模型是多对一、或者多对多模型,RNN就是这样的模型,输入和输出的长度都不需要固定,RNN很适合语音、文本,时序序列的数据。

RNN跟人的阅读习惯很类似,人每次看一个词,逐渐在大脑里积累信息,RNN每次看一个词,用状态h来积累阅读过的信息,我们把输入的一个词用word embedding变成一个词向量x,每次把一个词向量输入RNN,然后RNN就会更新状态h,把新的输入积累到状态h里面,h0里面包含了第一个词the的信息,h1包含了前两词the cat的信息,以此类推,状态h2包含了前三个词语的信息,the cat sat的信息,最后一个状态ht包含了整句话的信息,可以把ht看做是从这句话的the cat  sat on the mat抽取的特征向量

更新状态h的时候,需要用参数矩阵A,需要注意的是,整个RNN只有一个参数矩阵A,无论这条链有多长,参数矩阵只有一个,A随机初始化后,然后用训练数据来学习A

二、Simple RNN基本概念

首先讲Simple RNN简单循环神经网络。

我们来具体看一下Simple RNN是怎么把输入的词向量x输入到状态h里面的。

上一个装填记作ht-1,新输入的词向量记作xt,把这两个词向量做concatnation(串联),得到一个更高的向量

这个矩阵A是RNN的模型参数,计算矩阵A和这个向量的乘积,矩阵和向量的乘积是一个向量

然后把这个激活函数用在向量每一个元素上,这个激活函数是hyperbolic tangent function,双曲正切函数,输入是任意实数,输出在-1到1之间把激活函数的输出作为新的状态向量ht,由于用了双曲正切激活函数,向量ht的每一个元素都是-1到1之间,这张神经网络的结构图可以这样理解,新的状态ht,是旧状态ht-1和新的输入xt的函数,神经网络的模型参数是矩阵A,新的状态ht依赖于向量ht-1向量xt,以及矩阵A

来思考一个问题,为什么需要这个双曲正切激活函数作为激活函数,能否去掉这个激活函数,去掉之后会发生什么?

我们做一个简化,假设输入的x词向量全都是0,这等同于把输入的词向量x给去掉了,把矩阵A右边这一半也去掉,这样一来,

这样一来,第100状态向量h100就等于矩阵A乘以h99,就等于A的100次方乘以h0

假如矩阵A最大的特征值越小于1,例如最大的特征值等于0.9,那么会发生什么呢?0.9的100次方非常接近于0 了,所以矩阵A的100次方几乎是一个全0的矩阵,那么新的状态h100,也几乎也会一个全0的向量。

假如矩阵A最大的特征值越大于1,比如最大特征值等于1.2,那么会发生??

1.2的100次方等于八千多万,所以矩阵A的100次方的元素都超级大。那么新的状态h100,每个元素也都巨大,假如循环次数更多,或者A的特征值更大一些,状态向量就会爆炸,

假如没有这个激活函数,数值计算的时候很有可能会出问题,要么计算出的结果全都是0,要么爆炸了,用这个激活函数,每次更新状态h之后,都会做一个normalization,让h恢复到-11这个合适的区间里

我们来数一下,simple RNN有多少个模型参数,先看一个输入向量,这个向量的维度是h的维度加x的维度,矩阵A必须要有(h+x)维度的列

A的行数等于向量h的维度,所以矩阵A的大小就是

这个乘积就是simple RNN参数的数量

上节课我们用logistics regression来判断电影评价是正面的还是负面的,这节课我们改用RNN来解决这个问题,

我们来搭建一个神经网络,最底层是word embedding,它可以把词映射到向量x,词向量的维度由我们自己设置(是一个超参数),应该用交叉验证(Cross-validation)来选择最好的维度,我们这里设置x的维度是32,然后往上搭建一层simple RNN layer

输入的是词向量x,输出是状态h,h的维度也是由我们自己设置的(h是超参数),应该用交叉验证(Cross-validation)来选择最好的维度,这里我们设置h的维度是32,我们这里的h和x维度都是32,但是这个只是巧合而已,h和x的维度通常不是一样的

前面说过,状态向量h积累输入的信息,h0包含第一个单词i的信息,h1包含前两个词 I love的信息,最后一个状态ht积累了整句话的信息,可以让keras 输出所有的状态向量h,也可以让keras只输出最后一个ht,ht积累了整句话的信息,所以使用ht这一个向量就够了,我们只使用ht,把前边所有的状态都给丢掉。

Ht相当于从文本中提取出来的特征向量,把ht输入这个分类器,分类器就会输出一个0到1之间的数值。0代表负面电影评价,1代表正面评价然后

三、关键代码解释

设置这些超参数

设置vocabulary=10000,意思是词典里面有10000个词汇

Embedding_dimension=32,意思是词向量x的维度是32

word_num=500意思是每个电影评论里有500个单词,如果超过500个单词,就会被截掉,只保留500个,如果不到500,就用zero padding补偿长度到500

state_dim=32,意识是状态向量的维度等于32,

现在开始搭建网络,

sequential模型,sequential的意思是把神经网络的层按顺序搭起来,然后从layer里导入flatten、dense、embedding。

现在开始搭建一个网络,首先建立一个sequential模型,然后返回这个model对象,然后往model里面加层

Embedding Layer,把词映射成向量。

simple RNN layer,需要指定状态向量h的维度State dimension(state_dim)

最后是个全连接层, 输入RNN的最后一个状态h,输出一个0-1之间的数

意思是RNN只输入最后一个状态向量,把之前的状态向量全都扔掉

这是模型的一个概要

Embedding的输出是一个500*2的矩阵,500的意思是每个电影评论有500个单词,32的意思每个单词用32维的词向量表示

simple rnn的输出是一个32维的向量,他是rnn最后一个向量ht,前面的所有状态向量都被扔掉了,我们来一下,Rnn层的参数数量,它有2080个参数,是这样算出来的

h的维度*【h的维度+x的维度】,这是矩阵A的大小,后面的32来自偏移量,是为了防止模型过拟合而设置增加噪音的参数。

搭建好模型之后,编译模型,然后用训练数据来拟合模型,编译模型的时候使用算法RMS prop,损失函数是Cross entropy,评价标准是accuracy,然后用训练数据来拟合模型

我们让算法运行3个epochs,只运行3个epochs,是因为出现了过拟合,

我们发现运行了3个epochs后,模型准确度会变差,提前让算法停止运行,这叫做early stopping,early stopping,让算法在模型准确度变差之前,就停止

最后用测试数据来评价模型的表现,把测试数据作为输入,调用model.evaluate,返回loss和accuracy,测试的accuracy大约是84.4%,比线性回归模型好很多(75%)

刚才我们搭建模型的时候,只使用了最后一个状态ht,把之前的状态都丢掉了

我们想用h0到ht之间所有状态也完全可以,如果你让Keras返回所有状态,Rnn的输出就是个矩阵,矩阵的每一行是一个状态向量h如果用所有状态,需要加一个flatten层,把状态矩阵变成一个向量,然后把这个向量作为分类器的输入,来判断电影是正面的还是负面的,只需要把前面的网络结构稍作改动即可。

现在把RNN return_sequences=True,这样RNN就会返回所有状态向量h,然后再加一个flatten层就好了,一共就有这两处改动,这是网络的结构的一个概要。

以前我们只让RNN输出最后一个状态,所以RNN层的输出是一个32维的向量

现在我让RNN输出所有状态向量,所以RNN的输出是500*32的矩阵,500的意思是电影评里有500个单词,所以一共有500个状态向量,每个状态向量都是32维的,这是训练结果。

跟之前相比,并没有提升,之前只使用最后一个状态,准确率是84.4%,在这个应用中,用所有状态和最后一个状态,最后的准确率并没有得到显著的区别。

四、Simple RNN的缺陷

下面来看Simple RNN这种简单模型有什么缺陷

我们举个例子,现在有这样一个问题

给半句话,要求预测下一个单词,比如输入是clouds are in the、、、,

正确的输出应该是sky,如果在大量文本上训练RNN,RNN应该是有能力做出预测,在这个例子里,RNN只需要看最近的几个词,尤其是clouds are,RNN并不需要更多地上下文,并不需要看的更远,这个例子是对Simple RNN有利,Simple RNN很擅长这种short-term dependence。

Simple RNN不擅长long-term dependence,RNN中的状态h跟之前所有输入的x都有函数依赖关系,照理来说,如果你改变输入的状态x1,那么之后,所有状态都会发生变化,但是实际上Simple RNN并不具备这种性质,所以很不合理

如果你把第100个状态向量h100关于属于输入x1求导,我们会发现导数几乎等于0,导数几乎等于0说明,这说明改变x1,然而h100几乎不会发生任何变化,也就是说状态h100,跟100步之前的输入x1几乎没有关系,这显然不合理,这说明状态100,已经把之前的很多步给忘记了,

Simple RNN的遗忘会造成一些问题,

五、代码实现

从零开始实现

import time
import math
import numpy as np
import torch
from torch import nn, optim
import torch.nn.functional as F
import zipfileimport sys
sys.path.append("C:\Anaconda3\envs\Pytorch1-1\Lib")
import d2lzh_pytorch as d2l
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')with zipfile.ZipFile('./dataset/jaychou_lyrics.txt.zip') as zin:with zin.open('jaychou_lyrics.txt') as f:corpus_chars = f.read().decode('utf-8')
idx_to_char = list(set(corpus_chars))
char_to_idx = dict([(char, i) for i, char in enumerate(idx_to_char)])
vocab_size = len(char_to_idx)
vocab_size # 1027corpus_indices = [char_to_idx[char] for char in corpus_chars]
# (corpus_indices, char_to_idx, idx_to_char, vocab_size) = d2l.load_data_jay_lyrics()def one_hot(x, n_class, dtype=torch.float32):# X shape: (batch), output shape: (batch, n_class)x = x.long()res = torch.zeros(x.shape[0], n_class, dtype=dtype, device=x.device)res.scatter_(1, x.view(-1, 1), 1)return resx = torch.tensor([0, 2])
one_hot(x, vocab_size)# 本函数已保存在d2lzh_pytorch包中方便以后使用
def to_onehot(X, n_class):# X shape: (batch, seq_len), output: seq_len elements of (batch, n_class)return [one_hot(X[:, i], n_class) for i in range(X.shape[1])]X = torch.arange(10).view(2, 5)
inputs = to_onehot(X, vocab_size)
print(len(inputs), inputs[0].shape)num_inputs, num_hiddens, num_outputs = vocab_size, 256, vocab_size
print('will use', device)def get_params():def _one(shape):ts = torch.tensor(np.random.normal(0, 0.01, size=shape), device=device, dtype=torch.float32)return torch.nn.Parameter(ts, requires_grad=True)# 隐藏层参数W_xh = _one((num_inputs, num_hiddens))W_hh = _one((num_hiddens, num_hiddens))b_h = torch.nn.Parameter(torch.zeros(num_hiddens, device=device, requires_grad=True))# 输出层参数W_hq = _one((num_hiddens, num_outputs))b_q = torch.nn.Parameter(torch.zeros(num_outputs, device=device, requires_grad=True))return nn.ParameterList([W_xh, W_hh, b_h, W_hq, b_q])def init_rnn_state(batch_size, num_hiddens, device):return (torch.zeros((batch_size, num_hiddens), device=device), )def rnn(inputs, state, params):# inputs和outputs皆为num_steps个形状为(batch_size, vocab_size)的矩阵W_xh, W_hh, b_h, W_hq, b_q = paramsH, = stateoutputs = []for X in inputs:H = torch.tanh(torch.matmul(X, W_xh) + torch.matmul(H, W_hh) + b_h)Y = torch.matmul(H, W_hq) + b_qoutputs.append(Y)return outputs, (H,)state = init_rnn_state(X.shape[0], num_hiddens, device)
inputs = to_onehot(X.to(device), vocab_size)
params = get_params()
outputs, state_new = rnn(inputs, state, params)
print(len(outputs), outputs[0].shape, state_new[0].shape)# 本函数已保存在d2lzh_pytorch包中方便以后使用
def predict_rnn(prefix, num_chars, rnn, params, init_rnn_state,num_hiddens, vocab_size, device, idx_to_char, char_to_idx):state = init_rnn_state(1, num_hiddens, device)output = [char_to_idx[prefix[0]]]for t in range(num_chars + len(prefix) - 1):# 将上一时间步的输出作为当前时间步的输入X = to_onehot(torch.tensor([[output[-1]]], device=device), vocab_size)# 计算输出和更新隐藏状态(Y, state) = rnn(X, state, params)# 下一个时间步的输入是prefix里的字符或者当前的最佳预测字符if t < len(prefix) - 1:output.append(char_to_idx[prefix[t + 1]])else:output.append(int(Y[0].argmax(dim=1).item()))return ''.join([idx_to_char[i] for i in output])predict_rnn('分开', 10, rnn, params, init_rnn_state, num_hiddens, vocab_size,device, idx_to_char, char_to_idx)# 本函数已保存在d2lzh_pytorch包中方便以后使用
def grad_clipping(params, theta, device):norm = torch.tensor([0.0], device=device)for param in params:norm += (param.grad.data ** 2).sum()norm = norm.sqrt().item()if norm > theta:for param in params:param.grad.data *= (theta / norm)# 本函数已保存在d2lzh_pytorch包中方便以后使用
def train_and_predict_rnn(rnn, get_params, init_rnn_state, num_hiddens,vocab_size, device, corpus_indices, idx_to_char,char_to_idx, is_random_iter, num_epochs, num_steps,lr, clipping_theta, batch_size, pred_period,pred_len, prefixes):if is_random_iter:data_iter_fn = d2l.data_iter_randomelse:data_iter_fn = d2l.data_iter_consecutiveparams = get_params()loss = nn.CrossEntropyLoss()for epoch in range(num_epochs):if not is_random_iter:  # 如使用相邻采样,在epoch开始时初始化隐藏状态state = init_rnn_state(batch_size, num_hiddens, device)l_sum, n, start = 0.0, 0, time.time()data_iter = data_iter_fn(corpus_indices, batch_size, num_steps, device)for X, Y in data_iter:if is_random_iter:  # 如使用随机采样,在每个小批量更新前初始化隐藏状态state = init_rnn_state(batch_size, num_hiddens, device)else:# 否则需要使用detach函数从计算图分离隐藏状态, 这是为了# 使模型参数的梯度计算只依赖一次迭代读取的小批量序列(防止梯度计算开销太大)for s in state:s.detach_()inputs = to_onehot(X, vocab_size)# outputs有num_steps个形状为(batch_size, vocab_size)的矩阵(outputs, state) = rnn(inputs, state, params)# 拼接之后形状为(num_steps * batch_size, vocab_size)outputs = torch.cat(outputs, dim=0)# Y的形状是(batch_size, num_steps),转置后再变成长度为# batch * num_steps 的向量,这样跟输出的行一一对应y = torch.transpose(Y, 0, 1).contiguous().view(-1)# 使用交叉熵损失计算平均分类误差l = loss(outputs, y.long())# 梯度清0if params[0].grad is not None:for param in params:param.grad.data.zero_()l.backward()grad_clipping(params, clipping_theta, device)  # 裁剪梯度d2l.sgd(params, lr, 1)  # 因为误差已经取过均值,梯度不用再做平均l_sum += l.item() * y.shape[0]n += y.shape[0]if (epoch + 1) % pred_period == 0:print('epoch %d, perplexity %f, time %.2f sec' % (epoch + 1, math.exp(l_sum / n), time.time() - start))for prefix in prefixes:print(' -', predict_rnn(prefix, pred_len, rnn, params, init_rnn_state,num_hiddens, vocab_size, device, idx_to_char, char_to_idx))num_epochs, num_steps, batch_size, lr, clipping_theta = 250, 35, 32, 1e2, 1e-2
pred_period, pred_len, prefixes = 50, 50, ['分开', '不分开']train_and_predict_rnn(rnn, get_params, init_rnn_state, num_hiddens,vocab_size, device, corpus_indices, idx_to_char,char_to_idx, True, num_epochs, num_steps, lr,clipping_theta, batch_size, pred_period, pred_len,prefixes)
train_and_predict_rnn(rnn, get_params, init_rnn_state, num_hiddens,vocab_size, device, corpus_indices, idx_to_char,char_to_idx, False, num_epochs, num_steps, lr,clipping_theta, batch_size, pred_period, pred_len,prefixes)

简洁实现

import time
import math
import numpy as np
import torch
from torch import nn, optim
import torch.nn.functional as Fimport sys
sys.path.append("C:\Anaconda3\envs\Pytorch1-1\Lib")
import d2lzh_pytorch as d2l
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')(corpus_indices, char_to_idx, idx_to_char, vocab_size) = d2l.load_data_jay_lyrics()num_hiddens = 256
# rnn_layer = nn.LSTM(input_size=vocab_size, hidden_size=num_hiddens) # 已测试
rnn_layer = nn.RNN(input_size=vocab_size, hidden_size=num_hiddens)num_steps = 35
batch_size = 2
state = None
X = torch.rand(num_steps, batch_size, vocab_size)
Y, state_new = rnn_layer(X, state)
print(Y.shape, len(state_new), state_new[0].shape)# 本类已保存在d2lzh_pytorch包中方便以后使用
class RNNModel(nn.Module):def __init__(self, rnn_layer, vocab_size):super(RNNModel, self).__init__()self.rnn = rnn_layerself.hidden_size = rnn_layer.hidden_size * (2 if rnn_layer.bidirectional else 1)self.vocab_size = vocab_sizeself.dense = nn.Linear(self.hidden_size, vocab_size)self.state = Nonedef forward(self, inputs, state): # inputs: (batch, seq_len)# 获取one-hot向量表示X = d2l.to_onehot(inputs, self.vocab_size) # X是个listY, self.state = self.rnn(torch.stack(X), state)# 全连接层会首先将Y的形状变成(num_steps * batch_size, num_hiddens),它的输出# 形状为(num_steps * batch_size, vocab_size)output = self.dense(Y.view(-1, Y.shape[-1]))return output, self.state# 本函数已保存在d2lzh_pytorch包中方便以后使用
def predict_rnn_pytorch(prefix, num_chars, model, vocab_size, device, idx_to_char,char_to_idx):state = Noneoutput = [char_to_idx[prefix[0]]] # output会记录prefix加上输出for t in range(num_chars + len(prefix) - 1):X = torch.tensor([output[-1]], device=device).view(1, 1)if state is not None:if isinstance(state, tuple): # LSTM, state:(h, c)state = (state[0].to(device), state[1].to(device))else:state = state.to(device)(Y, state) = model(X, state)if t < len(prefix) - 1:output.append(char_to_idx[prefix[t + 1]])else:output.append(int(Y.argmax(dim=1).item()))return ''.join([idx_to_char[i] for i in output])model = RNNModel(rnn_layer, vocab_size).to(device)
predict_rnn_pytorch('分开', 10, model, vocab_size, device, idx_to_char, char_to_idx)# 本函数已保存在d2lzh_pytorch包中方便以后使用
def train_and_predict_rnn_pytorch(model, num_hiddens, vocab_size, device,corpus_indices, idx_to_char, char_to_idx,num_epochs, num_steps, lr, clipping_theta,batch_size, pred_period, pred_len, prefixes):loss = nn.CrossEntropyLoss()optimizer = torch.optim.Adam(model.parameters(), lr=lr)model.to(device)state = Nonefor epoch in range(num_epochs):l_sum, n, start = 0.0, 0, time.time()data_iter = d2l.data_iter_consecutive(corpus_indices, batch_size, num_steps, device) # 相邻采样for X, Y in data_iter:if state is not None:# 使用detach函数从计算图分离隐藏状态, 这是为了# 使模型参数的梯度计算只依赖一次迭代读取的小批量序列(防止梯度计算开销太大)if isinstance (state, tuple): # LSTM, state:(h, c)state = (state[0].detach(), state[1].detach())else:state = state.detach()(output, state) = model(X, state) # output: 形状为(num_steps * batch_size, vocab_size)# Y的形状是(batch_size, num_steps),转置后再变成长度为# batch * num_steps 的向量,这样跟输出的行一一对应y = torch.transpose(Y, 0, 1).contiguous().view(-1)l = loss(output, y.long())optimizer.zero_grad()l.backward()# 梯度裁剪d2l.grad_clipping(model.parameters(), clipping_theta, device)optimizer.step()l_sum += l.item() * y.shape[0]n += y.shape[0]try:perplexity = math.exp(l_sum / n)except OverflowError:perplexity = float('inf')if (epoch + 1) % pred_period == 0:print('epoch %d, perplexity %f, time %.2f sec' % (epoch + 1, perplexity, time.time() - start))for prefix in prefixes:print(' -', predict_rnn_pytorch(prefix, pred_len, model, vocab_size, device, idx_to_char,char_to_idx))
num_epochs, batch_size, lr, clipping_theta = 250, 32, 1e-3, 1e-2 # 注意这里的学习率设置
pred_period, pred_len, prefixes = 50, 50, ['分开', '不分开']
train_and_predict_rnn_pytorch(model, num_hiddens, vocab_size, device,corpus_indices, idx_to_char, char_to_idx,num_epochs, num_steps, lr, clipping_theta,batch_size, pred_period, pred_len, prefixes)

六、总结

(1)RNN是一种神经网络,但是他的结构不同于全连接层网络和卷积网络,RNN适用于文本、语音等一些时序序列数据

(2)RNN按照顺序读取每一个词向量,并且在状态h向量里积累看到过的信息,h0中包含了x0的信息,h1中包含了x0和x1的信息,ht中积累了之前所有x的信息,有一种错误的看法是ht中只包含了xt的信息,这是不对的,ht包含了之前的输入的所有信息,可以认为ht就是RNN从整个数据中抽取的特征向量,所以我们可以直接从ht中判断电影评价是正面的还是负面的

(3)RNN有一个缺点,RNN的记忆比较短,它会遗忘很久之前的输入x,如果整个时间序列很长,比如好几十步,最终的ht已经忘记了早先的输入

下节课我们学习LSTM,LSTM 的记忆会比RNN的记忆长很多,但还是会有遗忘的问题

(4)这节课我们介绍了Simple RNN,Simple RNN有一个参数矩阵A,它有可能一个偏移量b,这节课我们忽略了参数向量b。

(5)参数矩阵一开始随机初始化,然后从训练数据中学习这个参数矩阵,注意,Simple RNN只有一个参数矩阵,不管这个时序有多长,参数矩阵只有一个,所有模块的参数都是一样的。

七、参考连接

简介 - Dive-into-DL-PyTorch (tangshusen.me)

ShusenWang的个人空间_哔哩哔哩_bilibili

RNN模型与NLP应用:Simple RNN模型-3相关推荐

  1. 四、RNN模型 与 NLP应用 —— Stacked RNN

    Stacked RNN 与多层Dense, 多层CNN思想一样, 可以将多个RNN叠加. 最底层RNN的输入是词向量, 其输出作为第二层RNN(有自己的参数矩阵)的输入, -, 最后的输出hth_th ...

  2. RNN模型与NLP应用笔记(3):Simple RNN模型详解及完整代码实现

    一.写在前面 终于到RNN了,这篇文章首先介绍简易RNN模型,我们会以问题导向的方式一步一步对简易RNN模型进行改进.同样本文参考了王树森教授的深度学习课程内容,感谢大佬们提供的帮助. 现在开始讲述循 ...

  3. RNN模型与NLP应用:机器翻译与Seq2Seq模型-7/9

    目录 一.前言 二.Seq2Seq模型的搭建 三.Seq2Seq模型的预测 四.Seq2Seq的改进 五.总结 六.参考连接 一.前言 Seq2Seq模型把英语翻译成德语 我们可以注意到机器翻译是一个 ...

  4. 人工机器:NDC-谷歌机器翻译破世界纪录,仅用Attention模型,无需CNN和RNN

    终于找到ML日报的微信链接,抄之...................................... 请拜访原文链接:[谷歌机器翻译破世界纪录]仅用Attention模型,无需CNN和RNN. ...

  5. 序列到序列模型(一)(基本模型,RNN Search,注意力机制)

    文章目录 基本模型 序列到序列学习 基本模型 RNN Search 模型 注意力 模型定义 模型特点 References 序列到序列学习(sequence to sequence learning, ...

  6. 【PyTorch】4 姓氏分类RNN实战(Simple RNN)——18 种起源语言的数千种姓氏分类

    使用char-RNN对姓氏进行分类 1. 准备数据 2. 将名称转换为张量 3. 建立网络 4. 准备训练 5. 训练网络 6. 评估结果 7. 全部代码 小结 这是官方NLP From Scratc ...

  7. 原创 | 从ULMFiT、Transformer、BERT等经典模型看NLP 发展趋势

    自然语言处理(Natural Language Process,简称NLP)是计算机科学.信息工程以及人工智能的子领域,专注于人机语言交互,探讨如何处理和运用自然语言.自然语言处理的研究,最早可以说开 ...

  8. 斯坦福NLP名课带学详解 | CS224n 第12讲 - NLP子词模型(NLP通关指南·完结)

    作者:韩信子@ShowMeAI,路遥@ShowMeAI,奇异果@ShowMeAI 教程地址:https://www.showmeai.tech/tutorials/36 本文地址:https://ww ...

  9. 深度学习机器学习面试题——自然语言处理NLP,transformer,BERT,RNN,LSTM

    深度学习机器学习面试题--自然语言处理NLP,transformer,BERT,RNN,LSTM 提示:互联网大厂常考的深度学习基础知识 LSTM与Transformer的区别 讲一下Bert原理,B ...

最新文章

  1. 轻松理解汉诺塔问题(图解java描述)
  2. C# Redis写入程序
  3. python for android-Python-for-Android安装笔记
  4. 上海首次正式试用人脸识别系统抓医药代表:频繁出入的非就医可疑人员
  5. tf.train.exponential_decay
  6. 网易资深Java架构师:jdkjrejvm的区别和联系
  7. Python版组合数计算方法优化思路和源码
  8. collection集合 网_房地产信托业务(集合)2020年1-9月分析报告
  9. linux 0.11 源码学习(十四)
  10. python对象_Python对象()
  11. java匹配字符串所在位置_Java:获取字符串中匹配项位置的方法?
  12. LINUX开源监控平台Nagios(服务监控配置)
  13. EverWeb for Mac(网页设计软件)
  14. 144项PPT制作计划(精化)
  15. PayPal贝宝工商银行无法提现,怎么办?
  16. Excel表格快捷键使用
  17. 如何更改SpringBoot控制台图标?只需一步!
  18. 智慧水务一体化平台建设(解决方案)
  19. 解决VMware的虚拟网络编辑器中没有VMnet0的情况
  20. 【目标跟踪】基于迭代扩展卡尔曼滤波算法实现目标滤波跟踪(IEKF)附Matlab代码

热门文章

  1. H3C交换机远程更改中文配置乱码,交换机中文乱码不显示
  2. 机器学习_深度学习毕设题目汇总——车辆车牌
  3. 4. Python面向对象语法——类的构造函数
  4. 【计算几何】沃罗诺伊图 | KNN 最邻近算法 | Voronoi 函数 | 利用 make_classification 生成分类数据集 | 狄利克雷镶嵌 | 维诺图
  5. 使用自己的INDEMIND相机来运行ORBSLAM2单目,双目和深度模式(小觅相机和realsense通用)
  6. 【高等数学】不定积分
  7. 10 Python Matplotlib 绘制极坐标图和散点图
  8. [智慧供热]-客服系统解决方案
  9. 仓库 store getter
  10. 2017年6月最新木星照片