机器学习本科课程 大作业 多元时间序列预测

news2024/10/7 12:21:21

1. 问题描述

1.1 阐述问题

对某电力部门的二氧化碳排放量进行回归预测,有如下要求

  • 数据时间跨度从1973年1月到2021年12月,按月份记录。
  • 数据集包括“煤电”,“天然气”,“馏分燃料”等共9个指标的数据(其中早期的部分指标not available)
  • 要求预测从2022年1月开始的半年时间的以下各个部分的排放量

二氧化碳的排放情况具体分为九项指标:

  1. Coal Electric Power Sector CO2 Emissions(煤电力行业二氧化碳排放 )
  2. Natural Gas Electric Power Sector CO2 Emissions(天然气电力行业二氧化碳排放)
  3. Distillate Fuel, Including Kerosene-Type Jet Fuel, Oil Electric Power Sector CO2 Emissions(蒸馏燃料,包括喷气燃料、石油电力行业二氧化碳排放)
  4. Petroleum Coke Electric Power Sector CO2 Emissions(石油焦电力行业二氧化碳排放)
  5. Residual Fuel Oil Electric Power Sector CO2 Emissions(残余燃料油电力行业二氧化碳排放)
  6. Petroleum Electric Power Sector CO2 Emissions(石油电力行业二氧化碳排放)
  7. Geothermal Energy Electric Power Sector CO2 Emissions(地热能电力行业二氧化碳排放)
  8. Non-Biomass Waste Electric Power Sector CO2 Emissions(非生物质废物电力行业二氧化碳排放)
  9. Total Energy Electric Power Sector CO2 Emissions(总能源电力行业二氧化碳排放)

1.2 方案设计

  • 由于9个指标之间存在相关性,对一个指标的未来值进行预测,除了考虑自身的历史值以外,还需要引入其他指标对该指标的影响。
  • 数据量大、时间周期长,需要采用具有较强回归能力的、能够实现时间序列预测任务的机器学习模型。

1.3 方法概括

经过讨论研究,本次实验通过三种神经网络模型独立实现了多元时间序列回归预测任务,分别是:

模型介绍特点
BP误差反向传播网络通过多次学习获取非线性映射
TCN时间卷积网络因果卷积实现时间预测
LSTM长短时记忆网络门控结构保存长时记忆

通过从无到有建立模型、性能优化、模型比较等流程,小组成员强化了机器学习的基础知识,提升了机器学习相应技能的熟练程度,对机器学习的理论和部分模型的特性有了进一步的理解

2. BP神经网络(Backpropagation Neural Network)

2.1 模型原理

BP神经网络是一种前馈神经网络,采用反向传播算法进行训练。该网络由输入层、隐藏层和输出层组成。每个神经元与前一层的所有神经元相连接,每个连接都有一个权重,网络通过调整这些权重来学习输入与输出之间的映射关系。
BP神经网络通过反向传播(Backpropagation)计算模型输出与实际输出之间的误差,然后反向传播误差,调整网络参数以最小化误差。

在本次实验中,采取了500大小的隐藏层,以0.01学习率进行了2000轮的训练。

2.2.1数据处理

从xlsx读取数据,取前80%数据为训练集,后20%为测试集

import time
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.impute import SimpleImputer
from sklearn.preprocessing import StandardScaler

# 读取xlsx文件
data = pd.read_excel("data.xlsx")
side = 192  # 有缺失部分的长度
side2 = 587  # 整个已知数据的长度
seq_len = 10
batch_size = 64
data = data.iloc[1:side2 + 1]

# 提取全部列名
col_names = data.columns.values.tolist()
col_names = [col_names[i] for i in range(1, len(col_names))]
data_list = np.array(data[col_names].values.tolist())

# 处理缺失值,用平均值填充
data_list[data_list == "Not Available"] = np.nan
data_list = data_list.astype(float)
imputer = SimpleImputer(strategy='mean', fill_value=np.nan)
data_imputed = imputer.fit_transform(data_list)

# 标准化处理
scaler = StandardScaler()
data_normalized = scaler.fit_transform(data_imputed)

# 划分训练集和测试集
data_len = len(data_normalized)
train_data = data_normalized[:int(0.75 * data_len)]  # 取前75%作为训练集
test_data = data_normalized[int(0.75 * data_len):]   # 取剩下25%作为测试集

2.3.2 定义画图函数


