Python 基于数据帧的神经网络LSTM输入形状

Python 基于数据帧的神经网络LSTM输入形状,python,pandas,keras,lstm,Python,Pandas,Keras,Lstm,我正在努力实现一个新的目标 我知道Keras中的LSTM需要一个3D张量,其形状(nb_样本、时间步长、输入尺寸)。然而,在我的例子中,我并不完全确定输入应该是什么样子,因为对于每个输入,我只有一个T观察样本,而不是多个样本,即(nb\u samples=1,timesteps=T,input\u dim=N)。将我的每个输入拆分为长度T/M的样本是否更好T对我来说大约是几百万次观察,那么在这种情况下,每个样本应该有多长时间,也就是说,我应该如何选择M 还有,这个张量应该是这样的,对吗 [[[a

我正在努力实现一个新的目标

我知道Keras中的LSTM需要一个3D张量,其形状
(nb_样本、时间步长、输入尺寸)
。然而,在我的例子中,我并不完全确定输入应该是什么样子,因为对于每个输入,我只有一个
T
观察样本,而不是多个样本,即
(nb\u samples=1,timesteps=T,input\u dim=N)
。将我的每个输入拆分为长度
T/M
的样本是否更好
T
对我来说大约是几百万次观察,那么在这种情况下,每个样本应该有多长时间,也就是说,我应该如何选择
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?

张量形状

你是对的,Keras期望LSTM神经网络有一个3D张量,但我认为你缺少的是Keras期望每个观测可以有多个维度

例如,在Keras中,我使用词向量表示自然语言处理的文档。文档中的每个单词都由一个n维数字向量表示(因此,如果
n=2
,单词“cat”将由类似
[0.31,0.65]
的东西表示)。为了表示单个文档,单词向量按顺序排列(例如“cat sat.”=
[[0.12,0.99],[0.31,0.65],[0.94,0.04]
)。一份文件将是Keras LSTM中的一个样本

这类似于你的时间序列观察。文档类似于时间序列,单词类似于时间序列中的单个观察值,但在您的情况下,观察值的表示只是
n=1
维度

正因为如此,我认为你的张量应该像
[[[a1],[a2],…,[aT],[b1],[b2],[bT],…,[x1],[x2],…,[xT]]]
,其中
x
对应于
nb_样本
timesteps=T
,以及
input\u dim=1
,因为你的每一个观察值都只有一个数字

批量大小

批处理大小应设置为最大化吞吐量,而不超过机器上的内存容量。据我所知,您的输入不需要是批次大小的倍数,在训练模型和根据模型进行预测时也是如此

示例


如果您正在查找示例代码,在上有许多使用LSTM和其他具有序列输入的网络类型的示例。

下面是一个设置时间序列数据以训练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()
函数构建时间序列的序列:

# 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和RESOLAPE构建三维输入阵列

# 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)
其中
X
X\u train
的格式(样本数除外)相同,以便从模型中进行预测。

您能为您的问题添加一个示例数据集吗?因为不清楚哪个输入序列会在模型中产生什么样的目标输出。你能解释一下一次观测的格式或数据类型吗?它是一个数值,一组值,还是其他什么?谢谢你的回答。我发现从一个数据帧开始,很难获得您描述的形状的数据。至于批量大小,我相信Keras确实要求它是nb_样本的倍数,因为我看到它抛出了关于这一点的错误消息,这使得事情变得更加困难。我以前看过您链接到的示例,但它们实际上并不适用于时间序列和多输入,这确实使它变得更加困难(您将在尝试时看到)。你介意给我举个例子吗,即使它是一个使用SKLearn Boston数据集的基本数据集?Boston数据集是否包含时间序列数据?我不确定它是否真的是时间序列数据,但这并不重要,因为你可以这样处理,即,你的行为就像下一个数字对应于下一个数据点一样(无论如何,我对跟踪包含时间戳的列不感兴趣,因此数据集不包含时间列并不重要),并将其拆分为样本集内外进行预测。根据您最初的问题,听起来输入应该是一个数字,对吗?所以您只想选择一列作为输入,另一列作为输出,然后训练模型?不,我想我们彼此误解了。我的输入是每列n列T个观测值(n个时间序列)。每个观察都是一个数字,我想这就是你在评论部分想问我的。明确地说:输出:y=(y1,y2,。。
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()