【17-1】LSTM网络

目录

135-LSTM网络简介

LSTM 网络

LSTM网络结构图

136-LSTM实战

137-GRU网络

 LSTM 网络的变体 GRU

GRU结构图


135-LSTM网络简介

LSTM 网络

Long Short Term 网络(LSTM)是一种 RNN 特殊的类型可以学习长期依赖信息在很多问题,LSTM 都取得相当巨大的成功,并得到了广泛的使用,它是RNN事实上的标准。

LSTM的窍门在于拥有一个固定权值为1的自连接,以及一个线性激活函数,因此其局部偏导为1。这样的话,误差就能在时间步中传递,而不会消失或爆炸.

LSTM通过门对通过的信息进行控制:门是一种让信息选择式通过的方法。LSTM通过门可以让信息不通过完全通过、通过一部份。

LSTM网络结构图


136-LSTM实战

【参考文档】 17-2LSTM网络.ipynb

【导出代码】

# %% [markdown]
# # 136-LSTMcell实现文本分类

# %% [markdown]
# ![image.png](attachment:image.png)

# %% [markdown]
# * 三个输入
# 
# * 两个输出
# 
# * h_1,c_1 = nn.LSTMCell(input, (h_0, c_0))

# %%
import os
os.environ['KMP_DUPLICATE_LIB_OK'] = 'True'

import glob
import numpy as np


import torch
from torch import nn
from torch.utils import data
from torch.utils.data import DataLoader
import torchvision
from torchvision import transforms
import torch.nn.functional as F
import torchtext
from torchtext.data.utils import get_tokenizer
from torchtext.vocab import GloVe



from PIL import Image
import matplotlib.pyplot as plt
%matplotlib inline
from lxml import etree   
from matplotlib.patches import Rectangle       #绘制矩形框

# %%
nn.LSTMCell

# %% [markdown]
# ## 加载数据集

# %%
train_iter, test_iter = torchtext.datasets.IMDB()
train_data, test_data = list(train_iter), list(test_iter)

# %%
all_classes = set([label for (label, text) in train_data])
num_class = len(all_classes)

# %% [markdown]
# ## 处理文本

# %%
from torchtext.data.utils import get_tokenizer   #【分词工具】
from torchtext.vocab import build_vocab_from_iterator #【创建词表工具】

# %%
tokenizer = get_tokenizer('basic_english')

# %%
def yield_tokens(data):
    for _, text in data:
        yield tokenizer(text)
        
vocab = build_vocab_from_iterator(yield_tokens(train_data), specials=["<pad>", "<unk>"], min_freq=3)

# %%
vocab.set_default_index(vocab["<unk>"])     #查不到单词时的默认值

# %% [markdown]
# 创建分词函数

# %%
text_pipeline = lambda x: vocab(tokenizer(x))       #1-分词、2-词表映射
label_pipeline = lambda x: int(x == 1)

# %% [markdown]
# ## 批次处理函数

# %%
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

# %%
def cllote_batch(batch):
    label_list, text_list = [], []
    for (_label, _text) in batch:   #【batch返回一个元组:标签,文本同时返回】
        label_list.append(label_pipeline(_label))   #【每条评论的标签】
        #【创建切片:缩短评论长度,rnn不能创建长时依赖】
        pre_text = torch.tensor(text_pipeline(_text), dtype=torch.int64)[:100]      #【将每条文本评论转换成索引,再转换成张量类型。】
        text_list.append(pre_text)   #【每条评论的int类型的索引值的tensor】
    label_list = torch.tensor(label_list)
    #【每条评论长度不太,对应的tensor长度不同?】    【评论疮长度不同,批次训练要求长度相同】
    text_list = torch.nn.utils.rnn.pad_sequence(text_list)   #【按照最长评论进行填充】
    return label_list.to(device), text_list.to(device)   

# %%
#【将原始数据,每次处理512条,交给cllote_batch进行处理】
BATCHSIZE = 512
train_dl = DataLoader(dataset=train_data,
                      batch_size=BATCHSIZE,
                      shuffle=True,
                      collate_fn=cllote_batch)   #【批次处理函数】
test_dl = DataLoader(dataset=test_data,
                      batch_size=BATCHSIZE,
                      collate_fn=cllote_batch)

# %% [markdown]
# ## 序列再LSTM上展开

# %%
vocab_size = len(vocab)
embeding_dim = 300  
hidden =  128

