【PyTorch深度学习】利用图卷积神经网络预测北京地铁进站流量实战(附源码和数据集)

需要源码和数据集请点赞关注收藏后评论区留言私信~~~

一、数据预处理

AFC(Automatic Fare Collection System)数据是自动售检票系统在乘客通过闸机刷卡进出站时收集的关于乘客部分出行信息的数据记录,该系统通过乘客进、出站刷卡,可以精确记录乘客的卡号、进出站时间、进出站编码等信息,所有记录的信息包含42个字段。需要注意的是,卡数据中只记录起终点,并不会记录乘客的换乘信息等

使用北京地铁2016年2月29号-4月1号连续5周25个工作日的AFC刷卡数据,共计1.3亿条记录,数据跨度为05:00-23:00(18小时或1080分钟),原始卡数据记录了卡号、进出站时间、进出站车站编号、进出站车站名称等信息。2016年3月,北京市共计17条运营线路和276座运营车站(换乘车站不重复计数,不计机场线)。对于两条或三条线路交叉换乘的车站,给予不同的车站编号,其他车站给予唯一编号

地铁AFC数据中的信息均为编码类型,必须将车站编码和对应的车站名称进行匹配才能有实际的意义。提取客流时间序列主要需要的字段为卡发行号,进站编号,进站时间,出站编号,出站时间以及与进站编码和出站编码匹配后的进出站站点名称

考虑到,乘客一次出行通过自动售检票系统刷卡进出站会产生两条数据记录,刷卡进站时会产生一条记录,而乘客刷卡出站时产生的记录则既包含进站信息也包含出站信息,即增加了出站时间,出站站点编号等信息

综上考虑,可以将进站时产生的数据记录予以删除,大大减少数据量,减小数据处理难度。

因为数据量较大,该部分的数据清洗工作主要在Oracle数据库中进行。

 针对地铁AFC数据,考虑乘客出行的时空特点以及乘客出行规律,主要是删除逻辑上明显不合理的记录以及一些对本研究无用的变量,主要处理方法如下:

提取研究所需字段,删除无用字段,并将进出站编码和进出站站点名称匹配,并删除不能正常匹配站名的记录;

删除进站时间晚于出站时间的记录;

删除进出站时间在地铁运营时间范围之外的记录;

删除进出站日期不在同一天的记录(部分线路跨日运营);

删除进出站时间之差大于4个小时的记录,因为北京地铁规定站内逗留超4小时补3元,除乞讨,发小广告人员,极少数乘客能够乘坐超过4个小时的地铁;

删除出行时间与出行距离不匹配的记录,即乘客出行速度不在正常范围内;

删除同站进出的记录;

删除部分字段丢失的记录,例如对于某些字段为 “0”或NULL的记录,应予以删除

处理前的卡数据样例如下图所示:

处理后的卡数据样例如下图所示:

 

根据处理后的卡数据,分别提取不同时间粒度下的进站客流时间序列,提取的15分钟时间粒度下的客流时间序列如下图所示

 

其中车站编号按线路号及邻接关系进行排序。该客流序列数据使用min-max scaler归一化至(0,1)区间,结果评估时再反归一化至数据原始量级

该段代码的输入为处理后的卡数据,输出为不同时间粒度下的进站客流时间序列,(具体结构如上文所示)输出结果存储在CSV文件中 代码如下

# _*_coding:utf-8_*_
import os
import time
import numpy as np

# 以两天的数据为例,共计276个车站,15分钟时间粒度下,每天05:00-23:00共计18个小时,每天共72个时间片
# 两天共计144个时间片,所以最终得到的为276×144的矩阵

global_start_time = time.time()
print(global_start_time)

# 导入n天的客流数据
datalist = os.listdir('./data/')
print(datalist)
datalist.sort(key=lambda x: int(x[9:13]))
# 初始化n个空列表存放n天的数据
for i in range(0, len(datalist)):
	globals()['flow_'+str(i)] = []

