[Price forecast] LSTM price forecast model (hog price, multivariate-economic management)

I. Introduction

        This article is based on the LSTM model and is carried by torch. The input in this article is multivariate, and the output result is the price of live pigs. The data structure is shown in the figure below:

        Due to the copyright reasons of the data itself, only part of the data is published.

 2. Input feature selection

       Partners who know the price of pork should know the truth of the pig cycle. The following is my brief introduction:

The price of pork is a barometer of the agricultural product market, and pork is a key food in the people's vegetable basket. The importance of live pigs and grain prices can be seen from the annual No. 1 Central Document. For China, the Chinese eat half of the world's pork. From the "family" in China's five thousand years of "family culture", we can find that there is a pig in the house, which is enough to reflect the important position of pigs in Chinese national life and the cultural color of pigs. In terms of quantity, since 2010, the per capita pork consumption in China has been above 45 kg. In 2019, although affected by the African swine fever epidemic, domestic pork production has increased and decreased significantly , but it still reached 42.55 million tons . As for the fluctuation of pork prices, from the perspective of consumers , rising pork prices will reduce people's living standards, restrain pork consumption and other consumption, and raise prices; from the perspective of producers , since most pig farmers in China They are all free-range farmers in rural areas, and their economic rationality is low. When the price of pork rises, the profit of farmers raising pigs will increase, and they will expand pig breeding, which will lead to an increase in supply. It will cause the price of pork to fall, and the enthusiasm of farmers to raise pigs will decrease, thus reducing the supply of live pigs, and then the price of pork will rise, and farmers will start to raise pork, which will cause periodic fluctuations in pork prices. And this periodic fluctuation is called the pig cycle.

         "Pig cycle" and factors affecting pork prices: The pig cycle is an economic phenomenon in which pork prices fluctuate periodically with the market economy. The specific causes have been stated, and the specific cycle is:

 

        Since the price of pork is highly consistent with the fluctuation of the price of hogs, the price of pork can be represented by the price of hogs. From the above, it is necessary to focus on the influence of the pig cycle in the analysis of the fluctuation of the pig price. The pig cycle is one of the key reasons for fluctuations in pork prices, and pig farming is also highly related to farming costs and market demand, such as the price of pig food, prices of substitutes, and the macroeconomic environment.

> Therefore, when selecting the input variables, the influence of the pig cycle should be fully considered, and it is very important to choose the variable of how many lag periods.

>This paper chooses the selection method of correlation coefficient and mutual information.

 3. Sequence diagram drawing

        The left picture is a time series diagram, and the right picture is an STL decomposition diagram:

 

In the STL decomposition method , the cycle is roughly 6 months for the small cycle and about 4 years for the large cycle. Through the decomposition of the pig price time series, the existence of the pig cycle is directly proved. At the same time, it is not difficult to find that the seasonal effect of pig price fluctuations is also obvious, which is in line with objective cognition .

4. Autocorrelation Analysis

The autocorrelation graph shows that the price of live pigs has a very strong short-term correlation, but in fact there is still a certain correlation when it is extended to about 18 periods. In other words, the short-term correlation is as strong as the long-term correlation. It can be seen from the partial correlation diagram that the price of live pigs also shows a very obvious periodicity and seasonality. A large cycle lasts about 2 years, and there are also many small cycles and seasonal effects during the period. This further supports the existence of the pig cycle. And this fully demonstrates that in the analysis of live pig prices, it is necessary to include the impact of the lagging period of live pig prices. In addition, through the ADF test, the time series is a stationary time series

Five , LSTM model

 LSTM, the full name of Long Short Term Memory (long short-term memory), is a special recurrent neural network. This kind of network is different from the general feed-forward neural network. LSTM can use time series to analyze the input ; The content is completely irrelevant. In order to apply information in the time dimension, people have designed a recurrent neural network RNN . A simple recurrent neural network can be expressed in this way:,

 In the figure, xt is the input information at time t, and ht is the input information at time t. We can see that neuron A will call itself recursively and pass the information at time t-1 to time t.

