【问题标题】:Convolutional1D in Keras convolves on time steps instead of features?Keras 中的 Convolutional1D 卷积时间步而不是特征?
【发布时间】:2017-06-19 00:42:57
【问题描述】:

所以,我的输入是(1, 893, 463),或者更一般地说是(None, None, 463)。这对应于 893 个时间步长的 1 个样本,每个具有 463 个特征。输出形状为(1, 893, 2),即(None, None, 2)

我的网络结构是这样的:

model = Sequential()
model.add(Convolution1D(64, 5, input_dim = one_input_length, border_mode = "same", W_regularizer = l2(0.01)))
model.add(MaxPooling1D(10, border_mode = "same"))
model.add(Convolution1D(64, 5, border_mode = "same", W_regularizer = l2(0.01)))
model.add(MaxPooling1D(10, border_mode = "same"))
model.add(GRU(300, return_sequences = True, W_regularizer = l2(0.01), U_regularizer = l2(0.01)))
model.add(TimeDistributed(Dense(2, activation='sigmoid')))

这样编译:

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

问题是,当我执行model.fit(test_X, test_Y, nb_epochs = ....) 时,我收到以下错误:Incompatible shapes: [1,893] vs. [1,9],追溯到compile 行。

我使用this 技术记录了每一层的输出形状,并得出以下结论:

Input:  (1, 893, 463)
Conv_1: (1, 893, 64)
Pool_1: (1, 90, 64)
Conv_2: (1, 90, 64)
Pool_2: (1, 9, 64)
GRU:    (1, 9, 300)
Dense:  (1, 9, 2)

我怀疑当模型尝试计算准确度时会发生这种情况,并发现对于 893 个正确输出,它只有 9 个预测。出于某种原因,第二个Convolutional1D 层开始在时间步上进行卷积,而不是像第一个那样在特征上进行卷积。

为什么会这样,我该如何解决?

编辑:

模型总结:

____________________________________________________________________________________________________
Layer (type)                     Output Shape          Param #     Connected to
====================================================================================================
convolution1d_1 (Convolution1D)  (None, None, 64)      148224      convolution1d_input_1[0][0]
____________________________________________________________________________________________________
maxpooling1d_1 (MaxPooling1D)    (None, None, 64)      0           convolution1d_1[0][0]
____________________________________________________________________________________________________
convolution1d_2 (Convolution1D)  (None, None, 64)      20544       maxpooling1d_1[0][0]
____________________________________________________________________________________________________
maxpooling1d_2 (MaxPooling1D)    (None, None, 64)      0           convolution1d_2[0][0]
____________________________________________________________________________________________________
gru_1 (GRU)                      (None, None, 300)     328500      maxpooling1d_2[0][0]
____________________________________________________________________________________________________
timedistributed_1 (TimeDistribut (None, None, 2)       602         gru_1[0][0]
====================================================================================================
Total params: 497,870
Trainable params: 497,870
Non-trainable params: 0
____________________________________________________________________________________________________

我正在尝试制作一个 CNN-LSTM 分类器,给定时间序列数据,该分类器将为每个时间步提供一个输出。

完整的错误信息:

Traceback (most recent call last):
  File "/Users/user/.pyenvs/MLPy3/lib/python3.5/site-packages/tensorflow/python/client/session.py", line 1021, in _do_call
    return fn(*args)
  File "/Users/user/.pyenvs/MLPy3/lib/python3.5/site-packages/tensorflow/python/client/session.py", line 1003, in _run_fn
    status, run_metadata)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/contextlib.py", line 66, in __exit__
    next(self.gen)
  File "/Users/user/.pyenvs/MLPy3/lib/python3.5/site-packages/tensorflow/python/framework/errors_impl.py", line 469, in raise_exception_on_not_ok_status
    pywrap_tensorflow.TF_GetCode(status))
tensorflow.python.framework.errors_impl.InvalidArgumentError: Incompatible shapes: [1,893] vs. [1,9]
     [[Node: Equal = Equal[T=DT_INT64, _device="/job:localhost/replica:0/task:0/cpu:0"](ArgMax, ArgMax_1)]]

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "Stock_CNN_LSTM.py", line 89, in <module>
    model.fit(test_X, test_Y, nb_epoch=nb_epoch, verbose = 2, callbacks=[TestCallback((test_X, test_Y)), ModelCheckpoint("cnn_lstm_model-{epoch:02d}.h5")], initial_epoch = initial_epoch)
  File "/Users/user/.pyenvs/MLPy3/lib/python3.5/site-packages/keras/models.py", line 672, in fit
    initial_epoch=initial_epoch)
  File "/Users/user/.pyenvs/MLPy3/lib/python3.5/site-packages/keras/engine/training.py", line 1192, in fit
    initial_epoch=initial_epoch)
  File "/Users/user/.pyenvs/MLPy3/lib/python3.5/site-packages/keras/engine/training.py", line 892, in _fit_loop
    outs = f(ins_batch)
  File "/Users/user/.pyenvs/MLPy3/lib/python3.5/site-packages/keras/backend/tensorflow_backend.py", line 1900, in __call__
    feed_dict=feed_dict)
  File "/Users/user/.pyenvs/MLPy3/lib/python3.5/site-packages/tensorflow/python/client/session.py", line 766, in run
    run_metadata_ptr)
  File "/Users/user/.pyenvs/MLPy3/lib/python3.5/site-packages/tensorflow/python/client/session.py", line 964, in _run
    feed_dict_string, options, run_metadata)
  File "/Users/user/.pyenvs/MLPy3/lib/python3.5/site-packages/tensorflow/python/client/session.py", line 1014, in _do_run
    target_list, options, run_metadata)
  File "/Users/user/.pyenvs/MLPy3/lib/python3.5/site-packages/tensorflow/python/client/session.py", line 1034, in _do_call
    raise type(e)(node_def, op, message)