# %%
class LSTM_encode(nn.Module):
    def __init__(self, input_seq_length, hidden):      
        super(LSTM_encode, self).__init__()
        self.lstm_cell = nn.LSTMCell(input_size=input_seq_length,hidden_size=hidden)
    def forward(self, inputs):
        batch_s = inputs.shape[1]
        ht = torch.zeros(batch_s, hidden).to(device)
        ct = torch.zeros(batch_s, hidden).to(device)
        for word in inputs:
            ht, ct = self.lstm_cell(word, (ht, ct))
        return ht, ct
        

# %% [markdown]
# ## 创建分类模型

# %%
class LSTM_Net(nn.Module):
    def __init__(self, vocab_size, embeding_dim, hidden_unit):
        super(LSTM_Net, self).__init__()
        #【初始化词嵌入层】
        self.embedding = nn.Embedding(num_embeddings=vocab_size, embedding_dim=embeding_dim)        #【0-输入的文本(词表)大小、1-输出的大小(输入rnn_encode大小)】  
        self.lstmencode = LSTM_encode(embeding_dim, hidden_unit)      #【初始化rnn_encode】
        #【Linear输出层】
        self.fc1 = nn.Linear(in_features=hidden_unit, out_features=256)
        self.fc2 = nn.Linear(256, 3)
        
    def forward(self, inputs):
        x = self.embedding(inputs)
        _, x = self.lstmencode(x)
        x = F.relu(self.fc1(x))
        x = self.fc2(x)
        return x

# %% [markdown]
# ## 模型训练

# %%
model = LSTM_Net(vocab_size, embeding_dim, hidden_unit).to(device)

# %%
model

# %%
loss_fn = nn.CrossEntropyLoss()     #【输出层为2】
from torch.optim import lr_scheduler
optimizer = torch.optim.Adam(model.parameters(), betas=(0.5, 0.5), lr=0.001)
exp_lr_scheduler = lr_scheduler.StepLR(optimizer, step_size=15, gamma=0.1)

# %%
def train(dataloader):
    total_acc, total_count, total_loss = 0, 0, 0
    model.train()
    for label, text in dataloader:
        label, text= label.to(device), text.to(device)
        predited_label = model(text)  
        loss = loss_fn(predited_label, label)
        
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        
        with torch.no_grad():
            total_acc += (predited_label.argmax(1) == label).sum().item()
            total_count += label.size(0)
            total_loss += loss.item()*label.size(0)
            
    return total_loss/total_count, total_acc/total_count

# %%
def test(dataloader):
    total_acc, total_count, total_loss = 0, 0, 0
    model.eval()
    with torch.no_grad():
        for label, text in dataloader:
            predited_label = model(text)
            loss = loss_fn(predited_label, label)            
            total_acc += (predited_label.argmax(1) == label).sum().item()
            total_count += label.size(0)
            total_loss += loss.item()*label.size(0)
            
    return total_loss/total_count, total_acc/total_count

# %%
def fit(epochs, train_dl, test_dl):
    train_loss =[]
    train_acc = []
    test_loss = []
    test_acc = []
    
    for epoch in range(epochs):
        epoch_loss, epoch_acc = train(train_dl)
        epoch_test_loss, epoch_test_acc = test(test_dl)
        train_loss.append(epoch_loss)
        train_acc.append(epoch_acc)
        test_loss.append(epoch_test_loss)
        test_acc.append(epoch_test_acc)
        exp_lr_scheduler.step()
        template = ("epoch: {:2d}, train_loss: {:.5f}, train_acc: {:.1f}%," "test_loss: {:.5f}, test_acc: {:.1f}%")
        print(template.format(epoch, epoch_loss, epoch_acc*100, epoch_test_loss, 100*epoch_test_acc))
    print("Done!")
    
    return train_loss, train_acc, test_loss, test_acc

# %%
EPOCHS = 10
train_loss, train_acc, test_loss, test_acc = fit(epochs=EPOCHS, train_dl=train_dl, test_dl=test_dl)

# %%




137-GRU网络

 LSTM 网络的变体 GRU

GRU门限循环单元与LSTM相比,GRU结构更加简单,它有一个更新门,更新门决定了内部状态与输入state状态的融合比例,简单的说GRU与LSTM网络相比,建构简单,计算少,效果相当。

GRU结构图

【导出代码】

# 序列展开
class GRU_encode(nn.Module):
    def __init__(self, embeding_dim, hidden_size):
        super(GRU_encode, self).__init__()
        self.gru_cell = nn.GRUCell(input_size=embeding_dim, hidden_size=hidden_size)
    def forward(self, inputs):
        batch_size = inputs.shape[1]
        ht = torch.zeros(batch_size, hidden_size).to(device) 
        for word in inputs:
            ht = self.gru_celll(word, ht)
        return ht
            
        

