#/usr/bin/env python3 import argparse import os import pandas as pd import numpy as np from datetime import datetime as dt import pytz from pandas.tseries.holiday import USFederalHolidayCalendar try: import setGPU except ImportError: pass import torch from torch.autograd import Variable, Function import torch.cuda import setproctitle import model_classes, nets, plot import sys from IPython.core import ultratb sys.excepthook = ultratb.FormattedTB(mode='Verbose', color_scheme='Linux', call_pdb=1) def main(): parser = argparse.ArgumentParser( description='Run electricity scheduling task net experiments.') parser.add_argument('--save', type=str, required=True, metavar='save-folder', help='save folder path') parser.add_argument('--nRuns', type=int, default=10, metavar='runs', help='number of runs') args = parser.parse_args() setproctitle.setproctitle('pdonti.' + args.save) X1, Y1 = load_data_with_features('pjm_load_data_2008-11.txt') X2, Y2 = load_data_with_features('pjm_load_data_2012-16.txt') X = np.concatenate((X1, X2), axis=0) Y = np.concatenate((Y1, Y2), axis=0) # Train, test split. n_tt = int(len(X) * 0.8) X_train, Y_train = X[:n_tt], Y[:n_tt] X_test, Y_test = X[n_tt:], Y[n_tt:] # Construct tensors (without intercepts). X_train_ = Variable(torch.Tensor(X_train[:,:-1])).cuda() Y_train_ = Variable(torch.Tensor(Y_train)).cuda() X_test_ = Variable(torch.Tensor(X_test[:,:-1])).cuda() Y_test_ = Variable(torch.Tensor(Y_test)).cuda() variables_rmse = {'X_train_': X_train_, 'Y_train_': Y_train_, 'X_test_': X_test_, 'Y_test_': Y_test_} for run in range(args.nRuns): save_folder = os.path.join(args.save, str(run)) if not os.path.exists(save_folder): os.makedirs(save_folder) # Generation scheduling problem params. params = {"n": 24, "c_ramp": 0.4, "gamma_under": 50, "gamma_over": 0.5} # Run and eval rmse-minimizing net model_rmse = model_classes.Net(X_train[:,:-1], Y_train, [200, 200]) model_rmse.cuda() model_rmse = nets.run_rmse_net( model_rmse, variables_rmse, X_train, Y_train) nets.eval_net("rmse_net", model_rmse, variables_rmse, params, save_folder) # Run and eval task cost-weighted rmse-minimizing net (model defined/updated internally) model_rmse_weighted = nets.run_weighted_rmse_net(X_train, Y_train, X_test, Y_test, params) nets.eval_net("weighted_rmse_net", model_rmse_weighted, variables_rmse, params, save_folder) # Randomly construct hold-out set for task net training. th_frac = 0.8 inds = np.random.permutation(X_train.shape[0]) train_inds = inds[ :int(X_train.shape[0] * th_frac)] hold_inds = inds[int(X_train.shape[0] * th_frac):] X_train2, X_hold2 = X_train[train_inds, :], X_train[hold_inds, :] Y_train2, Y_hold2 = Y_train[train_inds, :], Y_train[hold_inds, :] X_train2_ = Variable(torch.Tensor(X_train2[:,:-1])).cuda() Y_train2_ = Variable(torch.Tensor(Y_train2)).cuda() X_hold2_ = Variable(torch.Tensor(X_hold2[:,:-1])).cuda() Y_hold2_ = Variable(torch.Tensor(Y_hold2)).cuda() variables_task = {'X_train_': X_train2_, 'Y_train_': Y_train2_, 'X_hold_': X_hold2_, 'Y_hold_': Y_hold2_, 'X_test_': X_test_, 'Y_test_': Y_test_} # Run and eval task-minimizing net, building off rmse net results. model_task = model_classes.Net(X_train2[:,:-1], Y_train2, [200, 200]) model_task.cuda() model_task = nets.run_rmse_net( model_task, variables_task, X_train2, Y_train2) model_task = nets.run_task_net( model_task, variables_task, params, X_train2, Y_train2, args) nets.eval_net("task_net", model_task, variables_task, params, save_folder) plot.plot_results(map( lambda x: os.path.join(args.save, str(x)), range(args.nRuns)), args.save) def load_data_with_features(filename): tz = pytz.timezone("America/New_York") df = pd.read_csv(filename, sep=" ", header=None, usecols=[1,2,3], names=["time","load","temp"]) df["time"] = df["time"].apply(dt.fromtimestamp, tz=tz) df["date"] = df["time"].apply(lambda x: x.date()) df["hour"] = df["time"].apply(lambda x: x.hour) df.drop_duplicates("time", inplace=True) # Create one-day tables and interpolate missing entries df_load = df.pivot(index="date", columns="hour", values="load") df_temp = df.pivot(index="date", columns="hour", values="temp") df_load = df_load.transpose().fillna(method="backfill").transpose() df_load = df_load.transpose().fillna(method="ffill").transpose() df_temp = df_temp.transpose().fillna(method="backfill").transpose() df_temp = df_temp.transpose().fillna(method="ffill").transpose() holidays = USFederalHolidayCalendar().holidays( start='2008-01-01', end='2014-12-31').to_pydatetime() holiday_dates = set([h.date() for h in holidays]) s = df_load.reset_index()["date"] data={"weekend": s.apply(lambda x: x.isoweekday() >= 6).values, "holiday": s.apply(lambda x: x in holiday_dates).values, "dst": s.apply(lambda x: tz.localize( dt.combine(x, dt.min.time())).dst().seconds > 0).values, "cos_doy": s.apply(lambda x: np.cos( float(x.timetuple().tm_yday)/365*2*np.pi)).values, "sin_doy": s.apply(lambda x: np.sin( float(x.timetuple().tm_yday)/365*2*np.pi)).values} df_feat = pd.DataFrame(data=data, index=df_load.index) # Construct features and normalize (all but intercept) X = np.hstack([df_load.iloc[:-1].values, # past load df_temp.iloc[:-1].values, # past temp df_temp.iloc[:-1].values**2, # past temp^2 df_temp.iloc[1:].values, # future temp df_temp.iloc[1:].values**2, # future temp^2 df_temp.iloc[1:].values**3, # future temp^3 df_feat.iloc[1:].values, np.ones((len(df_feat)-1, 1))]).astype(np.float64) X[:,:-1] = \ (X[:,:-1] - np.mean(X[:,:-1], axis=0)) / np.std(X[:,:-1], axis=0) Y = df_load.iloc[1:].values return X, Y if __name__=='__main__': main()