for i in range(0, len(datalist)):
	file = np.loadtxt('./data/'+ datalist[i], skiprows=1, dtype=str)
	for line in file:
		line = line.replace('"', '').strip().split(',')
		line = [int(x) for x in line]
		globals()['flow_'+str(i)].append(line)
	print("已导入第"+str(i)+"天的数据"+"  "+datalist[i])


# 获取车站在所给时间粒度下的进站客流序列
def get_tap_in(flow, time_granularity, station_num):
	# 一天共计1440分钟,去掉23点到5点五个小时300分钟的时间,一天还剩1080分钟,num为每天的时间片个数,
	# 当除不尽时,由于int是向下取整,会出现下标越界,所以加1
	if 1080 % time_granularity == 0:
		num = int(1080/time_granularity)
	else:
		num = int(1080/time_granularity)+1
	# 初始化278*278*num的多维矩阵,每个num代表第num个时间粒度
	OD_matrix = [[([0] * station_num) for i in range(station_num)] for j in range(num)]
	#print (matrix)
	for row in flow:
		# 每一列的含义 GRANT_CARD_CODE	TAP_IN	TAP_OUT	TIME_IN	TIME_OUT
		# row[1]为进站编码,row[2]为出站编码,row[3]为进站时间,t为进站时间所在的第几个时间粒度(角标是从0开始的所以要减1)
		# 通过row[3]将晚上11点到12点的数据删掉不予考虑
		if row[3] < 1380 and row[1] < 277 and row[2] < 277:
			m = int(row[1])-1
			n = int(row[2])-1
			t = int((int(row[3])-300)/time_granularity)+1
			# 对每一条记录,在相应位置进站量加1
			OD_matrix[t-1][m][n] += 1

	# 不同时间粒度下某个站点的进站量num列,行数为station_num
	O_matrix = [([0] * num) for i in range(station_num)]
	for i in range(num):
		for j in range(station_num):
			temp = sum(OD_matrix[i][j])
			O_matrix[j][i] = temp
	return O_matrix, OD_matrix


for i in [5, 10, 15, 30, 60]:
	print('正在提取第'+str(i)+'个时间粒度的时间序列')
	for j in range(len(datalist)):
		print('正在提取该时间粒度下第'+str(j)+'天的时间序列')
		globals()['O_flow_'+str(i)],  globals()['OD_matrix_'+str(i)] = get_tap_in(globals()['flow_'+str(j)], i, station_num=276)
		np.savetxt('O_flow_'+str(i)+'.csv', np.array(globals()['O_flow_'+str(i)]), delimiter=',', fmt='%i')
		print(globals()['O_flow_'+str(i)])

print('总时间为(s):', time.time() - global_start_time)

二、问题陈述及模型框架

 使用历史进站流数据,借助简单的图卷积神经网络(Kipf版本)以及二维卷积神经网络,预测未来15分钟所有地铁车站的进站流

模型框架如图所示:

其中,模型输入为周模式、日模式、实时模式三个模式下的短时进站流序列,分别经过GCN层和CNN层,输入下一时刻的进站流序列

代码的目录框架如下所示,其中:

 

data文件夹主要用于读取数据并将数据划分为训练集、验证集和测试集

model文件夹主要提供了图注意力网络(Graph Attention Network,GAT)和图卷积网络(Graph Convolutional Network,GCN)的PyTorch版本的layer,以及本章节所构建的短时客流预测深度学习模型

result文件夹用于存储模型预测结果

runs文件夹用于存储模型训练过程,可使用tensorboard可视化模型的训练损失和验证损失。save_model用于保存训练过程的模型

utils文件夹存放的文件主要用于终止模型训练、模型评价、获取图卷积中的拉普拉斯矩阵等

三、数据准备

 使用的为北京地铁连续5周25个工作日共计约1.3亿条刷卡数据提取的15分钟时间粒度的进站客流时间序列,维度为276*1800,使用过去10个时间步的数据预测未来1个时间步的数据,前4周的数据为训练集,其中又将训练集的10%(0.1)拿出来做了验证集,后一周的数据为测试集