tensorflow.python.framework.errors_impl.InvalidArgumentError: Incompatible shapes: [1,893] vs. [1,9]
     [[Node: Equal = Equal[T=DT_INT64, _device="/job:localhost/replica:0/task:0/cpu:0"](ArgMax, ArgMax_1)]]

Caused by op 'Equal', defined at:
  File "Stock_CNN_LSTM.py", line 71, in <module>
    model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
  File "/Users/user/.pyenvs/MLPy3/lib/python3.5/site-packages/keras/models.py", line 594, in compile
    **kwargs)
  File "/Users/user/.pyenvs/MLPy3/lib/python3.5/site-packages/keras/engine/training.py", line 713, in compile
    append_metric(i, 'acc', acc_fn(y_true, y_pred))
  File "/Users/user/.pyenvs/MLPy3/lib/python3.5/site-packages/keras/metrics.py", line 11, in categorical_accuracy
    K.argmax(y_pred, axis=-1)))
  File "/Users/user/.pyenvs/MLPy3/lib/python3.5/site-packages/keras/backend/tensorflow_backend.py", line 1275, in equal
    return tf.equal(x, y)
  File "/Users/user/.pyenvs/MLPy3/lib/python3.5/site-packages/tensorflow/python/ops/gen_math_ops.py", line 728, in equal
    result = _op_def_lib.apply_op("Equal", x=x, y=y, name=name)
  File "/Users/user/.pyenvs/MLPy3/lib/python3.5/site-packages/tensorflow/python/framework/op_def_library.py", line 759, in apply_op
    op_def=op_def)
  File "/Users/user/.pyenvs/MLPy3/lib/python3.5/site-packages/tensorflow/python/framework/ops.py", line 2240, in create_op
    original_op=self._default_original_op, op_def=op_def)
  File "/Users/user/.pyenvs/MLPy3/lib/python3.5/site-packages/tensorflow/python/framework/ops.py", line 1128, in __init__
    self._traceback = _extract_stack()

InvalidArgumentError (see above for traceback): Incompatible shapes: [1,893] vs. [1,9]
     [[Node: Equal = Equal[T=DT_INT64, _device="/job:localhost/replica:0/task:0/cpu:0"](ArgMax, ArgMax_1)]]

谢谢!

【问题讨论】:

  • 你能提供更多关于你想要达到的目标的信息吗?为什么你的TimeDistributed 是最后一个输出?您的目标 y 尺寸是多少?
  • 你能提供 - 你的输入和输出的形状,打印 model.summary() 和完整的错误信息吗?
  • 完成。感谢您的宝贵时间!

标签: python machine-learning keras conv-neural-network lstm


【解决方案1】:

现在所有的卷积/池化层都随着时间的推移而起作用。如果您想在特征空间中应用它们,您需要将它们设为TimeDistributed 并在输入末尾添加一个额外的维度。然后,您需要在将数据传递到GRU 层之前删除额外的维度。但是,只有在每个卷积有一个通道输出时,您才能做到这一点:

import keras.backend as K

model = Sequential()
model.add(Lambda(lambda x: K.expand_dims(x, -1)))
model.add(TimeDistributed(Convolution1D(1, 5, input_dim = one_input_length, border_mode = "same", W_regularizer = l2(0.01))))
model.add(TimeDistributed(MaxPooling1D(10, border_mode = "same")))
model.add(TimeDistributed(Convolution1D(1, 5, border_mode = "same", W_regularizer = l2(0.01))))
model.add(TimeDistributed(MaxPooling1D(10, border_mode = "same")))
model.add(Lambda(lambda x: K.squeeze(x, -1)))
model.add(GRU(300, return_sequences = True, W_regularizer = l2(0.01), U_regularizer = l2(0.01)))
model.add(TimeDistributed(Dense(2, activation='sigmoid')))

如果您想在卷积中使用多个输出通道,则需要创建某种 GRU 单元“矩阵”。

【讨论】:

  • 行得通,谢谢。但是为什么我必须为卷积和池化添加另一个维度?
  • @IvanVegner 好吧,我没有检查它是否在没有它的情况下工作,但原则上,对于每个示例(使用 TimeDistributed,对于每个时间步长)来说,一维卷积都有效,具有两个维度,它们是卷积维度(在您的情况下为 463 个特征)和卷积通道的数量(在您的情况下每个特征 1 个数字),因此您在最后添加一个维度,以便卷积操作将每个数字视为一维向量。我不确定这是否有帮助,我知道这很令人困惑:S
  • 我……我想我明白了。这是必要的,因为每个特征都可以有多个“通道”,因此为了表示它只有一个,我们必须添加该维度。对吗?
  • 是的,完全正确 :) 例如,图像通常是 3,但在这种情况下只有 1。
最近更新 更多