classSimpleRNN(nn.Module):def__init__(self,rnn_type,input_size,hidden_size,num_layers):super(SimpleRNN,self).__init__()self.hidden_size=hidden_sizeself.num_layers=num_layersself.rnn=nn.RNN(input_size=input_size,hidden_size=hidden_size,dropout=(0ifnum_layers==1else0.05),num_layers=num_layers,batch_first=True)self.out=nn.Linear(hidden_size,1)# Linear layer is output of modeldefforward(self,x,h_state):# Define our forward pass, we take some input sequence and an initial hidden state.r_out,h_state=self.rnn(x,h_state)final_y=self.out(r_out[:,-1,:])# Return only the last output of RNN.returnfinal_y,h_state
importnumpyasnpimporttorchfromtorch.utils.dataimportDatasetclassRNNDataset(Dataset):def__init__(self,x,y=None):self.data=xself.labels=ydef__len__(self):returnself.data.shape[0]def__getitem__(self,idx):ifself.labelsisnotNone:returnself.data[idx],self.labels[idx]else:returnself.data[idx]defcreate_dataset(sequence_length,train_percent=0.8):# Create sin wave at discrete time steps.num_time_steps=2000time_steps=np.linspace(start=0,stop=1000,num=num_time_steps,dtype=np.float32)discrete_sin_wave=(np.sin(time_steps*2*np.pi/20)).reshape(-1,1)# Take (sequence_length + 1) elements & put as a row in sequence_data, extra element is value we want to predict.# Move one time step and keep grabbing till we reach the end of our sampled sin wave.sequence_data=[]foriinrange(num_time_steps-sequence_length):sequence_data.append(discrete_sin_wave[i:i+sequence_length+1,0])sequence_data=np.array(sequence_data)# Split for train/val.num_total_samples=sequence_data.shape[0]num_train_samples=int(train_percent*num_total_samples)train_set=sequence_data[:num_train_samples,:]test_set=sequence_data[num_train_samples:,:]print('{} total sequence samples, {} used for training'.format(num_total_samples,num_train_samples))# Take off the last element of each row and this will be our target value to predict.x_train=train_set[:,:-1][:,:,np.newaxis]y_train=train_set[:,-1][:,np.newaxis]x_test=test_set[:,:-1][:,:,np.newaxis]y_test=test_set[:,-1][:,np.newaxis]train_data=RNNDataset(x_train,y_train)test_data=RNNDataset(x_test,y_test)torch.save(train_data,'train_data.pt')torch.save(test_data,'test_data.pt')if__name__=='__main__':create_dataset(sequence_length=80)
defpredict(model,device,dataloader,prediction_steps):model.eval()h_state=torch.zeros([model.num_layers,1,model.hidden_size]).to(device)# Adjusted to 3-D with batch size 1initial_input=next(iter(dataloader))[1].to(device)# Grab one initial sequence of data for use in prediction.ifinitial_input.dim()==2:initial_input=initial_input.unsqueeze(0)initial=initial_input.squeeze().cpu().numpy().tolist()predictions=[]for_inrange(prediction_steps):# Predict prediction_steps steps aheadpred,h_state=model(initial_input,h_state)predictions.append(pred.item())initial_input=pred.unsqueeze(0)# Ensure pred has the same dimensions as test_input[:, 1:, :]returninitial,predictions