第R4周-LSTM-火灾温度预测

news/2024/12/22 17:59:25 标签: lstm, 人工智能, rnn
  • 🍨 本文为🔗365天深度学习训练营 中的学习记录博客
  • 🍖 原作者:K同学啊

一、前期准备工作

import torch.nn.functional as F
import numpy  as np
import pandas as pd
import torch
from torch    import nn

1. 导入数据

data = pd.read_csv(r"/home/aiusers/space_yjl/深度学习训练营/进阶/第R4周:LSTM-火灾温度预测/woodpine2.csv")

data

在这里插入图片描述

2. 数据集可视化

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np  # 新增导入numpy库

# 读取CSV文件
data = pd.read_csv(r'/home/aiusers/space_yjl/深度学习训练营/进阶/第R4周:LSTM-火灾温度预测/woodpine2.csv')

# 提取列数据,并转换为numpy数组
time = np.array(data['Time'])
tem1 = np.array(data['Tem1'])
co1 = np.array(data['CO 1'])
soot1 = np.array(data['Soot 1'])

# 绘制折线图
plt.plot(time, tem1, label='Tem1')
plt.plot(time, co1, label='CO 1')
plt.plot(time, soot1, label='Soot 1')

# 添加标题和坐标轴标签
plt.title('Data Visualization')
plt.xlabel('Time')
plt.ylabel('Values')

# 添加图例
plt.legend()

# 显示图形
plt.show()

在这里插入图片描述
训练营中的这个有点问题 未解决 我换了一种方式可视化数据

import matplotlib.pyplot as plt
import seaborn as sns
 
plt.rcParams['savefig.dpi'] = 500 #图片像素
plt.rcParams['figure.dpi']  = 500 #分辨率
 
fig, ax =plt.subplots(1,3,constrained_layout=True, figsize=(14, 3))
 
sns.lineplot(data=data["Tem1"], ax=ax[0])
sns.lineplot(data=data["CO 1"], ax=ax[1])
sns.lineplot(data=data["Soot 1"], ax=ax[2])
plt.show()

在这里插入图片描述

dataFrame = data.iloc[:,1:]

dataFrame

在这里插入图片描述

二、构建数据集

1. 数据集预处理


from sklearn.preprocessing import MinMaxScaler

dataFrame = data.iloc[:,1:].copy()
sc  = MinMaxScaler(feature_range=(0, 1)) #将数据归一化,范围是0到1

for i in ['CO 1', 'Soot 1', 'Tem1']:
    dataFrame[i] = sc.fit_transform(dataFrame[i].values.reshape(-1, 1))

dataFrame.shape

在这里插入图片描述

2. 设置X、y

width_X = 8
width_y = 1

##取前8个时间段的Tem1、CO 1、Soot 1为X,第9个时间段的Tem1为y。
X = []
y = []

in_start = 0

for _, _ in data.iterrows():
    in_end  = in_start + width_X
    out_end = in_end   + width_y
    
    if out_end < len(dataFrame):
        X_ = np.array(dataFrame.iloc[in_start:in_end , ])
        y_ = np.array(dataFrame.iloc[in_end  :out_end, 0])

        X.append(X_)
        y.append(y_)
    
    in_start += 1

X = np.array(X)
y = np.array(y).reshape(-1,1,1)

X.shape, y.shape

在这里插入图片描述

检查数据集中是否有空值


print(np.any(np.isnan(X)))
print(np.any(np.isnan(y)))

在这里插入图片描述

3. 划分数据集


X_train = torch.tensor(np.array(X[:5000]), dtype=torch.float32)
y_train = torch.tensor(np.array(y[:5000]), dtype=torch.float32)

X_test  = torch.tensor(np.array(X[5000:]), dtype=torch.float32)
y_test  = torch.tensor(np.array(y[5000:]), dtype=torch.float32)
X_train.shape, y_train.shape

在这里插入图片描述

from torch.utils.data import TensorDataset, DataLoader

train_dl = DataLoader(TensorDataset(X_train, y_train),
                      batch_size=64, 
                      shuffle=False)

test_dl  = DataLoader(TensorDataset(X_test, y_test),
                      batch_size=64, 
                      shuffle=False)

三、模型训练

1. 构建模型

class model_lstm(nn.Module):
    def __init__(self):
        super(model_lstm, self).__init__()
        self.lstm0 = nn.LSTM(input_size=3 ,hidden_size=320, 
                             num_layers=1, batch_first=True)
        
        self.lstm1 = nn.LSTM(input_size=320 ,hidden_size=320, 
                             num_layers=1, batch_first=True)
        self.fc0   = nn.Linear(320, 1)
 
    def forward(self, x):
 
        out, hidden1 = self.lstm0(x) 
        out, _ = self.lstm1(out, hidden1) 
        out    = self.fc0(out) 
        return out[:, -1:, :]   #取2个预测值,否则经过lstm会得到8*2个预测

model = model_lstm()
model
model_lstm(
  (lstm0): LSTM(3, 320, batch_first=True)
  (lstm1): LSTM(320, 320, batch_first=True)
  (fc0): Linear(in_features=320, out_features=1, bias=True)
)

模型的输出数据集格式是什么

model(torch.rand(30,8,3)).shape

在这里插入图片描述

2. 定义训练函数

# 训练循环
import copy
def train(train_dl, model, loss_fn, opt, lr_scheduler=None):
    size        = len(train_dl.dataset)  
    num_batches = len(train_dl)   
    train_loss  = 0  # 初始化训练损失和正确率
    
    for x, y in train_dl:  
        x, y = x.to(device), y.to(device)
        
        # 计算预测误差
        pred = model(x)          # 网络输出
        loss = loss_fn(pred, y)  # 计算网络输出和真实值之间的差距
        
        # 反向传播
        opt.zero_grad()  # grad属性归零
        loss.backward()  # 反向传播
        opt.step()       # 每一步自动更新
        
        # 记录loss
        train_loss += loss.item()
        
    if lr_scheduler is not None:
        lr_scheduler.step()
        print("learning rate = {:.5f}".format(opt.param_groups[0]['lr']), end="  ")
    train_loss /= num_batches
    return train_loss

3. 定义测试函数

def test (dataloader, model, loss_fn):
    size        = len(dataloader.dataset)  # 测试集的大小
    num_batches = len(dataloader)          # 批次数目
    test_loss   = 0
    
    # 当不进行训练时,停止梯度更新,节省计算内存消耗
    with torch.no_grad():
        for x, y in dataloader:
            
            x, y = x.to(device), y.to(device)
            
            # 计算loss
            y_pred = model(x)
            loss        = loss_fn(y_pred, y)
            test_loss += loss.item()
        
    test_loss /= num_batches
    return test_loss

4. 正式训练模型

#设置GPU训练
device=torch.device("cuda" if torch.cuda.is_available() else "cpu")
device

在这里插入图片描述

#训练模型
model = model_lstm()
model = model.to(device)
loss_fn    = nn.MSELoss() # 创建损失函数
learn_rate = 1e-1   # 学习率
opt        = torch.optim.SGD(model.parameters(),lr=learn_rate,weight_decay=1e-4)
epochs     = 50
train_loss = []
test_loss  = []
lr_scheduler = torch.optim.lr_scheduler.CosineAnnealingLR(opt,epochs, last_epoch=-1) 

for epoch in range(epochs):
    model.train()
    epoch_train_loss = train(train_dl, model, loss_fn, opt, lr_scheduler)
 
    model.eval()
    epoch_test_loss = test(test_dl, model, loss_fn)

    train_loss.append(epoch_train_loss)
    test_loss.append(epoch_test_loss)
    
    template = ('Epoch:{:2d}, Train_loss:{:.5f}, Test_loss:{:.5f}')
    print(template.format(epoch+1, epoch_train_loss,  epoch_test_loss))
    
print("="*20, 'Done', "="*20)

在这里插入图片描述

四、模型评估

1. LOSS图

import matplotlib.pyplot as plt

plt.figure(figsize=(5, 3),dpi=120)
 
plt.plot(train_loss    , label='LSTM Training Loss')
plt.plot(test_loss, label='LSTM Validation Loss')
 
plt.title('Training and Validation Loss')
plt.legend()
plt.show()

在这里插入图片描述

2. 调用模型进行预测

predicted_y_lstm = sc.inverse_transform(model(X_test).detach().numpy().reshape(-1,1))                    # 测试集输入模型进行预测
y_test_1         = sc.inverse_transform(y_test.reshape(-1,1))
y_test_one       = [i[0] for i in y_test_1]
predicted_y_lstm_one = [i[0] for i in predicted_y_lstm]
 
plt.figure(figsize=(5, 3),dpi=120)
# 画出真实数据和预测数据的对比曲线
plt.plot(y_test_one[:2000], color='red', label='real_temp')
plt.plot(predicted_y_lstm_one[:2000], color='blue', label='prediction')
 
plt.title('Title')
plt.xlabel('X')
plt.ylabel('Y')
plt.legend()
plt.show()

在这里插入图片描述

3. R2值评估

from sklearn import metrics
"""
RMSE :均方根误差  ----->  对均方误差开方
R2   :决定系数,可以简单理解为反映模型拟合优度的重要的统计量
"""
RMSE_lstm  = metrics.mean_squared_error(predicted_y_lstm_one, y_test_1)**0.5
R2_lstm    = metrics.r2_score(predicted_y_lstm_one, y_test_1)
 
print('均方根误差: %.5f' % RMSE_lstm)
print('R2: %.5f' % R2_lstm)

在这里插入图片描述

五、个人总结

总的来说,这个模型先通过两层 LSTM 层对输入的序列数据进行特征提取和对序列中信息的记忆、传递处理,然后利用全连接层将提取到的特征转换为具体的预测值,并筛选出最后时刻对应的预测输出。

输入形状

对于这个模型,输入数据x的形状假设为(batch_size, seq_length, input_size)。在代码中,input_size被定义为3,batch_size是每次输入的批量大小(在代码中未明确限制,但由数据加载等环节决定),seq_length是序列长度,即每个样本序列包含的时间步数。

