[Pytorch系列-52]:循环神经网络RNN - 全连接网络与RNN网络在时间序列数据集上拟合的比较

作者主页(文火冰糖的硅基工坊):文火冰糖(王文兵)的博客_文火冰糖的硅基工坊_CSDN博客

本文网址:https://blog.csdn.net/HiWangWenBing/article/details/121526014


目录

第1章 概述

1.1 业务需求概述

1.2 业务分析

1.3 导入库

第1章 数据集

1.1 数据集概述

1.2 从文件中读取数据

1.3 提取有效数据

第2章 全连接网络的拟合

2.1 定义全连接网络

2.2 定义loss与优化器

2.3 训练前准备

2.4 开始训练

2.5 loss显示 

2.6 结果分析

第3章 RNN网络的拟合

3.1 定义RNN网络

3.2 生成网络

3.3 定义loss与优化器

3.4 训练前的准备

3.5 开始训练

3.6 显示loss

3.7 分析



第1章 概述

1.1 业务需求概述

有一批最近52周的销售数据,希望能够根据这些数据,预测未来几周销售数据。

1.2 业务分析

这是一个线性拟合的问题,那么每周的数据之间是独立的?还是每周的数据之间有时间的相关性?

本文就采用层数的全连接网络和RNN网络对数据进行拟合与比较。

如果全连接网络的拟合度比RNN网络好,则证明每周的数据是独立无关的。

如果全连接网络的拟合度没有RNN网络好,则证明每周的数据是具有时间相关性。

1.3 导入库

%matplotlib inline
import torch
import torch.nn as nn
from torch.nn import functional as F
from torch.autograd import Variable
from torch import optim

import numpy as np
import math, random
import matplotlib.pyplot as plt
import pandas as pd

from torch.utils.data import Dataset
from torch.utils.data import DataLoader

第1章 数据集

1.1 数据集概述

销售数据是通过Excel存放的:包含多个样本数据,每个样本包含52周的数据,如下图所示:

横轴:不同的样本

纵轴:每个样本包含的序列52周的销售数据。

1.2 从文件中读取数据

# 从excel文件中数据
sales_data = pd.read_csv('time_serise_sale.csv')

sales_data.head()

1.3 提取有效数据

# 提取有效数据
source_data = sales_data
source_data.values.shape
source_data.values
array([[0.00000000e+00, 2.29157429e+00, 2.88283833e+00, ...,
        2.52078778e+00, 2.63721001e+00, 2.74892268e+00],
       [1.00000000e+00, 6.09664112e-01, 2.52360427e+00, ...,
        1.66285479e+00, 2.48192522e+00, 2.41120153e+00],
       [2.00000000e+00, 3.42279275e+00, 1.81265116e+00, ...,
        1.72005177e+00, 2.16993942e+00, 2.16170153e+00],
       ...,
       [1.50490000e+04, 3.83370716e+00, 3.54807088e+00, ...,
        3.03134190e+00, 1.85208859e+00, 3.00563077e+00],
       [1.50500000e+04, 3.18643937e+00, 1.70323164e+00, ...,
        1.19605309e+00, 3.34099104e+00, 2.92155740e+00],
       [1.50510000e+04, 3.10427003e+00, 2.82717086e+00, ...,
        1.33781619e+00, 2.71468770e+00, 2.34349413e+00]])
# 显示数据集数据
source_data
Unnamed: 0week_1week_2week_3week_4week_5week_6week_7week_8week_9...week_43week_44week_45week_46week_47week_48week_49week_50week_51week_52
002.2915742.8828383.5818054.0138751.1099242.8342472.6250452.1968844.208887...1.2422502.7710723.7781433.1616343.7926452.0154812.8261842.5207882.6372102.748923
110.6096642.5236042.6095373.6959973.3992722.6166121.6519351.3482953.862523...2.4775052.2845133.4617833.1010523.4424201.9157762.4261681.6628552.4819252.411202
223.4227931.812651-0.0979661.7240643.0936601.7812782.8499462.9497073.560835...2.2196672.3598341.9320292.7319471.8362451.2199331.2227401.7200522.1699392.161702
333.3722832.5772543.8543083.4496792.5176762.6356792.3527062.8562161.948434...1.6709120.9091133.2166521.7753463.2704842.3997093.0320711.7036661.7505851.821736
442.9977271.7994153.6480902.3915672.3767781.8647170.4080622.3467263.260303...2.3040583.0389052.0387332.8251862.2329372.5090502.881796-1.7121312.1403661.926818
..................................................................
15047150471.9527261.5476371.9027890.8132612.6009792.9106382.8783960.5942163.526187...0.4860733.3362523.3072703.0268351.4721163.2207922.6640441.5461533.0269482.611774
15048150480.6528243.5891913.2577072.8212762.1859372.534801-0.7743753.8356953.776809...2.6841531.3849123.1845702.8329412.0920332.6061980.7531933.1605993.0858002.814394
15049150493.8337073.5480713.1941601.9934373.0135471.8250472.3051960.5224753.126647...2.9289371.6337543.0785982.4665630.4893803.5187253.4064663.0313421.8520893.005631
15050150503.1864391.7032323.1965912.407803-0.4743703.8799433.7624083.4156691.790529...1.6426122.3877702.1498930.6884633.1508053.2422092.9727281.1960533.3409912.921557
15051150513.1042702.8271711.1764283.2749672.9346552.3491882.4129351.2190542.843297...2.5512590.8192033.4165323.2420212.8101772.0374872.6816941.3378162.7146882.343494

