刘二大人《Pytorch深度学习与实践》12循环神经网络LSTM篇

具体代码如下

import torch

# 准备数据
index_chart = ['e', 'h', 'l', 'o']
x_data = [1, 0, 2, 2, 3]
y_data = [1, 0, 0, 3, 2]
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]
input_size = 4
batch_size = 1
inputs = torch.Tensor(x_one_hot).view(-1, batch_size, input_size)
labels = torch.LongTensor(y_data).view(-1, 1)  # 增加维度方便计算loss


# 设计网络模型
class LSTM(torch.nn.Module):
    # 进行基础设置
    def __init__(self):
        super(LSTM, self).__init__()
        self.lineari = torch.nn.Linear(4, 4)
        self.linearf = torch.nn.Linear(4, 4)
        self.linearc = torch.nn.Linear(4, 4)
        self.linearo = torch.nn.Linear(4, 4)
        self.sigmoid = torch.nn.Sigmoid()
        self.tanh = torch.nn.Tanh()

    # 设置前向传播函数
    def forward(self, x, hidden, C):
        i = self.sigmoid(self.lineari(x) + self.lineari(hidden))
        f = self.sigmoid(self.linearf(x) + self.linearf(hidden))
        c = self.sigmoid(self.linearc(x) + self.linearc(hidden))
        o = self.sigmoid(self.linearo(x) + self.linearo(hidden))
        C = f * C + i * c  # 候选状态x输入状态+遗忘状态x上一个细胞状态,得到此次细胞状态
        hidden = o * self.tanh(C)  # 此次得到的细胞状态进行激活后,再乘以输出门,最后得到隐藏层输出
        return hidden, C


net = LSTM()
# 计算损失和更新
criterion = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(net.parameters(), lr=0.03)
# 进行训练和更新
for epoch in range(100):
    loss = 0
    optimizer.zero_grad()  # 梯度每一次迭代完之后都要归零
    hidden = torch.zeros(batch_size, input_size)  # 初始的隐藏层的值均设置为0,形状为(batch_size,input_size)
    C = torch.zeros(batch_size, input_size)  # 初始的细胞状态值均设置为0,形状为(batch_size,input_size)
    print('Predicten string:', end='')
    for input, label in zip(inputs, labels):
        hidden, C = net(input, hidden, C)
        loss += criterion(hidden, label)  # hidden.shape=(1,4) label.shape=1
        _, idx = hidden.max(dim=1)  # 从第一个维度上取出预测概率最大的值和该值所在序号,_代表其最大概率对应的值,idx代表该值所对应的索引序号
        print(index_chart[idx.item()], end='')  # 按上面序号输出相应字母字符
    loss.backward()
    optimizer.step()
    print(', Epoch [%d/100] loss=%.4f' % (epoch + 1, loss.item()))

LSTM结合embedding的方法代码如下

import torch

batch_size = 1
input_size = 4
index_chart = ['e', 'h', 'l', 'o']  # 预测的结果是设置的索引,这样方便对结果更快地进行取值
x_data = torch.LongTensor([[1, 0, 2, 2, 3]]).view(5, 1)
print(x_data.shape)
y_data = [3, 1, 2, 3, 2]  # 标签
labels = torch.LongTensor(y_data).view(-1, 1)  # 增加维度方便计算loss,view(-1,1)表示一定转换成1列,-1表示根据列数是1,自动计算其行
emb = torch.nn.Embedding(4, 10)
inputs = emb(x_data)  # 将4维输入数据嵌入成10维,为后面的linear_ix等操作进行设置(5,1,10),嵌入值均是随机设定
print(inputs)
print(inputs.shape)


class emb_lstm(torch.nn.Module):
    def __init__(self):
        super(emb_lstm, self).__init__()
        # 上一时刻的内部状态g(x),外部状态h(x)
        self.linear_ix = torch.nn.Linear(10, 4)  # 输入门,输入值和上一阶段的外部状态值通过激活函数激活后成为输入值it
        self.linear_fx = torch.nn.Linear(10, 4)  # 遗忘门,输入值和上一阶段的外部状态值通过激活函数激活后成为遗忘值ft
        self.linear_gx = torch.nn.Linear(10, 4)  # 候选变量,输入值和上一阶段的外部状态值通过tanh激活函数激活后成为候选变量值
        self.linear_ox = torch.nn.Linear(10, 4)  # 输出值,输入值和上一阶段的外部状态值通过激活函数激活后成为输出值ot
        # 隐藏层的LSTM变换
        self.linear_ih = torch.nn.Linear(4, 4)
        self.linear_fh = torch.nn.Linear(4, 4)
        self.linear_gh = torch.nn.Linear(4, 4)
        self.linear_oh = torch.nn.Linear(4, 4)
        self.sigmoid = torch.nn.Sigmoid()
        self.tanh = torch.nn.Tanh()

    def forward(self, x, hidden, c):  # 输入x,外部状态hidden,以及候选状态c
        # 输入值x和外部状态h(x)相结合,再通过激活函数激活得到内部状态的i,f,g(候选状态),o值;
        i = self.sigmoid(self.linear_ix(x) + self.linear_ih(hidden))
        f = self.sigmoid(self.linear_fx(x) + self.linear_fh(hidden))
        g = self.tanh(self.linear_gx(x) + self.linear_gh(hidden))
        o = self.sigmoid(self.linear_ox(x) + self.linear_oh(hidden))
        # 候选状态g乘以输入值i,再加上上一时刻的内部状态c乘以遗忘值f,得到该时刻的更新的内部状态值c
        # 输出元素 o 乘以经过激活函数激活后的该时刻的内部状态值,得到该时刻的外部状态值
        c = f * c + i * g  # 上一层的结果c通过遗忘门f得到最后的输出值,加上通过输入门的上一层的候选结果g;g是候选变量相比于c,是在激活函数上不同
        hidden = o * self.tanh(c)  # 上式得到的结果c通过输出门
        return hidden, c


model = emb_lstm()
# 构建损失函数和优化器方法
criterion = torch.nn.CrossEntropyLoss()  # 交叉熵
optimizer = torch.optim.Adam(model.parameters(), lr=0.06)
# 进行训练和更新
for epoch in range(100):
    loss = 0
    optimizer.zero_grad()
    hidden = torch.zeros(batch_size, input_size)  # 提供初始化隐藏层
    c = torch.zeros(batch_size, input_size)
    print('Predicten string:', end='')
    for input, label in zip(inputs, labels):  # 并行遍历数据集 一个一个训练
        hidden, c = model(input, hidden, c)
        loss += criterion(hidden, label)
        _, idx = hidden.max(dim=1)  # 从第一个维度(即行维度)上取出预测概率最大的值和该值所在序号,_表示
        print(index_chart[idx.item()], end='')  # 按上面序号输出相应字母字符
    loss.backward(retain_graph=True)
    optimizer.step()
    print(', Epoch [%d/100] loss=%.4f' % (epoch + 1, loss.item()))

  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值