【pytorch】关于Embedding和GRU、LSTM的使用详解
1. Embedding的使用
pytorch中实现了Embedding,下面是关于Embedding的使用。
torch.nn包下的Embedding,作为训练的一层,随模型训练得到适合的词向量。
建立词向量层
embed = torch.nn.Embedding(n_vocabulary,embedding_size)
找到对应的词向量放进网络:词向量的输入应该是什么样子
实际上,上面通过随机初始化建立了词向量层后,建立了一个“二维表”,存储了词典中每个词的词向量。每个mini-batch的训练,都要从词向量表找到mini-batch对应的单词的词向量作为RNN的输入放进网络。那么怎么把mini-batch中的每个句子的所有单词的词向量找出来放进网络呢,输入是什么样子,输出是什么样子?
首先我们知道肯定先要建立一个词典,建立词典的时候都会建立一个dict:word2id:存储单词到词典序号的映射。假设一个mini-batch如下所示:
['I am a boy.','How are you?','I am very lucky.']
显然,这个mini-batch有3个句子,即batch_size=3
第一步首先要做的是:将句子标准化,所谓标准化,指的是:大写转小写,标点分离,这部分很简单就略过。经处理后,mini-batch变为:
[['i','am','a','boy','.'],['how','are','you','?'],['i','am','very','lucky','.']]
可见,这个list的元素成了一个个list。还要做一步:将上面的三个list按单词数从多到少排列。标点也算单词。至于为什么,后面会说到。
那就变成了:
batch = [['i','am','a','boy','.'],['i','am','very','lucky','.'],['how','are','you','?']]
可见,每个句子的长度,即每个内层list的元素数为:5,5,4。这个长度也要记录。
lens = [5,5,4]
之后,为了能够处理,将batch的单词表示转为在词典中的index序号,这就是word2id的作用。转换过程很简单,假设转换之后的结果如下所示,当然这些序号是我编的。
batch = [[3,6,5,6,7],[6,4,7,9,5],[4,5,8,7]]
同时,每个句子结尾要加EOS,假设EOS在词典中的index是1。
batch = [[3,6,5,6,7,1],[6,4,7,9,5,1],[4,5,8,7,1]]
那么长度要更新:
lens = [6,6,5]
很显然,这个mini-batch中的句子长度不一致!所以为了规整的处理,对长度不足的句子,进行填充。填充PAD假设序号是2,填充之后为:
batch = [[3,6,5,6,7,1],[6,4,7,9,5,1],[4,5,8,7,1,2]]
这样就可以直接取词向量训练了吗?
不能!上面batch有3个样例,RNN的每一步要输入每个样例的一个单词,一次输入batch_size个样例,所以batch要按list外层是时间步数(即序列长度),list内层是batch_size排列。即batch的维度应该是:
[seq_len,batch_size]
[seq_len,batch_size]
[seq_len,batch_size]
重要的问题说3遍。
怎么变换呢?变换方法可以是:使用itertools模块的zip_longest函数。而且,使用这个函数,连填充这一步都可以省略,因为这个函数可以实现填充!
batch = list(itertools.zip_longest(batch,fillvalue=PAD))
# fillvalue就是要填充的值,强制转成list
经变换,结果应该是:
batch = [[3,6,4],[6,4,5],[5,7,8],[6,9,7],[7,5,1],[1,1,2]]
记得我们还记录了一个lens:
lens = [6,6,5]
batch还要转成LongTensor:
batch=torch.LongTensor(batch)
这里的batch就是词向量层的输入。
词向量层的输出是什么样的?
好了,现在使用建立了的embedding直接通过batch取词向量了,如:
embed_batch = embed (batch)
假设词向量维度是6,结果是:
tensor([[[-0.2699, 0.7401, -0.8000, 0.0472, 0.9032, -0.0902],
[-0.2675, 1.8021, 1.4966, 0.6988, 1.4770, 1.1235],
[ 0.1146, -0.8077, -1.4957, -1.5407, 0.3755, -0.6805]],
[[-0.2675, 1.8021, 1.4966, 0.6988, 1.4770, 1.1235],
[ 0.1146, -0.8077, -1.4957, -1.5407, 0.3755, -0.6805],
[-0.0387, 0.8401, 1.6871, 0.3057, -0.8248, -0.1326]],
[[-0.0387, 0.8401, 1.6871, 0.3057, -0.8248, -0.1326],
[-0.3745, -1.9178, -0.2928, 0.6510, 0.9621, -1.3871],
[-0.6739, 0.3931, 0.1464, 1.4965, -0.9210, -0.0995]],
[[-0.2675, 1.8021, 1.4966, 0.6988, 1.4770, 1.1235],
[-0.7411, 0.7948, -1.5864, 0.1176, 0.0789, -0.3376],
[-0.3745, -1.9178, -0.2928, 0.6510, 0.9621, -1.3871]],
[[-0.3745, -1.9178, -0.2928, 0.6510, 0.9621, -1.3871],
[-0.0387, 0.8401, 1.6871, 0.3057, -0.8248, -0.1326],
[ 0.2837, 0.5629, 1.0398, 2.0679, -1.0122, -0.2714]],
[[ 0.2837, 0.5629, 1.0398, 2.0679, -1.0122, -0.2714],
[ 0.2837, 0.5629, 1.0398, 2.0679, -1.0122, -0.2714],
[ 0.2242, -1.2474, 0.3882, 0.2814, -0.4796, 0.3732]]],
grad_fn=<EmbeddingBackward>)
维度的前两维和前面讲的是一致的。可见多了一个第三维,这就是词向量维度。所以,Embedding层的输出是:
[seq_len,batch_size,embedding_size]
2 关于pytorch中的GRU
取词向量,放进GRU。
建立GRU
gru = torch.nn.GRU(input_size,hidden_size,n_layers)
# 这里的input_size就是词向量的维度,hidden_size就是RNN隐藏层的维度,这两个一般相同就可以
# n_layers是GRU的层数
可见,并不需要指定时间步数,也即seq_len,这是因为,GRU和LSTM都实现了自身的迭代。
GRU的输入应该是什么样子的?
上面的embed_batch作为Embedding层的输出,可以直接放进GRU中吗?
理论上可以,但这样不对!因为GRU并不知道哪些是填充的,并不是每一个句子都满足最大序列长度!所以我们事先用lens记录了长度。
将输出embed_batch转成pack_padded_sequence,使用torch.nn.utils.rnn. 下的pack_padded_sequence方法。
batch_packed = torch.nn.utils.rnn.pack_padded_sequence(embed_batch, lens)
# 注意这里的输入lens就是前面的长度list
这个 batch_packed 就是GRU的输入。
batch_packed 长啥样?
不妨看一下:
PackedSequence(data=tensor([[-0.2699, 0.7401, -0.8000, 0.0472, 0.9032, -0.0902],
[-0.2675, 1.8021, 1.4966, 0.6988, 1.4770, 1.1235],
[ 0.1146, -0.8077, -1.4957, -1.5407, 0.3755, -0.6805],
[-0.2675, 1.8021, 1.4966, 0.6988, 1.4770, 1.1235],
[ 0.1146, -0.8077, -1.4957, -1.5407, 0.3755, -0.6805],
[-0.0387, 0.8401, 1.6871, 0.3057, -0.8248, -0.1326],
[-0.0387, 0.8401, 1.6871, 0.3057, -0.8248, -0.1326],
[-0.3745, -1.9178, -0.2928, 0.6510, 0.9621, -1.3871],
[-0.6739, 0.3931, 0.1464, 1.4965, -0.9210, -0.0995],
[-0.2675, 1.8021, 1.4966, 0.6988, 1.4770, 1.1235],
[-0.7411, 0.7948, -1.5864, 0.1176, 0.0789, -0.3376],
[-0.3745, -1.9178, -0.2928, 0.6510, 0.9621, -1.3871],
[-0.3745, -1.9178, -0.2928, 0.6510, 0.9621, -1.3871],
[-0.0387, 0.8401, 1.6871, 0.3057, -0.8248, -0.1326],
[ 0.2837, 0.5629, 1.0398, 2.0679, -1.0122, -0.2714],
[ 0.2837, 0.5629, 1.0398, 2.0679, -1.0122, -0.2714],
[ 0.2837, 0.5629, 1.0398, 2.0679, -1.0122, -0.2714]],
grad_fn=<PackPaddedBackward>), batch_sizes=tensor([3, 3, 3, 3, 3, 2], grad_fn=<PackPaddedBackward>))
可以看到,属性batch_sizes清楚的记录了每个时间步上batch输出是多少,而且去除了PAD。
此外,GRU还需要一个初始隐藏向量(注意层数和方向),嫌麻烦直接传None也无妨。
所以输入应该是( batch_packed , None )
GRU的输出?
output,hidden = gru(batch_packed,None)
output:PackedSequence对象
PackedSequence(data=tensor([[ 0.0432, -0.0149, -0.0884, -0.0194, -0.0740, 0.1278],
[-0.0436, -0.0726, 0.0568, -0.0995, -0.1992, 0.1594],
[ 0.0582, 0.0625, -0.1639, 0.1474, 0.0077, 0.0542],
[-0.0052, -0.0732, 0.0031, -0.1367, -0.2336, 0.2307],
[ 0.0131, 0.0234, -0.0681, 0.0535, -0.1651, 0.1864],
[ 0.0324, 0.1441, -0.1788, 0.1800, -0.0816, 0.1684],
[-0.0788, -0.0148, -0.0292, -0.1348, -0.3352, 0.3045],
[ 0.0502, 0.0436, -0.1509, 0.1481, -0.1284, 0.1523],
[ 0.0627, 0.1626, -0.1888, 0.1341, -0.0984, 0.2627],
[-0.1391, -0.0149, 0.0473, -0.2069, -0.4410, 0.3690],
[ 0.1378, 0.0578, -0.2008, 0.1265, -0.0149, 0.2053],
[ 0.0780, 0.1199, -0.2107, 0.1460, -0.0906, 0.2291],
[-0.1019, 0.0055, -0.0304, -0.1277, -0.4149, 0.3582],
[ 0.0906, 0.1025, -0.1646, 0.0933, -0.0953, 0.2905],
[ 0.1004, 0.1175, -0.1911, 0.0979, -0.0877, 0.2771],
[-0.0607, 0.0469, -0.0935, -0.1002, -0.3568, 0.3707],
[ 0.0737, 0.1213, -0.1516, 0.0365, -0.1417, 0.3591]],
grad_fn=<CatBackward>), batch_sizes=tensor([3, 3, 3, 3, 3, 2], grad_fn=<PackPaddedBackward>))
前三个list对应于第一时间步,mini-batch的三个样例的输出。依次类推。最后只有两个,因为最后是有缺省的。
hidden:是个张量。维度[n_layers,batch_size,hidden_size]
tensor([[[-0.1057, 0.2273, 0.0964, 0.2777, 0.1391, -0.1769],
[-0.1792, 0.1942, 0.1248, 0.0800, -0.0082, 0.0778],
[-0.2631, 0.1654, 0.1455, -0.1428, 0.1888, -0.2379]],
[[-0.0607, 0.0469, -0.0935, -0.1002, -0.3568, 0.3707],
[ 0.0737, 0.1213, -0.1516, 0.0365, -0.1417, 0.3591],
[ 0.1004, 0.1175, -0.1911, 0.0979, -0.0877, 0.2771]]],
grad_fn=<ViewBackward>)
所以到这,为什么逆序,为什么记录长度也就清楚了。
3 关于pytroch中的LSTM
有点累了,过会写。差不对,就LSTM有两个隐藏层向量。
【pytorch】关于Embedding和GRU、LSTM的使用详解的更多相关文章
- RNN 与 LSTM 的原理详解
原文地址:https://blog.csdn.net/happyrocking/article/details/83657993 RNN(Recurrent Neural Network)是一类用于处 ...
- (数据科学学习手札39)RNN与LSTM基础内容详解
一.简介 循环神经网络(recurrent neural network,RNN),是一类专门用于处理序列数据(时间序列.文本语句.语音等)的神经网络,尤其是可以处理可变长度的序列:在与传统的时间序列 ...
- tensorflow LSTM+CTC使用详解
最近用tensorflow写了个OCR的程序,在实现的过程中,发现自己还是跳了不少坑,在这里做一个记录,便于以后回忆.主要的内容有lstm+ctc具体的输入输出,以及TF中的CTC和百度开源的warp ...
- pytorch学习笔记(十二):详解 Module 类
Module 是 pytorch 提供的一个基类,每次我们要 搭建 自己的神经网络的时候都要继承这个类,继承这个类会使得我们 搭建网络的过程变得异常简单. 本文主要关注 Module 类的内部是怎么样 ...
- torch.nn.LSTM()函数维度详解
123456789101112lstm=nn.LSTM(input_size, hidden_size, num_la ...
- PyTorch 中 torch.matmul() 函数的文档详解
官方文档 torch.matmul() 函数几乎可以用于所有矩阵/向量相乘的情况,其乘法规则视参与乘法的两个张量的维度而定. 关于 PyTorch 中的其他乘法函数可以看这篇博文,有助于下面各种乘法的 ...
- Pytorch学习笔记08----优化器算法Optimizer详解(SGD、Adam)
1.优化器算法简述 首先来看一下梯度下降最常见的三种变形 BGD,SGD,MBGD,这三种形式的区别就是取决于我们用多少数据来计算目标函数的梯度,这样的话自然就涉及到一个 trade-off,即参数更 ...
- IMPLEMENTING A GRU/LSTM RNN WITH PYTHON AND THEANO - 学习笔记
catalogue . 引言 . LSTM NETWORKS . LSTM 的变体 . GRUs (Gated Recurrent Units) . IMPLEMENTATION GRUs 0. 引言 ...
- pytorch nn.Embedding
pytorch nn.Embeddingclass torch.nn.Embedding(num_embeddings, embedding_dim, padding_idx=None, max_no ...
随机推荐
- 如何快速高效简洁的打开软件 干净利索的windows快捷程序启动器
本文的主题是如何高效快捷的打开你想要打开的软件 本文介绍的应该是最简洁的一种方式,借助于windows内部的path进行设置 也可以认为是一种形式的windows应用启动器程序---win+R快速打开 ...
- cocos creator主程入门教程(八)—— 代码结构
五邑隐侠,本名关健昌,10年游戏生涯,现隐居五邑.本系列文章以TypeScript为介绍语言. 这一篇简单介绍下代码结构,清晰的代码结构更有利于团队对项目的理解和维护. 1.前面我们介绍了一系列基础功 ...
- 还在问跨域?本文记录js跨域的多种实现实例
前言 众所周知,受浏览器同源策略的影响,产生了跨域问题,那么我们应该如何实现跨域呢?本文记录几种跨域的简单实现 前期准备 为了方便测试,我们启动两个服务,10086(就是在这篇博客自动生成的项目,请戳 ...
- QLineEdit拾遗:数据的过滤、验证和补全
QLineEdit是使用频率最高的控件之一,当我们想获取用户输入时自然而然得会用到它. 通常我们会将QLineEdit的信号或其他控件的信号绑定至槽函数,然后获取并处理编辑器内的数据.你会觉得我们拿到 ...
- Raptor井字棋游戏
作为大学第一个小作品,记录一下,也给那些想接触到Raptor游戏的人一个小小的参考QAQ至于Raptor的语法和使用,可以参考一下他的帮助手册,看不懂英文的话可以复制放到翻译上看. 以上是主函数 以下 ...
- 阿里、百度等多家公司Java面试记录与总结
算算自己大概面试了近十家公司,也拿到了几个Offer,现在面试告一段落,简单总结下面试经验. 我现在主要的方向是Java服务端开发,把遇到的问题和大家分享一下,也谈谈关于技术人员如何有方向的提高自己, ...
- mybatis 参数格式异常-- Error querying database. Cause: java.lang.NumberFormatException: For input string
mybatis中 <if></if>标签中进行判断时,如果传入的时字符格式和数字进行判断需要将数字进行转译,否则默认是数字和数字进行比较,这是就会出现参数格式异常如<if ...
- 桥接模式 桥梁模式 bridge 结构型 设计模式(十二)
桥接模式Bridge Bridge 意为桥梁,桥接模式的作用就像桥梁一样,用于把两件事物连接起来 意图 将抽象部分与他的实现部分进行分离,使得他们都可以独立的发展. 意图解析 依赖倒置原 ...
- ecstore中怎样使用ajax提交数据
//javascript代码 $$(".bb").addEvent('change',function(e){ var order_item_id = this.get('orde ...
- div在另一个div居中对齐
position:fixed; top:0; right:0; left:0; bottom:0; margin:auto;