# 画出曲线
def plot_results(X_test, Y_test, W1, b1, W2, b2, scaler, col_names):
    Y_pred, _ = forward(X_test, W1, b1, W2, b2)
    Y_pred_original = scaler.inverse_transform(Y_pred)
    Y_test_original = scaler.inverse_transform(Y_test)

    f, ax = plt.subplots(nrows=3, ncols=3, figsize=(20, 10))
    for i in range(3):
        for j in range(3):
            ax[i, j].plot(Y_pred_original[:, 3 * i + j], label='predictions')
            ax[i, j].plot(Y_test_original[:, 3 * i + j], label='true')
            ax[i, j].set_title(col_names[3 * i + j])
            ax[i, j].legend()
    plt.tight_layout()
    plt.show()

# 绘制Loss曲线
def plot_loss_curve(training_losses, testing_losses):
    plt.figure(figsize=(10, 6))
    plt.plot(training_losses, label='Training Loss', color='blue')
    plt.plot(testing_losses, label='Testing Loss', color='orange')
    plt.title('Training and Testing Loss Over Epochs')
    plt.xlabel('Epoch')
    plt.ylabel('Loss')
    plt.legend()
    plt.show()


2.3.3 定义BP神经网络结构

# 参数初始化
def initialize_parameters(input_size, hidden_size, output_size):
    np.random.seed(42)
    W1 = np.random.randn(input_size, hidden_size) * 0.01
    b1 = np.zeros((1, hidden_size))
    W2 = np.random.randn(hidden_size, output_size) * 0.01
    b2 = np.zeros((1, output_size))
    return W1, b1, W2, b2

# 前向传播
def forward(X, W1, b1, W2, b2):
    Z1 = np.dot(X, W1) + b1
    A1 = np.tanh(Z1)
    Z2 = np.dot(A1, W2) + b2
    return Z2, A1

# 损失函数
def compute_loss(Y, Y_pred):
    m = Y.shape[0]
    loss = np.sum((Y - Y_pred) ** 2) / m
    return loss

# 反向传播
def backward(X, A1, Y, Y_pred, W1, W2, b1, b2):
    m = X.shape[0]
    
    dZ2 = Y_pred - Y
    dW2 = np.dot(A1.T, dZ2) / m
    db2 = np.sum(dZ2, axis=0, keepdims=True) / m
    
    dA1 = np.dot(dZ2, W2.T)
    dZ1 = dA1 * (1 - np.tanh(A1) ** 2)
    dW1 = np.dot(X.T, dZ1) / m
    db1 = np.sum(dZ1, axis=0, keepdims=True) / m
    
    return dW1, db1, dW2, db2

# 梯度下降更新参数
def update_parameters(W1, b1, W2, b2, dW1, db1, dW2, db2, learning_rate):
    W1 -= learning_rate * dW1
    b1 -= learning_rate * db1
    W2 -= learning_rate * dW2
    b2 -= learning_rate * db2
    return W1, b1, W2, b2

# 训练神经网络
def train_neural_network(X_train, Y_train, X_test, Y_test, input_size, hidden_size, output_size, epochs, learning_rate):
    W1, b1, W2, b2 = initialize_parameters(input_size, hidden_size, output_size)
    
    training_losses = []
    testing_losses = []

    start_time = time.time()
    for epoch in range(epochs):
        # 前向传播训练集
        Y_pred_train, A1_train = forward(X_train, W1, b1, W2, b2)
        # 计算训练集损失
        train_loss = compute_loss(Y_train, Y_pred_train)
        training_losses.append(train_loss)
        
        # 前向传播测试集
        Y_pred_test, _ = forward(X_test, W1, b1, W2, b2)
        # 计算测试集损失
        test_loss = compute_loss(Y_test, Y_pred_test)
        testing_losses.append(test_loss)
        
        # 反向传播和参数更新
        dW1, db1, dW2, db2 = backward(X_train, A1_train, Y_train, Y_pred_train, W1, W2, b1, b2)
        W1, b1, W2, b2 = update_parameters(W1, b1, W2, b2, dW1, db1, dW2, db2, learning_rate)
        
        # 打印每个epoch的损失
        print(f"Epoch {epoch + 1}/{epochs} - Training Loss: {train_loss:.10f} - Testing Loss: {test_loss:.10f}")
    end_time = time.time()
    training_duration = end_time - start_time
    print(f"用时 {training_duration:.2f} s")

    # 结束后,画出图像
    plot_loss_curve(training_losses, testing_losses)
    plot_results(X_test, Y_test, W1, b1, W2, b2, scaler, col_names)
    
    return W1, b1, W2, b2, training_losses, testing_losses

2.3.4 模型训练流程及性能表现

# 将训练数据和测试数据准备为神经网络输入
X_train = train_data[:-seq_len]
Y_train = train_data[seq_len:]
X_test = test_data[:-seq_len]
Y_test = test_data[seq_len:]

