简体   繁体   English

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

[英]Mapping NN Output of Keras CNN in Python to interval [0;1]

I attempt to train a CNN to binary classify images of the (maybe uncommon) shape of height=2 and width=1000 pixels. 我尝试训练CNN以对高度= 2和宽度= 1000像素的(可能不常见)形状的图像进行二进制分类。 My first approach is a small and simple CNN coded as follows: 我的第一种方法是使用一个小型且简单的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)

The accuracy and prediction of the NN results in a value which reflects simply the distribution of values in the sample. NN的准确性和预测会得出一个仅反映样本中值分布的值。 Typical training output is 典型的训练输出是

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

The reason for this is that the NN assigns all input samples to one class. 这是因为NN将所有输入样本分配给一个类别。 So, in approximately two thirds it is correct by chance in the case of a sample distributed in exactly this way. 因此,在以这种方式分发样本的情况下,大约有三分之二是正确的。

In order to fix the problem and get the NN to produce better results I've inspected the output and encountered that the interval or domain of these values is relatively small, eg between [0.55;0.62]. 为了解决问题并使NN产生更好的结果,我检查了输出,并发现这些值的间隔或域相对较小,例如[0.55; 0.62]之间。 I've tried to map resp. 我已经尝试过绘制地图。 resize this interval to [0;1]. 将此间隔调整为[0; 1]。 As a result a got a really good accuracy of ~99%. 结果,获得了约99%的非常好的准确性。 I've done this mapping "by hand": subtract the minimum value of the array from each value and divide it by the difference of the maximum and minimum. 我已经手工完成了此映射:从每个值中减去数组的最小值,然后将其除以最大值和最小值之差。

Can I implement this mapping in Keras? 我可以在Keras中实现此映射吗? Is there a layer with this functionality? 有没有具有此功能的层?

Or did I do something completely wrong/not advisable with the layers, which leads to this narrow interval of the output? 还是我对图层做了完全错误/不建议做的事情,从而导致输出间隔很窄?

I'm not sure I entirely understand what you want to achieve. 我不确定我是否完全理解您想要实现的目标。 But I have three ideas out of which one or two may help you. 但是我有三个想法,其中一个或两个可以帮助您。

1) Add a Dense(2) layer before the output layer and change the activation of the output layer to softmax . 1)在输出层之前添加一个Dense(2)层,并将输出层的激活更改为softmax That way you'd have the previous layer classify the image as class 1 or class 2. The last Dense(1) layer would then "merge" that information into a single value 0 or 1 as output. 这样,您就可以使上一层将图像分类为1类或2类。最后一个Dense(1)层会将这些信息“合并”为单个值01作为输出。

2) I assume you could pick a threshold, eg 0.5 and simply compare the probability-based output of your NN and so something like result = output > 0.5 . 2)我假设您可以选择一个阈值,例如0.5然后简单地比较您的NN基于概率的输出,因此像result = output > 0.5 This could also be done inside a Lambda layer, ie model.add(Lambda(lambda x: 1 if x > 0.5 else 0)) 这也可以在Lambda层内完成,即model.add(Lambda(lambda x: 1 if x > 0.5 else 0))

3) When predicting, you can use predict_class instead of predict and get 0 or 1 as result instead of probabilities. 3)预测时,您可以使用predict_class而不是predict ,并得到01的结果,而不是概率。 This resembles my previous suggestion 2. 这类似于我先前的建议2。

I hope one of the suggestions matches your task. 希望其中一项建议与您的任务相符。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM