1
votes

I'm learning about ML, neural networks on MNIST set and I have problem with predict_proba function. I want to receive probability of prediction made by my model, but when I call function predict_proba I always receive array like [0, 0, 1., 0, 0, ...] that means that model always predict with 100% probability.

Could you tell me what is wrong in my model, why this happen and how to fix it?

My model looks like:

# Load MNIST data set and split to train and test sets
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()

# Reshaping to format which CNN expects (batch, height, width, channels)
train_images = train_images.reshape(train_images.shape[0], train_images.shape[1], train_images.shape[2], 1).astype(
    "float32")
test_images = test_images.reshape(test_images.shape[0], test_images.shape[1], test_images.shape[2], 1).astype("float32")

# Normalize images from 0-255 to 0-1
train_images /= 255
test_images /= 255

# Use one hot encode to set classes
number_of_classes = 10

train_labels = keras.utils.to_categorical(train_labels, number_of_classes)
test_labels = keras.utils.to_categorical(test_labels, number_of_classes)

# Create model, add layers
model = Sequential()
model.add(Conv2D(32, (5, 5), input_shape=(train_images.shape[1], train_images.shape[2], 1), activation="relu"))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Conv2D(32, (3, 3), activation="relu"))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.5))
model.add(Flatten())
model.add(Dense(128, activation="relu"))
model.add(Dropout(0.5))
model.add(Dense(number_of_classes, activation="softmax"))

# Compile model
model.compile(loss="categorical_crossentropy", optimizer=Adam(), metrics=["accuracy"])

# Learn model
model.fit(train_images, train_labels, validation_data=(test_images, test_labels), epochs=7, batch_size=200)

# Test obtained model
score = model.evaluate(test_images, test_labels, verbose=0)
print("Model loss = {}".format(score[0]))
print("Model accuracy = {}".format(score[1]))

# Save model
model_filename = "cnn_model.h5"
model.save(model_filename)
print("CNN model saved in file: {}".format(model_filename))

For loading image I use PIL and NP. I save model using save function from keras and load it in another script using load_model from keras.models then I just call

    def load_image_for_cnn(filename):
        img = Image.open(filename).convert("L")
        img = np.resize(img, (28, 28, 1))
        im2arr = np.array(img)
        return im2arr.reshape(1, 28, 28, 1)

    def load_cnn_model(self):
        return load_model("cnn_model.h5")

    def predict_probability(self, image):
        return self.model.predict_proba(image)[0]

Using it looks like:

predictor.predict_probability(predictor.load_image_for_cnn(filename))
1
Where is the call to predict_proba? its nowhere in the code you included. Please include it in your question.Dr. Snoopy
I forgot about it, Added.Jakub Prądzyński
Its not just one line, show us how the image was loaded, its quite important.Dr. Snoopy
I had written that I'm using load_model function from keras.models, but I add how its look like (save and load).Jakub Prądzyński
I am talking on how the input image is loaded and passed to predict_proba, not how the model is loaded.Dr. Snoopy

1 Answers

0
votes

Look at this part of your code:

# Normalize images from 0-255 to 0-1
train_images /= 255
test_images /= 255

You are not doing this while loading new images:

def load_image_for_cnn(filename):
    img = Image.open(filename).convert("L")
    img = np.resize(img, (28, 28, 1))
    im2arr = np.array(img)
    return im2arr.reshape(1, 28, 28, 1)

Applying the same normalization as the training set is requirement to test any new image, if you don't do it you get weird results. You can just normalize the image pixels as follows:

def load_image_for_cnn(filename):
    img = Image.open(filename).convert("L")
    img = np.resize(img, (28, 28, 1))
    im2arr = np.array(img)
    im2arr = im2arr / 255.0
    return im2arr.reshape(1, 28, 28, 1)