However, the above-mentioned simple recurrent neural network has flaws, that is, the problem of long-term dependence: the recurrent neural network can only deal with the context we need to be closer to. The LSTM was designed from the beginning to solve the long-standing problems that are common in general RNNs. Using LSTM can effectively convey and express information in long-term sequences without causing useful information long ago to be ignored. In addition, it can also solve the gradient explosion problem in RNN.

 Here, we can see that the output value ht−1 of A at time t−1 is copied to time t, and integrated with the input xt at time t to form an output after passing through a tanh function with weight and bias, and continue to The data is copied to time t+1, and the cycle repeats. But compared with the simple RNN in the above figure, a single LSTM unit has a more complex internal structure and input and output:

The above statement was borrowed from other bloggers on Zhihu and CSDN, and was invaded and deleted.

Therefore, LSTM is very suitable for predictive analysis of time series, and it can also show faster running speed and fitting ability in multi-feature time series forecasting. ,

6. Forecast data

Combined with the autocorrelation analysis of the pig price time series, I think that the period of 12 multi-step inclusions cannot even cover a large pig cycle, and the learning effect must be poor. The final fitting is just as I expected. Therefore, I think it is necessary to make a multi-step forecast of at least 18 periods. In order to reduce the learning of abnormal data from 2019 to the first half of 2021 and reduce the impact of extreme values, I think it is necessary to One more seasonal effect needs to be included, so a multi-step forecast of 21 steps is finally chosen.

 

7. SHAP visualization

1. The main defect of neural network is that it is a kind of black box , and it does not know the weight or coefficient of each variable like decision tree and linear regression. But the SHAP value (Shapley Additive explanations), that is, the Shapley addition and interpretation, is to attribute the output value to the shapely value of each feature. The impact of features on the final output value can be measured by the SHAP value of each feature. Explain in detail that I have little talent and knowledge, and refer to Zhihu code bloggers for explanations.

 2. Visualization of the impact of characteristic values ​​on the predicted value of live pig prices

The above image plots for each sample its SHAP value for each of its features, which allows for a better understanding of the overall pattern and allows spotting of predicted outliers. Each row represents a feature, and the abscissa is the SHAP value. A point represents a sample, and the color represents the feature value (red is high, blue is low).

Eight, part of the code

       Only some of the core steps are listed, please use Jupyter to complete, there is no one-step process. If you need the complete code, please private message.

import torch
from torch import nn,optim
import torch.utils.data as Data
import torch.nn.functional as F
import seaborn as sns
import numpy as np
import pandas as pd
import os ,re ,random
import matplotlib.pylab as plt
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus']=False
import sklearn.preprocessing as preprocessing
from sklearn.model_selection import train_test_split
from sklearn.metrics import f1_score,recall_score,precision_score,roc_curve,roc_auc_score,accuracy_score,confusion_matrix,r2_score
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.preprocessing import MinMaxScaler
from sklearn.metrics import brier_score_loss
from sklearn.calibration import calibration_curve
from sklearn import metrics
import scipy


df = pd.read_excel('生猪价格数据集-LSTM.xlsx',sheet_name="0")
df.head(148)


df = df.iloc[:,1:]


plt.plot(df['生猪价格'])


df = pd.read_excel('生猪价格数据集-LSTM.xlsx',sheet_name="0")
df = df.iloc[:,1:]
n=21

s1 = StandardScaler()
df = s1.fit_transform(df)
x = []
y = []
for i in range(len(df)-n-n):
    x.append(df[i:i+n])
    y.append(df[i+n:i+n+n,0])

x = np.array(x)
y = np.array(y)
# x = x.reshape(-1,15,n)
X_train,X_test,Y_train ,Y_test= train_test_split(x,y,test_size = 0.2,random_state=1)
X_train = torch.tensor(X_train,dtype = torch.float)
X_test = torch.tensor(X_test,dtype = torch.float)
Y_train  = torch.tensor(Y_train,dtype = torch.float)
Y_test  = torch.tensor(Y_test,dtype = torch.float)

train_loader = Data.DataLoader(
    dataset=Data.TensorDataset(X_train, Y_train),  # 封装进Data.TensorDataset()类的数据,可以为任意维度
    batch_size=13,  # 每块的大小
    shuffle=False,  
    drop_last =True, #丢弃最后一组数据
    num_workers=0,  # 多进程(multiprocess)来读数据
)
test_loader = Data.DataLoader(
    dataset=Data.TensorDataset(X_test, Y_test),  # 封装进Data.TensorDataset()类的数据,可以为任意维度
    batch_size=13,  # 每块的大小
    shuffle=False,  
    drop_last =True, 
    num_workers=0,  # 多进程(multiprocess)来读数据
)
Y_test = Y_test.detach().numpy()
print(Y_test)
Y_train = Y_train.detach().numpy()


