ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

embedding、LSTM、seq2seq+attention的知识总结

2021-10-05 10:03:15  阅读:222  来源: 互联网

标签:torch attention seqlen seq2seq embedding output print input size


一、 embedding

1. input : [ seqlen , batchsize ]
2. output: [ seq_len, batchsize, embed_dim ]

二、 LSTM

输入:

1. input: [ seq_len, batch, input_size]
2. h0   : [ num_layers * num_directions,batch_size,hidden_size ]

输出:

1. out: [ seq_len, batch, num_directions * hidden_size ]
2. hn : [ num_layers * num_directions, batch, hidden_size ]

三、seq2seq的架构图和维度

在这里插入图片描述

在这里插入图片描述
因为Encode的h和c会作为Decode的第一次的输入,所以Encode和Decode的LSTM中hiddensize必须一致。

在decode过程中,每次的input是target的每一项,或者是上一次的预测(output),而h和c则一直选取上次的。

但是这里我存在一个问题: 在decode时,我们从target中每次拿一项,循环放进lstm中拿出结果;
但是在encode时,我们直接把整个seqlen都扔到lstm中。
这两种放数据方式存在什么不同吗?

检验代码

import torch
import torch.nn as nn

bilstm = nn.LSTM(input_size=10, hidden_size=20)
inputs = torch.randn(5, 3, 10)  # [seq_len, batch, inputsize]

h0 = torch.randn(1, 3, 20)   # layernum , batch , hiddensize
c0 = torch.randn(1, 3, 20)
output, (hn, cn) = bilstm(inputs, (h0, c0))

print('output shape: ', output.shape) # seqlen, batch, hiddensize
print('hn shape: ', hn.shape) # layer , batch, hiddensize
print('cn shape: ', cn.shape)
print(output)
print('----------')

outputs = torch.zeros(5, 3, 20)
seqlen = inputs.size(0)
for i in range(seqlen):
    input = torch.Tensor(inputs[i])
    input = input.unsqueeze(0)
    output, (h0, c0) = bilstm(input, (h0, c0))
    outputs[i] = output

print(outputs)

结论:
把一个seqlen的序列直接扔到lstm 和 for循环每次扔一个, 扔seqlen次,最后的结果是一样的。
通过这个例子,我顺便明白了LSTM的反人类设计之:为什么seqlen作为第一个参数?
因为LSTM内部也是通过for循环每次取出seqlen的一个,然后扔进LSTM中运行的,一共循环seqlen次,所以seqlen作为第一个维度比较好做。 (哈哈啊哈啊哈哈我真聪明!)

Pytorch中的torch.cat()函数

C = torch.cat( (A,B),0 ) #按维数0拼接(竖着拼)
C = torch.cat( (A,B),1 ) #按维数1拼接(横着拼)

import torch
>>> A=torch.ones(2,3)    #2x3的张量(矩阵)                                     
>>> A
tensor([[ 1.,  1.,  1.],
        [ 1.,  1.,  1.]])
>>> B=2*torch.ones(4,3)  #4x3的张量(矩阵)                                    
>>> B
tensor([[ 2.,  2.,  2.],
        [ 2.,  2.,  2.],
        [ 2.,  2.,  2.],
        [ 2.,  2.,  2.]])
>>> C=torch.cat((A,B),0)  #按维数0(行)拼接
>>> C
tensor([[ 1.,  1.,  1.],
         [ 1.,  1.,  1.],
         [ 2.,  2.,  2.],
         [ 2.,  2.,  2.],
         [ 2.,  2.,  2.],
         [ 2.,  2.,  2.]])
>>> C.size()
torch.Size([6, 3])
>>> D=2*torch.ones(2,4) #2x4的张量(矩阵)
>>> C=torch.cat((A,D),1)#按维数1(列)拼接
>>> C
tensor([[ 1.,  1.,  1.,  2.,  2.,  2.,  2.],
        [ 1.,  1.,  1.,  2.,  2.,  2.,  2.]])
>>> C.size()
torch.Size([2, 7])

Pytorch中的torch.repeat()函数

相当于把某个整体,在某个方向广播。

import torch
x = torch.tensor([1, 2, 3])
print(x.repeat(4, 1))
print("###################################")
print(x.repeat(4, 2, 1))
print("###################################")
print(x.repeat(4, 1, 2))

output:
tensor([[1, 2, 3],
        [1, 2, 3],
        [1, 2, 3],
        [1, 2, 3]])
###################################
tensor([[[1, 2, 3],
         [1, 2, 3]],

        [[1, 2, 3],
         [1, 2, 3]],

        [[1, 2, 3],
         [1, 2, 3]],

        [[1, 2, 3],
         [1, 2, 3]]])
###################################
tensor([[[1, 2, 3, 1, 2, 3]],

        [[1, 2, 3, 1, 2, 3]],

        [[1, 2, 3, 1, 2, 3]],

        [[1, 2, 3, 1, 2, 3]]])

Pytorch中的torch.bmm()函数

torch.bmm(input, mat2, out=None) → Tensor

torch.bmm()是tensor中的一个相乘操作,类似于矩阵中的A*B。
input,mat2:两个要进行相乘的tensor结构,两者必须是3D维度的,每个维度中的大小是相同的。
并且相乘的两个矩阵,要满足一定的维度要求:input(p,m,n) * mat2(p,n,a) ->output(p,m,a)。这个要求,可以类比于矩阵相乘。前一个矩阵的列等于后面矩阵的行才可以相乘。

四、初探Attention 机制

在这里插入图片描述
实现Attention的方式有很多种,这里展示比较常用的一种。在Encoder的过程中保留每一步RNN单元的隐藏状态h1……hn,组成编码的状态矩阵Encoder_outputs;在解码过程中,原本是通过上一步的输出yt-1和前一个隐藏层h作为输入,现又加入了利用Encoder_outputs计算注意力权重attention_weight的步骤。
相比于原始的Encoder-Decoder模型,加入Attention机制后最大的区别就是它不在要求编码器将所有输入信息都编码进一个固定长度的向量之中。而是,编码器需要将输入编码成一个向量的序列,在解码的时候,每一步都会选择性的从向量序列中挑选一个子集进行进一步处理。这样,在产生每一个输出的时候,都能够做到充分利用输入序列携带的信息。而且这种方法在翻译任务中取得了非常不错的成果。

这是一个基本的attention模型,encoder保存每次的hidden。在decoder端把input传入和隐藏单元拼接起来传入线性层,将其映射到seqlen维,每一维描述的是输入encoder中各位置元素对当前decoder输出单词的重要性占比。然后利用矩阵相乘获取到加权求和之后的注意力向量,用于描述“划了重点”之后的输入序列对当前预测这个单词的影响。然后将注意力向量和input拼接在一起,再利用一个线性层将其映射到RNN的输入维度,最后送入RNN,得到新的hidden和output。output作为下一个的输入。
请添加图片描述

标签:torch,attention,seqlen,seq2seq,embedding,output,print,input,size
来源: https://blog.csdn.net/weixin_40982849/article/details/120524421

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有