由于数据量有限,且预测模型中考虑了周模式、日模式、实时模式三个模式,因此第4周的数据既在训练集中使用,又在测试集中使用,在训练集中,第4周的数据作为train Y,在测试集中,第4周的数据作为test X

其中所有自定义参数含义下图所示:

在Pytorch中,Dataset和Dataloder是进行数据载入的部件。必须将数据载入后,再进行深度学习模型的训练。在pytorch的一些案例教学中,常使用torch.torchvision.datasets自带的MNIST、CIFAR-10等数据集,一般流程如下图所示:

 但是,在本例的模型训练中,需要使用非官方自制的数据集。这时可以通过改写 torch.utils.data.Dataset 中的 __getitem__ 和 __len__ 来载入我们自己的数据集。创建完 Dataset 类之后,与 dataloader 一起使用,可在训练模型时不断为模型提供数据

基于父类Dataset创建子类时,其所有的子类必须重写 __getitem__() 方法和 __len__() 方法:

其中__getitem__()函数的作用是根据索引index遍历数据

__len__()函数的作用是返回数据集的长度(即个数)

在创建的dataset类中可根据自己的需求对数据进行处理

可编写独立的数据处理函数,在__getitem__()函数中进行调用;或者直接将数据处理方法写在__getitem__()函数中或者__init__()函数中,但__getitem__()必须根据index返回响应的值,该值会通过index传到dataloader中进行后续的batch批处理

数据使用min-max scaler归一化后进行训练,然后再反归一化至原始维度进行测试

四、模型构建

模型构建模块,主要提供了两个文件,一个为GCN层文件,一个为本例中构建的模型

GCN层H^l+1=f(H^l, A)=σ(D ̂^−1/2A ̂D ̂^−1/2H^lW^l+b^l)中,D ̂^−1/2A ̂D ̂^−1/2为固定值,始终保持不变,可利用utils文件中的 get_normalized_adj 函数将其事先算出。本章提供的GCN层输入为特征矩阵H^l,以及处理过后的邻接矩阵D ̂^−1/2A ̂D ̂^−1/2,分别对应其中的x和adj

此外,初始化GCN层时,需要确定每个节点的输入特征个数in_features以及输出特征个数out_features

在本案例中,A代表邻接矩阵,维度为276*276,D ̂^−1/2A ̂D ̂^−1/2为归一化后的邻接矩阵,其形状不变,仍然为276*276,也即GCN的输入之一adj。x代表着训练集train X,本案例中其维度为 batchsize*276*30。in_features 代表时间步,即为输入的10个时间步,输出特征个数 out_features 可作为参数进行调节,本案例设置为10。整个GCN层如下所示

构建的短时客流预测模型为GCN层和普通卷积层的叠加,其中,周模式、日模式、实时模式三个模式下的进站客流分别经过GCN层处理,然后进行特征叠加后,使用CNN再次提取时空特征,随后使用全连接层进行降为输出结果。该模型输入的形状为batchsize*273*30,输出的形状为batchsize*276*1

五、模型终止以及评价

模型终止部分采用early stopping技术,该部分主要有两个作用:

借助验证集损失,来保存截止当前的最优模型 当模型训练到一定标准后终止模型训练

实例化该 EarlyStoping 类时,会自动调用__call__函数,其输入为验证集的损失 val_loss ,模型的参数字典 model_dict ,模型类model,当前的迭代次数epoch,以及模型的保存路径 save_path

关于模型评价,本案例主要使用了均方根误差RMSE,皮尔逊相关系数R2,平均绝对误差MAE,加权平均绝对百分比误差WMAPE四个指标

本案例提供了分别针对一维数据和二维数据的评估函数,即真实值和预测值均为一维数据,或真实值和预测值均为二维数据。函数输入即为numpy.array形式的真实值和预测值,输出值为相应的评价指标