# 参数设置
input_size = X_train.shape[1]
hidden_size = 500
output_size = Y_train.shape[1]
epochs = 2000
learning_rate = 0.01

# 训练神经网络
W1_final, b1_final, W2_final, b2_final, training_losses, testing_losses = train_neural_network(X_train, Y_train, X_test, Y_test, input_size, hidden_size, output_size, epochs, learning_rate)

# 在训练完成后,使用训练好的模型对训练集和测试集进行预测
Y_pred_train, _ = forward(X_train, W1_final, b1_final, W2_final, b2_final)
Y_pred_test, _ = forward(X_test, W1_final, b1_final, W2_final, b2_final)

# 将预测值逆归一化
Y_pred_train_original = scaler.inverse_transform(Y_pred_train)
Y_pred_test_original = scaler.inverse_transform(Y_pred_test)

# 逆归一化训练集和测试集的真实值
Y_train_original = scaler.inverse_transform(Y_train)
Y_test_original = scaler.inverse_transform(Y_test)

# 计算 MAE 和 MSE
mse_on_train = np.mean((Y_train_original - Y_pred_train_original) ** 2)
mse_on_test = np.mean((Y_test_original - Y_pred_test_original) ** 2)
mae_on_train = np.mean(np.abs(Y_train_original - Y_pred_train_original))
mae_on_test = np.mean(np.abs(Y_test_original - Y_pred_test_original))


# 输出最终的 MAE 和 MSE
print(f"mse_on_train: {mse_on_train:.10f}     mse_on_test: {mse_on_test:.10f}")
print(f"mae_on_train: {mae_on_train:.10f}     mae_on_test: {mae_on_test:.10f}")

3. TCN网络(Temporal Convolutional Network)

3.1 模型原理

TCN是一种基于卷积操作的神经网络,特别适用于处理时序数据。与传统的循环神经网络(RNN)和LSTM相比,TCN使用卷积层捕捉时序数据中的模式,从而更好地捕获长期依赖关系。

从结构上来说,TCN通常由一个或多个卷积层组成,卷积层的感受野逐渐增大,从而能够捕捉不同尺度的模式。此外,TCN还可以通过残差连接来加强梯度的流动,从而更容易训练深层网络。

3.2.1 数据处理

在第一个实验方案中,BP网络直接将整段历史信息输入给了模型;为了更充分地考虑数据集中的时序信息以及加快训练速度,TCN网络和LSTM采取了时间窗口的划分方式。

滑动窗口(rolling window)将时间序列划分为多个窗口,在每个窗口内进行训练和测试,如果存在较大的波动或季节性变化,而且这些变化的周期较长,使用滑动窗口可以更好地捕捉到这些特征。

TCN中,仍然设定前80%为训练数据,时间窗口大小为16

import pandas as pd
import numpy as np
import torch
from torch import optim
from torch.utils.data import Dataset, DataLoader,TensorDataset
import torch.nn as nn
from sklearn.preprocessing import StandardScaler, Normalizer
import matplotlib.pyplot as plt

def windows_split(data, seq_len):
    res = []
    label = []
    for i in range(len(data) - seq_len):
        res.append(data[i:i + seq_len])
        label.append(data[i + seq_len])
    res = np.array(res).astype(np.float32)
    label = np.array(label).astype(np.float32)
    return res, label


data = pd.read_excel("data.xlsx")
side = 192  # 有缺失部分的长度
side2 = 587  # 整个已知数据的长度
seq_len = 16
batch_size = 64

# 提取全部列名
col_names = data.columns.values.tolist()
col_names = [col_names[i] for i in range(1, len(col_names))]
data.replace("Not Available", np.nan, inplace=True)

interpolated = data[col_names].interpolate(method='spline', order=3)
data_list = np.array(data[col_names].values.tolist())

scalar = StandardScaler()
data_list = scalar.fit_transform(data_list)
data_list[np.isnan(data_list)] = 0


data_split, label_split = windows_split(data_list[side:side2], seq_len)
data_split = np.transpose(data_split, (0, 2, 1))
length = data_split.shape[0]


data_train = torch.Tensor(data_split[0:int(0.8 * length), :])
label_train = torch.Tensor(label_split[0:int(0.8 * length)])
data_test = torch.Tensor(data_split[int(0.8 * length):int(length), :])
label_test = torch.Tensor(label_split[int(0.8 * length):label_split.shape[0]])

dataset_train = TensorDataset(data_train, label_train)
dataset_test = TensorDataset(data_test, label_test)

