記事ディレクトリ
LSTM 時系列予測
誰もが LSTM ニューラル ネットワークの概念に精通している必要があるため、この記事では LSTM の概念の解釈は含まれませんが、 pytorchを使用して時系列予測に LSTM を使用し、コードを使用して実装されたプロセス全体を復元する方法のみを説明します。
データの取得と前処理
まず、この実験で使用されたデータ セットをプレビューします。データ セットには 3 つの特性があり、最後の列のコンプレッサー出口温度がラベル予測として使用されます (このデータ セットは私が git で収集したものです)
xls ファイルを読み取るための関数を定義します。data.iloc() 関数はデータフレーム内のデータをスライスし、データとラベルを返します。
# 文件读取
def get_Data(data_path):
data=pd.read_excel(data_path)
data=data.iloc[:,:3] # 以三个特征作为数据
label=data.iloc[:,2:] # 取最后一个特征作为标签
print(data.head())
print(label.head())
return data,label
sklearn の前処理モジュールの正規化関数を使用してデータを正規化します。 data=data.values 関数は、データフレーム内のデータを pd 形式から np 配列に変換し、軸ラベルを削除し、fit_transform を削除します。関数はfit()です。transform()と組み合わせると、fitとtransform、結果が1つのステップで結合され、最終的にデータ、ラベル、および正規化されたラベル値が返されます。
# 数据预处理
def normalization(data,label):
mm_x=MinMaxScaler() # 导入sklearn的预处理容器
mm_y=MinMaxScaler()
data=data.values # 将pd的系列格式转换为np的数组格式
label=label.values
data=mm_x.fit_transform(data) # 对数据和标签进行归一化等处理
label=mm_y.fit_transform(label)
return data,label,mm_y
データを正規化した後、データは np 配列形式になっているため、それをベクトル形式に変換してリストに格納する必要があるため、最初に 2 つの空のリストを作成し、for ループを作成し、最後に前処理されたデータを押します。 x.size(0),seq_length,features)をリストに出力します。このうち、seq_length はタイムステップを表し、x.size(0) はデータの最初の次元を表し、features はデータの特徴の数を表します。x、y の寸法を出力し、x、y を返します。
# 时间向量转换
def split_windows(data,seq_length):
x=[]
y=[]
for i in range(len(data)-seq_length-1): # range的范围需要减去时间步长和1
_x=data[i:(i+seq_length),:]
_y=data[i+seq_length,-1]
x.append(_x)
y.append(_y)
x,y=np.array(x),np.array(y)
print('x.shape,y.shape=\n',x.shape,y.shape)
return x,y
データとラベルが準備された後、データを分離することができ、データをトレーニング セットとテスト セットに分離できます。split_data() 関数を定義します。ここで、split_ratio はセットされたテスト セットの比率です。この実験におけるトレーニング セットとテスト セットの比率は 9:1、つまり、split_ratio=0.1 です。分離したデータをVariableにパックして個別にパッケージ化し、配列をテンソル形式に変換してテストセットとトレーニングセットを取得します。データ セットをカプセル化するには Variable 関数を使用する必要があることに注意してください。そうしないと、後続のトーチ反復がサポートされません。
# 数据分离
def split_data(x,y,split_ratio):
train_size=int(len(y)*split_ratio)
test_size=len(y)-train_size
x_data=Variable(torch.Tensor(np.array(x)))
y_data=Variable(torch.Tensor(np.array(y)))
x_train=Variable(torch.Tensor(np.array(x[0:train_size])))
y_train=Variable(torch.Tensor(np.array(y[0:train_size])))
y_test=Variable(torch.Tensor(np.array(y[train_size:len(y)])))
x_test=Variable(torch.Tensor(np.array(x[train_size:len(x)])))
print('x_data.shape,y_data.shape,x_train.shape,y_train.shape,x_test.shape,y_test.shape:\n{}{}{}{}{}{}'
.format(x_data.shape,y_data.shape,x_train.shape,y_train.shape,x_test.shape,y_test.shape))
return x_data,y_data,x_train,y_train,x_test,y_test
パッケージ化されたトレーニング セットとテスト セットを torch でサポートされる反復可能オブジェクト torch.utils.data.DataLoader にロードします。num_epochs は計算された反復数であり、train_loader、test_loader、num_epochs を返します。このようにして、データ セットは前処理され、モデルを構築することができます。
# 数据装入
def data_generator(x_train,y_train,x_test,y_test,n_iters,batch_size):
num_epochs=n_iters/(len(x_train)/batch_size) # n_iters代表一次迭代
num_epochs=int(num_epochs)
train_dataset=Data.TensorDataset(x_train,y_train)
test_dataset=Data.TensorDataset(x_test,y_test)
train_loader=torch.utils.data.DataLoader(dataset=train_dataset,batch_size=batch_size,shuffle=False,drop_last=True) # 加载数据集,使数据集可迭代
test_loader=torch.utils.data.DataLoader(dataset=test_dataset,batch_size=batch_size,shuffle=False,drop_last=True)
return train_loader,test_loader,num_epochs
モデル構築
torch を使用してモデルを構築することは、クラスを定義し、このクラスでモデル インスタンスと順伝播関数を定義するだけです。非常に簡単です。見てみましょう。
# 定义一个类
class Net(nn.Module):
def __init__(self,input_size,hidden_size,num_layers,output_size,batch_size,seq_length) -> None:
super(Net,self).__init__()
self.input_size=input_size
self.hidden_size=hidden_size
self.num_layers=num_layers
self.output_size=output_size
self.batch_size=batch_size
self.seq_length=seq_length
self.num_directions=1 # 单向LSTM
self.lstm=nn.LSTM(input_size=input_size,hidden_size=hidden_size,num_layers=num_layers,batch_first=True) # LSTM层
self.fc=nn.Linear(hidden_size,output_size) # 全连接层
def forward(self,x):
# e.g. x(10,3,100) 三个句子,十个单词,一百维的向量,nn.LSTM(input_size=100,hidden_size=20,num_layers=4)
# out.shape=(10,3,20) h/c.shape=(4,b,20)
batch_size, seq_len = x.size()[0], x.size()[1] # x.shape=(604,3,3)
h_0 = torch.randn(self.num_directions * self.num_layers, x.size(0), self.hidden_size)
c_0 = torch.randn(self.num_directions * self.num_layers, x.size(0), self.hidden_size)
# output(batch_size, seq_len, num_directions * hidden_size)
output, _ = self.lstm(x, (h_0, c_0)) # output(5, 30, 64)
pred = self.fc(output) # (5, 30, 1)
pred = pred[:, -1, :] # (5, 1)
return pred
まず、必要なパラメータ input_size、hidden_size、num_layers、output_size、batch_size、seq_length を含むインスタンスを定義します。self.num_directions を 1 に設定すると、これが単一アイテムの LSTM であることを意味し、lstm 層と全結合層 fc を追加します。lstm 層の入力次元は (input_size=input_size, hidden_size=hidden_size, num_layers=num_layers) になります。 、set、batch_first=True は、shape=(batch_size, seq_size, hidden_size) を意味し、fc 層のパラメータは (hidden_size, Output_size) であり、pred を返します。
トレーニングとテスト
モデルをトレーニングし、i、(batch_x、batch_y) を初期化し、train_loader を列挙型として設定します。optimizer.zero_grad() は、各伝播中に勾配の累積をクリアすることを意味します。optimizer.zero_grad() が torch で宣言されていない場合は、常に累積 勾配を計算し、100 入力ごとに損失を出力するように設定します
# train
iter=0
for epochs in range(num_epochs):
for i,(batch_x, batch_y) in enumerate (train_loader):
outputs = moudle(batch_x)
optimizer.zero_grad() # 将每次传播时的梯度累积清除
# print(outputs.shape, batch_y.shape)
loss = criterion(outputs,batch_y) # 计算损失
loss.backward() # 反向传播
optimizer.step()
iter+=1
if iter % 100 == 0:
print("iter: %d, loss: %1.5f" % (iter, loss.item()))
最近の負け数は以下の通り
iter: 2400, loss: 0.00331
iter: 2500, loss: 0.00039
...
iter: 4400, loss: 0.00332
iter: 4500, loss: 0.00022
iter: 4600, loss: 0.00380
iter: 4700, loss: 0.00032
最終トレーニング セットとテスト セットの MAE/RMSE を描画して、最終結果を取得します。
def result(x_data, y_data):
moudle.eval()
train_predict = moudle(x_data)
data_predict = train_predict.data.numpy()
y_data_plot = y_data.data.numpy()
y_data_plot = np.reshape(y_data_plot, (-1,1))
data_predict = mm_y.inverse_transform(data_predict)
y_data_plot = mm_y.inverse_transform(y_data_plot)
plt.plot(y_data_plot)
plt.plot(data_predict)
plt.legend(('real', 'predict'),fontsize='15')
plt.show()
print('MAE/RMSE')
print(mean_absolute_error(y_data_plot, data_predict))
print(np.sqrt(mean_squared_error(y_data_plot, data_predict) ))
result(x_data, y_data)
result(x_test,y_test)
最終結果: トレーニング セット: MAE/RMSE: 35.114613\75.8706
テスト セット: MAE/RMSE: 213.30313\213.31061
この記事は、lstm を構築するための pytorch の使用法を示すことのみを目的としており、予測結果はあまり正確ではありません (ドロップアウトが正しくないなど)。参考のためにのみ追加しました。
完全なコードについては、私の github を参照してください: https://github.com/Tuniverj/Pytorch-lstm-forecast