class LSTM(nn.Module):
    def __init__(self, P,input_size, output_size,w, hidden_layer_size=50):
        """
        :param input_size: 输入数据的维度
        :param hidden_layer_size:隐层的数目
        :param output_size: 输出的个数
        """
        super().__init__()
#         self.li1 = nn.Sequential(
#             self.lstm(input_x, hidden_cell)
        
        
        
        
#         )
        self.hidden_layer_size = hidden_layer_size
        self.lstm = nn.LSTM(input_size, hidden_layer_size,num_layers=2,bidirectional =True,dropout=0.3,batch_first=True)
        self.sigmoid = nn.Sigmoid()
        self.linear1 = nn.Linear(hidden_layer_size*2, output_size)
        self.linear2 = nn.Linear(hidden_layer_size*2, hidden_layer_size*2)
        self.dropout = nn.Dropout(p=P)
        self.relu = nn.ReLU()
        self.ww = w
    def forward(self, input_x):
        torch.manual_seed(1)
        input_x = input_x.reshape(-1,15,n)
        input_x = self.dropout(input_x)

        lstm_out, (h_n, h_c) = self.lstm(input_x)
#         print(lstm_out.shape)
        alpha = F.softmax(self.linear2(lstm_out),dim=1)
#         print(alpha.shape)
        lstm_out = lstm_out*alpha
        lstm_out = torch.sum(lstm_out,1)

        linear_out = self.linear1(lstm_out.view(len(input_x), -1))  

        return linear_out



model = LSTM(p,input_size,output_size,hidden_size)
loss_function = nn.MSELoss()  # loss
optimizer = torch.optim.Adam(model.parameters(), lr=l)  # 优化器
scheduler = optim.lr_scheduler.StepLR(optimizer, step_size=9, gamma=0.95)
result = {}
result['train-mse'] = []
result['train-mape']= []
result['train-loss']= []
result['train-r2']= []
result['test-mse']= []
result['test-mape']= []
result['test-loss']= []
result['test-r2']= []
R2 = 0
for epochs in range(Epochs):
    loss_mean_train = 0
    loss_mean_test = 0
    r2_train = 0
    r2_test = 0
    model.train()
    for data_l in train_loader:
        
        seq, labels = data_l
        optimizer.zero_grad()
        y_pred = model(seq)
        labels = torch.squeeze(labels)
        single_loss = loss_function(y_pred, labels)
        
        loss_mean_train += single_loss.item()
        single_loss.backward()
        optimizer.step()
    scheduler.step()
    model.eval()
    y_predict = model(X_train).detach().numpy()
#     mse1 = np.sum((Y_train- y_predict) ** 2) / len(Y_train)
    mape1 = (sum(abs((y_predict - Y_train)/(Y_train+1)))/len(Y_train))*100
    mape1 = sum(mape1)/len(mape1)
    r2_train = r2_score(y_predict,Y_train)

    y_predict = model(X_test)
    single_loss_test = loss_function(y_predict, torch.squeeze(torch.tensor(Y_test,dtype = torch.float))).item()
    y_predict = y_predict.detach().numpy()
#     mse2 = np.sum((Y_test - y_predict) ** 2) / len(Y_test)
    mape2 = (sum(abs((y_predict - Y_test)/(Y_test+1)))/len(Y_test))*100
    mape2 = sum(mape2)/len(mape2)
    r2_test = r2_score(y_predict,Y_test)


#     result['train-mse'].append(mse1)
#     result['test-mse'].append(mse2)
    result['train-mape'].append(mape1)
    result['test-mape'].append(mape2)
    result['train-r2'].append(r2_train)
    result['test-r2'].append(r2_test)
    result['train-loss'].append(loss_mean_train/len(train_loader))
    result['test-loss'].append(single_loss_test)
        
    print('Epochs',epochs,'loss_train',loss_mean_train/len(train_loader),'r2_train',r2_train)
    print('Epochs',epochs,'loss_test',single_loss_test,'r2_test',r2_test)
    if R2 < r2_test:
        R2 =r2_test
        torch.save(model, 'model_lstm3.pth')
        print('已更新保存模型')

Guess you like

Origin blog.csdn.net/m0_56120502/article/details/130445101