如何在python中使用keras获取概率/置信度作为CNN的输出?

epggiuax  于 12个月前  发布在  Python
关注(0)|答案(4)|浏览(166)

所以,我是深度学习的新手,我已经开始使用Keras的CNN模型的猫和狗数据集。
在我的代码中,我无法得到classifier.predictclassifier.predict_proba的概率输出。我只是得到[[0,1]][[1,0]]的输出。我已经尝试了几个图像。
但我在找类似[[0.4,0.6]][[0.89,0.11]]的东西
我试着把损失函数从binary_crossentropy改为categorical_crossentropy
我尝试将输出层的激活函数从sigmoid更改为softmax
我还尝试将flow_from_directory中的class_modebinary更改为categorical

  • 我想我可能在数据类型上出错了,因为输出数组的类型是float 32。但即使这是错误,我也不知道如何更改它。*

我找不到我错在哪里。请澄清/帮助。谢谢。
为什么需要概率?
在我的另一个项目中,我将把一个图像分割成n个小块。然后我将分别对n个小块使用分类器,并找到概率最大的一个小块。为此,我不会使用猫和狗的数据集。它是用于装箱的,该数据集也将二进制输出为“YES”或“NO”。欢迎对此提出任何建议。谢谢。
Link在Github中的代码。

#Building the CNN
    
    from keras.models import Sequential
    from keras.layers import Convolution2D
    from keras.layers import MaxPooling2D
    from keras.layers import Flatten
    from keras.layers import Dense
    
    #Initialising the CNN
    
    classifier = Sequential()
    
    #Step 1 - Convolution
    classifier.add(Convolution2D(filters=32,kernel_size=[3,3],input_shape=(64,64,3),activation='relu'))
    
    #Step 2 - Pooling
    classifier.add(MaxPooling2D(pool_size=(2,2),strides=2))
    
    #Adding another Convolutional Layer for better accuracy
    #classifier.add(Convolution2D(filters=32,kernel_size=[3,3],activation='relu'))
    #classifier.add(MaxPooling2D(pool_size=(2,2),strides=2))
    
    #Step 3 - Flattening
    classifier.add(Flatten()) 
    
    #Step 4 - Fully Connected Layers
    classifier.add(Dense(units= 64, activation='relu'))
    classifier.add(Dense(units= 2, activation='softmax'))
    
    
    #Compiling the CNN
    classifier.compile(optimizer='adam',loss = 'categorical_crossentropy', metrics=['accuracy'])
    
    #Part 2 - Fitting the CNN to the images
    from keras.preprocessing.image import ImageDataGenerator
    
    train_datagen=ImageDataGenerator(
            rescale=1./255,
            shear_range=0.2,
            zoom_range=0.2,
            horizontal_flip=True)
    
    test_datagen=ImageDataGenerator(rescale=1./255)
    
    training_set = train_datagen.flow_from_directory('dataset/training_set',
                                                     target_size=(64,64),
                                                     batch_size=32,
                                                     class_mode='categorical')
    
    test_set = test_datagen.flow_from_directory('dataset/test_set',
                                                target_size=(64,64),
                                                batch_size=32,
                                                class_mode='categorical')
    
    classifier.fit_generator(training_set,
                        steps_per_epoch=250,
                        epochs=3,                       #Just for time being I've kept very few epochs.
                        validation_data=test_set,
                        validation_steps=62)
    
    
    #Making new Predictions
    import numpy as np
    from keras.preprocessing import image
    
    test_image_luna=image.load_img('dataset/single/SkilletLuna.JPG',target_size=(64,64))
    test_image2=image.img_to_array(test_image_luna)
    test_image2=np.expand_dims(test_image2,axis=0)
    luna=classifier.predict_proba(test_image2)

In [11]: luna
    ...: 
Out[11]: array([[0., 1.]], dtype=float32)

字符串

wqnecbli

wqnecbli1#

我想我发现了错误。您正在使用ImageDataGenerator重新调整训练和测试数据。但在测试单个图像时,您没有这样做。试试这个:

# Making new Predictions
import numpy as np
from keras.preprocessing import image

test_image_luna = image.load_img('D:\\NR\\data\\live2013\\caps.bmp', target_size=(64,64))
test_image2 = image.img_to_array(test_image_luna)/255.
test_image2 = np.expand_dims(test_image2, axis=0)
luna = classifier.predict_proba(test_image2)

字符串
高输入值导致非常高的输出值。由于您使用softmax激活,这些值导致预测非常接近0和1。

ih99xse1

ih99xse12#

我正在寻找类似,0.4,0.60.89,0.11的值
classifier.predict是你应该用来得到概率的方法。考虑到下面的提示,你能再检查一次吗?
有两种方法可以构建一个二元分类器:

  1. NN具有一个输出神经元,具有sigmoid激活。输出a被解释为类别1的概率,因此类别2的概率为1-a
    1.使用softmax activation两个输出神经元的NN。每个神经元然后被解释为一个类的概率。
    这两个选项都是有效的,但由于您正在执行2.您应该使用softmax激活。
    我尝试将损失函数从binary_crossentropy改为categorical_crossentropy。
    这应该没有什么区别,基本上是相同的公式。
    我想我的数据类型可能出错了,因为输出数组的类型是float32。但即使这是错误,我也不知道如何更改它。
    这也不是错误的原因,因为float32类型对于概率输出是正确的。
r6vfmomb

r6vfmomb3#

predict()或predict_generator()都可以工作。

import numpy as np
from keras.preprocessing import image

test_image_luna=image.load_img('dataset/single/SkilletLuna.JPG',target_size=(64,64))
test_image2=image.img_to_array(test_image_luna)
test_image2=np.expand_dims(test_image2,axis=0)
luna=classifier.predict(test_image2)

print(luna)

字符串
如果你想在“n”个图像(或者在你的例子中是一个图像的“n”个子集)上预测概率,你可以尝试predict_generator():

from keras.preprocessing.image import ImageDataGenerator

test_datagen=ImageDataGenerator(rescale=1./255)
test_set = test_datagen.flow_from_directory('dataset/test_set',
                                             target_size=(64,64),
                                             batch_size=32,
                                             class_mode='categorical')

predicted_probabilities = classifier.predict_generator(test_set)
print(predicted_probabilities)


使用以下命令以四舍五入到小数点后2位的百分比打印:

print(np.round(luna*100,2))
print(np.round(predicted_probabilities*100,2))


让我知道如果这对你有用!

a9wyjsp7

a9wyjsp74#

只需将activation ='relu'或activation ='softmax'替换为activation ='sigmoid'。Sigmoid返回一个0到1之间的值,表示置信度,relu/softmax只会返回1表示最有可能的答案,而返回0表示其他答案。

相关问题