train_loader = DataLoader(dataset_train, batch_size=batch_size, shuffle=True)
test_loader = DataLoader(dataset_test, batch_size=batch_size, shuffle=False)

input_size = 9
output_size = 9
num_channels = [32, 64, 128, 256]
kernel_size = 3
dropout = 0
num_epochs = 200

3.2.2 模型定义

每层TCN定义为:[conv, chomp, relu, dropout]*2
学习率0.0001,训练轮数200

import torch
import torch.nn as nn
from torch.nn.utils import weight_norm

class Chomp1d(nn.Module):
    def __init__(self, chomp_size):
        super(Chomp1d, self).__init__()
        self.chomp_size = chomp_size

    def forward(self, x):
        return x[:, :, :-self.chomp_size].contiguous()


class TemporalBlock(nn.Module):
    def __init__(self, n_inputs, n_outputs, kernel_size, stride, dilation, padding, dropout=0.2):
        super(TemporalBlock, self).__init__()
        self.conv1 = weight_norm(nn.Conv1d(n_inputs, n_outputs, kernel_size,
                                           stride=stride, padding=padding, dilation=dilation))
        self.chomp1 = Chomp1d(padding)
        self.relu1 = nn.ReLU()
        self.dropout1 = nn.Dropout(dropout)

        self.conv2 = weight_norm(nn.Conv1d(n_outputs, n_outputs, kernel_size,
                                           stride=stride, padding=padding, dilation=dilation))
        self.chomp2 = Chomp1d(padding)
        self.relu2 = nn.ReLU()
        self.dropout2 = nn.Dropout(dropout)

        self.net = nn.Sequential(self.conv1, self.chomp1, self.relu1, self.dropout1,
                                 self.conv2, self.chomp2, self.relu2, self.dropout2)
        self.downsample = nn.Conv1d(n_inputs, n_outputs, 1) if n_inputs != n_outputs else None
        self.relu = nn.ReLU()
        self.init_weights()

    def init_weights(self):
        self.conv1.weight.data.normal_(0, 0.01)
        self.conv2.weight.data.normal_(0, 0.01)
        if self.downsample is not None:
            self.downsample.weight.data.normal_(0, 0.01)

    def forward(self, x):
        out = self.net(x)
        res = x if self.downsample is None else self.downsample(x)
        return self.relu(out + res)


class TemporalConvNet(nn.Module):
    def __init__(self, num_inputs, num_channels, kernel_size=2, dropout=0.2):
        super(TemporalConvNet, self).__init__()
        layers = []
        num_levels = len(num_channels)
        for i in range(num_levels):
            dilation_size = 2 ** i
            in_channels = num_inputs if i == 0 else num_channels[i-1]
            out_channels = num_channels[i]
            layers += [TemporalBlock(in_channels, out_channels, kernel_size, stride=1, dilation=dilation_size,
                                     padding=(kernel_size-1) * dilation_size, dropout=dropout)]

        self.network = nn.Sequential(*layers)

    def forward(self, x):
        return self.network(x)


class TCN(nn.Module):
    def __init__(self, input_size, output_size, num_channels, kernel_size, dropout):
        super(TCN, self).__init__()
        self.tcn = TemporalConvNet(input_size, num_channels, kernel_size=kernel_size, dropout=dropout)
        self.linear = nn.Linear(num_channels[-1], output_size)

    def forward(self, inputs):
        """Inputs have to have dimension (N, C_in, L_in)"""
        y1 = self.tcn(inputs)  # input should have dimension (N, C, L)
        o = self.linear(y1[:, :, -1])
        return o

3.2.3 模型训练流程及性能表现

model = TCN(input_size, output_size, num_channels, kernel_size, dropout)
optimizer = optim.Adam(model.parameters(), lr=1e-4)
criterion = nn.MSELoss()
criterion2 = nn.L1Loss()

loss_train_list = []
loss_test_list = []
for i in range(num_epochs):
    model.train()
    n = 0
    loss_total = 0

    for data, label in train_loader:
        optimizer.zero_grad()
        pred = model(data)
        loss = criterion(pred, label)

        loss.backward()
        optimizer.step()
        n += 1
        loss_total += loss.item()
    loss_total /= n
    loss_train_list.append(loss_total)

    model.eval()
    loss_test_total = 0
    n = 0
    for data,label in test_loader:
        with torch.no_grad():
            pred = model(data)
            loss = criterion(pred, label)

            loss_test_total += loss.item()
            n+=1
    loss_test_total /= n
    loss_test_list.append(loss_test_total)
    print('epoch:{0}/{1}    loss_train:{2}      loss_test:{3}'.format(i + 1, num_epochs, loss_total,loss_test_total))

