【问题标题】:Mapping NN Output of Keras CNN in Python to interval [0;1]将 Python 中 Keras CNN 的 NN 输出映射到区间 [0;1]
【发布时间】:2017-10-08 03:32:23
【问题描述】:

我尝试训练 CNN 对高度 = 2 和宽度 = 1000 像素(可能不常见)形状的图像进行二进制分类。我的第一种方法是一个小而简单的 CNN,编码如下:

def cnn_model_01():
    model = Sequential()
    # Assembly of layers
    model.add(Conv2D(16, (2, 2), input_shape=(1, 2, 1000), activation='relu'))
    model.add(MaxPooling2D(pool_size=(1, 1)))
    model.add(Dropout(0.2))
    model.add(Flatten())
    model.add(Dense(128, activation='relu'))
    model.add(Dense(1, activation='sigmoid'))
    # Compilation of model
    model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
    return model

model = cnn_model_01()

# Fit the model
model.fit(X_train, y_train, validation_data=(X_test, y_test), epochs=5, batch_size=200, verbose=2)

NN 的准确性和预测会产生一个简单地反映样本中值分布的值。典型的训练输出是

13s - loss: 0.7772 - acc: 0.5680 - val_loss: 0.6657 - val_acc: 0.6048
Epoch 2/5
15s - loss: 0.6654 - acc: 0.5952 - val_loss: 0.6552 - val_acc: 0.6048
Epoch 3/5
15s - loss: 0.6514 - acc: 0.5952 - val_loss: 0.6396 - val_acc: 0.6048
Epoch 4/5
15s - loss: 0.6294 - acc: 0.5952 - val_loss: 0.6100 - val_acc: 0.6048
Epoch 5/5
13s - loss: 0.5933 - acc: 0.6116 - val_loss: 0.5660 - val_acc: 0.6052

这样做的原因是 NN 将所有输入样本分配给一个类。因此,在样本以这种方式分布的情况下,大约有三分之二是偶然正确的。

为了解决问题并让 NN 产生更好的结果,我检查了输出并发现这些值的区间或域相对较小,例如在 [0.55;0.62] 之间。我试图映射resp。将此间隔调整为 [0;1]。结果,a 的准确率非常好,约为 99%。我已经“手动”完成了这个映射:从每个值中减去数组的最小值,然后除以最大值和最小值的差。

我可以在 Keras 中实现这个映射吗?有这个功能的层吗?

或者我对层做了什么完全错误/不可取的事情,导致输出的间隔很窄?

【问题讨论】:

  • 标准化输入和输出是您必须做的事情,没有它,训练 NN 要困难得多。
  • 是的,我很清楚。然而,我的印象是 Keras 或多或少是神经网络的综合接口。我已经实现了神经网络,例如Java 和 MatLab。在这些语言中,很明显要注意这种预处理和后处理。所以,我对 Keras 的感觉有点不同。不过,这绝对没问题,现在我知道该怎么做了。

标签: python keras conv-neural-network keras-layer


【解决方案1】:

我不确定我是否完全理解您想要实现的目标。 但我有三个想法,其中一两个可能会对你有所帮助。

1) 在输出层前添加Dense(2)层,将输出层的激活改为softmax。这样一来,您就可以让前一层将图像分类为 1 类或 2 类。最后一个 Dense(1) 层会将这些信息“合并”为单个值 01 作为输出。

2) 我假设您可以选择一个阈值,例如0.5 并简单地比较你的 NN 的基于概率的输出,比如 result = output > 0.5。这也可以在Lambda 层内完成,即model.add(Lambda(lambda x: 1 if x > 0.5 else 0))

3) 预测时,您可以使用predict_class 代替predict 并得到01 作为结果而不是概率。这类似于我之前的建议 2。

我希望其中一个建议符合您的任务。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-09-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-07
    • 2018-09-01
    • 2021-09-20
    • 2020-12-02
    相关资源
    最近更新 更多