Solving time series comes handy in many circumtances including trading digital currencies, estimating next day weather, or estimating number of customer for future. Plethora of approaches, methods and tools are avialbe to achieve this goal. Here we want to solve a very simple problem as a hello world to time series problem. Lets assume that or signal is following sine wave and we want to predict its next value from previous one. I notice that in real world we do not know the pattern of out times series, obviously. However, we contemplate sine wave as our ground truth.

Our project has been written in pytorch and has three files, including main, configs, and util. main contains primary part of codes as orchestrator of whole project. config is some simple number such as learning rates, number of epochs, etc in order to avoid using magic numbers in our codes. Furthermore, it helps to adjust aforementioned number and settings without wasting time to find and search them in whole code. Finally, util is used as repository for some hand function for type convertion or making dataset. now lets jump to the codes and start from configs:

step_x = 0.1

look_back = 15
hope = 2

n_epoch = 1000
n_batch = 32
lr = 0.1

trn_sz = 0.6
vld_sz = 0.1
vld_step = 50

hidden_sz = 20

step_x is used to extend the period sine function in order to have more values for input. look_back indicate the amount of data that we use to predict future. In this case we have used 15 number of values to predict 16th value. hope is amount jump for data acquition. Assume we start data gathering for look_back from index 0 to 14, next data gathering will start from 1 to 15 if hope be equal be to 1. To put in another way, if hope be equal to 2 next data gathering will be from 2 to 16. n_epoch points to number of epochs, n_batch is also number of batch for learning, and eventually lr stands for learning rate which is equal to 0.1.  trn_sz and vld_sz are training size and validation, respectively. In constrast to Keras library, in pytorch program should manually estiblish validation mechanism. Here, we use vld_step as number of epoch to evaluate the training procedure of out netwok. It mean after 50 epoch we evaluate our network which is 1 by default in Keras.

Now, we go to util file to describe its methods:

1 from torch.utils.data import DataLoader, TensorDataset
2 import torch
3 import numpy as np

 As first line of the codes demonstrates, two clesses, DataLoader and TensorDataset have been imported to our codes. In the second and third lines torch and numpy libraries have also added.

06    def slide(seq, look_back, hope):
07        x = []
08        y = []
09   
10        i =
0
11        while i < len(seq) - look_back:
12            x.append(seq[i:i + look_back])
13            y.append([seq[i + look_back]])
14            i += hope
15   
16        x = np.array(x)
17        y = np.array(y)
18   
19       
return x, y

code above, shows implementation of slide function with three input parameters. seq is a list of numbers. look_back denotes number of features or previous will be used for predication and hope is number of jump as we mentioned before. From line 11 to 14, values of seq from i to i + look_back are stored to x and value i + look_back is stored to y. This iteration has been repeated until all possible values of seq are appended to x and y. Both lists x and y are converted to numpy arrays in line 16 and 17 and are returned in line 19.

22    def create_dataloader(x, y, batch_sz, shuffle):
23        tensor_x = torch.Tensor(x)
24        tensor_y = torch.Tensor(y)
25   
26        dataset = TensorDataset(tensor_x
, tensor_y)
27        dataloader = DataLoader(
28            dataset
,
29            batch_size=batch_sz,
30            shuffle=shuffle)
31   
32       
return dataloader

in line 22, function create_dataloader is defined. It has 4 parameters, x, and y which are network samples (input and target), batch size that is abriviated by batch_sz and shuffle. shuffle cause to sequence of samples be randomized. Main goal of this method is conversion of samples to a DataLoader. You can use just torch.Tensor instances for training your network but I saw some samples in other guys code in this way. So I use DataLoader and please do not blame me. in line 23 and 24, x and y are converted to Tensor, followed by conversion to TensorDataset as dataset in line 26. in Line 27, an instance of DataLoader is created and finally is returned in line 32. Now we move to most difficult of our program, function train:

 

 

35    def train(
36            mdl
,
37            train_dataloader,
38            valid_dataloader,
39            n_epoch,
40            opt,
41            loss,
42            valid_step,
43            save_path):
44        min_valid_loss =
float('inf')
45   
46        best_state =
0
47   
48        vld_losses = []
49        trn_losses = []
50   
51       
train_loss = 0.0
52        valid_loss = 0.0
53   
54        for e in range(0, n_epoch):
55            mdl.train()
56            train_loss =
0.0
57            for i, (inp, out) in enumerate(train_dataloader):
58                opt.zero_grad()
59                pred = mdl(inp)
60                ls = loss(pred
, out)
61                ls.backward()
62                opt.step()
63                train_loss += ls.item()
64   
65            trn_losses.append(train_loss)
66   
67           
if e % valid_step != 0 and e != 0:
68                vld_losses.append(valid_loss)
69               
continue
70   
71            mdl.eval()
72            valid_loss =
0.0
73            with torch.no_grad():
74               
for i, (inp, out) in enumerate(valid_dataloader):
75                    pred = mdl(inp)
76                    ls = loss(pred
, out)
77                    valid_loss += ls.item()
78   
79            vld_losses.append(valid_loss)
80   
81           
if valid_loss < min_valid_loss:
82                best_state = mdl.state_dict()
83               
if save_path != '':
84                    p = save_path.format(
85                       
en=n_epoch,
86                        vl=valid_loss,
87                        tl=train_loss)
88                    torch.save(mdl
, p)
89   
90           
print('epoch: ' + str(e + 1))
91            
print('train loss: ' + str(train_loss / len(train_dataloader)))
92           
print('valid loss: ' + str(valid_loss / len(valid_dataloader)))
93           
print('\n')
94   
95       
return trn_losses, vld_losses, best_state

 

function train is prepared to accomplish primarly