def run_demo(best_path, record_save_path): print("============Begin Testing============") test_record_path = f'{record_save_path}/stgat_test_record.csv' dataloader = util.load_dataset(device, args.data_path, args.batch_size, args.batch_size, args.batch_size) g_temp = util.add_nodes_edges(adj_filename=args.adj_path, num_of_vertices=args.num_nodes) scaler = dataloader['scaler'] run_gconv = 1 lr_decay_rate = 0.97 model = stgat(g=g_temp, run_gconv=run_gconv) model.to(device) model.zero_grad() optimizer = torch.optim.Adam(model.parameters(), lr=1e-3) optimizer.zero_grad() scheduler = torch.optim.lr_scheduler.LambdaLR( optimizer, lr_lambda=lambda epoch: lr_decay_rate ** epoch) if torch.cuda.is_available(): model.load_state_dict(torch.load(best_path)) else: model.load_state_dict(torch.load(best_path, map_location='cpu')) outputs = [] target = torch.Tensor(dataloader['y_test']).to(device) target = target[:, :, :, 0] print("201 y_test:", target.shape) for iter, (x, y) in enumerate(dataloader['test_loader'].get_iterator()): testx = torch.Tensor(x).to(device).transpose(1, 3) testx = nn.functional.pad(testx, (1, 0, 0, 0)) with torch.no_grad(): pred = model.forward(testx).squeeze(3) print("iter: ", iter) print("pred: ", pred.shape) outputs.append(pred) yhat = torch.cat(outputs, dim=0) yhat = yhat[:target.size(0), ...] test_record, amape, armse, amae = [], [], [], [] pred = scaler.inverse_transform(yhat) for i in range(12): pred_t = pred[:, i, :] real_target = target[:, i, :] evaluation = evaluate_all(pred_t, real_target) log = 'test for horizon {:d}, Test MAPE: {:.4f}, Test RMSE: {:.4f}, Test MAE: {:.4f}' print(log.format(i + 1, evaluation[0], evaluation[1], evaluation[2])) amape.append(evaluation[0]) armse.append(evaluation[1]) amae.append(evaluation[2]) test_record.append([x for x in evaluation]) test_record_df = pd.DataFrame(test_record, columns=['mape', 'rmse', 'mae']).rename_axis('t') test_record_df.round(3).to_csv(test_record_path) log = 'On average over 12 horizons, Test MAE: {:.4f}, Test MAPE: {:.4f}, Test RMSE: {:.4f}' print(log.format(np.mean(amae), np.mean(amape), np.mean(armse))) print("=" * 10)
def run_demo(best_path, record_save_path, model_type): print("============Begin Testing============") test_record_path = f'{record_save_path}/test_record.csv' dataloader = util.load_dataset(device, args.data_path, args.batch_size, args.batch_size, args.batch_size) g_temp = util.add_nodes_edges(adj_filename=args.adj_path, num_of_vertices=args.num_nodes) scaler = dataloader['scaler'] run_gconv = 1 lr_decay_rate = 0.97 sensor_ids, sensor_id_to_ind, adj_mx = util.load_adj( args.adj_path_forbase, args.adjtype) supports = [torch.tensor(i).to(device) for i in adj_mx] _, _, A = util.load_pickle(args.adj_path_forbase) A_wave = util.get_normalized_adj(A) A_wave = torch.from_numpy(A_wave).to(device) # print("A_wave:", A_wave.shape, type(A_wave)) best_mae = 100 if args.randomadj: adjinit = None else: adjinit = supports[0] if args.aptonly: supports = None if model_type == "GWaveNet": print("=========Model:GWaveNet=========") print("with scaler") model = GWNET(device, args.num_nodes, args.dropout, supports=supports, gcn_bool=args.gcn_bool, addaptadj=args.addaptadj, aptinit=adjinit, in_dim=args.in_dim, out_dim=args.seq_length, residual_channels=args.nhid, dilation_channels=args.nhid, skip_channels=args.nhid * 8, end_channels=args.nhid * 16) if model_type == "STGCN": print("=========Model:STGCN=========") print("with scaler") model = STGCN(A_wave.shape[0], 2, num_timesteps_input=12, num_timesteps_output=12) if model_type == "LSTM": print("=========Model:LSTM=========") input_dim = 2 hidden_dim = 2 output_dim = 2 model = LSTM(input_dim, hidden_dim, output_dim) model.to(device) model.zero_grad() optimizer = torch.optim.Adam(model.parameters(), lr=1e-3) optimizer.zero_grad() scheduler = torch.optim.lr_scheduler.LambdaLR( optimizer, lr_lambda=lambda epoch: lr_decay_rate**epoch) if torch.cuda.is_available(): model.load_state_dict(torch.load(best_path)) else: model.load_state_dict(torch.load(best_path, map_location='cpu')) outputs = [] target = torch.Tensor(dataloader['y_test']).to(device) target = target[:, :, :, 0] print("201 y_test:", target.shape) for iter, (x, y) in enumerate(dataloader['test_loader'].get_iterator()): testx = torch.Tensor(x).to(device).transpose(1, 3) testx = nn.functional.pad(testx, (1, 0, 0, 0)) with torch.no_grad(): pred = model.forward(testx).squeeze(3) print("iter: ", iter) print("pred: ", pred.shape) outputs.append(pred) yhat = torch.cat(outputs, dim=0) yhat = yhat[:target.size(0), ...] test_record, amape, armse, amae = [], [], [], [] pred = scaler.inverse_transform(yhat) for i in range(12): pred_t = pred[:, i, :] real_target = target[:, i, :] evaluation = evaluate_all(pred_t, real_target) log = 'test for horizon {:d}, Test MAPE: {:.4f}, Test RMSE: {:.4f}, Test MAE: {:.4f}' print(log.format(i + 1, evaluation[0], evaluation[1], evaluation[2])) amape.append(evaluation[0]) armse.append(evaluation[1]) amae.append(evaluation[2]) test_record.append([x for x in evaluation]) test_record_df = pd.DataFrame(test_record, columns=['mape', 'rmse', 'mae']).rename_axis('t') test_record_df.round(3).to_csv(test_record_path) log = 'On average over 12 horizons, Test MAE: {:.4f}, Test MAPE: {:.4f}, Test RMSE: {:.4f}' print(log.format(np.mean(amae), np.mean(amape), np.mean(armse))) print("=" * 10)
def main(): print("*" * 10) print(args) print("*" * 10) dataloader = util.load_dataset(device, args.data_path, args.batch_size, args.batch_size, args.batch_size) g_temp = util.add_nodes_edges(adj_filename=args.adj_path, num_of_vertices=args.num_nodes) scaler = dataloader['scaler'] test_scaler = dataloader['test_scaler'] clip = 3 run_gconv = 1 best_mae = 100 continue_train = 0 lr_decay_rate = 0.97 record = [] model = stgat(g=g_temp, run_gconv=run_gconv) model.to(device) model.zero_grad() optimizer = torch.optim.Adam(model.parameters(), lr=1e-3) optimizer.zero_grad() scheduler = torch.optim.lr_scheduler.LambdaLR( optimizer, lr_lambda=lambda epoch: lr_decay_rate**epoch) loss = util.masked_mae best_path = os.path.join(args.save, 'best_model.pkl') # / in path ???? # if you want to train model with the last parameters if continue_train: path = './experiment/last_record.pkl' print("reload the model from :{}", path) model.load_state_dict(torch.load(path)) print("============Begin Training============") his_loss, val_time, train_time = [], [], [] for epoch in range(args.num_epochs): print('-' * 10) print('Epoch {}/{}'.format(epoch, args.num_epochs - 1)) train_loss, train_mape, train_rmse = [], [], [] t1 = time.time() t = time.time() dataloader['train_loader'].shuffle() for iter, (x, y) in enumerate(dataloader['train_loader'].get_iterator()): trainx = torch.Tensor(x).to(device).transpose( 1, 3) # x: (64, 2, 207, 12) trainy = torch.Tensor(y).to(device) # (64, 12, 207, 2) trainy = trainy[:, :, :, 0] # only predict speed/ you can replace it with any features you want if trainx.shape[0] != args.batch_size: continue # print("117:", trainx.shape) trainx = nn.functional.pad(trainx, (1, 0, 0, 0)) # ([64, 2, 207, 13]) # print("119:", trainx.shape) pred = model.forward(trainx).squeeze(3) pred = scaler.inverse_transform(pred) # pred = test_scaler.inverse_transform(pred) if iter == 0: print("trainy:", trainy.shape) # ([64, 12, 207]) print("pred:", pred.shape) # loss_train = loss_MSE(pred, trainy) mae_loss_train = loss(pred, trainy, 0.0) optimizer.zero_grad() mae_loss_train.backward() if clip is not None: torch.nn.utils.clip_grad_norm_(model.parameters(), clip) optimizer.step() evaluation = evaluate(pred, trainy) train_loss.append(mae_loss_train.item()) train_mape.append(evaluation[0]) train_rmse.append(evaluation[1]) if iter % args.interval == 0: log = 'Iter: {:03d}|Train Loss: {:.4f}|Time: {:.4f}' print(log.format(iter, train_loss[-1], time.time() - t), flush=True) t = time.time() scheduler.step() t2 = time.time() train_time.append(t2 - t1) # validation valid_loss, valid_mape, valid_rmse = [], [], [] s1 = time.time() for iter, (x_val, y_val) in enumerate( dataloader['val_loader'].get_iterator()): inputs_val = torch.Tensor(x_val).to(device).transpose( 1, 3) # x: (64, 24, 207, 2) labels_val = torch.Tensor(y_val).to(device) labels_val = labels_val[:, :, :, 0] inputs_val = nn.functional.pad(inputs_val, (1, 0, 0, 0)) pred_val = model.forward(inputs_val).squeeze(3) pred_val = scaler.inverse_transform(pred_val) # pred_val = test_scaler.inverse_transform(pred_val) mae_loss_val = loss(pred_val, labels_val, 0.0) optimizer.zero_grad() mae_loss_val.backward() evaluation = evaluate(pred_val, labels_val) valid_loss.append(mae_loss_val.item()) valid_mape.append(evaluation[0]) valid_rmse.append(evaluation[1]) s2 = time.time() # log = 'Epoch: {:03d}, Inference Time: {:.4f} secs' # print(log.format(epoch, (s2 - s1))) val_time.append(s2 - s1) mtrain_loss = np.mean(train_loss) mtrain_mape = np.mean(train_mape) mtrain_rmse = np.mean(train_rmse) mvalid_loss = np.mean(valid_loss) mvalid_mape = np.mean(valid_mape) mvalid_rmse = np.mean(valid_rmse) his_loss.append(mvalid_loss) # save best model parameters, evaluation of every epochs message = dict(train_loss=mtrain_loss, train_mape=mtrain_mape, train_rmse=mtrain_rmse, valid_loss=mvalid_loss, valid_mape=mvalid_mape, valid_rmse=mvalid_rmse) message = pd.Series(message) record.append(message) record_df = pd.DataFrame(record) record_df.round(3).to_csv(f'{args.save}/record.csv') if message.valid_loss < best_mae: torch.save(model.state_dict(), best_path) best_mae = message.valid_loss epochs_since_best_mae = 0 best_epoch = epoch else: epochs_since_best_mae += 1 log = 'Epoch: {:03d}, Training Time: {:.4f}/epoch,\n' \ 'Train Loss: {:.4f} \n' \ 'Valid Loss: {:.4f}, Valid MAPE: {:.4f}, Valid RMSE: {:.4f}' \ 'best epoch: {} , best val_loss: {}, epochs since best: {}' print(log.format(epoch, (t2 - t1), mtrain_loss, mvalid_loss, mvalid_mape, mvalid_rmse, best_epoch, record_df.valid_loss.min().round(3), epochs_since_best_mae), flush=True) print("#" * 20) # finished train print("=" * 10) print("Average Train Time: {:.4f} secs/epoch".format(np.mean(train_time))) print("Average Valid Time: {:.4f} secs".format(np.mean(val_time))) print("=" * 10) # Testing bestid = np.argmin(his_loss) print("bestid: ", bestid) model.load_state_dict(torch.load(best_path)) outputs = [] target = torch.Tensor(dataloader['y_test']).to(device) target = target[:, :, :, 0] for iter, (x, y) in enumerate(dataloader['test_loader'].get_iterator()): testx = torch.Tensor(x).to(device).transpose(1, 3) testx = nn.functional.pad(testx, (1, 0, 0, 0)) with torch.no_grad(): pred = model.forward(testx).squeeze(3) outputs.append(pred) yhat = torch.cat(outputs, dim=0) yhat = yhat[:target.size(0), ...] test_record, amape, armse, amae = [], [], [], [] pred = scaler.inverse_transform(yhat) for i in range(12): pred_t = pred[:, i, :] real_target = target[:, i, :] evaluation = evaluate_all(pred_t, real_target) log = 'test for horizon {:d}, Test MAPE: {:.4f}, Test RMSE: {:.4f}, Test MAE: {:.4f}' print(log.format(i + 1, evaluation[0], evaluation[1], evaluation[2])) amape.append(evaluation[0]) armse.append(evaluation[1]) amae.append(evaluation[2]) test_record.append([x for x in evaluation]) test_record_df = pd.DataFrame(test_record, columns=['mape', 'rmse', 'mae']).rename_axis('t') test_record_df.round(3).to_csv(f'{args.save}/test_record.csv') log = 'On average over 12 horizons, Test MAE: {:.4f}, Test MAPE: {:.4f}, Test RMSE: {:.4f}' print(log.format(np.mean(amae), np.mean(amape), np.mean(armse))) print("=" * 10)
def main(): print("*" * 10) print(args) print("*" * 10) dataloader = util.load_dataset(device, args.data_path, args.batch_size, args.batch_size, args.batch_size) scaler = dataloader['scaler'] test_scaler = dataloader['test_scaler'] g_temp = util.add_nodes_edges(adj_filename=args.adj_path, num_of_vertices=args.num_nodes) record = [] clip = 3 best_mae = 100 lr_decay_rate = 0.97 run_gconv = 0 loss = util.masked_mae model = batch_g_gat(g_temp, run_gconv) print("run_gconv:", run_gconv) model.to(device) model.zero_grad() optimizer = torch.optim.Adam(model.parameters(), lr=1e-3) optimizer.zero_grad() scheduler = torch.optim.lr_scheduler.LambdaLR( optimizer, lr_lambda=lambda epoch: lr_decay_rate**epoch) bar = progress_bar(list(range(1, args.num_epochs + 1))) best_path = os.path.join(args.save, 'best_model.pth') his_loss, val_time, train_time = [], [], [] print("============Begin Training============") for epoch in bar: # print('-' * 10) # print('Epoch {}/{}'.format(epoch, args.num_epochs - 1)) train_loss, train_mape, train_rmse = [], [], [] dataloader['train_loader'].shuffle() for iter, (x, y) in enumerate(dataloader['train_loader'].get_iterator()): trainx = torch.Tensor(x).to(device).transpose( 1, 3) # x: (64, 2, 207, 12) trainy = torch.Tensor(y).to(device) # (64, 12, 207, 2) trainy = trainy[:, :, :, 0] if trainx.shape[0] != args.batch_size: continue trainx = nn.functional.pad(trainx, (1, 0, 0, 0)) pred = model.forward(trainx).squeeze(3) pred = scaler.inverse_transform(pred) # pred = test_scaler.inverse_transform(pred) # loss_train = loss_MSE(pred, trainy) mae_loss_train = loss(pred, trainy, 0.0) optimizer.zero_grad() mae_loss_train.backward() if clip is not None: torch.nn.utils.clip_grad_norm_(model.parameters(), clip) optimizer.step() evaluation = evaluate(pred, trainy) train_loss.append(mae_loss_train.item()) train_mape.append(evaluation[0]) train_rmse.append(evaluation[1]) scheduler.step() # validation valid_loss, valid_mape, valid_rmse = [], [], [] for iter, (x_val, y_val) in enumerate( dataloader['val_loader'].get_iterator()): inputs_val = torch.Tensor(x_val).to(device).transpose( 1, 3) # x: (64, 24, 207, 2) labels_val = torch.Tensor(y_val).to(device) labels_val = labels_val[:, :, :, 0] inputs_val = nn.functional.pad(inputs_val, (1, 0, 0, 0)) pred_val = model.forward(inputs_val).squeeze(3) pred_val = scaler.inverse_transform(pred_val) # pred_val = test_scaler.inverse_transform(pred_val) mae_loss_val = loss(pred_val, labels_val, 0.0) optimizer.zero_grad() mae_loss_val.backward() evaluation = evaluate(pred_val, labels_val) valid_loss.append(mae_loss_val.item()) valid_mape.append(evaluation[0]) valid_rmse.append(evaluation[1]) mtrain_loss = np.mean(train_loss) mtrain_mape = np.mean(train_mape) mtrain_rmse = np.mean(train_rmse) mvalid_loss = np.mean(valid_loss) mvalid_mape = np.mean(valid_mape) mvalid_rmse = np.mean(valid_rmse) his_loss.append(mvalid_loss) message = dict(train_loss=mtrain_loss, train_mape=mtrain_mape, train_rmse=mtrain_rmse, valid_loss=mvalid_loss, valid_mape=mvalid_mape, valid_rmse=mvalid_rmse) message = pd.Series(message) record.append(message) # save model parameters if message.valid_loss < best_mae: torch.save(model.state_dict(), best_path) best_mae = message.valid_loss epochs_since_best_mae = 0 best_epoch = epoch else: epochs_since_best_mae += 1 record_df = pd.DataFrame(record) bar.comment = f'best epoch: {best_epoch}, best val_loss: {record_df.valid_loss.min(): .3f}, current val_loss: {message.valid_loss:.3f},current train loss: {message.train_loss: .3f}' record_df.round(3).to_csv(f'{args.save}/record.csv') # Testing bestid = np.argmin(his_loss) # print("bestid: ", bestid) # print("best_epoch: ", best_epoch) # print("best_path: ", best_path) model.load_state_dict(torch.load(best_path)) outputs = [] target = torch.Tensor(dataloader['y_test']).to(device) target = target[:, :, :, 0] for iter, (x, y) in enumerate(dataloader['test_loader'].get_iterator()): testx = torch.Tensor(x).to(device).transpose(1, 3) testx = nn.functional.pad(testx, (1, 0, 0, 0)) with torch.no_grad(): pred = model.forward(testx).squeeze(3) outputs.append(pred) yhat = torch.cat(outputs, dim=0) yhat = yhat[:target.size(0), ...] amape, armse, amae = [], [], [] # test_mape, test_rmse, test_mae = evaluate_all(yhat, target) # print("=" * 10) # print("yhat:", yhat.shape) # yhat: torch.Size([6850, 12, 207]) # print("target:", target.shape) # target: torch.Size([6850, 12, 207]) pred = scaler.inverse_transform(yhat) # pred = test_scaler.inverse_transform(yhat) test_record = [] for i in range(12): pred_t = pred[:, i, :] real_target = target[:, i, :] evaluation = evaluate_all(pred_t, real_target) log = 'test data for {:d}, Test MAPE: {:.4f}, Test RMSE: {:.4f}, Test MAE: {:.4f}' print(log.format(i + 1, evaluation[0], evaluation[1], evaluation[2])) amape.append(evaluation[0]) armse.append(evaluation[1]) amae.append(evaluation[2]) test_record.append([x for x in evaluation]) test_record_df = pd.DataFrame(test_record, columns=['mape', 'rmse', 'mae']).rename_axis('t') test_record_df.round(3).to_csv(f'{args.save}/test_record.csv') log = 'On average over 12 horizons, Test MAE: {:.4f}, Test MAPE: {:.4f}, Test RMSE: {:.4f}' print(log.format(np.mean(amae), np.mean(amape), np.mean(armse)))