model.eval()
prediction = model(data_test)
prediction = prediction.detach().numpy()
label_test = label_test.detach().numpy()

prediction = scalar.inverse_transform(prediction)
label_test = scalar.inverse_transform(label_test)

f,ax = plt.subplots(nrows=3,ncols=3,figsize=(10, 10))
for i in range(3):
    for j in range(3):
        ax[i,j].plot(prediction[:,3 * i + j],label = 'predictions')
        ax[i,j].plot(label_test[:,3 * i + j],label = 'true')
        ax[i,j].set_title(col_names[3 * i + j])
        ax[i,j].legend()
plt.tight_layout()
plt.show()

plt.plot(loss_test_list,label = 'loss_on_test')
plt.plot(loss_train_list,label = 'loss_on_train')
plt.legend()
plt.show()

prediction_train = model(data_train)
prediction_train = prediction_train.detach().numpy()
prediction_train = scalar.inverse_transform(prediction_train)
label_train = scalar.inverse_transform(label_train)

mse_on_train = criterion(torch.Tensor(prediction_train),torch.Tensor(label_train))
rmse_on_train = torch.sqrt(mse_on_train)
mae_on_train = criterion2(torch.Tensor(prediction_train),torch.Tensor(label_train))

mse_on_test = criterion(torch.Tensor(prediction),torch.Tensor(label_test))
rmse_on_test = torch.sqrt(mse_on_test)
mae_on_test = criterion2(torch.Tensor(prediction),torch.Tensor(label_test))

print('mse_on_train:{0}     mse_on_test:{1}'.format(mse_on_train,mse_on_test))
print('rmse_on_train:{0}     rmse_on_test:{1}'.format(rmse_on_train,rmse_on_test))
print('mae_on_train:{0}     mae_on_test:{1}'.format(mae_on_train,mae_on_test))

# data_split = torch.Tensor(data_split)
# label_split = torch.Tensor(label_split)

# prediction_rest = []
# windows = torch.cat((data_split[-1,:,1:],label_split[-1].unsqueeze(1)),dim = 1).unsqueeze(0)
# for i in range(6):
#     pred = model(windows)
#     prediction_rest.append(pred.detach().numpy().squeeze())
#     windows = torch.cat((windows[-1,:,1:],torch.transpose(pred, 0, 1)),dim = 1).unsqueeze(0)

# # print(prediction_rest)
# prediction_rest = np.array(prediction_rest)
# prediction_rest = scalar.inverse_transform(prediction_rest)

# prediction_total = model(data_split)
# prediction_total = prediction_total.detach().numpy()
# label_split = label_split.detach().numpy()


# prediction_total = scalar.inverse_transform(prediction_total)
# label_split = scalar.inverse_transform(label_split)
# f,ax = plt.subplots(nrows=3,ncols=3,figsize=(10, 10))

# length = prediction_total.shape[0]
# for i in range(3):
#     for j in range(3):
#         ax[i,j].plot(range(length),prediction_total[:,3 * i + j],label = 'predictions')
#         ax[i,j].plot(range(length),label_split[:,3 * i + j],label = 'true')
#         ax[i,j].plot(range(length,length+6),prediction_rest[:,3 * i + j],label = 'rest')
#         ax[i,j].set_title(col_names[3 * i + j])
#         ax[i,j].legend()
# plt.tight_layout()
# plt.show()

4. LSTM网络

4.1 模型原理

LSTM是一种循环神经网络(RNN)的变体,专门设计用来解决长期依赖问题。LSTM引入了门控机制,包括输入门、遗忘门和输出门,以有效地控制信息的流动。

LSTM中的记忆单元可以保留和读取信息,使其能够更好地处理时序数据中的长期依赖关系。遗忘门可以选择性地遗忘先前的信息,输入门可以添加新的信息,输出门控制输出的信息。

4.2.1 数据处理

此部分与TCN相同,采取前80%为训练数据,后20%为测试集,时间窗口大小为16

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.preprocessing import StandardScaler

data = pd.read_excel("data.xlsx")

empty = 192  # 有缺失部分的长度
side = 587  # 整个已知数据的长度
seq_len = 10
batch_size = 64

# 提取全部列名
col_names = data.columns.values.tolist()
col_names = [col_names[i] for i in range(1, len(col_names))]
for col in col_names:
    data[col] = pd.to_numeric(data[col], errors='coerce').astype(float)
    
