Checkpoint SGD: продолжить обучение после перезапуска
Обучение через partial_fit прошло две порции из трёх и остановилось. В файле есть коэффициенты, но простое присваивание coef_ новому estimator не восстановит весь процесс. Для продолжения важны и дополнительные параметры состояния алгоритма.
Сохранять объект вместе с положением в данных
SGDClassifier хранит не только coef_ и intercept_, но и состояние процедуры обновления. Например, счётчик шагов влияет на расписание скорости обучения. Сериализация estimator целиком сохраняет эти сведения. Рядом нужен номер следующей порции и идентификатор снимка данных, иначе модель может повторно увидеть уже обработанные строки.
Пример использует неизменный список трёх порций и shuffle=False. Эталонный объект проходит все порции подряд. Второй объект проходит первые две, сохраняется через joblib, загружается новым объектом и получает только оставшуюся порцию. Проверяем состояние и ответы против непрерывного обучения.
Сначала сделать точный локальный контроль
Учебная проверка выполняет реальную запись и загрузку доверенного локального файла. Положение next_batch соответствует уже обновлённому estimator. В рабочем процессе эти две части должны публиковаться как согласованный checkpoint: новый файл сначала полностью записывают, затем делают доступным для возобновления.
Если процесс завершится между обновлением модели и сохранением checkpoint, продолжение идёт от предыдущего полного checkpoint и повторяет соответствующую порцию. Это нормально только при неизменном входе и понятном учёте. Не записывайте next_batch заранее, до завершения обновления.
from pathlib import Path
from tempfile import TemporaryDirectory
import joblib
from sklearn.linear_model import SGDClassifier
batches = [([[-2], [-1]], [0, 0]), ([[1], [2]], [1, 1]),
([[-1.5], [1.5]], [0, 1])]
def fresh():
return SGDClassifier(loss="log_loss", random_state=11, shuffle=False)
def update(model, start, stop):
for index in range(start, stop):
X, y = batches[index]
if index == 0:
model.partial_fit(X, y, classes=[0, 1])
else:
model.partial_fit(X, y)
reference = fresh()
update(reference, 0, 3)
interrupted = fresh()
update(interrupted, 0, 2)
with TemporaryDirectory() as directory:
path = Path(directory) / "checkpoint.joblib"
joblib.dump({"model": interrupted, "next_batch": 2,
"snapshot": "demo-v1"}, path)
state = joblib.load(path)
assert state["snapshot"] == "demo-v1"
resumed = state["model"]
assert resumed is not interrupted
update(resumed, state["next_batch"], 3)
assert resumed.t_ == reference.t_
assert resumed.coef_.tolist() == reference.coef_.tolist()
assert resumed.intercept_.tolist() == reference.intercept_.tolist()
assert resumed.predict([[-2], [2]]).tolist() == reference.predict([[-2], [2]]).tolist()
print("restored training step:", resumed.t_)Что добавляется в настоящем потоке
Нужны устойчивые границы порций, версия схемы признаков и версия обучающего кода. Если порядок строк при повторном чтении меняется, тот же номер порции уже не задаёт тот же вход. При случайном перемешивании сохраните его расписание или состояние источника случайности.
Обучающий checkpoint также лучше отделять от модели, опубликованной для прогнозов. Продолжение может временно ухудшить поведение, а объект обновляется на месте. Сначала завершите выбранный этап обучения и проверку, затем опубликуйте новую неизменяемую версию для потребителей.
Закрепить базовую операцию
Открытый урок сохранения через joblib даёт базовый цикл dump и load. Используйте его для целого estimator и добавьте к артефакту положение в данных, необходимое для продолжения обучения. Откройте урок «Сохранение обученной модели через joblib». Затем вернитесь к сценарию статьи и проверьте его на своём небольшом наборе. Посмотрите программу курса первой ML-модели, чтобы пройти путь от обучения к использованию результата.
Продолжить на практике
- Машинное обучение с нуля на Python: первая модель ↗
Бесплатный курс машинного обучения на Python: обучите первую модель в scikit-learn, проверьте её качество и решите 106 задач в браузере.