以下是一个用CNN-BiLSTM预测电池健康状态的MATLAB代码,希望能对您有所帮助。在代码中,我们使用了MATLAB自带的Deep Learning Toolbox和Signal Processing Toolbox。 ``` % 加载数据 load bat_data.mat % 数据预处理 data = normalize(data); % 划分训练集和测试集 train_ratio = 0.8; train_size = round(train_ratio * size(data, 1)); train_data = data(1:train_size, :); test_data = data(train_size+1:end, :); % 设置超参数 input_size = size(data, 2); output_size = 3; num_filters = 32; filter_size = 5; lstm_units = 64; dropout_rate = 0.5; learning_rate = 0.001; num_epochs = 100; mini_batch_size = 64; % 构建CNN-BiLSTM模型 layers = [ sequenceInputLayer(input_size) convolution2dLayer([filter_size 1], num_filters) batchNormalizationLayer reluLayer maxPooling2dLayer([2 1]) sequenceFoldingLayer bilstmLayer(lstm_units, 'OutputMode', 'last') dropoutLayer(dropout_rate) fullyConnectedLayer(output_size) softmaxLayer classificationLayer ]; % 设置训练选项 options = trainingOptions('adam', ... 'InitialLearnRate', learning_rate, ... 'MaxEpochs', num_epochs, ... 'MiniBatchSize', mini_batch_size, ... 'Plots', 'training-progress'); % 训练模型 XTrain = cell(size(train_data, 1), 1); for i = 1:size(train_data, 1) XTrain{i} = train_data(i, :)'; end YTrain = categorical(train_label); model = trainNetwork(XTrain, YTrain, layers, options); % 测试模型 XTest = cell(size(test_data, 1), 1); for i = 1:size(test_data, 1) XTest{i} = test_data(i, :)'; end YTest = categorical(test_label); YPred = classify(model, XTest); accuracy = sum(YPred == YTest) / numel(YTest); disp(['Accuracy: ' num2str(accuracy)]); ``` 下面是对每一行代码的详细解释: 1. `load bat_data.mat`: 加载数据,这里我们假设数据文件名为`bat_data.mat`。 2. `data = normalize(data)`: 数据预处理,对数据进行归一化处理,使其在0到1之间。 3. `train_ratio = 0.8;`: 划分训练集和测试集的比例,这里我们将80%的数据用于训练,20%的数据用于测试。 4. `train_size = round(train_ratio * size(data, 1));`: 计算训练集的大小,即前80%的数据。 5. `train_data = data(1:train_size, :);`: 获取训练集数据。 6. `test_data = data(train_size+1:end, :);`: 获取测试集数据。 7. `input_size = size(data, 2);`: 获取输入数据的特征维度。 8. `output_size = 3;`: 输出数据的类别数,这里我们假设有3个类别。 9. `num_filters = 32;`: CNN层使用的卷积核数量。 10. `filter_size = 5;`: CNN层使用的卷积核大小。 11. `lstm_units = 64;`: BiLSTM层使用的LSTM单元数量。 12. `dropout_rate = 0.5;`: Dropout层的丢弃比例。 13. `learning_rate = 0.001;`: Adam优化器的初始学习率。 14. `num_epochs = 100;`: 训练的轮数。 15. `mini_batch_size = 64;`: 每个小批量的大小。 16. `layers = [...]`: 构建CNN-BiLSTM模型的网络层,具体解释见下文。 17. `options = trainingOptions('adam', ...`: 设置训练选项,包括优化器类型、学习率、轮数、小批量大小等。 18. `XTrain = cell(size(train_data, 1), 1);`: 将训练集数据转换为cell数组。 19. `for i = 1:size(train_data, 1)`: 将每个训练样本的特征转换为列向量。 20. `XTrain{i} = train_data(i, :)';`: 将训练样本的特征转换为列向量。 21. `YTrain = categorical(train_label);`: 将训练集标签转换为分类向量。 22. `model = trainNetwork(XTrain, YTrain, layers, options);`: 训练CNN-BiLSTM模型。 23. `XTest = cell(size(test_data, 1), 1);`: 将测试集数据转换为cell数组。 24. `for i = 1:size(test_data, 1)`: 将每个测试样本的特征转换为列向量。 25. `XTest{i} = test_data(i, :)';`: 将测试样本的特征转换为列向量。 26. `YTest = categorical(test_label);`: 将测试集标签转换为分类向量。 27. `YPred = classify(model, XTest);`: 使用训练好的模型对测试集数据进行分类预测。 28. `accuracy = sum(YPred == YTest) / numel(YTest);`: 计算分类准确率。 29. `disp(['Accuracy: ' num2str(accuracy)]);`: 输出分类准确率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值