# print(data)
data_list = np.array(data[col_names].values.tolist())
# print(data_list)
data_list = data_list[:data_list.shape[0]-6,:]
# print(data_list)
# print(type(data_list[1][1]))
scaler = StandardScaler()
data_list_scaled = scaler.fit_transform(data_list)
data_scaled = pd.DataFrame(data_list_scaled, columns=col_names)

def get_data():
    return data_list
def get_data_scaled():
    data_list_scaled[np.isnan(data_list_scaled)] = 0
    # print(data_list_scaled)
    return data_list_scaled[192:588], data_list_scaled

def plot(prediction, label_test):
    plt.figure()
    f,ax = plt.subplots(nrows=3,ncols=3,figsize=(10, 10))
    for i in range(3):
        for j in range(3):
            ax[i,j].plot(label_test[:,3 * i + j],'b-', label = 'true')
            ax[i,j].plot(prediction[:,3 * i + j],'r-', label = 'predictions')
            ax[i,j].set_title(col_names[3 * i + j])
            ax[i,j].legend()
    plt.tight_layout()
    plt.show()
    
def plot_loss(train_loss):
    plt.figure()
    plt.xlabel('epoch')
    plt.ylabel('loss')
    plt.title('Loss-Rate')
    temp_list = []
    for i in range(len(train_loss)):
        temp_list.append(train_loss[i].to('cpu').detach().numpy())
    plt.plot([i for i in range(len(train_loss))], temp_list, 'b-', label=u'train_loss')
    plt.legend() 
    plt.show()
    
def create_sliding_window(data, seq_len, test=False):
    """
    ## 创建滑动窗口,生成输入序列和对应的目标值。

    参数:
    - data: 输入的时序数据,形状为 (num_samples, num_features)
    - seq_len: 滑动窗口的大小

    返回:
    - X: 输入序列,形状为 (num_samples - seq_len, seq_len, num_features)
    - y: 目标值,形状为 (num_samples - seq_len, num_features)
    """
    X, y = [], []
    num_samples, num_features = data.shape

    for i in range(num_samples - seq_len):
        window = data[i : i + seq_len, :]
        target = data[i + seq_len, :]
        X.append(window)
        y.append(target)
    if test:
        X.append(X[len(X)-1])
    return np.array(X), np.array(y)

def inverse_scale(data):
    return scaler.inverse_transform(data)

4.2.2 模型定义

import torch
import torch.nn as nn
import torch.optim as optim
import time
# 定义多层LSTM模型
class myLSTM(nn.Module):
    def __init__(self, input_size, hidden_size, num_layers=2, output_size=9):
        super(myLSTM, self).__init__()
        # self.lstm = nn.LSTM(input_size=input_size, hidden_size=hidden_size, num_layers=num_layers, batch_first=True)
        self.lstm_layers = nn.ModuleList([
            nn.LSTM(input_size=input_size if i == 0 else hidden_size,
                   hidden_size=hidden_size,
                   batch_first=True)
            for i in range(num_layers)
        ])
        self.fc = nn.Linear(hidden_size, output_size)

    def forward(self, x):
        for lstm_layer in self.lstm_layers:
            x, _ = lstm_layer(x)
            
        if len(x.shape) == 3:
            output = self.fc(x[:, -1, :])  # 取最后一个时间步的输出
            return output
        else:
            return x

def train_epoch(model, X_train, y_train, epochs=10, lr=0.001, 
                   criterion=nn.MSELoss(), optimizer=None):
    if optimizer == None:
        optimizer = optim.Adam(model.parameters(), lr=lr)
    print(model)
    # 训练模型
    train_loss = []
    t1 = time.time()
    for epoch in range(epochs):
        model.train()
        optimizer.zero_grad()
        outputs = model(X_train)
        loss = criterion(outputs, y_train)
        loss.backward()
        optimizer.step()
        train_loss.append(loss)
        if (epoch + 1) % 5 == 0:
            print(f'Epoch {epoch + 1}/{epochs}, Loss: {loss.item()}')
        if (epoch + 1) % 20 == 0:
            t2 = time.time()
            print('当前耗时:{:.2f}s'.format(t2-t1))
    return train_loss
# X_train 的形状为 (samples, time_steps, features)
# y_train 的形状为 (samples, num_targets)

4.2.3 模型训练及性能表现

相关参数:LSTM层数:3,隐藏层大小:2048,学习率:0.0005,训练轮数:400轮

import torch
import numpy as np
import matplotlib.pyplot as plt
ign_data, _ = get_data_scaled()
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# device = 'cpu'
# ign_data.shape=(396, 9)

