绘师岸田 2021-06-29 19:18 采纳率: 0%
浏览 658

为什么用lstm做时序预测结果这么差(用paddlepaddle实现的)

from __future__ import print_function
import numpy as np
import math
import matplotlib.pyplot as plt
import paddle
import paddle.fluid as fluid
import pandas as pd
#数据预处理用的模块
import math
from sklearn.preprocessing import MinMaxScaler

confirmed_df = pd.read_csv('time_series_covid19_confirmed_global.csv')
Japan_df = confirmed_df.iloc[[139]]
dataset = Japan_df.values.reshape(-1,1)
Japan_dataset = []
l = len(dataset)
for i in range(4,l):
    Japan_dataset.append(dataset[i])
Japan_array_dataset = np.array(Japan_dataset)
Japan_array_dataset = Japan_array_dataset.astype(np.float32)
print(Japan_array_dataset.dtype)
Japan_df_dataset = pd.DataFrame(Japan_array_dataset)
# 处理样本数据
#look_back 就是预测下一步所需要的 time_steps
def create_dataset(dataset, time_steps=1):
    dataX, dataY = [], []
    for i in range(len(dataset)-time_steps-1):
        a = Japan_array_dataset[i:(i+time_steps), 0]
        dataX.append(a)
        dataY.append(dataset[i + time_steps, 0])
    return np.array(dataX), np.array(dataY)

np.random.seed(6)
# 归一化,将数据重新调整到0到1的范围,因为LSTM对数据比较敏感
scaler = MinMaxScaler(feature_range=(0, 1))
Japan_array_dataset = scaler.fit_transform(Japan_array_dataset)
 
#  划分训练集与测试集
train_size = int(len(Japan_array_dataset) * 0.7) #训练集样本数量
test_size = len(Japan_array_dataset) - train_size #测试集样本数量
train, test = Japan_array_dataset[0:train_size,:], Japan_array_dataset[train_size:len(Japan_array_dataset),:]

time_steps = 1
train_x, train_y = create_dataset(train, time_steps) #获取训练集(样本数据,样本标签)
test_x, test_y = create_dataset(test, time_steps) #获取测试集(样本数据,样本标签)

#定义Data Reader
def read_data(data_x,data_y):
    def reader():
        for x, y in zip(data_x,data_y):
            yield x[:], y
    return reader
#定义数据提供器(Datafeeder)
train_reader = paddle.batch(
    read_data(train_x,train_y),
    batch_size=10)
#定义网络结构
x = fluid.layers.data(name='x',shape=[1],dtype='float32',lod_level= 1) #lod_level=0则表示输入数据不是一个序列
y = fluid.layers.data(name='y',shape=[1],dtype='float32')
print(x)
#构建LSTMC层
DIM = 1 #隐藏层大小
fc = fluid.layers.fc(input=x, size=DIM * 4)
lstm_h, c = fluid.layers.dynamic_lstm( input=fc, size=DIM * 4, is_reverse=False) #paddlepaddle中规定了size=4*隐藏层大小
# 最大池化
lstm_max = fluid.layers.sequence_pool(input=lstm_h, pool_type='max')
# 激活函数
lstm_max_tanh = fluid.layers.tanh(lstm_max)
# 全连接层
prediction = fluid.layers.fc(input=lstm_max_tanh, size=1, act='tanh')
from paddle.utils.plot import Ploter

cost = fluid.layers.square_error_cost(input=prediction,label=y)  # 利用标签数据和输出的预测数据,求一个batch的损失值
avg_loss = fluid.layers.mean(cost) #  求均值,得到平均损失

# 克隆main_program得到test_program
test_program = fluid.default_main_program().clone(for_test=True)

#配置优化器(Optimizer Function)
sgd_optimezer = fluid.optimizer.Adam(learning_rate=0.001)
sgd_optimezer.minimize(avg_loss)


#配置运算场所
use_cuda = False
place = fluid.CUDAPlace(0) if use_cuda else fluid.CPUPlace()

# 创建执行器,初始化参数
exe = fluid.Executor(place)
exe.run(fluid.default_startup_program())    #启动模型
 #配置数据提供器
feeder = fluid.DataFeeder(place=place,feed_list=[x,y])
#配置Event Handler
train_prompt = "Train cost"
test_prompt = "Test cost"
cost_ploter = Ploter(train_prompt, test_prompt)

# 将训练过程绘图表示
def event_handler_plot(ploter_title, step, cost):
    cost_ploter.append(ploter_title, step, cost)
    cost_ploter.plot()
