神经网络中的seq2seq原理和代码实现

释放双眼,带上耳机,听听看~!
了解神经网络中的seq2seq原理和代码实现,掌握编码器-解码器架构的基本操作和实现过程,适用于机器翻译等不定长序列转化的任务。

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第7天,点击查看活动详情

不管你懂不懂seq2seq都没事,你都可以看这篇文章,只要你懂什么是神经网络你就可以看懂这篇文章。

这个不需要什么太多知识储备就能看懂。

原理

先看一下神经网络,神经网络是在做什么:输入经过隐藏层计算,得到输出

比如一个痴汉,经过计算发现自己是小丑。

神经网络中的seq2seq原理和代码实现

实际过程是这样的:

神经网络中的seq2seq原理和代码实现

假设现在是在一个单隐藏层的神经网络中。

假设我的输入是个长为10的向量(因为有十个字),那现在inpput:[X]10×1inpput: [X]_{10times 1}

经过一个隐藏层计算之后,隐藏层长度是12,现在hidden:[H]12×1hidden: [H]_{12times 1}

最后得到输出向量长度为7,那就是output:[Y]7×1output:[Y]_{7times 1}

计算过程就是:

H=WHXX+bHH = W_{HX}X + b_{H}
Y=WYHH+bYY = W_{YH}H + b_{Y}

其中权重WW和偏置bb的维度为别是:
[WHX]12×10[W_{HX}]_{12times 10}[bH]12×1[b_{H}]_{12times 1}[WYH]7×12[W_{YH}]_{7times 12}[bY]7×1[b_{Y}]_{7times 1}

普通长度的神经网络确实可以改变向量的长度,但是他能做的事情太有限了,并且随着数据量的增大以及向量的边长, 计算开销会爆炸增长。这个时候我们可能就需要用到一些别的东西来进行计算。

比如对于一些不定长序列的转化,例如机器翻译,我们可以使用一种称为seq2sqe的东西,即一个sequence到另一个sequence,这就要用到一个所谓的encoder-decoder。

从原理上来讲,这两部分主要负责的功能是:

  • encoder:表示输入
  • decoder:得到输出

encoder-decoder就是处理输入并得到对应的输出的一个架构。

图呢看起来还是这个图,但是你可以把前一部分做向量对其的封装起来做encoder,后一部分计算输出的封装起来做decoder。

神经网络中的seq2seq原理和代码实现

当然了,既然变复杂了,功能也不是完全一样的,在decoder部分我们还是可以接收额外的输入的。

神经网络中的seq2seq原理和代码实现

也就是输入在接受编码器产生的结果的同时,还可以接纳新的输入进行相应的计算。

神经网络中的seq2seq原理和代码实现

代码

from torch import nn

基本操作先导个包。

class Encoder(nn.Module):
    def __init__(self, **kwargs):
        super(Encoder, self).__init__(**kwargs)

    def forward(self, X, *args):
        raise NotImplementedError

encoder部分搞一个类,传入对应的参数,这里定义一个前向传播进行计算,接受输入X,对其进行计算,得到中间状态。

class Decoder(nn.Module):
    def __init__(self, **kwargs):
        super(Decoder, self).__init__(**kwargs)

    def init_state(self, enc_outputs, *args):
        raise NotImplementedError

    def forward(self, X, state):
        raise NotImplementedError 

decoder部分看一下子,这里开始也是进行一些参数的初始化。

中间有个init_state是接受encoder传来的计算结果,所以参数列表里有个enc_outputs即encoder的输出作为该部分的输入。

decoder部分也有一个前向传播的计算过程,这个是接受额外输入的,是否使用这一部分取决于你是否要在这一部分添加输入。

class EncoderDecoder(nn.Module):
    def __init__(self, encoder, decoder, **kwargs):
        super(EncoderDecoder, self).__init__(**kwargs)
        self.encoder = encoder
        self.decoder = decoder

    def 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)

最后将二者一个合并,初始化对其使用相应的encoder和decoder。
在计算部分可以看到有两个参数enc_Xdec_X,这两个分别是encoder的输入和decoder的输入。

decoder的状态是使用encoder的初始化函数,对encoder的输出进行计算的。最后的输出是使用decoder的输入和上一步获得的decoder的状态进行计算的。

大致框架是这样的,具体内容要根据实际操作进行填充。

本网站的内容主要来自互联网上的各种资源,仅供参考和信息分享之用,不代表本网站拥有相关版权或知识产权。如您认为内容侵犯您的权益,请联系我们,我们将尽快采取行动,包括删除或更正。
AI教程

2022年机器学习中无服务器推理的发展和优势

2023-12-17 16:37:14

AI教程

YOLOv5模型环境搭建及性能测试

2023-12-17 16:40:14

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索