六、模型训练以及测试

由于训练过程中,借助earlystopping技术可能会保存多个模型,为方便测试,本案例将训练验证部分写在了主函数里,将测试部分重新写了一个函数

对每一个epoch,先进行训练,再进行验证,过程中借助SummaryWriter保存训练损失和验证损失,可借助tensorboard进行可视化。每一次验证结束后,借助earlystopping判断是否保存当前模型以及是否终止模型训练。保存的模型的判定标准是只要验证集损失有所下降,便保存当前模型,终止模型训练的判断标准是当验证集损失超过100次不再下降时,便终止训练过程,鉴于此,模型的epoch可尽量设置大一些,可避免模型过早地终止训练

模型测试部分代码稍有不同,但和训练测试过程中代码大体一致。测试过程首先需要利用torch.load函数将保存的模型重新导入进来,然后利用model.load_state_dict将保存的参数字典加载到模型中,此时模型中的参数即为训练过程中训练好的参数

测试时,需要将预测结果反归一化至原始数据量级进行测试

七、模型训练以及结果展示

模型展示:

模型训练过程展示:

 

真实值和预测值对比:

可见模型拟合的效果十分准确,尤其是在往常一些模型对于极大值和极小值的拟合效果较差的情况下,这个模型对于极大值和极小值的拟合也非常的精确 

 
 八、代码

最后 部分代码如下 需要全部代码和数据集请点赞关注收藏后评论区留言私信~~~

main.py 

import numpy as np
import os, time, torch
from torch import nn
from torch.utils.tensorboard import SummaryWriter
from utils.utils import GetLaplacian
from model.main_model import Model
from utils.earlystopping import EarlyStopping
from data.get_dataloader import get_inflow_dataloader, get_outflow_dataloader
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")

print(device)

epoch_num = 1000
lr = 0.001
time_interval = 15
time_lag = 10
tg_in_one_day = 72
forecast_day_number = 5
pre_len = 1
batch_size = 32
station_num = 276
model_type = 'ours'
TIMESTAMP = str(time.strftime("%Y_%m_%d_%H_%M_%S"))
save_dir = './save_model/' + model_type + '_' + TIMESTAMP
if not os.path.exists(save_dir):
	os.makedirs(save_dir)

inflow_data_loader_train, inflow_data_loader_val, inflow_data_loader_test, max_inflow, min_inflow = \
	get_inflow_dataloader(time_interval=time_interval, time_lag=time_lag, tg_in_one_day=tg_in_one_day, forecast_day_number=forecast_day_number, pre_len=pre_len, batch_size=batch_size)
outflow_data_loader_train, outflow_data_loader_val, outflow_data_loader_test, max_outflow, min_outflow = \
	get_outflow_dataloader(time_interval=time_interval, time_lag=time_lag, tg_in_one_day=tg_in_one_day, forecast_day_number=forecast_day_number, pre_len=pre_len, batch_size=batch_size)

# get normalized adj
adjacency = np.loadtxt('./data/adjacency.csv', delimiter=",")
adjacency = torch.tensor(GetLaplacian(adjacency).get_normalized_adj(station_num)).type(torch.float32).to(device)

global_start_time = time.time()
writer = SummaryWriter()


# 用于初始化卷积层的参数,可提升模型训练效果
def weights_init(m):
	classname = m.__class__.__name__
	if classname.find('Conv2d') != -1:
		nn.init.xavier_normal_(m.weight.data)
		nn.init.constant_(m.bias.data, 0.0)
	if classname.find('ConvTranspose2d') != -1:
		nn.init.xavier_normal_(m.weight.data)
		nn.init.constant_(m.bias.data, 0.0)


model = Model(time_lag, pre_len, station_num, device)
print(model)
model.apply(weights_init)
if torch.cuda.is_available():
	model.cuda()

model = model.to(device)
optimizer = torch.optim.Adam(model.parameters(), lr=lr)
mse = torch.nn.MSELoss().to(device)

