Запуск процесса Fine-tuning: Гиперпараметры и мониторинг

50 минут Урок 22

Урок 5.2: Запуск процесса Fine-tuning: Гиперпараметры и мониторинг

Приветствую, коллеги. Мы переходим от подготовки данных к самому интересному этапу — «магии» обучения. Если подготовка датасета была закладкой фундамента, то запуск процесса файн-тюнинга (Fine-tuning) — это возведение стен. И здесь роль архитектора решений становится критической.

Многие думают, что файн-тюнинг — это просто вызов метода create_tuned_model и ожидание чуда. На уровне Junior-разработчика это, возможно, так. Но на уровне Architect мы должны понимать, что происходит «под капотом», как управлять процессом через гиперпараметры и, самое главное, как интерпретировать метрики в реальном времени, чтобы не сжечь бюджет на бесполезную модель.

В этом уроке мы разберем:

  • Анатомию запуска: Как Gemini API управляет задачами обучения.
  • Гиперпараметры: Эпохи, батчи и learning rate — что мы можем контролировать, а что Google берет на себя.
  • Мониторинг: Как читать графики функции потерь (Loss) и распознавать переобучение на ранних стадиях.

Гиперпараметры: Рычаги управления

В машинном обучении гиперпараметры — это настройки, которые вы задаете до начала обучения. Они определяют, как модель будет учиться. В экосистеме Gemini API Google стремится к максимальной автоматизации (AutoML), но оставляет нам ключевые рычаги влияния.

Рассмотрим «Святую Троицу» настроек тюнинга:

1. Эпохи (Epochs)

Эпоха — это один полный проход алгоритма обучения через весь ваш обучающий набор данных.

  • Мало эпох (1-3): Модель может недоучиться (underfitting). Она увидит примеры, но не успеет сформировать устойчивые нейронные связи для новых паттернов.
  • Много эпох (10+): Риск переобучения (overfitting). Модель начнет просто «зубрить» ваши примеры наизусть, вместо того чтобы понять принцип. На новых данных она будет бесполезна.
  • Рекомендация архитектора: Для малых датасетов (< 500 примеров) часто требуется больше эпох (5-10), чтобы «вбить» знания. Для крупных датасетов (> 10,000 примеров) может хватить и 1-3 эпох.

2. Размер батча (Batch Size)

Модель не учится на всех данных сразу. Она берет кусочек данных (батч), делает предсказание, смотрит на ошибку и обновляет веса.

  • Большой батч дает более стабильную, но усредненную оценку градиента. Это быстрее считается, но требует больше памяти (что на стороне Google Cloud нас волнует меньше, но влияет на лимиты).
  • Gemini API часто управляет этим параметром автоматически, но понимание принципа важно для оценки скорости обучения.

3. Learning Rate (Скорость обучения)

Это размер шага, который модель делает в сторону минимизации ошибки.

  • Слишком большой шаг: Модель будет «прыгать» вокруг правильного решения, но никогда в него не попадет. График Loss будет скакать.
  • Слишком маленький шаг: Обучение займет вечность, и модель может застрять в локальном минимуме (неоптимальном решении).
  • В Gemini мы часто используем Learning Rate Multiplier — множитель к базовой скорости обучения, которую выбрал Google. Значение 1.0 — стандарт. 0.1 — аккуратное обучение, 2.0 — агрессивное.

python
import google.generativeai as genai
import time

# Настройка API ключа
genai.configure(api_key="YOUR_API_KEY")

# 1. Подготовка файла (предполагаем, что файл уже загружен и есть его имя)
# training_file_name = "tuned_data_v1.jsonl"

# 2. Настройка параметров запуска
# Обратите внимание: мы задаем уникальное id для модели
model_id = "gemini-tech-support-bot-v01"

operation = genai.create_tuned_model(
    # Базовая модель, которую мы дообучаем
    source_model="models/gemini-1.5-flash-001-tuning",
    
    # Данные для обучения
    training_data="tuned_data_v1.jsonl",
    
    # Идентификатор вашей новой модели
    id=model_id,
    
    # Название для отображения в консоли
    display_name="Tech Support Assistant (Epoch 5)",
    
    # ГИПЕРПАРАМЕТРЫ
    epoch_count=5,  # 5 полных проходов по данным
    batch_size=4,   # Размер пакета данных (зависит от размера датасета)
    learning_rate=0.001, # Явное задание LR (или используйте multiplier)
)

print(f"Запущена операция тюнинга: {operation.name}")

# Модель не создается мгновенно. Это асинхронная операция.
# Ссылка на модель будет доступна сразу, но статус будет 'creating'"

Мониторинг: Пульс вашего ИИ

