I want to plot a confusion matrix on the validation data.
Specifically, I want to calculate a confusion matrix of the model output on the validation data.
I tried everything online, but couldn’t figure it out.
here is my model:
JavaScript
x
17
17
1
import tensorflow as tf
2
from tensorflow.keras import datasets, layers, models
3
4
(train_images, train_labels), (test_images, test_labels) = datasets.cifar10.load_data()
5
train_images, test_images = train_images / 255.0, test_images / 255.0
6
7
model = models.Sequential()
8
# layers here
9
10
model.compile(optimizer='adam',
11
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
12
metrics=['accuracy'])
13
14
history = model.fit(train_images, train_labels, epochs=1,
15
validation_data=(test_images, test_labels))
16
17
Advertisement
Answer
Here is a dummy example.
DataSet
JavaScript
1
10
10
1
(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()
2
3
# train set / data
4
x_train = x_train.reshape(-1, 28*28)
5
x_train = x_train.astype('float32') / 255
6
7
# train set / target
8
num_of_classess = 10
9
y_train = tf.keras.utils.to_categorical(y_train , num_classes=num_of_classess )
10
Model
JavaScript
1
9
1
model = Sequential()
2
model.add(Dense(800, input_dim=784, activation="relu"))
3
model.add(Dense(num_of_classess , activation="softmax"))
4
model.compile(loss="categorical_crossentropy", optimizer="SGD", metrics=["accuracy"])
5
history = model.fit(x_train, y_train,
6
batch_size=200,
7
epochs=20,
8
verbose=1)
9
Confusion Matrix
Your interest is mostly here.
JavaScript
1
23
23
1
# get predictions
2
y_pred = model.predict(x_train, verbose=2)
3
4
# compute confusion matrix with `tf`
5
confusion = tf.math.confusion_matrix(
6
labels = np.argmax(y_train, axis=1), # get trule labels
7
predictions = np.argmax(y_pred, axis=1), # get predicted labels
8
num_classes=num_of_classess) # no. of classifier
9
10
print(confusion)
11
<tf.Tensor: shape=(10, 10), dtype=int32, numpy=
12
array([[5750, 0, 16, 13, 9, 25, 40, 9, 54, 7],
13
[ 2, 6570, 28, 34, 8, 26, 6, 16, 45, 7],
14
[ 35, 44, 5425, 82, 93, 12, 69, 79, 100, 19],
15
[ 15, 24, 105, 5628, 4, 136, 26, 60, 82, 51],
16
[ 9, 29, 33, 6, 5483, 2, 60, 10, 33, 177],
17
[ 58, 32, 26, 159, 51, 4864, 101, 19, 67, 44],
18
[ 32, 18, 28, 3, 43, 60, 5697, 2, 33, 2],
19
[ 26, 46, 74, 19, 62, 10, 3, 5895, 15, 115],
20
[ 27, 101, 46, 142, 25, 71, 52, 15, 5304, 68],
21
[ 34, 30, 20, 94, 173, 21, 4, 162, 32, 5379]],
22
dtype=int32)>
23
Visualization
Let’s visualize.
JavaScript
1
10
10
1
import seaborn as sns
2
import pandas as pd
3
4
cm = pd.DataFrame(confusion.numpy(), # use .numpy(), because now confusion is tensor
5
range(num_of_classess),range(num_of_classess))
6
7
plt.figure(figsize = (10,10))
8
sns.heatmap(cm, annot=True, annot_kws={"size": 12}) # font size
9
plt.show()
10
Update
Based on the conversation, if you’ve to use
JavaScript
1
2
1
tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True)
2
then don’t transform your integer label as I’ve shown you above (i.e. y_train = tf.keras.utils.to_categorical(y_train, num_classes=10)
). But do just as follows
JavaScript
1
14
14
1
(x_train, y_train), (x_test, y_test) = tf.keras.datasets.cifar10.load_data()
2
3
# train set / data
4
x_train = x_train.astype('float32') / 255
5
6
print(x_train.shape, y_train.shape)
7
# (50000, 32, 32, 3) (50000, 1)
8
9
model
10
model.compile(
11
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
12
.
13
)
14
And in predicting time don’t use np.argmax()
on ground truth as they are already an integer now as we didn’t use tf.keras.utils.to_categorical
this time.
JavaScript
1
9
1
print(np.argmax(y_pred, axis=1).shape, y_train.reshape(-1).shape)
2
# (50000,) (50000,)
3
4
y_pred = model.predict(x_train, verbose=2) # take prediction
5
confusion = tf.math.confusion_matrix(
6
labels = y_train.reshape(-1), # get trule labels
7
predictions = np.argmax(y_pred, axis=1), # get predicted labels
8
)
9
Now rest of the stuff is good to use.