Подготовка и очистка датасетов для обучения Gemini

50 минут Урок 22

Введение: Данные — это новое топливо для вашего AI

Добро пожаловать на пятый модуль. Мы подходим к одной из самых критически важных тем во всем курсе: Fine-Tuning (дообучение). Но прежде чем мы нажмем кнопку «Start Tuning» в консоли Google Cloud или запустим скрипт API, нам нужно поговорить о фундаменте.

В машинном обучении есть золотое правило, которое не меняется десятилетиями: Garbage In, Garbage Out (Мусор на входе — мусор на выходе). Gemini 3 — это невероятно мощная модель, обладающая огромным контекстным окном и способностью к сложным рассуждениям. Однако, если вы попытаетесь дообучить её на несогласованных, «грязных» или плохо отформатированных данных, вы не просто не улучшите её работу — вы можете вызвать так называемую катастрофическую забывчивость (catastrophic forgetting), когда модель теряет свои базовые способности.

В этом уроке мы не будем писать сложные нейросети. Мы займемся работой «data engineer'а»: подготовкой, очисткой и форматированием датасетов. Это 80% успеха любого проекта по дообучению.

Анатомия идеального датасета для Gemini

Для начала разберемся с форматом. Gemini API ожидает данные в специфическом формате JSONL (JSON Lines). В отличие от обычного JSON, где весь файл — это один большой объект или массив, в JSONL каждая строка — это отдельный валидный JSON-объект. Это позволяет эффективно обрабатывать гигантские файлы потоком, не загружая всё в оперативную память.

Каждый пример для обучения должен содержать структуру, отражающую то, как вы планируете использовать модель. Для Gemini 3 типичная структура выглядит так:

  • messages: массив сообщений, имитирующий диалог.
  • role: роль участника ('user' или 'model').
  • content: само содержание сообщения.

Важный нюанс: Если вы используете системные инструкции (System Instructions) в продакшене, их также желательно включать в процесс подготовки данных или учитывать контекст, который они создают, хотя в самом файле тюнинга они часто подаются отдельно или неявно подразумеваются в зависимости от конкретной версии API.

json
// Пример одной строки в файле training_data.jsonl
// Обратите внимание: это одна строка, переносы добавлены только для читаемости!

{
  "messages": [
    {
      "role": "user",
      "content": "Классифицируй обращение клиента: 'У меня списали деньги дважды за одну подписку'"
    },
    {
      "role": "model",
      "content": "{\"category\": \"billing\", \"priority\": \"high\", \"sentiment\": \"negative\"}"
    }
  ]
}

Этап 1: Очистка и нормализация данных

Данные из реального мира всегда «грязные». Логи чат-ботов, выгрузки из CRM, электронные письма — всё это содержит шум. Вот чек-лист того, что необходимо устранить:

  1. PII (Personal Identifiable Information): Это критично. Если вы обучаете модель на реальных логах поддержки, там могут быть номера кредитных карт, телефоны, адреса. Модель может выучить их и выдать случайному пользователю. Это дыра в безопасности.
  2. Сломанная кодировка: Символы вроде или некорректно декодированный UTF-8 могут сбить токенизатор с толку.
  3. Дубликаты: Если один и тот же пример повторяется 100 раз, модель переобучится на нём (overfitting) и начнет отвечать этим шаблоном даже там, где это неуместно.
  4. Служебный мусор: HTML-теги (если они не нужны по задаче), системные логи, заголовки писем.

Давайте посмотрим, как можно автоматизировать очистку PII с помощью Python.

python
import pandas as pd
import re

# Пример функции для очистки чувствительных данных
def clean_pii(text):
    # Замена email адресов на токен <EMAIL>
    text = re.sub(r'[\w\.-]+@[\w\.-]+\.\w+', '<EMAIL>', text)
    
    # Замена телефонных номеров (упрощенный паттерн) на <PHONE>
    text = re.sub(r'\+?\d[\d -]{8,12}\d', '<PHONE>', text)
    
    # Замена потенциальных номеров карт (очень грубый фильтр) на <CARD>
    text = re.sub(r'\d{4}[ -]?\d{4}[ -]?\d{4}[ -]?\d{4}', '<CARD>', text)
    
    return text

# Загрузка сырых данных
df = pd.DataFrame({
    'user_input': [
        'Меня зовут Иван, мой email ivan@example.com',
        'Проблема с оплатой по карте 4444-5555-6666-7777',
        'Привет, Gemini!'
    ],
    'model_output': [
        'Привет, Иван. Отправил инструкции на почту.',
        'Вижу попытку транзакции.',
        'Привет! Чем могу помочь?'
    ]
})

