2
votes

Comment obtenir une probabilité / confiance en sortie pour un CNN en utilisant des keras en python?

Je suis donc novice dans l'apprentissage en profondeur et j'ai commencé avec un ensemble de données sur les chats et les chiens pour un modèle CNN utilisant Keras.

Dans mon code, je ne parviens pas à obtenir les probabilités en sortie pour les deux classifier.predict ou classifier.predict_proba . J'obtiens juste la sortie comme [[0,1]] ou [[1,0]] . J'ai essayé avec plusieurs images.

Mais je cherche quelque chose comme, [[0.4,0.6]] , [[0.89,0.11]]

J'ai essayé de changer la fonction de perte de binary_crossentropy à categorical_crossentropy.

J'ai essayé de changer l'activation fonction de la couche de sortie de sigmoïde à softmax.

J'ai aussi essayé de changer le class_mode dans flow_from_directory de binaire à categorical.

Je pense que je me trompe peut-être avec le type de données, en tant que type de tableau de sortie est float32. Mais même si c'est l'erreur, je ne sais pas comment la changer.

Je ne parviens pas à trouver où je me trompe. Veuillez clarifier / aider. Merci.

Pourquoi ai-je besoin de probabilités?

Dans mon autre projet, je diviserai une image en un nombre 'n' de morceaux plus petits. J'utiliserai ensuite le classificateur sur un nombre «n» de pièces séparément et trouverai la pièce avec la plus grande probabilité. Pour cela, je n'utiliserai pas le jeu de données des chats et des chiens. C'est pour la sélection de bacs et cet ensemble de données sera également une sortie binaire sous la forme «OUI» ou «NON». Toute suggestion à ce sujet est également la bienvenue. Merci.

Lien pour le code dans 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)


2 commentaires

Avez-vous vérifié l'exactitude des prédictions? Le NN a-t-il appris au moins quelque chose?


Ouais, il a appris. Il a une précision de 50% avec 1 époque. 80% de précision avec 25 époques. Il classe sans problèmes, la seule chose est qu'il devrait me donner des valeurs décimales pour au moins certaines images (lorsque j'utilise classifer.predict) et ce n'est pas le cas, ce qui me dérange. @markuscosinus


3 Réponses :


1
votes

Je recherche quelque chose comme, [[0.4,0.6]], [[0.89,0.11]]

classifier.predict est la méthode à utiliser pour obtenir des probabilités. Pourriez-vous vérifier à nouveau en tenant compte des conseils suivants?

Il existe deux façons de créer un classificateur binaire:

  1. NN avec un neurone de sortie avec activation sigmoïde . La sortie a est interprétée comme la probabilité pour la classe 1, donc la probabilité pour la classe 2 est 1-a .
  2. NN avec deux neurones de sortie à l'aide de l ' activation softmax . Chaque neurone est alors interprété comme la probabilité d'une classe.

Les deux sont des options valides, mais puisque vous faites 2. vous devez utiliser l'activation softmax.

J'ai essayé de changer la fonction de perte de binary_crossentropy à categorical_crossentropy.

Cela ne devrait pas faire de différence, c'est essentiellement la même formule.

Je pense que je me trompe peut-être avec le type de données, car le type de tableau de sortie est float32. Mais même si c'est l'erreur, je ne le fais pas sachez cependant comment le changer.

Ce n'est pas non plus la cause de l'erreur, car le type float32 convient aux sorties de probabilité.


1 commentaires

Oui, je suis d'accord que classifier.predict devrait donner une probabilité, mais d'une manière ou d'une autre, il s'arrondit à 0 ou à 1 avec le code ci-dessus. De plus, j'ai essayé avec 1 neurone de sortie pour sigmoïde et 2 pour softmax, le résultat pour les deux est une sortie arrondie de 0 ou 1. Je ne pense pas que le classificateur soit aussi confiant. De plus, pour résoudre ce problème, j'ai même essayé d'exécuter moins d'époques (comme 1 ou 3) pour obtenir des probabilités en décimales, mais cela ne donne que 0 ou 1.



1
votes

Prédire () ou prédire_generator () fonctionnerait.

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

Si vous voulez des probabilités de prédiction sur «n» images (ou «n» sous-ensembles d'une image comme dans votre cas ), vous pouvez essayer 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)

Utilisez ce qui suit pour imprimer en pourcentage arrondi à 2 décimales:

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)

Faites-moi savoir si cela fonctionne pour vous!


4 commentaires

Merci pour le prédicteur de prédire n images simultanément. Oui, je suis d'accord que classifier.predict devrait fonctionner, mais d'une manière ou d'une autre, il s'arrondit à 0 ou à 1 avec le code ci-dessus. De plus, j'ai essayé avec 1 neurone de sortie pour sigmoïde et 2 pour softmax, le résultat pour les deux est une sortie arrondie de 0 ou 1. Je ne pense pas que le classificateur soit aussi confiant. De plus, pour résoudre ce problème, j'ai même essayé d'exécuter moins d'époques (comme 1 ou 3) pour obtenir des probabilités en décimales, mais cela ne donne que 0 ou 1.


Vous pouvez l'inclure en haut de votre code: np.set_printoptions (precision = 3, suppress = False) . Je pense que c'est un problème de formatage de tableau. La fonction Softmax et les époques semblent bonnes!


Oui, c'était un problème de formatage de tableau, je n'avais pas redimensionné les tableaux de données de test uniques.


@ Snitch30 Comment avez-vous résolu ce problème? Je suis également confronté au même problème.



3
votes

Je pense avoir trouvé l'erreur. Vous redéfinissez votre train et vos données de test avec ImageDataGenerator . Mais vous ne faites pas cela lorsque vous testez une seule image. Essayez ceci:

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

Les valeurs d'entrée élevées conduisent à des valeurs de sortie très élevées. Puisque vous utilisez l'activation softmax, ces valeurs conduisent à des prédictions très proches de 0 et 1.


0 commentaires