Get order of class labels for Keras predict function

15,078

Solution 1

noobalert, to get the top 2 predictions, as you requested to the Matias Valdenegro 's question in the comments section, you can do the following code:

prediction1 = model.predict(your_data)
# sorting the predictions in descending order
sorting = (-prediction1).argsort()

# getting the top 2 predictions
sorted_ = sorting[0][:2]

for value in sorted_:
    # you can get your classes from the encoder(your_classes = encoder.classes_) 
    # or from a dictionary that you created before.
    # And then we access them with the predicted index.
    predicted_label = your_classes[value]

    # just some rounding steps
    prob = (prediction1[0][value]) * 100
    prob = "%.2f" % round(prob,2)
    print("I have %s%% sure that it belongs to %s." % (prob, predicted_label)

Solution 2

As correctly presented by matias, you should use np.argmax function

But since you usually deal with inputs in batches your prediction output will most likely be a matrix. You can deal with it by applying argmax to each one individually, but I think it's better to use the axis argument.

In short:

predictions = model.predict(Input)
classes = np.argmax(predictions, axis=1)

In not so short, a runnable code you can test:

from __future__ import print_function
import keras
import numpy as np
from keras.datasets import mnist



(x_train, y_train), (x_test, y_test) = mnist.load_data()
num_classes = 10
y_test_cat = keras.utils.to_categorical(y_test, num_classes)
print(y_test)
print(np.argmax(y_test_cat,axis=1))

error = y_test-np.argmax(y_test_cat,axis=1)

all_zero = not np.any(error)

print (all_zero)

Explanation:

First all those keras and numpy imports and print function (because why not)

from __future__ import print_function
import keras
import numpy as np
from keras.datasets import mnist

Then load mnist data

(x_train, y_train), (x_test, y_test) = mnist.load_data()

After that, change your target classes to one hot encoding with to_categorical

y_test_cat = keras.utils.to_categorical(y_test, num_classes)

Then go back to the classes you need:

print(np.argmax(y_test_cat,axis=1))

In this example, y_test_cat would be the output of your model.predict() function, so that's how you'd pass it to argmax to recover your class from highest probability prediction.

Now, just to make sure our classes "predictions" are exactly the original classes (as they should be since the "predictions" were already the right classes) the error is computed. and printed

error = y_test-np.argmax(y_test_cat,axis=1)

all_zero = not np.any(error)

print (all_zero)

Solution 3

A better option is to use sklearn's label encoder, which is designed for exactly this purpose.

>>> from sklearn.preprocessing import LabelEncoder()
>>> le = LabelEncoder()
>>> le.fit_tranform([1, 2, 2, 6])
array([0, 0, 1, 2])
>>> le.inverse_transform([0, 0, 1, 2])
[1, 2, 2, 6]

Essentially, this can be used to map any collection (including those containing non-numerics) into an integer mapping in a way that can be reversed after the training process in order to cleanly associate with class labels.

Note that in a keras model, you can use the predict_class function to get the transformed class labels directly (at which point you can perform the inverse_transform) or if you want to go from the multiclass output vector directly - which is what you get when you call predict and have a softmax activation for the output layer, for instance, you can use Numpy's argmax as has been mentioned by others in conjunction with the encoder:

true_labels = le.inverse_transform(list(map(lambda x: np.argmax(x))))
Share:
15,078
noobalert
Author by

noobalert

I'm a BS Computer Science student.

Updated on June 14, 2022

Comments

  • noobalert
    noobalert almost 2 years

    I have the same question as this question here in SO. However, when I tried using the probas_to_classes() utility function, **it is already missing in the current code:

    """Numpy-related utilities."""
    from __future__ import absolute_import
    
    import numpy as np
    
    
    def to_categorical(y, num_classes=None):
        """Converts a class vector (integers) to binary class matrix.
    
        E.g. for use with categorical_crossentropy.
    
        # Arguments
            y: class vector to be converted into a matrix
                (integers from 0 to num_classes).
            num_classes: total number of classes.
    
        # Returns
            A binary matrix representation of the input.
        """
        y = np.array(y, dtype='int').ravel()
        if not num_classes:
            num_classes = np.max(y) + 1
        n = y.shape[0]
        categorical = np.zeros((n, num_classes))
        categorical[np.arange(n), y] = 1
        return categorical
    
    
    def normalize(x, axis=-1, order=2):
        """Normalizes a Numpy array.
    
        # Arguments
            x: Numpy array to normalize.
            axis: axis along which to normalize.
            order: Normalization order (e.g. 2 for L2 norm).
    
        # Returns
            A normalized copy of the array.
        """
        l2 = np.atleast_1d(np.linalg.norm(x, order, axis))
        l2[l2 == 0] = 1
        return x / np.expand_dims(l2, axis)
    

    Do you have any other alternatives in order to get the classes associated with the output of the model?