web-dev-qa-db-fra.com

Comment prédire l'image d'entrée à l'aide d'un modèle formé à Keras?

Je commence seulement par les keras et l'apprentissage automatique en général.

J'ai formé un modèle pour classer les images de 2 classes et je l'ai enregistré avec model.save(). Voici le code que j'ai utilisé:

from keras.preprocessing.image import ImageDataGenerator
from keras.models import Sequential
from keras.layers import Conv2D, MaxPooling2D
from keras.layers import Activation, Dropout, Flatten, Dense
from keras import backend as K


# dimensions of our images.
img_width, img_height = 320, 240

train_data_dir = 'data/train'
validation_data_dir = 'data/validation'
nb_train_samples = 200  #total
nb_validation_samples = 10  # total
epochs = 6
batch_size = 10

if K.image_data_format() == 'channels_first':
    input_shape = (3, img_width, img_height)
else:
    input_shape = (img_width, img_height, 3)

model = Sequential()
model.add(Conv2D(32, (3, 3), input_shape=input_shape))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))

model.add(Conv2D(32, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))

model.add(Conv2D(64, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))

model.add(Flatten())
model.add(Dense(64))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(1))
model.add(Activation('sigmoid'))

model.compile(loss='binary_crossentropy',
              optimizer='rmsprop',
              metrics=['accuracy'])

# this is the augmentation configuration we will use for training
train_datagen = ImageDataGenerator(
    rescale=1. / 255,
    shear_range=0.2,
    zoom_range=0.2,
    horizontal_flip=True)

# this is the augmentation configuration we will use for testing:
# only rescaling
test_datagen = ImageDataGenerator(rescale=1. / 255)

train_generator = train_datagen.flow_from_directory(
    train_data_dir,
    target_size=(img_width, img_height),
    batch_size=batch_size,
    class_mode='binary')

validation_generator = test_datagen.flow_from_directory(
    validation_data_dir,
    target_size=(img_width, img_height),
    batch_size=batch_size,
    class_mode='binary')

model.fit_generator(
    train_generator,
    steps_per_Epoch=nb_train_samples // batch_size,
    epochs=epochs,
    validation_data=validation_generator,
    validation_steps=5)

model.save('model.h5')

Il s’est entraîné avec une précision de 0,98, ce qui est plutôt bon. Pour charger et tester ce modèle sur de nouvelles images, j'ai utilisé le code ci-dessous:

from keras.models import load_model
import cv2
import numpy as np

model = load_model('model.h5')

model.compile(loss='binary_crossentropy',
              optimizer='rmsprop',
              metrics=['accuracy'])

img = cv2.imread('test.jpg')
img = cv2.resize(img,(320,240))
img = np.reshape(img,[1,320,240,3])

classes = model.predict_classes(img)

print classes

Il produit:

[[0]]

Pourquoi ne donnerait-il pas le nom réel de la classe et pourquoi [[0]]?

Merci d'avance.

32
ritiek

keras predict_classes ( docs ) génère un tableau numpy de prédictions de classe. Quel dans votre cas modèle, l'indice de neurone d'activation maximale de votre dernière couche (softmax). [[0]] signifie que votre modèle a prédit que vos données de test sont de classe 0. (vous transmettez généralement plusieurs images et le résultat ressemble à [[0], [1], [1], [0]])

Vous devez convertir votre étiquette réelle (par exemple 'cancer', 'not cancer') en codage binaire (0 pour 'cancer', 1 pour 'pas cancer') pour la classification binaire. Ensuite, vous interpréterez la sortie de séquence de [[0]] comme ayant le libellé de classe 'cancer'

13
DNK

Si quelqu'un a encore du mal à faire des prédictions sur les images, voici le code optimisé pour charger le modèle enregistré et faire des prédictions:

# Modify 'test1.jpg' and 'test2.jpg' to the images you want to predict on

from keras.models import load_model
from keras.preprocessing import image
import numpy as np

# dimensions of our images
img_width, img_height = 320, 240

# load the model we saved
model = load_model('model.h5')
model.compile(loss='binary_crossentropy',
              optimizer='rmsprop',
              metrics=['accuracy'])

# predicting images
img = image.load_img('test1.jpg', target_size=(img_width, img_height))
x = image.img_to_array(img)
x = np.expand_dims(x, axis=0)

images = np.vstack([x])
classes = model.predict_classes(images, batch_size=10)
print classes

# predicting multiple images at once
img = image.load_img('test2.jpg', target_size=(img_width, img_height))
y = image.img_to_array(img)
y = np.expand_dims(y, axis=0)

# pass the list of multiple images np.vstack()
images = np.vstack([x, y])
classes = model.predict_classes(images, batch_size=10)

# print the classes, the images belong to
print classes
print classes[0]
print classes[0][0]
17
ritiek

Vous pouvez utiliser model.predict() pour prédire la classe d'une seule image comme suit [doc] :

# load_model_sample.py
from keras.models import load_model
from keras.preprocessing import image
import matplotlib.pyplot as plt
import numpy as np
import os


def load_image(img_path, show=False):

    img = image.load_img(img_path, target_size=(150, 150))
    img_tensor = image.img_to_array(img)                    # (height, width, channels)
    img_tensor = np.expand_dims(img_tensor, axis=0)         # (1, height, width, channels), add a dimension because the model expects this shape: (batch_size, height, width, channels)
    img_tensor /= 255.                                      # imshow expects values in the range [0, 1]

    if show:
        plt.imshow(img_tensor[0])                           
        plt.axis('off')
        plt.show()

    return img_tensor


if __name__ == "__main__":

    # load model
    model = load_model("model_aug.h5")

    # image path
    img_path = '/media/data/dogscats/test1/3867.jpg'    # dog
    #img_path = '/media/data/dogscats/test1/19.jpg'      # cat

    # load a single image
    new_image = load_image(img_path)

    # check prediction
    pred = model.predict(new_image)

Dans cet exemple, une image est chargée sous la forme d'un tableau numpy de forme (1, height, width, channels). Ensuite, nous le chargeons dans le modèle et prédisons sa classe, renvoyée sous forme de valeur réelle comprise dans l'intervalle [0, 1] (classification binaire dans cet exemple).

12
auraham

C'est parce que vous obtenez la valeur numérique associée à la classe. Par exemple, si vous avez deux classes chiens et chats, Keras leur associera les valeurs numériques 0 et 1. Pour obtenir le mappage entre vos classes et la valeur numérique associée, vous pouvez utiliser

>>> classes = train_generator.class_indices    
>>> print(classes)
    {'cats': 0, 'dogs': 1}

Vous connaissez maintenant la correspondance entre vos classes et vos index. Alors maintenant, ce que vous pouvez faire est

if classes[0][0] == 1: prediction = 'dog' else: prediction = 'cat'

3
Javapocalypse

En transmettant l'exemple par @ritiek, je suis également un débutant en langage ML. Peut-être que ce type de formatage vous permettra de voir le nom plutôt que le numéro de classe.

images = np.vstack([x, y])

prediction = model.predict(images)

print(prediction)

i = 1

for things in prediction:  
    if(things == 0):
        print('%d.It is cancer'%(i))
    else:
        print('%d.Not cancer'%(i))
    i = i + 1
0
Vineeth Sai