Я хочу изменить конкретное предсказание моей CNN-модели на вероятность

#python #tensorflow #keras #deep-learning #neural-network

#python #тензорный поток #keras #глубокое обучение #нейронная сеть

Вопрос:

Я обучил модель классифицировать изображения по двум разным типам. Все работает довольно хорошо, но моя модель может выполнять только определенное предсказание (1 или 0 в моем случае), но мне интересно иметь прогноз, который больше похож на вероятность (например, 90% 1 и 10% 0). Где часть моего кода, которую я должен изменить сейчас? Это что-то с сигмоидной функцией в конце, которая решает, 1 это или 0? Помощь была бы приятной. Заранее спасибо.

 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')
  

Если я попытаюсь получить изображение в моей модели следующим образом:

 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)
  

Я просто получаю такой результат: [[1.]] также, если я добавлю список с несколькими изображениями. Само предсказание, похоже, работает.

Комментарии:

1. То, что вы моделируете, уже является вероятностью положительного класса.

2. До сих пор, когда я загружаю новое изображение с: model = tf.keras.models.load_model('second_try') prediction = model.predict(prepare(files)) Я получаю только 1 или 0. Prepare — это функция, которая просто придает изображениям правильную форму и помещает ее в массив numpy

3. попробуйте softmax вместо sigmoid

4. Оно должно выдавать выходные данные от 0 до 1. Я проверил ваш код, немного изменил его и протестировал на MNIST и получил значения, как 0.49863368 в выходных данных. Итак, как сказал @Dr.Snoopy, ваш код должен быть в порядке, и он в порядке

5. Спасибо за информацию. Возможно, я делаю что-то не так в той части, где я использую свою модель для новых изображений

Ответ №1:

короткий ответ: измените функцию активации сигмоида на последнем уровне на softmax

почему?

поскольку диапазон выходных данных сигмоида составляет от 0.0 до 1.0, поэтому для осмысленной интерпретации этого вывода вы выбираете соответствующий порог, выше которого представляет положительный класс, а все, что ниже, — отрицательный класс.(для задачи двоичной классификации)

даже softmax имеет тот же диапазон выходных данных, но разница в том, что его выходные данные представляют собой нормализованные вероятности классов подробнее об этом здесь, поэтому, если ваша модель выводит 0,99 для любого заданного ввода, то это можно интерпретировать как модель на 99,0% уверена, что это положительный класс, и на 0,1% уверена, что он принадлежит к классу с положительным значением.отрицательный класс.

обновление: как предложил @amin, если вам нужны нормализованные вероятности, вам следует внести еще пару изменений, чтобы это сработало.

  1. измените свой генератор данных так, чтобы он выводил 2 класса / метки вместо одного.

  2. измените последний плотный слой с 1 узла на 2 узла.

Комментарии:

1. Softmax следует использовать, когда ваш вывод содержит более одного нейрона (посмотрите на формулу, и вы поймете, почему), поэтому я думаю, что это не подходит для этого вопроса

2. @amin спасибо за информирование, я забыл суммирование в знаменателе!