RNN卷积神经网络

RNN

介绍

DNN的问题是参数过多、难以修改,那么我们有了CNN和BP算法解决了,为什么还有有RNN呢?
仔细想一下,这两个东西好像只在乎上一个传过来的值,不在意其他时刻的输入,比如文档前后文内容的预测。

RNN之所以称为循环神经网路,即一个序列当前的输出与前面的输出也有关。具体的表现形式为网络会对前面的信息进行记忆并应用于当前输出的计算中,即隐藏层之间的节点不再无连接而是有连接的,并且隐藏层的输入不仅包括输入层的输出还包括上一时刻隐藏层的输出。

是怎么实现记忆功能的方法呢? 是靠隐层的循环更新,也就是说下一层的值,是根据前面所有层的输出进行累加的。

那么参数值是怎么进行更新的呢

每一次的输出值Ot都会产生一个误差值Et, 则总的误差可以表示为: E = ∑ t e t E=\sum_{t} e_t E=tet

损失函数可以使用交叉熵损失函数也可以使用平方误差损失函数.
交叉熵损失函数 在这里插入图片描述

RNN的反向传播,也称为基于时间的反向传播算法BPTT(back propagation through time)。对所有参数求损失函数的偏导,并不断调整这些参数使得损失函数变得尽可能小。

RNN的缺点

随着间隔的拉长,RNN变得无法学会信息连接。

为什么RNN在长序列文本方面存在巨大的问题? 根据设计,RNN 在每个时间步长上都会接受两个输入:一个输入向量(例如,输入句子中的一个词)和一个隐藏状态(例如,以前词中的记忆表示)。

RNN下一个时间步长采用第二个输入向量和第一隐藏状态来创建该时间步长的输出。 因此,为了捕获长序列中的语义,我们需要在多个时间步长上运行RNN,将展开的RNN变成一个非常深的网络。

RNN 文档

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • RNN中的输入(SeqLen ∗ * batchsize ∗ * inputsize)
  • RNN中的输出(SeqLen ∗ * batchsize ∗ * hiddensize)

RNNCell 文档

在这里插入图片描述
在这里插入图片描述

  • RNNCell中的输入(batchsize ∗ * inputsize)
  • RNNCell中的输出(batchsize ∗ * hiddensize)

RNNCELL其实就是RNN的一个单元,许多RNNCELL组成一个RNN。

相比RNN,RNNCELL公式中少了参数t

Parameters:

  • 只有input_size 和 hidden_size,没有了 num_layers。
    num_layers其实就可以认为是有多少个RNNCELL。所以在RNN的输入输出的参数中就会增加一个num_layers,用来计数。
  • nonlinearity : 用来指定是用relu函数还是tan函数进行激活
  • batch_first :设置为True的时候,会把 (batch, seq, feature) 转换为(seq, batch, feature).
  • dropout :float 会随机的删去一部分神经元,设置的是概率。

RNN例子

import torch

input_size = 4
hidden_size = 3
batch_size = 1
num_layers = 1
seq_len = 5

#构建输入输出字典
idx2char_1 = ['e', 'h', 'l', 'o']
idx2char_2 = ['h', 'l', 'o']
x_data = [1, 0, 2, 2, 3]
y_data = [2, 0, 1, 2, 1]
# y_data = [3, 1, 2, 2, 3]
one_hot_lookup = [[1, 0, 0, 0],
                  [0, 1, 0, 0],
                  [0, 0, 1, 0],
                  [0, 0, 0, 1]]

x_one_hot = [one_hot_lookup[x] for x in x_data]

inputs = torch.Tensor(x_one_hot).view(seq_len, batch_size, input_size)

labels = torch.LongTensor(y_data)

class Model(torch.nn.Module):
    def __init__(self, input_size, hidden_size, batch_size, num_layers=1):
        super(Model, self).__init__()
        self.batch_size = batch_size #构造H0
        self.input_size = input_size
        self.hidden_size = hidden_size
        self.num_layers = num_layers
        self.rnn = torch.nn.RNN(input_size = self.input_size,
                                hidden_size = self.hidden_size,
                                num_layers=num_layers)

    def forward(self, input):
        hidden = torch.zeros(self.num_layers,
                             self.batch_size,
                             self.hidden_size)
        out, _ = self.rnn(input, hidden)
        
        return out.view(-1, self.hidden_size)

net = Model(input_size, hidden_size, batch_size, num_layers)


criterion = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(net.parameters(), lr=0.05)

#RNN中的输入(SeqLen*batchsize*inputsize)
#RNN中的输出(SeqLen*batchsize*hiddensize)
#labels维度 hiddensize*1
for epoch in range(15):
    optimizer.zero_grad()
    outputs = net(inputs)
    loss = criterion(outputs, labels)
    loss.backward()
    optimizer.step()

    _, idx = outputs.max(dim=1)
    idx = idx.data.numpy()
    print('Predicted string: ',''.join([idx2char_2[x] for x in idx]), end = '')
    print(", Epoch [%d/15] loss = %.3f" % (epoch+1, loss.item()))

RNNCell例子

import torch

input_size = 4
hidden_size = 3
batch_size = 1

#构建输入输出字典
idx2char_1 = ['e', 'h', 'l', 'o']
idx2char_2 = ['h', 'l', 'o']
x_data = [1, 0, 2, 2, 3]
y_data = [2, 0, 1, 2, 1]

one_hot_lookup = [[1, 0, 0, 0],
                  [0, 1, 0, 0],
                  [0, 0, 1, 0],
                  [0, 0, 0, 1]]
                  
#构造独热向量,此时向量维度为(SeqLen*InputSize)
x_one_hot = [one_hot_lookup[x] for x in x_data]
#view(-1……)保留原始SeqLen,并添加batch_size,input_size两个维度
inputs = torch.Tensor(x_one_hot).view(-1, batch_size, input_size)
#将labels转换为(SeqLen*1)的维度
labels = torch.LongTensor(y_data).view(-1, 1)

class Model(torch.nn.Module):
    def __init__(self, input_size, hidden_size, batch_size):
        super(Model, self).__init__()
        self.batch_size = batch_size
        self.input_size = input_size
        self.hidden_size = hidden_size

        self.rnncell = torch.nn.RNNCell(input_size = self.input_size,
                                        hidden_size = self.hidden_size)

    def forward(self, input, hidden):

        hidden = self.rnncell(input, hidden)
        return hidden

    #初始化零向量作为h0,只有此处用到batch_size
    def init_hidden(self):
        return torch.zeros(self.batch_size, self.hidden_size)

net = Model(input_size, hidden_size, batch_size)

criterion = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(net.parameters(), lr=0.1)

#RNNCell中的输入(batchsize*inputsize)
#RNNCell中的输出(batchsize*hiddensize)

for epoch in range(15):
    #损失及梯度置0,创建前置条件h0
    loss = 0
    optimizer.zero_grad()
    hidden = net.init_hidden()

    print("Predicted string: ",end="")

    for input, label in zip(inputs, labels):
        hidden = net(input, hidden)
        #序列的每一项损失都需要累加
        loss += criterion(hidden, label)
        #多分类取最大
        _, idx = hidden.max(dim=1)
        print(idx2char_2[idx.item()], end='')

    loss.backward()
    optimizer.step()

    print(", Epoch [%d/15] loss = %.4f" % (epoch+1, loss.item()))
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值