中间层形状变化

lstm0_363">第一个 LSTM 层(self.lstm0):

输入形状为(batch_size, seq_length, 3),经过self.lstm0后,输出out的形状变为(batch_size, seq_length, 320),隐藏状态hidden1的形状为(1, batch_size, 320)。这里的320是第一个 LSTM 层定义的隐藏状态维度hidden_size,1是层数(num_layers)。

lstm1_367">第二个 LSTM 层(self.lstm1):

它接收第一个 LSTM 层的输出out(形状为(batch_size, seq_length, 320))和隐藏状态hidden1(形状为(1, batch_size, 320))作为输入。输出out的形状在经过self.lstm1后仍然保持为(batch_size, seq_length, 320),因为这一层的参数设置(input_size = 320,hidden_size = 320)没有改变数据的维度规模,只是对数据进行了进一步的特征提取和序列信息处理。

全连接层(self.fc0):

接收形状为(batch_size, seq_length, 320)的out,经过线性变换self.fc0后,输出out的形状变为(batch_size, seq_length, 1)。这是因为全连接层的定义是nn.Linear(320, 1),将输入的维度为320的特征向量映射到维度为1的输出空间。

输出形状

最后通过return out[:, -1:, :]操作,输出形状变为(batch_size, 1, 1)。这里的操作是提取每个样本序列(batch_size个样本)的最后一个时间步(-1:表示最后一个位置)对应的预测值,并且由于全连接层输出的最后一个维度是1,所以最终输出形状是(batch_size, 1, 1),每个样本对应一个最终的预测值(维度为1)。


http://www.niftyadmin.cn/n/5795662.html

相关文章

【网络安全】用 Frida 修改软件为你所用

用 Frida 修改软件为你所用 Frida是一个强大的设备操作工具&#xff0c;它允许我们分析、修改和与运行中的应用程序交互。Frida通过在目标进程中创建一个线程&#xff0c;并通过这个线程执行一些启动代码来实现交互功能。这种交互被称为“代理”&#xff0c;它允许我们添加Jav…

单元测试(C++)——gmock通用测试模版(个人总结)

引言 在现代软件开发中&#xff0c;单元测试是保证代码质量的重要工具之一。Google Mock&#xff08;简称gMock&#xff09;是谷歌提供的一个强大的C框架&#xff0c;用于创建mock对象。它允许开发者模拟复杂的行为&#xff0c;从而简化了单元测试的编写。 本文将介绍如何构建一…

算法-滑动窗口注意力机制

1、算法流程 1.1 将序列按给定窗口大小和滑动步长进行划分&#xff1b; 1.2 对每个窗口计算自注意力&#xff0c; 首先是计算窗口内每个元素的查询Q、键K和值V&#xff0c;这一步是使用一个线性层实现的&#xff0c;输入和输出的大小都是元素的维度。 其次是Q乘以K的转置计算窗…

python中wb有什么用

‘wb’&#xff1a;表示以二进制写方式打开&#xff0c;只能写文件&#xff0c; 如果文件不存在&#xff0c;创建该文件&#xff1b;如果文件已存在&#xff0c;则覆盖写。 Python文件使用“wb”方式打开&#xff0c;写入字符串会报错&#xff0c;因为这种打开方式为&#xff…

Java开发经验——数据库开发经验

摘要 本文主要介绍了Java开发中的数据库操作规范&#xff0c;包括数据库建表规范、索引规约、SQL规范和ORM规约。强调了在数据库设计和操作中应遵循的最佳实践&#xff0c;如字段命名、数据类型选择、索引创建、SQL语句编写和ORM映射&#xff0c;旨在提高数据库操作的性能和安…

【083】基于51单片机智能烘手器【Proteus仿真+Keil程序+报告+原理图】

☆、设计硬件组成&#xff1a;51单片机最小系统LCD1602液晶显示DS18B20温度传感器TCRT5000红外感应传感器AT24C02存储芯片风扇加热片继电器LED灯按键设置。 1、设计采用STC89C51/52、AT89C51/52、AT89S51/52作为主控芯片&#xff1b; 2、系统采用DS18B20温度传感器感应当前环…

智慧医疗挂号前沿:SSM+Vue 医院预约挂号系统设计与突破

4系统概要设计 4.1概述 本系统采用B/S结构(Browser/Server,浏览器/服务器结构)和基于Web服务两种模式&#xff0c;是一个适用于Internet环境下的模型结构。只要用户能连上Internet,便可以在任何时间、任何地点使用。系统工作原理图如图4-1所示&#xff1a; 图4-1系统工作原理…

maven项目运行时NoSuchMethodError问题排查记录(依赖冲突解决)

控制台异常如下&#xff1a; Handler dispatch failed; nested exception is java.lang.NoSuchMethodError: org.apache.commons.io.input.BoundedInputStream.builder()Lorg/apache/commons/io/input/BoundedInputStream$Builder;问题明显&#xff0c;根据NoSuchMethodError…