temp_time = time.time()
early_stopping = EarlyStopping(patience=100, verbose=True)
for epoch in range(0, epoch_num):
	# model train
	train_loss = 0
	model.train()
	for inflow_tr, outflow_tr in zip(enumerate(inflow_data_loader_train), enumerate(outflow_data_loader_train)):
		i_batch, (train_inflow_X, train_inflow_Y) = inflow_tr
		i_batch, (train_outflow_X, train_outflow_Y) = outflow_tr
		train_inflow_X, train_inflow_Y = train_inflow_X.type(torch.float32).to(device), train_inflow_Y.type(torch.float32).to(device)
		train_outflow_X, train_outflow_Y = train_outflow_X.type(torch.float32).to(device), train_outflow_Y.type(torch.float32).to(device)
		target = model(train_inflow_X, train_outflow_X, adjacency)
		loss = mse(input=train_inflow_Y, target=target)
		train_loss += loss.item()
		optimizer.zero_grad()
		loss.backward()
		optimizer.step()

	with torch.no_grad():
		# model validation
		model.eval()
		val_loss = 0
		for inflow_val, outflow_val in zip(enumerate(inflow_data_loader_val), enumerate(outflow_data_loader_val)):
			i_batch, (val_inflow_X, val_inflow_Y) = inflow_tr
			i_batch, (val_outflow_X, val_outflow_Y) = outflow_tr
			val_inflow_X, val_inflow_Y = val_inflow_X.type(torch.float32).to(device), val_inflow_Y.type(torch.float32).to(device)
			val_outflow_X, val_outflow_Y = val_outflow_X.type(torch.float32).to(device), val_outflow_Y.type(torch.float32).to(device)
			target = model(val_inflow_X, val_outflow_X, adjacency)
			loss = mse(input=val_inflow_Y, target=target)
			val_loss += loss.item()

	avg_train_loss = train_loss/len(inflow_data_loader_train)
	avg_val_loss = val_loss/len(inflow_data_loader_val)
	writer.add_scalar("loss_train", avg_train_loss, epoch)
	writer.add_scalar("loss_eval", avg_val_loss, epoch)
	print('epoch:', epoch, 'train Loss', avg_train_loss, 'val Loss:', avg_val_loss)

	if epoch > 0:
		# early stopping
		model_dict = model.state_dict()
		early_stopping(avg_val_loss, model_dict, model, epoch, save_dir)
		if early_stopping.early_stop:
			print("Early Stopping")
			break
	# 每10个epoch打印一次训练时间
	if epoch % 10 == 0:
		print("time for 10 epoches:", round(time.time() - temp_time, 2))
		temp_time = time.time()
global_end_time = time.time() - global_start_time
print("global end time:", global_end_time)

Train_time_ALL = []

Train_time_ALL.append(global_end_time)
np.savetxt('result/lr_' + str(lr) + '_batch_size_' + str(batch_size) + '_Train_time_ALL.txt', Train_time_ALL)
print("end")

main_predict.py

import numpy as np
import os, time, torch
from torch import nn
from torch.utils.tensorboard import SummaryWriter
from utils.utils import GetLaplacian
from model.main_model import Model
import matplotlib.pyplot as plt
from utils.metrics import Metrics, Metrics_1d
from data.get_dataloader import get_inflow_dataloader, get_outflow_dataloader

device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
print(device)

epoch_num = 1000
lr = 0.001
time_interval = 15
time_lag = 10
tg_in_one_day = 72
forecast_day_number = 5
pre_len = 1
batch_size = 32
station_num = 276
model_type = 'ours'
TIMESTAMP = str(time.strftime("%Y_%m_%d_%H_%M_%S"))
save_dir = './save_model/' + model_type + '_' + TIMESTAMP
if not os.path.exists(save_dir):
	os.makedirs(save_dir)

