Keras:LSTM神经网络中输入形状错误

时间:2018-03-21 16:09:23

标签: python neural-network keras lstm rnn

我正在尝试训练LSTM递归神经网络,用于序列分类。

我的数据有以下格式:

Input: [1,5,2,3,6,2, ...] -> Output: 1
Input: [2,10,4,6,12,4, ...] -> Output: 1
Input: [4,1,7,1,9,2, ...] -> Output: 2
Input: [1,3,5,9,10,20, ...] -> Output: 3
.
.
.

所以基本上我想提供一个序列作为输入并获得一个整数作为输出。

每个输入序列的长度= 2000个浮点数,我有大约1485个样本用于训练

输出只是1到10之间的整数

这就是我试图做的事情:

# Get the training numpy 2D array for the input (1485X 2000). 
# Each element is an input sequence of length 2000
# eg: [ [1,2,3...], [4,5,6...], ... ]
x_train = get_training_x() 

# Get the training numpy 2D array for the outputs (1485 X 1). 
# Each element is an integer output for the corresponding input from x_train
# eg: [ 1, 2, 3, ...]
y_train = get_training_y()

# Create the model
model = Sequential()
model.add(LSTM(100, input_shape=(x_train.shape)))
model.add(Dense(1, activation='sigmoid'))
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
print(model.summary())
model.fit(x_train, y_train, nb_epoch=3, batch_size=64)

我收到以下错误:

Error when checking input: expected lstm_1_input to have 3 dimensions, but got array with shape (1485, 2000)

我尝试使用此代码:

model.add(LSTM(100, input_shape=(1485, 1, 2000)))

但这次又出现了另一个错误:

ValueError: Input 0 is incompatible with layer lstm_1: expected ndim=3, found ndim=4

任何人都能解释一下我输入的形状是什么吗?我做错了什么?

由于

3 个答案:

答案 0 :(得分:1)

尝试将您的培训数据重新整理为:

x_train=x_train.reshape(x_train.shape[0], 1, x_train.shape[1])

答案 1 :(得分:1)

input_shape=(None, x_train.shape[1], 1),其中None是批量大小,x_train.shape[1]是每个要素序列的长度,1是每个要素长度。 (不确定Sequential型号是否需要批量大小。)

然后将您的数据重塑为x_train = x_train.reshape(-1, x_train.shape[1], 1)

答案 2 :(得分:0)

考虑到输入和输出的格式,您可以使用其中一个官方Keras examples采用的方法部分。更具体地说,由于您不是在创建二进制分类器,而是预测整数,因此可以使用单热编码使用y_trainto_categorical()进行编码。

# Number of elements in each sample
num_vals = x_train.shape[1]

# Convert all samples in y_train to one-hot encoding
y_train = to_categorical(y_train)

# Get number of possible values for model inputs and outputs
num_x_tokens = np.amax(x_train) + 1
num_y_tokens = y_train.shape[1]

model = Sequential()
model.add(Embedding(num_x_tokens, 100))
model.add(LSTM(100))
model.add(Dense(num_y_tokens, activation='sigmoid'))

model.compile(loss='binary_crossentropy',
              optimizer='adam',
              metrics=['accuracy'])

model.fit(x_train, y_train,
              batch_size=64,
              epochs=3)

上面代码中的num_x_tokens将是您的一个输入样本中元素的最大大小(例如,如果您有两个样本[1, 7, 2][3, 5, 4],那么{{1}是num_x_tokens)。如果您使用7,则可以使用numpy找到此信息。同样,np.amax(x_train)是您在num_y_tokens中的类别数。

训练后,您可以使用以下代码运行预测。在此配置中使用y_train有效地撤消了np.argmax

to_categorical

您可以使用model_out = model.predict(x_test) model_out = np.argmax(model_out, axis=1) to_categorical使用from keras.utils import to_categorical导入Embedding,使用from keras.layers import Embedding导入numpy。

此外,您不必执行import numpy as npprint(model.summary())足以打印摘要。

修改

如果输入的格式为model.summary()(例如,使用[[0.12, 0.31, ...], [0.22, 0.95, ...], ...]生成),则可以使用x_train = np.random.rand(num_samples, num_vals)更改数组的形状以输入它进入LSTM层。在这种情况下训练模型的代码是:

x_train = np.reshape(x_train, (num_samples, num_vals, 1))

num_samples = x_train.shape[0] num_vals = x_train.shape[1] # Number of elements in each sample # Reshape for what LSTM expects x_train = np.reshape(x_train, (num_samples, num_vals, 1)) y_train = to_categorical(y_train) # Get number of possible values for model outputs num_y_tokens = y_train.shape[1] model = Sequential() model.add(LSTM(100, input_shape=(num_vals, 1))) model.add(Dense(num_y_tokens, activation='sigmoid')) model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy']) model.fit(x_train, y_train, batch_size=64, epochs=3) num_vals中每个样本数组的长度。 x_train将每个样本从np.reshape(x_train, (num_samples, num_vals, 1))形式更改为[0.12, 0.31, ...]形式,这是LSTM随后采用的形状([[0.12], [0.31], ...])。在这种情况下额外的input_shape=(num_vals, 1)似乎很奇怪,但是有必要为LSTM的输入添加额外的维度,因为它希望每个样本至少有两个维度,通常称为1,或者这种情况(timesteps, data_dim)

要了解在Keras中如何使用LSTM,您可以参考:

Keras Sequential model guide(有几个LSTM示例)

Keras examples(查找名称中(num_vals, 1)的{​​{1}}个文件)