简体   繁体   English

我想将我的 CNN 模型的特定预测更改为概率

[英]I want to change the specific prediction of my CNN-model to a probability

I trained a model to categorize pictures in two different types.我训练了一个模型来对两种不同类型的图片进行分类。 Everything is working quite good, but my Model can only do a specific prediction (1 or 0 in my case), but I am interested to have a prediction which is more like a probability (For example 90% 1 and 10% 0).一切都很好,但我的模型只能进行特定的预测(在我的情况下为 1 或 0),但我有兴趣进行更像是概率的预测(例如 90% 1 和 10% 0)。 Where is the part of my code which I should change now?我现在应该更改的代码部分在哪里? Is it something with the sigmoid function in the end which decides if its 1 or 0?最终是否有 sigmoid 函数决定它是 1 还是 0? Help would be nice.帮助会很好。 Thanks in advance.提前致谢。

import numpy as np
from keras.callbacks import TensorBoard
from keras import regularizers
from keras.models import Sequential
from keras.layers import Activation, Dropout, Flatten, Dense, Conv2D, MaxPooling2D
from keras.optimizers import Adam
from keras.metrics import categorical_crossentropy
from keras.preprocessing.image import ImageDataGenerator, array_to_img, img_to_array, load_img
from keras.layers.normalization import BatchNormalization

from utils import DataGenerator, PATH

train_path = 'Dataset/train'
valid_path = 'Dataset/valid'
test_path = 'Dataset/test'

model = Sequential()
model.add(Conv2D(16, (3, 3), input_shape=(640, 640, 1), padding='same', activation='relu',
                 kernel_regularizer=regularizers.l2(1e-4),
                 bias_regularizer=regularizers.l2(1e-4)))
model.add(MaxPooling2D(pool_size=(4, 4)))

model.add(Conv2D(32, (3, 3), activation='relu',
                 kernel_regularizer=regularizers.l2(1e-4),
                 bias_regularizer=regularizers.l2(1e-4)))
model.add(MaxPooling2D(pool_size=(5, 5)))

model.add(Conv2D(64, (3, 3), activation='relu',
                 kernel_regularizer=regularizers.l2(1e-4),
                 bias_regularizer=regularizers.l2(1e-4)))
model.add(MaxPooling2D(pool_size=(6, 6)))

model.add(Flatten())
model.add(Dense(64, activation='relu',
                kernel_regularizer=regularizers.l2(1e-4),
                bias_regularizer=regularizers.l2(1e-4)))
model.add(Dropout(0.3))
model.add(Dense(1, activation='sigmoid',
                kernel_regularizer=regularizers.l2(1e-4),
                bias_regularizer=regularizers.l2(1e-4)))
print(model.summary())

model.compile(loss='binary_crossentropy', optimizer=Adam(lr=1e-3), metrics=['accuracy'])

epochs = 50
batch_size = 16

datagen = DataGenerator()
datagen.load_data()

model.fit_generator(datagen.flow(batch_size=batch_size), epochs=epochs, validation_data=datagen.get_validation_data(),
                    callbacks=[TensorBoard(log_dir=PATH+'/tensorboard')])

#model.save_weights('first_try.h5')
model.save('second_try')

If I try to get a picture in my model like this:如果我尝试在我的模型中像这样获取图片:

path = 'train/clean/picturenumber2'  
def prepare(filepath):   
  IMG_SIZE = 640    
  img_array = cv2.imread(filepath, cv2.IMREAD_GRAYSCALE)    
  new_array = cv2.resize(img_array, (IMG_SIZE, IMG_SIZE))   
  return new_array.reshape(-1, IMG_SIZE, IMG_SIZE, 1) 

model = tf.keras.models.load_model('second_try') 
prediction = model.predict(prepare(path))
print(prediction)

I just get an output like this: [[1.]] Also if I put in a list with multiple pictures.我只是得到这样的输出: [[1.]]另外,如果我放入一个包含多张图片的列表。 The prediction itself seems to be working.预测本身似乎奏效了。

short answer : change sigmoid activation function in the last layer to softmax简短回答:将最后一层中的sigmoid激活函数更改为softmax

why ?为什么 ?

because sigmoid output range is 0.0 to 1.0, so to make a meaningful interpretation of this output, you choose an appropriate threshold above which represents the positive class and anything below as negative class.(for a binary classification problem)因为 sigmoid 输出范围是 0.0 到 1.0,所以为了对这个输出做出有意义的解释,你选择一个合适的阈值,高于它代表正类,低于任何代表负类。(对于二元分类问题)

even softmax has the same output range but the difference being its outputs are normalized class probabilities more on that here , so if your model outputs 0.99 on any given input, then it can be interpreted as the model is 99.0% confident that it is a positive class and 0.1% confident that it belongs to a negative class.甚至SOFTMAX具有相同的输出范围,但区别在于它的输出是归类的概率更多的是在这里,所以如果你的模型在任何给定的输入输出0.99,则可以把它理解为模型是99.0%,有信心,这是一个积极的类和 0.1% 的信心它属于负类。

update : as @amin suggested, if you need normalized probabilities you should do couple more changes for it to work.更新:正如@a​​min 建议的那样,如果您需要标准化概率,您应该做更多的更改才能使其工作。

  1. modify your data generator to output 2 classes/labels instead of one.修改您的数据生成器以输出 2 个类/标签而不是一个。

  2. change last Dense layer from 1 node to 2 nodes.将最后一个 Dense 层从 1 个节点更改为 2 个节点。

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

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