inflow_data_loader_train, inflow_data_loader_val, inflow_data_loader_test, max_inflow, min_inflow = \
	get_inflow_dataloader(time_interval=time_interval, time_lag=time_lag, tg_in_one_day=tg_in_one_day, forecast_day_number=forecast_day_number, pre_len=pre_len, batch_size=batch_size)
outflow_data_loader_train, outflow_data_loader_val, outflow_data_loader_test, max_outflow, min_outflow = \
	get_outflow_dataloader(time_interval=time_interval, time_lag=time_lag, tg_in_one_day=tg_in_one_day, forecast_day_number=forecast_day_number, pre_len=pre_len, batch_size=batch_size)

# get normalized adj
adjacency = np.loadtxt('./data/adjacency.csv', delimiter=",")
adjacency = torch.tensor(GetLaplacian(adjacency).get_normalized_adj(station_num)).type(torch.float32).to(device)

global_start_time = time.time()
writer = SummaryWriter()

model = Model(time_lag, pre_len, station_num, device)

if torch.cuda.is_available():
	model.cuda()

model = model.to(device)
optimizer = torch.optim.Adam(model.parameters(), lr=lr)
mse = torch.nn.MSELoss().to(device)

path = 'D:/subway flow prediction_for book/save_model/1_ours2021_04_12_14_34_43/model_dict_checkpoint_29_0.00002704.pth'
checkpoint = torch.load(path)
model.load_state_dict(checkpoint, strict=True)
optimizer = torch.optim.Adam(model.parameters(), lr=lr)

# test
result = []
result_original = []
if not os.path.exists('result/prediction'):
	os.makedirs('result/prediction/')
if not os.path.exists('result/original'):
	os.makedirs('result/original')
with torch.no_grad():
	model.eval()
	test_loss = 0
	for inflow_te, outflow_te in zip(enumerate(inflow_data_loader_test), enumerate(outflow_data_loader_test)):
		i_batch, (test_inflow_X, test_inflow_Y, test_inflow_Y_original) = inflow_te
		i_batch, (test_outflow_X, test_outflow_Y, test_outflow_Y_original) = outflow_te
		test_inflow_X, test_inflow_Y = test_inflow_X.type(torch.float32).to(device), test_inflow_Y.type(torch.float32).to(device)
		test_outflow_X, test_outflow_Y = test_outflow_X.type(torch.float32).to(device), test_outflow_Y.type(torch.float32).to(device)

		target = model(test_inflow_X, test_outflow_X, adjacency)

		loss = mse(input=test_inflow_Y, target=target)
		test_loss += loss.item()

		# evaluate on original scale
		# 获取result (batch, 276, pre_len)
		clone_prediction = target.cpu().detach().numpy().copy() * max_inflow  # clone(): Copy the tensor and allocate the new memory
		# print(clone_prediction.shape)  # (16, 276, 1)
		for i in range(clone_prediction.shape[0]):
			result.append(clone_prediction[i])

		# 获取result_original
		test_inflow_Y_original = test_inflow_Y_original.cpu().detach().numpy()
		# print(test_OD_Y_original.shape)  # (16, 276, 1)
		for i in range(test_inflow_Y_original.shape[0]):
			result_original.append(test_inflow_Y_original[i])

	print(np.array(result).shape, np.array(result_original).shape)  # (num, 276, 1)
	# 取整&非负取0
	result = np.array(result).astype(np.int)
	result[result < 0] = 0
	result_original = np.array(result_original).astype(np.int)
	result_original[result_original < 0] = 0
	# # 保存为一个npy文件
	# np.save("result/prediction/result.npy", np.array(result))
	# np.save("result/original/result_original.npy", np.array(result_original))
	# # 每一个时间步保存为一个OD矩阵
	# for i in range(np.array(result).shape[0]):
	# 	np.savetxt("result/prediction/" + str(i) + ".csv", result[i], delimiter=",")
	# 	np.savetxt("result/original/" + str(i) + "_original.csv", result_original[i], delimiter=",")
	#
	# # 取出多个车站进行画图   # (num, 276, 1)   # (num, 276, 2)  # (num, 276, 3)
	x = [[], [], [], [], []]
	y = [[], [], [], [], []]
	for i in range(result.shape[0]):
		x[0].append(result[i][4][0])
		y[0].append(result_original[i][4][0])
		x[1].append(result[i][18][0])
		y[1].append(result_original[i][18][0])
		x[2].append(result[i][30][0])
		y[2].append(result_original[i][30][0])
		x[3].append(result[i][60][0])
		y[3].append(result_original[i][60][0])
		x[4].append(result[i][94][0])
		y[4].append(result_original[i][94][0])
	result = np.array(result).reshape(station_num, -1)
	result_original = result_original.reshape(station_num, -1)

	RMSE, R2, MAE, WMAPE = Metrics(result_original, result).evaluate_performance()

	avg_test_loss = test_loss / len(inflow_data_loader_test)
	print('test Loss:', avg_test_loss)

	RMSE_y0, R2_y0, MAE_y0, WMAPE_y0 = Metrics_1d(y[0], x[0]).evaluate_performance()
	RMSE_y1, R2_y1, MAE_y1, WMAPE_y1 = Metrics_1d(y[1], x[1]).evaluate_performance()
	RMSE_y2, R2_y2, MAE_y2, WMAPE_y2 = Metrics_1d(y[2], x[2]).evaluate_performance()
	RMSE_y3, R2_y3, MAE_y3, WMAPE_y3 = Metrics_1d(y[3], x[3]).evaluate_performance()
	RMSE_y4, R2_y4, MAE_y4, WMAPE_y4 = Metrics_1d(y[4], x[4]).evaluate_performance()

