将Python中的Keras CNN的NN输出映射到区间[0; 1]

时间:2017-05-09 17:29:25

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

我尝试训练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]。结果得到了非常好的准确率~99%。我已经“手动”完成了这个映射:从每个值中减去数组的最小值,然后除以最大值和最小值的差值。

我可以在Keras中实现此映射吗?是否有具有此功能的图层?

或者我是否做了一些完全错误/不建议的图层,导致输出的这个狭窄间隔?

1 个答案:

答案 0 :(得分:0)

我不确定我完全理解你想要达到的目标。 但我有三个想法,其中一两个可以帮助你。

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

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。

我希望其中一条建议符合你的任务。