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()
预测结果为:
我一开始以为是神经网络的层数不够,后来加了几层之后,训练结果跟现在没有什么区别,我觉得是标签有问题,但是我觉得代码也没有问题,有没有大佬帮忙解答一下,谢谢
绿色为预测值,红色为真实值