# Применяем очистку
df['clean_input'] = df['user_input'].apply(clean_pii)
df['clean_output'] = df['model_output'].apply(clean_pii)

print(df[['clean_input', 'clean_output']])

Этап 2: Балансировка и качество примеров

Очистка от мусора — это только начало. Следующий шаг — работа со смыслом. Gemini учится на паттернах. Если в вашем датасете 90% примеров — это простые приветствия, и только 10% — сложные технические вопросы, модель станет отличным «здоровальщиком», но плохим техническим консультантом.

Принципы качественного датасета:

  • Разнообразие (Diversity): Примеры должны покрывать разные сценарии использования. Если вы учите модель писать код, нужны примеры и на Python, и на JS, и с ошибками, и без.
  • Согласованность (Consistency): Это самая частая ошибка. Если на вопрос «Как дела?» в одном примере модель отвечает «Я AI, у меня нет дел», а в другом — «Всё супер!», модель запутается. Вы должны выработать единый «Tone of Voice» (стиль общения) и придерживаться его во всех примерах.
  • Chain-of-Thought (Цепочка рассуждений): Для сложных задач (математика, логика) недостаточно просто дать ответ. В поле content ответа модели лучше включить ход решения. Это значительно повышает качество работы Gemini 3.

Упражнение

У вас есть три примера данных для обучения бота техподдержки хостинга. Найдите в них проблемы (логические или форматные) и предложите исправленный вариант JSON-объекта для одного из них.<br><br>Данные:<br>1. User: 'Сайт лежит 500 ошибка'. Model: 'Попробуйте перезагрузить роутер'. (Проблема: некомпетентный ответ)<br>2. User: 'Сколько стоит тариф PRO?'. Model: 'Тариф PRO стоит 500 рублей'. (Проблема: цены могут меняться, лучше давать ссылку или говорить 'согласно прайсу')<br>3. User: 'Привет'. Model: 'Здравствуйте! Я бот техподдержки'. (Проблема: слишком просто, мало контекста)

Этап 3: Разделение данных (Train / Validation Split)

Никогда, запомните, никогда не обучайте модель на всех имеющихся данных без остатка. Вам обязательно нужно выделить часть данных для валидации.

Зачем это нужно?
В процессе обучения Google Cloud будет показывать вам метрики (Loss). Но Loss на обучающей выборке будет неизбежно падать. Вам нужно знать, не начала ли модель просто «зазубривать» примеры. Для этого используется валидационный датасет, который модель не видит во время обучения. Если ошибка на тренировочных данных падает, а на валидационных растет — поздравляю, у вас Overfitting (переобучение). Останавливайте процесс.

Стандартная пропорция: 80% — обучение, 20% — валидация. Или 90/10 для очень больших датасетов.

python
import json
from sklearn.model_selection import train_test_split

# Загружаем подготовленный список словарей
dataset = [
    {"messages": [{"role": "user", "content": "..."}, {"role": "model", "content": "..."}]},
    # ... еще 1000 примеров ...
    {"messages": [{"role": "user", "content": "..."}, {"role": "model", "content": "..."}]}
]

# Разделяем данные
train_data, val_data = train_test_split(dataset, test_size=0.1, random_state=42)

# Функция сохранения в JSONL
def save_jsonl(data, filename):
    with open(filename, 'w', encoding='utf-8') as f:
        for entry in data:
            json.dump(entry, f, ensure_ascii=False)
            f.write('\n')

save_jsonl(train_data, 'gemini_train.jsonl')
save_jsonl(val_data, 'gemini_validation.jsonl')

print(f"Обучающая выборка: {len(train_data)} строк")
print(f"Валидационная выборка: {len(val_data)} строк")

Продвинутая техника: Синтетические данные

Что делать, если данных мало? Вы можете использовать саму Gemini (например, Pro или Ultra версию) для генерации данных для обучения более компактной версии (например, Flash) или для специализации той же модели. Этот процесс иногда называют дистилляцией знаний.

Алгоритм:

  1. Возьмите 10-20 идеальных примеров (Golden Dataset), написанных человеком вручную.
  2. Напишите промпт для Gemini Pro: «На основе этих примеров сгенерируй еще 50 аналогичных ситуаций, но с другими входными данными и сохраняя стиль ответа».
  3. Внимательно проверьте сгенерированные данные. AI может галлюцинировать.
  4. Используйте проверенные синтетические данные для расширения вашего датасета.

Это позволяет превратить 50 примеров в 5000, что часто необходимо для качественного fine-tuning.

Вопрос

Почему при подготовке датасета для Fine-Tuning критически важно удалять дубликаты примеров?