# 超参数
input_size = 9      # 每个时间步的特征数:9
hidden_size = 2048    # 隐藏层大小
output_size = 9     # 输出特征数
epochs = 400          # 轮数
lr = 0.0005          # learing rate
num_layers = 3
model = myLSTM(input_size=input_size, hidden_size=hidden_size, num_layers=num_layers, output_size=output_size).to(device)

seq_len = 16         # 暂定窗口为16
X_, y_ = create_sliding_window(ign_data, seq_len=seq_len)

split_rate = 0.8
split_idx = X_.shape[0]*split_rate
split_idx = round(split_idx)
# X_train = torch.tensor(X_, dtype=torch.float32)
# y_train = torch.tensor(y_, dtype=torch.float32)
X_train = torch.tensor(X_[:split_idx,:,:], dtype=torch.float32)
y_train = torch.tensor(y_[:split_idx,:], dtype=torch.float32)
X_test = torch.tensor(X_[split_idx:,:,:], dtype=torch.float32)
y_test = torch.tensor(y_[split_idx:,:], dtype=torch.float32)
# X_test = torch.tensor(ign_data[split_idx:,:,:], dtype=torch.float32)
# y_test = torch.tensor(ign_data[split_idx:,:], dtype=torch.float32)
# 训练模型
train_loss = train_epoch(model, X_train.to(device), y_train.to(device), epochs=epochs, lr=lr)
# 保存模型
torch.save(model.state_dict(),'LSTM-hidden2048-3-copy')


plot_loss(train_loss)
model.eval()
with torch.no_grad():
    predictions = model(X_test.to(device))
    
predictions = predictions.to('cpu').numpy()
# print(predictions)

plot(prediction=predictions, label_test=y_test.numpy())

5. 实验结果

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1434244.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

yarn/npm certificate has expired

目录 报错 原因:HTTPS 证书验证失败 方法 a.检查网络安全软件:可能会拦截或修改 HTTPS 流量 b.strict-ssl:false关闭验证【临时方法】 报错 info No lockfile found. [1/4] Resolving packages... error Error: certificate has expired at TLS…

【华三】GRE VPN 实验配置

