Appearance
10. Дебаг классификаторов ИИ: Визуализация Матрицы Ошибок (Confusion Matrix)
Роль Confusion Matrix в оценке качества моделей
Как по тепловой карте мгновенно определить слабые места ИИ
Когда вы обучаете модель многоклассовой классификации (например, распознавание рукописных цифр MNIST от 0 до 9 или классификацию медицинских снимков), итоговой метрики точности Accuracy недостаточно. Точечный показатель 92% не говорит о том, где именно ошибается нейросеть.
Для глубокого дебага применяется Confusion Matrix (Матрица Ошибок). Это квадратная матрица размером [Num_Classes, Num_Classes], где:
- Строки соответствуют истинным меткам классов (Истинное / Actual).
- Столбцы соответствуют ответам, которые выдала модель (Предсказанное / Predicted).
В идеальном случае, когда классификатор работает безошибочно, все числа будут сосредоточены строго на главной диагонали матрицы, а в остальных ячейках будут нули. Однако если модель путает похожие классы (например, принимает цифру 3 за 8 или путает изображения собак и кошек), на пересечении этих осей появятся числа. Визуализация этой матрицы через тепловую карту позволяет AI-инженеру мгновенно локализовать проблемные классы и понять, какие данные нужно добрать в обучающую выборку.
Проектирование контрастной подсветки ошибок
Настройка палитры и подписей осей
Для построения Матрицы Ошибок используется метод ax.imshow(). Главная инженерная задача при визуализации Confusion Matrix — сделать её максимально читаемой для разработчиков и бизнеса:
- Выбор палитры (
cmap): Обычно выбирается последовательный градиент (например,"Oranges","Blues"или"Greens"). Чем больше ошибок совершила модель в конкретной ячейке, тем темнее и ярче будет окрашен пиксель. - Метки осей: Оси обязательно должны быть размечены текстовыми названиями классов (а не просто индексами
0, 1, 2), а координатная сетка должна иметь четкие подписи: горизонтальная ось —"Predicted Class", вертикальная —"Actual Class". - Числовое аннотирование: Внутри ячеек в цикле обязательно печатаются точные цифры количества объектов, чтобы можно было оценить масштаб ошибок в абсолютных значениях.
python
import numpy
import matplotlib.pyplot
fig, ax = matplotlib.pyplot.subplots(figsize=(6, 6))
# Simulated 3x3 Confusion Matrix: Classes are [Cat, Dog, Bird]
confusion_matrix = numpy.array([[45, 5, 0], # Actual Cats: 45 right, 5 confused with Dogs
[ 8, 38, 4], # Actual Dogs: 38 right, 8 confused with Cats
[ 2, 1, 47]]) # Actual Birds: 47 right
# Rendering with an explicit sequential color map
img = ax.imshow(confusion_matrix, cmap="Oranges")
# Configuring the tick ticks positions and string classes labels
classes = ["Cat", "Dog", "Bird"]
ax.set_xticks(range(3))
ax.set_yticks(range(3))
ax.set_xticklabels(classes)
ax.set_yticklabels(classes)
# Essential labels metadata nodes
ax.set_title("Classifier Confusion Matrix Analytics")
ax.set_xlabel("Predicted Class Label")
ax.set_ylabel("Actual Class Label")
# Overlaying data numbers on top of the heatmap cells
for i in range(3):
for j in range(3):
ax.text(x=j, y=i, s=str(confusion_matrix[i, j]), ha="center", va="center")Упражнения базовые (5 шт) (только с опорой на объясненную в данном уроке теорию)
1. Построение базовой матрицы ошибок 2x2
Задача: Дана бинарная матрица ошибок: numpy.array([[90, 10], [5, 95]]). Создайте холст и осей, отобразите массив через .imshow() с последовательной палитрой "Blues".
Посмотреть решение
python
import numpy
import matplotlib.pyplot
binary_matrix = numpy.array([[90, 10], [5, 95]])
# Drawing a standard 2x2 confusion matrix array layout
fig, ax = matplotlib.pyplot.subplots()
ax.imshow(binary_matrix, cmap="Blues")2. Маркировка координатных осей классов
Задача: На основе матрицы из прошлого упражнения настройте деления осей так, чтобы вместо индексов 0 и 1 на графике отображались текстовые метки классов ["Negative", "Positive"] по обеим осям.
Посмотреть решение
python
import numpy
import matplotlib.pyplot
binary_matrix = numpy.array([[90, 10], [5, 95]])
classes_labels = ["Negative", "Positive"]
fig, ax = matplotlib.pyplot.subplots()
ax.imshow(binary_matrix, cmap="Blues")
# Binding categorical text descriptions to coordinates ticks anchors
ax.set_xticks([0, 1])
ax.set_yticks([0, 1])
ax.set_xticklabels(classes_labels)
ax.set_yticklabels(classes_labels)3. Аннотирование осей («Predicted» против «Actual»)
Задача: Добавьте к текущей координатной сетке матрицы ошибок обязательный контекст: заголовок "Binary Classification Confusion Matrix", подпись оси X — "Predicted Class", подпись оси Y — "Actual Class".
Посмотреть решение
python
import numpy
import matplotlib.pyplot
fig, ax = matplotlib.pyplot.subplots()
ax.imshow(numpy.zeros((2, 2)))
# Attaching descriptive validation strings to text components nodes
ax.set_title("Binary Classification Confusion Matrix")
ax.set_xlabel("Predicted Class")
ax.set_ylabel("Actual Class")4. Наложение численных значений поверх ячеек бинарной матрицы
Задача: Напишите двойной вложенный цикл for, который с помощью метода ax.text() напечатает точные численные значения поверх ячеек матрицы numpy.array([[88, 12], [4, 96]]), отцентрировав текст по центру пиксельных квадратов.
Посмотреть решение
python
import numpy
import matplotlib.pyplot
matrix_data = numpy.array([[88, 12], [4, 96]])
fig, ax = matplotlib.pyplot.subplots()
ax.imshow(matrix_data, cmap="Greens")
# Iterating coordinates cells to overlay text metrics dynamically
for row in range(2):
for col in range(2):
cell_num = matrix_data[row, col]
ax.text(x=col, y=row, s=str(cell_num), ha="center", va="center")5. Динамическое изменение цвета текста аннотаций для читаемости
Задача: Если ячейка матрицы окрашена в очень темный цвет, черный текст поверх нее станет нечитаемым. Напишите логику внутри цикла: если значение ячейки матрицы matrix[i, j] больше 50, цвет текста color в методе ax.text() должен быть белым ("white"), иначе — черным ("black").
Посмотреть решение
python
import numpy
import matplotlib.pyplot
matrix = numpy.array([[95, 5], [15, 85]])
fig, ax = matplotlib.pyplot.subplots()
ax.imshow(matrix, cmap="Reds")
for i in range(2):
for j in range(2):
val = matrix[i, j]
# Conditional threshold styling logic to preserve text contrast readability
text_color = "white" if val > 50 else "black"
ax.text(x=j, y=i, s=str(val), ha="center", va="center", color=text_color)Упражнения смешанные (5 шт) (включают материал прошлых уроков)
6. Headless-генерация Confusion Matrix на базе предсказаний и истинных ответов NumPy
Задача: В ходе инференса модели классификации токенов получены два целочисленных массива numpy.int8 (Урок 4 модуля NumPy): истинные метки y_true = numpy.array([0, 1, 2, 0, 1, 2]) и ответы модели y_pred = numpy.array([0, 2, 2, 0, 1, 1]). Напишите ручной расчет матрицы ошибок 3x3: создайте пустую матрицу из нулей размера (3, 3) (Урок 11 модуля NumPy) и в цикле for t, p in zip(y_true, y_pred): сделайте инкремент соответствующих ячеек matrix[t, p] += 1 (Урок 8 модуля NumPy). Переведите Matplotlib в headless-режим (Урок 3 модуля Matplotlib). Отрендерите полученную матрицу ошибок через ax.imshow() с палитрой "Oranges" (Урок 10 модуля Matplotlib). Добавьте подписи осей, числовые значения в центре ячеек и экспортируйте результат в файл "mnist_debug.png" (Урок 3 / Урок 10 модуля Matplotlib).
Посмотреть решение
python
import numpy
import matplotlib
# Locking non-interactive visualization state for server pipelines (Lesson 3)
matplotlib.use('Agg')
import matplotlib.pyplot
y_true = numpy.array([0, 1, 2, 0, 1, 2], dtype=numpy.int8)
y_pred = numpy.array([0, 2, 2, 0, 1, 1], dtype=numpy.int8)
# Step 1: Manual calculation of 3x3 confusion matrix allocation blocks (NumPy Lessons 8 & 11)
confusion_matrix = numpy.zeros((3, 3), dtype=numpy.int32)
for true_label, pred_label in zip(y_true, y_pred):
confusion_matrix[true_label, pred_label] += 1
# Step 2: Establish Explicit Canvas Environment (Matplotlib Lesson 2)
fig, ax = matplotlib.pyplot.subplots(figsize=(6, 6))
img = ax.imshow(confusion_matrix, cmap="Oranges")
# Step 3: Axis labeling and context layout (Matplotlib Lesson 10)
classes = ["Class A", "Class B", "Class C"]
ax.set_xticks(range(3))
ax.set_yticks(range(3))
ax.set_xticklabels(classes)
ax.set_yticklabels(classes)
ax.set_title("Token Classifier Confusion Matrix Report")
ax.set_xlabel("Predicted Class")
ax.set_ylabel("Actual Class")
# Step 4: Programmatic cells text annotation loops
for i in range(3):
for j in range(3):
val = confusion_matrix[i, j]
ax.text(x=j, y=i, s=str(val), ha="center", va="center")
# Export directly to server file system block (Matplotlib Lesson 3)
fig.savefig("mnist_debug.png")7. Визуализация матрицы ошибок табличного батча логов из Parquet-файла Pandas
Задача: Загрузите файл выгрузки инференса классификатора "predictions_logs.parquet" (Урок 8 модуля Pandas). В нем содержатся два числовых столбца: "actual_label" и "predicted_label" (Урок 5 модуля Pandas). С помощью встроенного в Pandas мощного инструмента кросс-табуляции pandas.crosstab(df["actual_label"], df["predicted_label"]) постройте двумерную матрицу сопряженности (это готовый DataFrame-вариант Confusion Matrix). Настройте headless-режим (Урок 3 модуля Matplotlib). Оберните полученную кросс-таблицу в тепловую карту ax.imshow(), выбрав палитру "Blues" (Урок 10 модуля Matplotlib). Настройте подписи осей именами уникальных классов из метаданных таблицы и запишите результат в "pandas_confusion_matrix.png".
Посмотреть решение
python
import pandas
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot
# Loading tabular dataset tracking elements from disk (Pandas Lesson 8)
logs_df = pandas.read_parquet(path="predictions_logs.parquet")
# Computing cross-tabulation table which represents the confusion matrix (Pandas Lesson 5)
cross_tab_matrix = pandas.crosstab(logs_df["actual_label"], logs_df["predicted_label"])
fig, ax = matplotlib.pyplot.subplots(figsize=(7, 7))
img = ax.imshow(cross_tab_matrix.values, cmap="Blues")
ax.set_title("Cross-tabulation Inference Validation Profile")
ax.set_xlabel("Predicted Label")
ax.set_ylabel("Actual Label")
# Binding coordinate index ticks names directly from dataframe headers text strings
class_names = [str(name) for name in cross_tab_matrix.columns]
ax.set_xticks(range(len(class_names)))
ax.set_yticks(range(len(class_names)))
ax.set_xticklabels(class_names)
ax.set_yticklabels(class_names)
fig.colorbar(img, ax=ax) # Attaching data metrics scale bar (Matplotlib Lesson 9)
fig.tight_layout()
fig.savefig("pandas_confusion_matrix.png")8. Аннотирование подматрицы ошибок классификации после очистки NaN и дубликатов
Задача: Прочитайте текстовый файл логов тестирования "raw_validation_runs.csv", ограничив загрузку столбцами ["true_class", "pred_class"] (Урок 8 модуля Pandas). Удалите из таблицы полностью идентичные строки-дубликаты (Урок 9 модуля Pandas). Заполните все оставшиеся случайные пропуски NaN константой 0 на месте (Урок 9 модуля Pandas). Выделите из таблицы компактный батч первых двух строк с помощью позиционного среза .iloc[0:2] (Урок 6 модуля Pandas) и переведите полученную подматрицу 2x2 в сырой массив NumPy методом .to_numpy() (Урок 11 модуля Pandas). В неинтерактивном headless-режиме постройте тепловую карту этой матрицы ошибок 2x2 (Урок 10). Наложите точные числовые значения поверх ячеек с динамической настройкой контрастного цвета текста: белый, если значение больше 10, иначе черный (Урок 10). Сохраните в "sanitized_confusion_matrix.png".
Посмотреть решение
python
import pandas
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot
# Loading raw telemetry streams from disk (Pandas Lesson 8)
raw_df = pandas.read_csv(filepath_or_buffer="raw_validation_runs.csv", usecols=["true_class", "pred_class"])
# Purging duplicate pattern strings and patching missing slots flags (Pandas Lesson 9)
raw_df.drop_duplicates(inplace=True)
raw_df.fillna(0, inplace=True)
# Slicing target sub-matrix coordinate blocks and exporting to array format (Pandas Lessons 6 & 11)
matrix_2d = raw_df.iloc[0:2, :].to_numpy()
fig, ax = matplotlib.pyplot.subplots()
ax.imshow(matrix_2d, cmap="Purples")
ax.set_title("Sanitized Validation Runs Subset 2x2")
ax.set_xlabel("Predicted Model Output")
ax.set_ylabel("Actual Reference Value")
# Dual nested loops executing precision text color contrast adjustments (Matplotlib Lesson 10)
for i in range(2):
for j in range(2):
scalar_val = matrix_2d[i, j]
text_color = "white" if scalar_val > 10 else "black"
ax.text(x=j, y=i, s=str(scalar_val), ha="center", va="center", color=text_color)
fig.savefig("sanitized_confusion_matrix.png")9. Мультипанельное side-by-side сравнение двух матриц ошибок разных архитектур ИИ
Задача: Даны две матрицы ошибок размером 2x2 для двух разных моделей: model_resnet = numpy.array([[85, 15], [10, 90]]) и model_vit = numpy.array([[95, 5], [2, 98]]) (Урок 11 модуля NumPy). Настройте неинтерактивный режим работы (Урок 3). Создайте мультипанельный холст, состоящий из 1 строки и 2 столбцов графиков (Урок 8 модуля Matplotlib). В первом окне (axes) постройте тепловую карту ошибок для ResNet с палитрой "Oranges" (Урок 10). Во втором окне (axes) постройте тепловую карту для ViT с палитрой "Greens". Подпишите оси классов ["Class 0", "Class 1"] для обеих панелей (Урок 10). Примените метод выравнивания отступов fig.tight_layout() и выгрузите итоговый холст сравнения архитектур в файл "models_confusion_comparison.png".
Посмотреть решение
python
import numpy
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot
model_resnet = numpy.array([[85, 15], [10, 90]])
model_vit = numpy.array([[95, 5], [2, 98]])
classes = ["Class 0", "Class 1"]
# Creating a synchronized 1x2 layout dashboard grid (Matplotlib Lesson 8)
fig, axes = matplotlib.pyplot.subplots(nrows=1, ncols=2, figsize=(12, 5))
# Left panel: ResNet analytics (Matplotlib Lesson 10)
axes.imshow(model_resnet, cmap="Oranges")
axes.set_title("ResNet Architecture Confusion Matrix")
axes.set_xticks([0, 1])
axes.set_yticks([0, 1])
axes.set_xticklabels(classes)
axes.set_yticklabels(classes)
axes.set_xlabel("Predicted")
axes.set_ylabel("Actual")
# Right panel: ViT analytics
axes.imshow(model_vit, cmap="Greens")
axes.set_title("ViT Architecture Confusion Matrix")
axes.set_xticks([0, 1])
axes.set_yticks([0, 1])
axes.set_xticklabels(classes)
axes.set_yticklabels(classes)
axes.set_xlabel("Predicted")
axes.set_ylabel("Actual")
fig.tight_layout()
fig.savefig("models_confusion_comparison.png")10. Сквозной поиск документации по методам изменения делений шкал set_xticks в Jupyter
Задача: Напишите строку кода для выполнения в ячейке Jupyter Notebook, которая открывает интерактивную Docstring-инструкцию по встроенному методу конфигурации подписей и делений координатных осей matplotlib.axes.Axes.set_xticks с помощью символа интроспекции (Урок 1 модуля NumPy / Урок 1 модуля Pandas).
Посмотреть решение
python
import matplotlib.axes
# Running this cell evaluation line pulls up the complete ticks configuration constraints guide
?matplotlib.axes.Axes.set_xticks