# L3, = plt.plot(x[0], color="r")
# L4, = plt.plot(y[0], color="b")
# plt.legend([L3, L4], ["L3-prediction", "L4-true"], loc='best')
# plt.show()

ALL = [RMSE, MAE, WMAPE]
y0_ALL = [RMSE_y0, MAE_y0, WMAPE_y0]
y1_ALL = [RMSE_y1, MAE_y1, WMAPE_y1]
y2_ALL = [RMSE_y2, MAE_y2, WMAPE_y2]
y3_ALL = [RMSE_y3, MAE_y3, WMAPE_y3]
y4_ALL = [RMSE_y4, MAE_y4, WMAPE_y4]

np.savetxt('result/lr_' + str(lr) + '_batch_size_' + str(batch_size) + '_ALL.txt', ALL)
np.savetxt('result/lr_' + str(lr) + '_batch_size_' + str(batch_size) + '_y0_ALL.txt', y0_ALL)
np.savetxt('result/lr_' + str(lr) + '_batch_size_' + str(batch_size) + '_y1_ALL.txt', y1_ALL)
np.savetxt('result/lr_' + str(lr) + '_batch_size_' + str(batch_size) + '_y2_ALL.txt', y2_ALL)
np.savetxt('result/lr_' + str(lr) + '_batch_size_' + str(batch_size) + '_y3_ALL.txt', y3_ALL)
np.savetxt('result/lr_' + str(lr) + '_batch_size_' + str(batch_size) + '_y4_ALL.txt', y4_ALL)
np.savetxt('result/X_original.txt', x)
np.savetxt('result/Y_prediction.txt', y)

print("ALL:", ALL)
print("y0_ALL:", y0_ALL)
print("y1_ALL:", y1_ALL)
print("y2_ALL:", y2_ALL)
print("y3_ALL:", y3_ALL)
print("y4_ALL:", y4_ALL)

print("end")

x = x[0]
y = y[0]
L1, = plt.plot(x, color="r")
L2, = plt.plot(y, color="y")
plt.legend([L1, L2], ["pre", "actual"], loc='best')
plt.show()

创作不易 觉得有帮助请点赞关注收藏~~~

猜你喜欢

转载自blog.csdn.net/jiebaoshayebuhui/article/details/130454177