#创建训练过程
save_dirname = "lstm.inference.model"   # 将模型参数存储在名为 save_dirname 的文件中
num_epochs = 150
step = 0
for pass_id in range(num_epochs):
    #step = 0 # 画图用
    total_loss_pass = 0 #初始化每一个epoch的损失值初始值为0
    for data_train in train_reader():
        avg_loss_value = exe.run(program=fluid.default_main_program(),
                                  feed = feeder.feed(data_train),
                                  fetch_list = [avg_loss])
        total_loss_pass += avg_loss_value[0] #计算每个epoch的总损失值
    event_handler_plot(train_prompt, step, total_loss_pass)
    step += 1
    if pass_id % 10 == 0:
        print("%s,Pass %d, total avg cost = %f" % ( "train cost",pass_id, total_loss_pass))
   
     # 保存训练好的模型参数用于预测
    if save_dirname is not None:
        fluid.io.save_inference_model(save_dirname, ['x'], [prediction], exe)
def convert2LODTensor(temp_arr, len_list):
    temp_arr = np.array(temp_arr) 
    temp_arr = temp_arr.flatten().reshape((-1, 1))#把测试样本的array平坦化到一维数据的格式
    print(temp_arr.shape)
    return fluid.create_lod_tensor(
        data=temp_arr,
        recursive_seq_lens =[len_list],
        place=fluid.CPUPlace()
        )#返回:A fluid LoDTensor object with tensor data and recursive_seq_lens info

def get_tensor_label(mini_batch):  
    tensor = None
    labels = []
    temp_arr = []
    len_list = []
    for _ in mini_batch:    
        labels.append(_[1]) #收集 label----y 
        temp_arr.append(_[0]) #收集序列本身--x 
        len_list.append(len(_[0])) #收集每个序列x的长度,和上边x的维度对应,
    tensor = convert2LODTensor(temp_arr, len_list)    
    return tensor, labels
 
test_reader = paddle.batch(
    read_data(test_x,test_y),
    batch_size=test_size)#由于数据量不大,使得所有测试集数据为一个batch
#创建预测用的Executor
infer_exe = fluid.Executor(place)
inference_scope = fluid.core.Scope()

#使用验证集进行预测
with fluid.scope_guard(inference_scope):
    # 使用 fluid.io.load_inference_model 获取 inference program desc,
    # feed_target_names 用于指定需要传入网络的变量名
    # fetch_targets 指定希望从网络中fetch出的变量名
    [inference_program, 
     feed_target_names,
     fetch_targets] = fluid.io.load_inference_model(save_dirname, infer_exe)
    


    prediction = []
    labels = []
    for data_test in test_reader():
        tensor,label = get_tensor_label(data_test)# 转换成tensor格式的x和y
        results = infer_exe.run(inference_program,
                      feed= {'x':tensor},
                      fetch_list=fetch_targets)
        result_print = results[0].flatten()
        prediction.append(result_print)
        labels.append(label)
    
    plt.figure()
    labels = scaler.inverse_transform(labels)#标签转换回原始数据
    prediction = scaler.inverse_transform(prediction)#预测值转换回原始数据大小区间范围

    print("predictions")
    print("------------------")
    print(prediction)
    print("===========================")
    print("===========================")
    print("labels")
    print("----------------------")
    print(labels)

    plt.plot(list(range(len(labels[0]))), labels[0], color='r')  #红线为真实值
    plt.plot(list(range(len(prediction[0]))), prediction[0], color='g')  #绿线为预测值
    plt.show()
        

预测结果为:

我一开始以为是神经网络的层数不够,后来加了几层之后,训练结果跟现在没有什么区别,我觉得是标签有问题,但是我觉得代码也没有问题,有没有大佬帮忙解答一下,谢谢

绿色为预测值,红色为真实值

  • 写回答

2条回答 默认 最新

  • qq_46699884 2021-12-10 17:15
    关注

    解决了吗

    评论

报告相同问题?

悬赏问题

  • ¥20 显示器休眠后重新唤醒出现蓝屏,蓝屏代码为DRIVER-POWER.STATE-FAILURE
  • ¥20 alt+tab怎么恢复到以前的模式
  • ¥15 来一个会抓包app支付链接的
  • ¥15 MMdetection安装
  • ¥15 STM32U535系列stop3模式进入和RTC唤醒
  • ¥15 如何提取全民K歌没下载过但播放过很多次的音频?
  • ¥15 树莓派运行detect.py
  • ¥15 pdfplumber提起文本内容如何过滤水印内容
  • ¥15 kingbase容器启动失败,sudo:/bin/sudo must be owned by uid 0 and have the setuid bit set
  • ¥20 黑神话悟空调用机械硬盘导致卡顿