15052 rows × 53 columns

第2章 全连接网络的拟合

2.1 定义全连接网络

class FullyConnected(nn.Module):
    def __init__(self, x_size, hidden_size, output_size):
        super(FullyConnected, self).__init__()
        self.hidden_size = hidden_size

        self.linear_with_tanh = nn.Sequential(
            nn.Linear(10, self.hidden_size),
            nn.Tanh(),
            nn.Linear(self.hidden_size, self.hidden_size),
            nn.Tanh(),
            nn.Linear(self.hidden_size, output_size)
        )
        
    def forward(self, x):
        yhat = self.linear_with_tanh(x)
        
        return yhat
# 输入样本的size
x_size = 1

# 隐藏层的size:try to change this parameters 
hidden_size = 2 

#数据特征的size
output_size = 10

fc_model = FullyConnected(x_size = x_size, hidden_size = hidden_size, output_size = output_size)
print(fc_model)

fc_model = fc_model.double()
print(fc_model)
FullyConnected(
  (linear_with_tanh): Sequential(
    (0): Linear(in_features=10, out_features=2, bias=True)
    (1): Tanh()
    (2): Linear(in_features=2, out_features=2, bias=True)
    (3): Tanh()
    (4): Linear(in_features=2, out_features=10, bias=True)
  )
)

fc_model.state_dict()['linear_with_tanh.0.weight']
tensor([[ 0.2028,  0.0721,  0.0101,  0.2866, -0.3106,  0.1612,  0.0082, -0.1394,
          0.2630, -0.2903],
        [ 0.0596, -0.2646,  0.2036, -0.2676, -0.0198,  0.2969,  0.2596,  0.0965,
          0.0746, -0.0195]], dtype=torch.float64)

2.2 定义loss与优化器

#定义loss函数
criterion = nn.MSELoss()

# 使用 Adam 优化器 比课上使用的 SGD 优化器更加稳定 
optimizer = optim.AdamW(fc_model.parameters(), lr=0.01) 

2.3 训练前准备

n_epochs = 30
n_layers = 1
batch_size = seq_length
seq_length = 10

fc_losses = np.zeros(n_epochs) 


data_loader = torch.utils.data.DataLoader(source_data.values, batch_size = batch_size, shuffle=True)
print(data_loader)
print(data_loader.batch_size )

2.4 开始训练

# 开始训练
for epoch in range(n_epochs):
    # 定义用于每个epoch的平均loss
    epoch_losses = []
    
    # 读取batch数据
    for iter_, data in enumerate(data_loader):
        #当读到数据不足batch size时,跳过batch size
        if data.shape[0] != batch_size: 
            continue 
        
        #随机的获取长度=seq_length的数据
        random_index = random.randint(0, data.shape[-1] - seq_length - 1)
        train_x = data[:, random_index: random_index+seq_length]
        #train_y = data[:, random_index + 1: random_index + seq_length + 1]
        train_y = train_x
        
        #进行前向运算
        outputs = fc_model(train_x.double())
        
        #复位梯度
        optimizer.zero_grad()
        
        #求此次前向运算的loss
        loss = criterion(outputs, train_y)
        
        #反向求导
        loss.backward()
        
        #梯度迭代
        optimizer.step()

        #
        epoch_losses.append(loss.detach())
        
        if iter_  == 0:
            plt.clf();
            plt.ion()
            plt.title("Epoch {}, iter {}".format(epoch, iter_))
            plt.plot(torch.flatten(train_y),'c-',linewidth=1,label='Label')
            #plt.plot(torch.flatten(train_x),'g-',linewidth=1,label='Input')
            plt.plot(torch.flatten(outputs.detach()),'r-',linewidth=1,label='Output')
            plt.draw();
            plt.pause(0.05);
    fc_losses[epoch] = np.mean(epoch_losses)

 ................................................................

2.5 loss显示 

plt.plot(fc_losses)

2.6 结果分析

全连接网络应对这种时序序列问题,拟合性不是很好。

第3章 RNN网络的拟合

3.1 定义RNN网络

