Повторный fit в scikit-learn: как не перезаписать готовую модель

В словарь результатов добавили модель для каждого набора параметров. После цикла у всех записей одинаковые коэффициенты. Причина может оказаться проще случайности обучения: в словарь несколько раз положили один объект, а следующий fit изменял его на месте.

Модель хранит результат внутри себя

Конструктор LinearRegression создаёт объект с настройками. После fit у этого же объекта появляются коэффициенты coef_ и свободный член intercept_. Метод fit возвращает сам estimator. Поэтому присваивание trained = estimator.fit(X, y) удобно для цепочки вызовов, но не создаёт новую обученную модель.

Словарь и список хранят ссылки на объекты. Если добавлять один estimator под разными ключами, новые ключи не замораживают старое состояние. Для экспериментов нужно создавать отдельный объект до каждого обучения. Тогда изменение следующего кандидата не затронет результат предыдущего. Это правило относится к жизненному циклу Python-объекта и не зависит от выбранной метрики.

Когда нужен clone

sklearn.base.clone переносит параметры estimator в новый необученный объект. Он полезен, когда прототип уже содержит настроенную структуру: например, выбранный алгоритм и его параметры. Обученное состояние в такой копии отсутствует. Проверять готовность следует через check_is_fitted или попытку predict с ожидаемым NotFittedError, а не через наличие знакомого имени переменной.

В примере исходный шаблон намеренно уже обучен. Это помогает увидеть границу clone: первая копия получает настройки, но не коэффициенты. Два новых обучения используют одинаковые входные значения и разные целевые зависимости. Полученные предсказания различаются, а шаблон продолжает давать первоначальный ответ.

Независимое обучение двух кандидатов

Сохраните код в отдельный файл и выполните в окружении со scikit-learn. Используются настоящие LinearRegression и clone. Числа в проверках следуют из двух прямых зависимостей: удвоения входа и удвоения с добавлением десяти. Для вещественных результатов применяется допуск.

from sklearn.base import clone
from sklearn.linear_model import LinearRegression
from sklearn.exceptions import NotFittedError
from sklearn.utils.validation import check_is_fitted

X = [[0], [1], [2], [3]]
template = LinearRegression().fit(X, [0, 2, 4, 6])
fresh = clone(template)
try:
    check_is_fitted(fresh)
except NotFittedError:
    pass
else:
    raise AssertionError("clone must be unfitted")

models = {}
for name, target in [("base", [0, 2, 4, 6]),
                     ("shifted", [10, 12, 14, 16])]:
    models[name] = clone(template).fit(X, target)

assert models["base"] is not models["shifted"]
assert abs(models["base"].predict([[4]])[0] - 8) < 1e-9
assert abs(models["shifted"].predict([[4]])[0] - 18) < 1e-9
assert abs(template.predict([[4]])[0] - 8) < 1e-9
print({name: model.predict([[4]]).tolist()
       for name, model in models.items()})

Сохранить модель и клонировать настройки — разные действия

Если нужен экземпляр с уже найденными коэффициентами для нового процесса, clone не подходит. Такой объект сохраняют выбранным способом сериализации и загружают в совместимом окружении. Если нужен новый эксперимент с теми же настройками, используйте clone. Разделение полезно закрепить в именах: template для прототипа, fitted_model для результата обучения.

Повторный fit у большинства estimator начинает обучение заново. У отдельных алгоритмов есть warm_start, который меняет это поведение при соблюдении условий конкретного класса. Не используйте его как универсальную замену независимым экспериментам: тогда кандидаты начнут зависеть от порядка запуска. Для сравнения конфигураций проще оставить прототип неизменным и обучать его копии.

Начать с наблюдаемого fit и predict

В открытом уроке «Первый fit и predict на своих данных» вы создадите estimator, обучите его и получите прогноз. Повторите этот путь для двух отдельных объектов, затем вернитесь к clone из статьи. Откройте программу курса первой ML-модели, чтобы связать обучение с использованием результата и сохранением модели.

Продолжить на практике