我正在尝试使用Keras实施LSTM。
我知道Keras中的LSTM需要3D张量与形状(nb_samples, timesteps, input_dim)作为输入。但是,我不能完全确定输入在我的情况下的样子,因为我T对每个输入只有一个观察样本,而不是多个样本,即(nb_samples=1, timesteps=T, input_dim=N)。将我的每个输入分成长度样本是否更好T/M?T对我而言,大约有几百万个观测值,因此在这种情况下,每个样本应保留多长时间,即我将如何选择M?
(nb_samples, timesteps, input_dim)
T
(nb_samples=1, timesteps=T, input_dim=N)
T/M
M
另外,我是对的,这个张量应该看起来像:
[[[a_11, a_12, ..., a_1M], [a_21, a_22, ..., a_2M], ..., [a_N1, a_N2, ..., a_NM]], [[b_11, b_12, ..., b_1M], [b_21, b_22, ..., b_2M], ..., [b_N1, b_N2, ..., b_NM]], ..., [[x_11, x_12, ..., a_1M], [x_21, x_22, ..., x_2M], ..., [x_N1, x_N2, ..., x_NM]]]
其中M和N如前所述,x对应于我如上所述从拆分中获得的最后一个样本?
最后,给定一个熊猫数据框,T每一列中都有观察值,每一列中都有观察值N,如何创建这样的输入以馈给Keras?
N
以下是设置时间序列数据以训练LSTM的示例。该模型输出是胡说八道,因为我仅将其设置为演示如何构建模型。
import pandas as pd import numpy as np # Get some time series data df = pd.read_csv("https://raw.githubusercontent.com/plotly/datasets/master/timeseries.csv") df.head()
时间序列数据帧:
Date A B C D E F G 0 2008-03-18 24.68 164.93 114.73 26.27 19.21 28.87 63.44 1 2008-03-19 24.18 164.89 114.75 26.22 19.07 27.76 59.98 2 2008-03-20 23.99 164.63 115.04 25.78 19.01 27.04 59.61 3 2008-03-25 24.14 163.92 114.85 27.41 19.61 27.84 59.41 4 2008-03-26 24.44 163.45 114.84 26.86 19.53 28.02 60.09
您可以将输入输入构建为向量,然后使用pandas.cumsum()函数构建时间序列的序列:
.cumsum()
# Put your inputs into a single list df['single_input_vector'] = df[input_cols].apply(tuple, axis=1).apply(list) # Double-encapsulate list so that you can sum it in the next step and keep time steps as separate elements df['single_input_vector'] = df.single_input_vector.apply(lambda x: [list(x)]) # Use .cumsum() to include previous row vectors in the current row list of vectors df['cumulative_input_vectors'] = df.single_input_vector.cumsum()
可以类似的方式设置输出,但是它将是单个向量而不是序列:
# If your output is multi-dimensional, you need to capture those dimensions in one object # If your output is a single dimension, this step may be unnecessary df['output_vector'] = df[output_cols].apply(tuple, axis=1).apply(list)
输入序列必须具有相同的长度才能在模型中运行,因此您需要将其填充为累积向量的最大长度:
# Pad your sequences so they are the same length from keras.preprocessing.sequence import pad_sequences max_sequence_length = df.cumulative_input_vectors.apply(len).max() # Save it as a list padded_sequences = pad_sequences(df.cumulative_input_vectors.tolist(), max_sequence_length).tolist() df['padded_input_vectors'] = pd.Series(padded_sequences).apply(np.asarray)
训练数据可以从数据框中提取并放入numpy数组中。 请注意,从数据框中出来的输入数据不会构成3D数组。 它使数组成为数组,这是不一样的。
您可以使用hstack和reshape来构建3D输入数组。
# Extract your training data X_train_init = np.asarray(df.padded_input_vectors) # Use hstack to and reshape to make the inputs a 3d vector X_train = np.hstack(X_train_init).reshape(len(df),max_sequence_length,len(input_cols)) y_train = np.hstack(np.asarray(df.output_vector)).reshape(len(df),len(output_cols))
为了证明这一点:
>>> print(X_train_init.shape) (11,) >>> print(X_train.shape) (11, 11, 6) >>> print(X_train == X_train_init) False
获得训练数据后,您可以定义输入层和输出层的尺寸。
# Get your input dimensions # Input length is the length for one input sequence (i.e. the number of rows for your sample) # Input dim is the number of dimensions in one input vector (i.e. number of input columns) input_length = X_train.shape[1] input_dim = X_train.shape[2] # Output dimensions is the shape of a single output vector # In this case it's just 1, but it could be more output_dim = len(y_train[0])
建立模型:
from keras.models import Model, Sequential from keras.layers import LSTM, Dense # Build the model model = Sequential() # I arbitrarily picked the output dimensions as 4 model.add(LSTM(4, input_dim = input_dim, input_length = input_length)) # The max output value is > 1 so relu is used as final activation. model.add(Dense(output_dim, activation='relu')) model.compile(loss='mean_squared_error', optimizer='sgd', metrics=['accuracy'])
最后,您可以训练模型并将训练日志保存为历史记录:
# Set batch_size to 7 to show that it doesn't have to be a factor or multiple of your sample size history = model.fit(X_train, y_train, batch_size=7, nb_epoch=3, verbose = 1)
输出:
Epoch 1/3 11/11 [==============================] - 0s - loss: 3498.5756 - acc: 0.0000e+00 Epoch 2/3 11/11 [==============================] - 0s - loss: 3498.5755 - acc: 0.0000e+00 Epoch 3/3 11/11 [==============================] - 0s - loss: 3498.5757 - acc: 0.0000e+00
而已。使用model.predict(X)whereX与为X_train从模型进行预测时使用相同的格式(样本数量除外)。
model.predict(X)
X
X_train