Here’s the data handling part:
class Data_utility(object):
def __init__(self, dt_x, dt_y, train, valid, cuda, horizon, window, normalize=2, shuffle=True, only_test=False):
self.cuda = cuda
self.P = window
self.h = horizon
self.normalize = normalize
self.shuffle = shuffle
self.only_test = only_test
self.rawdat_x, self.rawdat_y = np.array(dt_x), np.array(dt_y)
self.dat_x = np.zeros(self.rawdat_x.shape)
self.dat_y = np.zeros(self.rawdat_y.shape)
self.df, self.n, self.m = self.dat_x.shape
self.ny, self.my = self.dat_y.shape
if not (self.ny==self.n)&(self.my==self.m): raise ValueError('X AND Y SHAPE DO NOT MATCH.')
self.scale_x = np.ones_like(self.dat_x)
self.scale_y = np.ones_like(self.dat_y)
self._normalized()
self._split(int(train), int(train+valid), self.n)
def _normalized(self):
self.scale_y = np.repeat(np.nanmax(np.abs(self.rawdat_y), axis=1, keepdims=True), self.rawdat_y.shape[1], axis=1)
self.dat_y = np.where(self.scale_y==0., self.rawdat_y, self.rawdat_y/self.scale_y)
if (self.normalize == 0):
self.dat_x = self.rawdat_x
if (self.normalize == 1):
for f in range(self.df):
self.scale_x[f, :, :] = np.nanmax(np.abs(self.rawdat_x[f, :, :]))
self.dat_x = np.where(self.scale_x==0., self.rawdat_x, self.rawdat_x/self.scale_x)
if (self.normalize == 2):
for f in range(self.df):
std_x = np.nanstd(self.rawdat_x[f, :, :])
mean_x = np.nanmean(self.rawdat_x[f, :, :])
if std_x == 0.: self.dat_x[f, :, :] = (self.rawdat_x[f, :, :]-mean_x)
else: self.dat_x[f, :, :] = (self.rawdat_x[f, :, :]-mean_x)/std_x
def _split(self, train, valid, test):
if self.only_test:
test_set = range(valid, self.n)
self.test = self._batchify(test_set)
else:
train_set = range(self.P+self.h-1, train)
valid_set = range(train, valid)
test_set = range(valid, self.n)
self.train = self._batchify(train_set)
self.valid = self._batchify(valid_set)
self.test = self._batchify(test_set)
def _batchify(self, idx_set):
n = len(idx_set)
if n==0:
X = torch.zeros((1,self.df,self.P,self.m))
Y = torch.zeros((1,self.m))
X[0,:,:,:] = torch.from_numpy(self.dat_x[:,-self.P:,:])
return [X, Y]
else:
X = torch.zeros((n,self.df,self.P,self.m))
Y = torch.zeros((n,self.m), dtype=torch.float)
for i in range(n):
end = idx_set[i] - self.h + 1
start = end - self.P
X[i,:,:,:] = torch.from_numpy(self.dat_x[:,start:end,:])
Y[i,:] = torch.from_numpy(self.dat_y[idx_set[i], :])
return [X, Y]
def get_batches(self, inputs, targets, batch_size, shuffle=True):
length = len(inputs)
if shuffle: index = torch.randperm(length)
else: index = torch.LongTensor(range(length))
start_idx = 0
while (start_idx < length):
end_idx = min(length, start_idx + batch_size)
excerpt = index[start_idx:end_idx]
X = inputs[excerpt]
Y = targets[excerpt]
if (self.cuda):
X = X.cuda()
Y = Y.cuda()
yield Variable(X, requires_grad = False), Variable(Y, requires_grad = False)
start_idx += batch_size
Training part:
def train(data, X, Y, model, criterion, batch_size, optim, max_grad_norm):
model.train()
total_loss = 0
n_samples = 0
for X, Y in data.get_batches(X, Y, batch_size, data.shuffle):
model.zero_grad()
output = model(X)
loss = criterion(output, Y)
loss.backward()
nn.utils.clip_grad_norm_(model.parameters(), max_grad_norm)
optim.step()
total_loss += float(loss.data.item())
n_samples += 1
return total_loss/n_samples
Last, the main part:
temp_dat_x = fill_nan(temp_dat_x)
temp_dat_y = fill_nan(temp_dat_y)
if self.pos==0:
'''build data'''
Data = Data_utility(temp_dat_x, temp_dat_y, self.args.train_len, self.args.valid_len, self.args.cuda, self.args.horizon, self.args.window, self.args.normalize, self.args.shuffle)
model = Model(self.args, Data)
model.apply(weights_init)
if self.args.cuda: model.cuda()
criterion = makeLossFunction(self.args.loss)
evaluateL1 = nn.L1Loss(reduction='mean')
evaluateL2 = nn.MSELoss(reduction='mean')
if self.args.cuda:
criterion = criterion.cuda()
evaluateL1 = evaluateL1.cuda()
evaluateL2 = evaluateL2.cuda()
best_val = 1e8
optimizer = makeOptimizer(self.args.optim, self.args.lr, model)
scheduler = makeScheduler(optimizer, self.args.skdlr)
try:
count = 0
for epoch in range(self.args.epochs):
if count >= 10:
if self.model == []: self.model = model
print 'valid loss stays at ', best_val, ' early stopping at epoch ', epoch
break
epoch_start_time = int(round(time.time()*1000))
train_loss = train(Data, Data.train[0], Data.train[1], model, criterion, self.args.batch_size, optimizer, self.args.clip)
val_loss, val_rae, val_rse, val_corr = evaluate(Data, Data.valid[0], Data.valid[1], model, criterion, evaluateL1, evaluateL2, self.args.batch_size)
scheduler.step(val_loss)
'''save the best model'''
if val_loss < best_val:
self.model = model
best_val = val_loss
count = 0
else: count += 1