class SimpleRNN(nn.Module):
    def __init__(self, x_size, hidden_size, n_layers, batch_size, output_size):
        super(SimpleRNN, self).__init__()
        self.hidden_size = hidden_size
        self.n_layers = n_layers
        self.batch_size = batch_size
        #self.inp = nn.Linear(1, hidden_size) 
        self.rnn = nn.RNN(x_size, hidden_size, n_layers, batch_first=True)
        self.out = nn.Linear(hidden_size, output_size) # 10 in and 10 out

    def forward(self, inputs, hidden=None):
        hidden = self.__init__hidden()
        #print("Forward hidden {}".format(hidden.shape))
        #print("Forward inps {}".format(inputs.shape))
        output, hidden = self.rnn(inputs.float(), hidden.float())
        #print("Out1 {}".format(output.shape))
        output = self.out(output.float());
        #print("Forward outputs {}".format(output.shape))

        return output, hidden

    def __init__hidden(self):
        hidden = torch.zeros(self.n_layers, self.batch_size, self.hidden_size, dtype=torch.float64)
        return hidden

3.2 生成网络

x_size = 1
hidden_size = 2 # try to change this parameters 
n_layers = 1
seq_length = 10
output_size = 1

#rnn_model = SimpleRNN(x_size, hidden_size, n_layers, seq_length, output_size)
rnn_model = SimpleRNN(x_size, hidden_size, n_layers, seq_length, output_size)

print(rnn_model)
SimpleRNN(
  (rnn): RNN(1, 2, batch_first=True)
  (out): Linear(in_features=2, out_features=1, bias=True)
)

3.3 定义loss与优化器

# 定义loss
criterion = nn.MSELoss()

#定义优化器
optimizer = optim.AdamW(rnn_model.parameters(), lr=0.01) # 使用 Adam 优化器 比课上使用的 SGD 优化器更加稳定 

3.4 训练前的准备

# 训练前的准备
n_epochs = 30
rnn_losses = np.zeros(n_epochs) 

data_loader = torch.utils.data.DataLoader(source_data.values, batch_size=seq_length, shuffle=True)

3.5 开始训练

# 开始训练
for epoch in range(n_epochs):
    for iter_, t in enumerate(data_loader):
        if t.shape[0] != seq_length: continue 

        random_index = random.randint(0, t.shape[-1] - seq_length - 1)
        train_x = t[:, random_index: random_index+seq_length]
        #train_y = t[:, random_index + 1: random_index + seq_length + 1]
        train_y = train_x
        
        #获取输出
        outputs, hidden = rnn_model(train_x.double().unsqueeze(2), hidden_size)
        
        #梯度复位
        optimizer.zero_grad()
        
        #定义损失函数
        loss = criterion(outputs.double(), train_y.double().unsqueeze(2))
        
        # 反向求导
        loss.backward()
        
        #梯度迭代
        optimizer.step()
        
        #记录loss
        epoch_losses.append(loss.detach())
        
        #显示拟合图像
        if iter_ == 0:
            plt.clf();
            plt.ion()
            plt.title("Epoch {}, iter {}".format(epoch, iter_))
            plt.plot(torch.flatten(train_y),'c-',linewidth=1,label='Label')
            plt.plot(torch.flatten(train_x),'g-',linewidth=1,label='Input')
            plt.plot(torch.flatten(outputs.detach()),'r-',linewidth=1,label='Output')
            plt.draw();
            plt.pause(0.05);
    rnn_losses[epoch] = np.mean(epoch_losses)

 

3.6 显示loss

3.7 分析

RNN网络在第一个epoch完成后,拟合度就非常好。


作者主页(文火冰糖的硅基工坊):文火冰糖(王文兵)的博客_文火冰糖的硅基工坊_CSDN博客

本文网址:https://blog.csdn.net/HiWangWenBing/article/details/121526014

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
对于搭建循环神经网络执行探测任务,你可以按照以下步骤进行: 1. 数据准备:根据你的预测任务,收集并准备相关的数据集。确保数据集包含输入序列和对应的目标值。例如,如果你的任务是预测天气,数据集可以包含历史天气数据和对应的未来天气情况。 2. 数据预处理:对数据进行预处理,包括数据清洗、特征提取、归一化等。确保数据格式适用于循环神经网络的输入。 3. 构建循环神经网络模型:选择适合的循环神经网络类型,如RNN、LSTM、GRU等,并使用深度学习框架(如TensorFlow、PyTorch)搭建模型。根据任务的复杂程数据集规模,可以选择单层或多层的循环神经网络结构。 4. 模型训练:将准备好的数据集划分为训练集和测试集,使用训练集对模型进行训练。在训练过程中,通过反向传播算法优化模型参数,使其能够更好地拟合数据。 5. 模型评估和调优:使用测试集评估模型的性能,可以使用一些指标如均方误差(Mean Square Error)或准确率来评估模型的预测效果。如果模型表现不佳,可以尝试调整超参数、增加数据量或改进模型结构等方式进行调优。 6. 模型应用:经过训练和调优后,你的循环神经网络模型可以用于预测任务。输入新的序列数据,通过模型的前向传播过程得到预测结果。 以上是一个基本的框架,具体的实施步骤和细节可能因任务的不同而有所差异。希望对你有所帮助!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

文火冰糖的硅基工坊

你的鼓励是我前进的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值