После запуска кода выше, самая большая ошибка — уйти пить кофе на 2 часа и вернуться только к результату. Как архитектор, вы должны уметь диагностировать проблемы в процессе.

Ключевая метрика, за которой мы следим — Loss (Функция потерь). Это число, которое показывает, насколько сильно предсказание модели отличается от идеального ответа в вашем датасете.

Паттерны кривой обучения (Loss Curve):

  1. Идеальный спуск: Линия начинается высоко и плавно снижается, постепенно выходя на плато. Это значит, модель учится.
  2. Отсутствие сходимости: Линия прямая или хаотично скачет вверх-вниз.
    Причины: «Грязные» данные, слишком высокий Learning Rate, неправильный формат данных.
  3. Резкий обрыв в ноль: Если Loss падает почти до нуля слишком быстро.
    Диагноз: Переобучение (Overfitting). Модель просто запомнила ответы. На реальных данных она провалится.
  4. Рост ошибки (Divergence): Loss начинает снижаться, а потом резко идет вверх.
    Диагноз: Слишком агрессивное обучение, модель «сломала» свои веса.

В Gemini API мы можем получать метрики периодически, пока идет процесс state=ACTIVE.

python
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

# Функция для визуализации процесса обучения
def plot_loss_curve(model_name):
    model = genai.get_tuned_model(model_name)
    
    # Получаем снимки состояния (snapshots) обучения
    snapshots = model.tuning_task.snapshots
    
    data = []
    for snap in snapshots:
        # Извлекаем среднюю ошибку и номер шага/эпохи
        data.append({
            "step": snap.step,
            "epoch": snap.epoch,
            "mean_loss": snap.mean_loss
        })
        
    if not data:
        print("Данных для графика пока нет.")
        return

    df = pd.DataFrame(data)
    
    # Рисуем график
    plt.figure(figsize=(10, 6))
    sns.lineplot(data=df, x="step", y="mean_loss", marker="o")
    plt.title(f"Кривая обучения (Loss Curve): {model_name}")
    plt.xlabel("Шаги обучения (Steps)")
    plt.ylabel("Loss (Ошибка)")
    plt.grid(True)
    plt.show()

# Проверка статуса в цикле (простой поллинг)
import time

my_model_name = f"tunedModels/{model_id}"

while True:
    model_info = genai.get_tuned_model(my_model_name)
    status = model_info.state.name
    print(f"Текущий статус: {status}")
    
    if status == 'ACTIVE':
        print("Обучение завершено!")
        plot_loss_curve(my_model_name)
        break
    elif status == 'FAILED':
        print("Обучение упало с ошибкой.")
        print(model_info.tuning_task.error_message)
        break
        
    # Ждем 60 секунд перед следующей проверкой
    time.sleep(60)

Стратегия "Early Stopping" (Ручная эмуляция)

В классическом ML есть понятие Early Stopping — остановка обучения, если ошибка на проверочной выборке перестала падать. В API Gemini на данный момент мы часто задаем фиксированное количество эпох.

Совет Архитектора:
Если вы не уверены в гиперпараметрах, запустите эксперимент с запасом эпох (например, 10), но внимательно следите за графиком. Если вы видите, что на 4-й эпохе Loss вышел на плато и перестал значимо меняться (изменения < 0.01), дальнейшее обучение — это пустая трата ресурсов и риск переобучения.

Хотя вы не всегда можете остановить процесс «на лету» и сохранить промежуточный чекпоинт (в зависимости от текущей версии API), вы можете использовать эти данные для следующего запуска, выставив epoch_count=4.

Чек-лист перед запуском в Production-обучение:

  • [ ] Валидация данных: Прошел ли датасет проверку на формат и отсутствующие поля?
  • [ ] Бейзлайн: Проверили ли вы промпты на базовой модели? Если базовая модель справляется на 80%, нужен ли вам тюнинг?
  • [ ] Стоимость: Оценили ли вы количество токенов в датасете * количество эпох? Это определяет бюджет.

Упражнение

Сценарий: Вы обучаете модель для генерации SQL-запросов по естественному языку. Датасет: 500 примеров. Вы запустили обучение на 20 эпох. На графике вы видите, что Loss падал до 5-й эпохи (до значения 0.3), а затем к 20-й эпохе упал до 0.001. При тестировании модель идеально отвечает на запросы из обучающей выборки, но выдает синтаксический мусор на совершенно новых запросах.<br><br>Задание: <br>1. Диагностируйте проблему.<br>2. Предложите изменение гиперпараметров для следующего запуска.

Вопрос

Какой показатель на графике обучения (Loss Curve) наиболее явно сигнализирует о том, что процесс обучения идет нормально и модель усваивает закономерности?