【问题标题】:Activation function error in a 1D CNN in KerasKeras 中的一维 CNN 中的激活函数错误
【发布时间】:2017-05-22 11:55:50
【问题描述】:

我正在创建一个模型来分类输入波形是否包含 I2C 线的 SDA 的上升沿。

我的输入有 20000 个数据点和 100 个训练数据。

我最初在Keras 1D CNN: How to specify dimension correctly?Keras 1D CNN: How to specify dimension correctly?中找到了有关输入的答案

但是,我在激活函数中遇到错误:

ValueError: Error when checking target: expected activation_1 to have 3 dimensions, but got array with shape (100, 1)

我的模型是:

model.add(Conv1D(filters=n_filter,
             kernel_size=input_filter_length,
             strides=1,
             activation='relu',
             input_shape=(20000,1)))
model.add(BatchNormalization())
model.add(MaxPooling1D(pool_size=4, strides=None))

model.add(Dense(1))
model.add(Activation("sigmoid"))

adam = Adam(lr=learning_rate)

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

model.fit(train_data, train_label,
      nb_epoch=10,
      batch_size=batch_size, shuffle=True)

score = np.asarray(model.evaluate(test_new_data, test_label, batch_size=batch_size))*100.0

我无法确定这里的问题。关于为什么激活函数需要一个 3D 张量。

【问题讨论】:

  • 你想用这个网络解决什么任务?分类?回归?您能否提供更多关于模型编译、拟合和模型目标的详细信息?
  • 这是二分类问题。我添加了更多代码。

标签: python machine-learning neural-network deep-learning keras


【解决方案1】:

问题在于,从keras 2.0 开始,应用于序列的Dense 层会将层应用于每个时间步 - 所以给定一个序列,它将产生一个序列。所以你的Dense 实际上是在产生一个单元素向量序列,这会导致你的问题(因为你的目标不是序列)。

有几种方法可以将序列简化为向量,然后对其应用Dense

  1. GlobalPooling:

    您可以使用GlobalPooling 层,例如GlobalAveragePooling1DGlobalMaxPooling1D,例如:

    model.add(Conv1D(filters=n_filter,
             kernel_size=input_filter_length,
             strides=1,
             activation='relu',
             input_shape=(20000,1)))
    model.add(BatchNormalization())
    model.add(GlobalMaxPooling1D(pool_size=4, strides=None))
    
    model.add(Dense(1))
    model.add(Activation("sigmoid"))
    
  2. Flattening:

    您可以使用Flatten 层将整个序列折叠为单个向量:

    model.add(Conv1D(filters=n_filter,
             kernel_size=input_filter_length,
             strides=1,
             activation='relu',
             input_shape=(20000,1)))
    model.add(BatchNormalization())
    model.add(MaxPooling1D(pool_size=4, strides=None))
    model.add(Flatten())
    
    model.add(Dense(1))
    model.add(Activation("sigmoid"))
    
  3. RNN后处理:

    您还可以在序列顶部添加一个循环层,并使其仅返回最后一个输出:

    model.add(Conv1D(filters=n_filter,
             kernel_size=input_filter_length,
             strides=1,
             activation='relu',
             input_shape=(20000,1)))
    model.add(BatchNormalization())
    model.add(MaxPooling1D(pool_size=4, strides=None))
    model.add(SimpleRNN(10, return_sequences=False))
    
    model.add(Dense(1))
    model.add(Activation("sigmoid"))
    

【讨论】:

  • 是的,我打算再添加 4 个卷积层,在密集之前有一个扁平层。但是,relu部分有错误。即使只有一个 CNN 层。
  • 这不是relu 的一部分。这是sigmoidactivation_1 来自第一个独立激活,这是最后一层。此外——当我经常使用Keras 时——我知道这是由于目标形状不匹配造成的。尝试我的一种解决方案并检查它是否可行。
  • 是的,扁平化确实有效!我打算使用全局池化,但扁平化是最简单的,所以我先尝试了。
【解决方案2】:

Conv1D 的输出是 3 维的(它会一直保持到 Dense 层)。

Conv 输出:(BatchSize, Length, Filters)

要让 Dense 层只输出一个结果,您需要添加 Flatten()Reshape((shape)) 层,使其仅 (BatchSize, Lenght)。

如果您调用model.summary(),您将准确看到每一层输出的形状。您必须将输出调整为与作为正确结果传递的数组的形状完全相同。出现在这些形状中的None 是批量大小,可以忽略。


关于你的模型:我认为你需要更多的卷积层,逐渐减少过滤器的数量,因为在单个 Dense 层中压缩这么多数据通常不会带来好的结果。

关于尺寸: keras layers toturial and samples

【讨论】:

  • 其实错误在第一个激活函数。据我了解,过滤器后的输出应该是(100,1)和过滤器的数量。这就是为什么我不明白这个错误。
  • 调用model.summary()并确认尺寸。
  • 这个错误很典型,“你的模型”的输出维度和你传递给拟合的“目标数组”(train_label)的维度不同。
猜你喜欢
  • 1970-01-01
  • 2017-08-10
  • 2019-09-10
  • 2023-03-05
  • 1970-01-01
  • 2023-03-13
  • 1970-01-01
  • 2020-09-12
  • 1970-01-01
相关资源
最近更新 更多