【华三】GRE VPN 实验配置 前言报文格式实验需求配置思路配置拓扑GRE配置步骤R1基础配置GRE 配置ISP_R2基础配置R3基础配置GRE 配置PCPC1PC2抓包检查OSPF建立GRE隧道建立配置文档前言 VPN :(Virtual Private Network),即“虚拟专用网络”。 它是一种通过公用网络(通常是互…

骨传导耳机是什么原理?适合什么场景使用?

骨传导耳机是一种非常特殊的蓝牙耳机,它们通过骨传导技术将声音直接传送到内耳。这种技术不同于传统耳机,它不通过空气传送声音,而是通过头骨的振动来传送声音。 骨传导耳机的传声原理跟传统耳机有所不同,传统耳机通过空气振动将…

爱上算法:每日算法(24-2月2号)

🌟坚持每日刷算法,将其变为习惯🤛 题目链接:101. 对称二叉树 最开始肯定是比较简单的想法,就是遍历左右节点呀,不相等我就直接返回false。 但是这样错了,我们要的是以根节点为轴,而…

使用 Python、Elasticsearch 和 Kibana 分析波士顿凯尔特人队

作者:来自 Jessica Garson 大约一年前,我经历了一段压力很大的时期,最后参加了一场篮球比赛。 在整个过程中,我可以以一种我以前无法做到的方式断开连接并找到焦点。 我加入的第一支球队是波士顿凯尔特人队。 波士顿凯尔特人队是…

【Linux】文件周边002之初步理解文件管理(打开的文件)

👀樊梓慕:个人主页 🎥个人专栏:《C语言》《数据结构》《蓝桥杯试题》《LeetCode刷题笔记》《实训项目》《C》《Linux》《算法》 🌝每一个不曾起舞的日子,都是对生命的辜负 目录 前言 1.(打开…

PMP资料怎么学?PMP备考经验分享

PMP考试前大家大多都是提前备考个一两个月,但是有些朋友喜欢“不走寻常路”,并不打算去考PMP认证,想要单纯了解PMP,不管要不要考证,即使是仅仅学习了解一下我个人都非常支持,因为专业的基础的确能提高工作效…

【Linux系统 02】Shell脚本

目录 一、Shell概述 二、输入输出 三、分支控制 1. 表达式 2. if 分支 3. case 分支 四、循环控制 1. for 循环 2. while 循环 3. select 循环 五、函数 一、Shell概述 Shell是Linux系统连接用户和操作系统的外壳程序,将用户的输入和请求选择性传递给操…

Unity笔记:相机移动

基础知识 鼠标输入 在Unity中,开发者在“Edit” > “Project Settings” > “Input Manager”中设置输入,如下图所示: 在设置了Mouse X后,Input.GetAxis("Mouse X")返回的是鼠标在X轴上的增量值。这意味着它会…

考勤|基于Springboot的大学生考勤系统设计与实现(源码+数据库+文档)

大学生考勤系统目录 目录 基于Springboot的大学生考勤系统设计与实现 一、前言 二、系统功能设计 三、系统实现 1、系统登录注册 2、管理员功能模块 3、教师功能模块 4、学生功能模块 四、数据库设计 1、实体ER图 2、具体的表设计如下所示: 五、核心代码…

【CSS + ElementUI】更改 el-carousel 指示器样式且隐藏左右箭头

需求 前三条数据以走马灯形式展现&#xff0c;指示器 hover 时可以切换到对应内容 实现 <template><div v-loading"latestLoading"><div class"upload-first" v-show"latestThreeList.length > 0"><el-carousel ind…

@所有人 您需要的 幻兽帕鲁服务器搭建教程 已上线

所有人 您需要的 幻兽帕鲁服务器搭建教程 已上线 幻兽帕鲁一键购买及部署体验购买及部署购买云服务器ECS部署幻兽帕鲁 创建账户并登录Steam其他操作更新服务器修改游戏参数其他操作释放资源 一直拖到今天才来写这篇幻兽帕鲁服务器搭建教程&#xff0c;确实是因为前段时间有事耽…

【Rust】——rust前言与安装rust

&#x1f383;个人专栏&#xff1a; &#x1f42c; 算法设计与分析&#xff1a;算法设计与分析_IT闫的博客-CSDN博客 &#x1f433;Java基础&#xff1a;Java基础_IT闫的博客-CSDN博客 &#x1f40b;c语言&#xff1a;c语言_IT闫的博客-CSDN博客 &#x1f41f;MySQL&#xff1a…

机器学习系列5-特征组合、简化正则化

1.特征组合 1.1特征组合&#xff1a;编码非线性规律 我们做出如下假设&#xff1a;蓝点代表生病的树。橙色的点代表健康的树。 您可以绘制一条直线将生病的树与健康的树清晰地分开吗&#xff1f;不可以。这是一个非线性问题。您绘制的任何线条都无法很好地预测树的健康状况…

R语言学习case12:ggplot 置信区间(多线型)

接上文&#xff1a;多条曲线 R语言学习case11&#xff1a;ggplot 置信区间&#xff08;包含多子图&#xff09; 在ggplot2中&#xff0c;每个geom函数都接受一个映射参数。然而&#xff0c;并非每个美学属性都适用于每个geom。你可以设置点的形状&#xff0c;但不能设置线的“…

群晖NAS开启FTP服务结合内网穿透实现公网远程访问本地服务

⛳️ 推荐 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。 文章目录 ⛳️ 推荐1. 群晖安装Cpolar2. 创建FTP公网地址3. 开启群晖FTP服务4. 群晖FTP远程连接5. 固定FTP公网地址6. 固定FTP…

产品经理学习-产品运营《如何策划一场活动》

互联网活动怎么玩 最常听到的有&#xff1a; 注册有奖、拉新有奖 签到积分 秒杀、大促、神券 和过去相比&#xff0c;现在活动的特征变化&#xff1a; 线上化、形式丰富、覆盖人群广、即时性、效果可控 什么是活动运营 通过策划不同形式的活动&#xff0c;进行有效的资源和…

LFU缓存(Leetcode460)

例题&#xff1a; 分析&#xff1a; 这道题可以用两个哈希表来实现&#xff0c;一个hash表&#xff08;kvMap&#xff09;用来存储节点&#xff0c;另一个hash表&#xff08;freqMap&#xff09;用来存储双向链表&#xff0c;链表的头节点代表最近使用的元素&#xff0c;离头节…

SpringBoot注解--02---常用注解汇总

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 1.SpringBoot 配置启动注解SpringBootApplication 2.Bean处理注解2.1 依赖注入AutoWired、Qualifier、Resource 2.2 类被 Spring 容器创建&#xff0c;管理 iocComp…

基于ESP8266 开发板(MCU)遥控小车

遥控小车 ​ 遥控界面 ​ 【项目源码】 第一版ESP8266 https://github.com/liyinchigithub/esp8266_car_webServerhttps://github.com/liyinchigithub/esp8266_car_webServer 第二版ESP32 GitHub - liyinchigithub/esp32-wroom-car: 嵌入式单片机 ESP32 Arduino 遥控小车&a…