Визуализация ошибок, как навигатор к скрытым проблемам модели
Визуализация — это язык, который позволяет нам видеть данные и понимать их смысл. Простой и эффективный способ диагностики результатов работы модели на различных объектах заключается в анализе разницы между прогнозами и целями. Он может показать, что в некоторых группах поведение модели имеет особенности (например, склонность к завышению или занижению прогнозов). Для демонстрации того, как строится такая визуализация загрузим набор данных:
from sklearn.datasets import load_diabetes import pandas as pd import numpy as np import matplotlib.pyplot as plt np.random.seed(0) df, y = load_diabetes(return_X_y=True, as_frame=True) df['target'] = y display(df.head()) display(df.shape)
Разобьем датасет на две группы для обучения и оценки:
from sklearn.model_selection import train_test_split
X_tr, X_ts, y_tr, y_ts = train_test_split(df.drop(columns='target').copy(),
df['target'], test_size=0.2)
y_tr.shape[0], y_ts.shape[0]Теперь построим модель и сделаем предсказания:
from sklearn.linear_model import LinearRegression model = LinearRegression() model.fit(X_tr, y_tr) y_p = model.predict(X_ts)
Аналитический прием, о котором шла речь выше, заключается в визуализации распределения разности между целями и прогнозами (ошибками). Это можно сделать, например, путем построения гистограммы или графика разброса точек с координатами по оси y - ошибки, x - предсказания. Объявим функцию с соответствующими свойствами и вызовем ее:
def plot_residuals(target, predictions, bins_num, figsize=(20, 8), style='seaborn'):
error = target - predictions
with plt.style.context(style=style):
plt.figure(figsize=figsize)
plt.suptitle(f'Анализ ошибок', fontsize=16)
plt.subplot(1, 2, 1)
plt.hist(error, edgecolor='blue', bins=bins_num)
plt.axvline(x=0, color='black', label='ноль', linestyle='--')
plt.axvline(x=error.median(), color='red', label='медиана')
plt.axvline(x=error.mean(), color='orange', label='среднее')
plt.title(f'Гистограмма ошибок', fontsize=15)
plt.ylabel('плотность распределения', fontsize=14)
plt.xlabel('ошибки', fontsize=14)
plt.legend()
plt.subplot(1, 2, 2)
plt.scatter(predictions, error, alpha=0.4)
plt.axhline(y=0, color='red', label='ноль', linestyle='--')
plt.title(f'Анализ дисперсии ошибок', fontsize=15)
plt.ylabel('ошибки', fontsize=14)
plt.xlabel('предсказания модели', fontsize=14)
plot_residuals(y_ts, y_p, bins_num = 10, figsize=(20, 5), style='bmh')
На графике ошибки распределены равномерно относительно нуля, их среднее и медиана почти совпадают и равны 0.
Аналогичные графики можно построить с библиотекой sklearn (потребуется использовать метод from_predictions класса PredictionErrorDisplay из модуля sklearn.metrics):
from sklearn.metrics import PredictionErrorDisplay PredictionErrorDisplay.from_predictions(y_ts, y_p)
По оси y можно вывести вместо ошибок реальные значения (цели) против предсказанных по оси x:
PredictionErrorDisplay.from_predictions(y_ts, y_p, kind='actual_vs_predicted')
А теперь для демонстрационных целей добавим выброс в виде новой точки с очень большой целью и снова обучим модель:
model.fit(pd.concat([X_tr, X_tr.iloc[[-1]]]),
pd.concat([y_tr.to_frame(), pd.Series([1e10]).to_frame('target')])['target'])
y_p = model.predict(X_ts)
plot_residuals(y_ts, y_p, bins_num = 10, figsize=(20, 5), style='bmh')После обучения на большом выбросе, модель для одних точек стала сильно занижать предсказания, а для других - завышать. Такой эффект может быть вызван не только выбросами в обучающих данных, но и простотой модели, плохими признаками. Например, вы пытаетесь предсказать цену квартиры, основываясь только на площади, и не учитываете особенности района, близость к метро. Тогда, если в датасете имеется перекос в сторону квартир из элитных райнов, фактор площади может остаться недооцененным.
Таким образом, неравномерность распределения ошибок относительно нуля является индикатором того, что модель требует доработки и оптимизации, а причины могут от случая к случаю меняться.