partial_fit в scikit-learn: обучение порциями без сброса модели
Новые размеченные примеры поступают каждый день. Полностью переобучать модель после каждой порции неудобно, а вызов fit на очередном файле обычно начнёт обучение заново. Нужен алгоритм с отдельной операцией продолжения.
Проверить поддержку инкрементального обучения
Метод partial_fit есть у ограниченного набора estimator. У SGDClassifier он выполняет одну эпоху по переданной порции и сохраняет состояние для следующего вызова. Размер порций, порядок примеров и число проходов становятся частью процедуры обучения. Заменять fit на partial_fit у произвольной модели нельзя: у неё может вообще не быть такого метода.
При первом вызове классификатору нужен полный набор возможных классов. Первая порция может содержать только класс 0, но модель должна заранее знать о будущем классе 1. Параметр classes задаёт пространство ответов. В следующих вызовах его можно не повторять, если состав классов остаётся прежним.
Отделить состояние модели от порции
Объект создаётся один раз перед циклом. Каждая итерация получает новую порцию X и y и обновляет тот же estimator. Если перенести конструктор внутрь цикла, модель будет забывать прошлое. Если вызвать fit между partial_fit, часть обучающего состояния, включая счётчик шагов, будет сброшена.
В примере признаки уже находятся в сопоставимом небольшом диапазоне. Для SGD это существенно: разные масштабы влияют на обновления весов. Если добавляете преобразования, их способ обновления тоже должен быть определён для потока. Обычный Pipeline не превращает все шаги автоматически в инкрементальные.
from sklearn.linear_model import SGDClassifier
batches = [
([[-2.0], [-1.0]], [0, 0]),
([[1.0], [2.0]], [1, 1]),
([[-1.5], [1.5]], [0, 1]),
]
model = SGDClassifier(loss="log_loss", random_state=7,
learning_rate="constant", eta0=0.1,
shuffle=False)
steps = []
for index, (X, y) in enumerate(batches):
if index == 0:
model.partial_fit(X, y, classes=[0, 1])
else:
model.partial_fit(X, y)
steps.append(model.t_)
assert model.classes_.tolist() == [0, 1]
assert steps == [3.0, 5.0, 7.0]
prediction = model.predict([[-2.0], [2.0]])
assert prediction.tolist() == [0, 1]
print("steps:", steps, "predictions:", prediction.tolist())Что сохранять между запусками
Сохраните обученный estimator целиком и положение в потоке. Коэффициентов недостаточно для точного продолжения: алгоритм использует дополнительное состояние. Каждая порция должна быть учтена ровно столько раз, сколько предполагает процедура обучения. Повтор после сбоя может незаметно обучить модель на тех же строках второй раз.
Счётчик t_ в примере подтверждает, что обновления продолжались. Он не измеряет полезность модели на будущих данных. Для выбора режима обучения потребуется отдельная отложенная проверка, а для эксплуатации — понятная граница публикации новой версии. Обучающий объект лучше не менять одновременно с использованием его для прогнозов.
Закрепить базовую операцию
В открытой практике вы создадите estimator, вызовете fit и получите прогноз через predict. Это основа, с которой удобно сравнить отдельную операцию продолжения partial_fit. Откройте урок «Первый fit и predict на своих данных». Затем вернитесь к сценарию статьи и проверьте его на своём небольшом наборе. Посмотрите программу курса первой ML-модели, чтобы пройти путь от обучения к использованию результата.
Продолжить на практике
- Машинное обучение с нуля на Python: первая модель ↗
Бесплатный курс машинного обучения на Python: обучите первую модель в scikit-learn, проверьте её качество и решите 106 задач в браузере.
