HOWTO · Python
在 Python 中繪製混淆矩陣
學習在 Python 中用 Matplotlib、Seaborn 或 Pretty Confusion Matrix 繪製並標註混淆矩陣。
本頁內容
要在 Python 中繪製混淆矩陣,先統計每個實際類別與預測類別組合的次數,然後用 Matplotlib 或 Seaborn 顯示這些計數。本文還介紹了基於套件的 Pretty Confusion Matrix 選項。列表示實際類別,欄表示預測類別。
在 Python 中使用 Matplotlib 繪製混淆矩陣
混淆矩陣儲存每個實際類別與預測類別組合的計數。只定義一次類別順序,使矩陣的列和欄與坐標軸標籤相符。在這個例子中,y_true 包含每個樣本的觀測類別,y_pred 包含相應的模型預測。第一列和第一欄代表 bat;第二列和第二欄代表 ball。下面這個可執行的範例只使用 Python 標準函式庫來構建計數矩陣。
執行此範例:
classes = ["bat", "ball"]
y_true = ["bat", "ball", "ball", "bat", "bat", "bat"]
y_pred = ["bat", "bat", "ball", "ball", "bat", "bat"]
matrix = [
[sum(actual == row and predicted == column
for actual, predicted in zip(y_true, y_pred))
for column in classes]
for row in classes
]
print(matrix)
[[3, 1], [1, 1]]
下面這個完整的 Matplotlib 程式會把完成的圖保存到 confusion-matrix-matplotlib.png,因此無論有沒有顯示器都能同樣執行;在互動式會話中,你可以把 savefig 一列換成 plt.show()。
import matplotlib.pyplot as plt
classes = ["bat", "ball"]
y_true = ["bat", "ball", "ball", "bat", "bat", "bat"]
y_pred = ["bat", "bat", "ball", "ball", "bat", "bat"]
matrix = [
[sum(actual == row and predicted == column
for actual, predicted in zip(y_true, y_pred))
for column in classes]
for row in classes
]
fig, ax = plt.subplots(figsize=(5, 4))
image = ax.imshow(matrix, cmap="Blues", origin="upper")
fig.colorbar(image, ax=ax, label="Count")
for row in range(len(classes)):
for column in range(len(classes)):
value = matrix[row][column]
ax.text(column, row, str(value), ha="center", va="center",
color="white" if value > 1.5 else "black")
ax.set_xticks(range(len(classes)))
ax.set_yticks(range(len(classes)))
ax.set_xticklabels(classes)
ax.set_yticklabels(classes)
ax.set_xlabel("Predicted class")
ax.set_ylabel("Actual class")
ax.set_title("Confusion Matrix")
fig.tight_layout()
fig.savefig("confusion-matrix-matplotlib.png", bbox_inches="tight")
矩陣計算得到 [[3, 1], [1, 1]]:三隻實際的 bat 被預測為 bat,一隻實際的 bat 被預測為 ball,一隻實際的 ball 被預測為 bat,一隻實際的 ball 被預測為 ball。對角線儲存格統計正確預測;非對角線儲存格統計錯誤分類。這些是計數,不是百分比。
圖中的列是實際標籤,欄是預測標籤。標註迴圈讀取 matrix[row][column],但傳給 ax.text 的是 (column, row),因為 x 是水平方向,y 是垂直方向。對於像 [[3, 2], [1, 4]] 這樣的不對稱矩陣,這會把 2 放在 x=1、y=0,把 1 放在 x=0、y=1;交換這些坐標會標錯儲存格。origin="upper" 讓第一個實際類別保持在頂部。
改編這個程式時,提供等長的標籤清單,把相應的觀測保持在相同位置,並把每個觀測到的類別都包含在 classes 中。否則,zip 會截斷不匹配的項目,或者推導式會省略你沒有宣告的類別。
在 Python 中使用 Seaborn 繪製混淆矩陣
Seaborn 的 heatmap 會替你處理儲存格標註。這個獨立程式定義了自己的資料和矩陣,因此不依賴於先執行前一節。它需要 Seaborn 和 Matplotlib,並把圖保存到 confusion-matrix-seaborn.png。
import matplotlib.pyplot as plt
import seaborn as sns
classes = ["bat", "ball"]
y_true = ["bat", "ball", "ball", "bat", "bat", "bat"]
y_pred = ["bat", "bat", "ball", "ball", "bat", "bat"]
matrix = [
[sum(actual == row and predicted == column
for actual, predicted in zip(y_true, y_pred))
for column in classes]
for row in classes
]
fig, ax = plt.subplots(figsize=(5, 4))
sns.heatmap(matrix, annot=True, fmt="d", cmap="Blues", square=True,
xticklabels=classes, yticklabels=classes,
cbar_kws={"label": "Count"}, ax=ax)
ax.set_xlabel("Predicted class")
ax.set_ylabel("Actual class")
ax.set_title("Confusion Matrix")
ax.tick_params(axis="y", labelrotation=0)
fig.tight_layout()
fig.savefig("confusion-matrix-seaborn.png", bbox_inches="tight")
在這裡,annot=True 把數值寫入儲存格,fmt="d" 把它們格式化為整數。計數計算同樣得到 [[3, 1], [1, 1]]。兩個刻度標籤清單都遵循宣告的順序,先 bat 後 ball,而不是無關的布林標籤。實際類別沿垂直軸排列;預測類別沿水平軸排列。使用你自己的資料時,要把配對的觀測和類別清單一起替換。
在 Python 中使用 Pretty Confusion Matrix 繪製混淆矩陣
Pretty Confusion Matrix 提供 pp_matrix_from_data 入口,用配對的實際標籤和預測標籤繪圖。該套件的 PyPI 專案頁面提供其 API 範例、安裝指導和依賴中繼資料。發行版名稱是 pretty-confusion-matrix,而 Python 匯入使用底線:pretty_confusion_matrix。
下面這個完整範例會把該套件的圖保存到 confusion-matrix-pretty.png。它已按原文針對該套件及其依賴的目前版本執行過;搭建你自己的環境時,請查閱該專案的依賴要求。
import matplotlib.pyplot as plt
from pretty_confusion_matrix import pp_matrix_from_data
classes = ["bat", "ball"]
y_true = ["bat", "ball", "ball", "bat", "bat", "bat"]
y_pred = ["bat", "bat", "ball", "ball", "bat", "bat"]
# Numeric IDs make the package's sorted class order match the display names.
class_ids = {label: index for index, label in enumerate(classes)}
true_values = [class_ids[label] for label in y_true]
predicted_values = [class_ids[label] for label in y_pred]
pp_matrix_from_data(true_values, predicted_values,
columns=classes, pred_val_axis="col")
plt.savefig("confusion-matrix-pretty.png", bbox_inches="tight")
true_values 包含實際類別的 ID,predicted_values 包含相應的預測。把 bat 編碼為 0、ball 編碼為 1,使它們排序後的順序與 columns=classes 一致;columns 參數提供顯示名稱,而不是對觀測重新排序。pred_val_axis="col" 選擇預測類別為欄,實際類別為列。底層的類別計數是 [[3, 1], [1, 1]];該套件的呈現還可以包含彙總總計,因此它的版面與上面兩張普通熱力圖不同。這裡沒有聲稱任何額外的指標結果。
這個程式生成的圖是: