Перейти к содержимому

Обучите свою первую модель на вашей разметке

Запустите учебное исследование Potato с отзывами на ноутбуке без GPU, разметьте 120 отзывов симулятором, обучите sklearn-text и посмотрите предварительные метки модели.

Новое в v2.14.0

В этом руководстве классификатор тональности обучается на метках учебного исследования, а ответы классификатора показываются следующему разметчику как предварительные метки. Руководство написано для владельца исследования, который впервые пробует обучение моделей в Potato, и каждый шаг выполняется на ноутбуке без GPU и без установки чего-либо, кроме самого Potato. Вы запускаете учебный проект Potato с отзывами, поручаете симулятору пользователей разметить 120 из 160 отзывов проекта, обучаете sklearn-text со страницы Training в админке, читаете оценку запуска на отложенных объектах и входите как новый разметчик, чтобы увидеть ответы модели. Что делает каждая часть цикла в общем случае, описано в обзоре обучения моделей.

Установка Potato и примера проекта

В руководстве используется sklearn-text, тренер, который превращает каждый отзыв в признаки TF-IDF и обучает классификатор на основе логистической регрессии. sklearn-text не требует дополнительной установки, потому что scikit-learn входит в основные зависимости Potato. Учебный проект лежит в репозитории Potato на GitHub, а не в пакете pip, поэтому установите Potato и клонируйте репозиторий:

bash
pip install --upgrade potato-annotation
git clone https://github.com/davidjurgens/potato.git
cd potato

Все команды ниже выполняются из корня репозитория. В папке проекта examples/ai-assisted/model-training/ три файла.

  • config.yaml — конфигурация исследования, в комментариях которой есть команды этого руководства.
  • data/reviews.json содержит 160 синтетических отзывов на товары, по одному объекту JSON в строке, с полями id и text.
  • data/gold.json задаёт верную метку для каждого отзыва. Симулятор отвечает по этому файлу.

Пример конфигурации

Конфигурация задаёт одну схему radio с именем sentiment и метками positive и negative и включает обучение моделей. Блок ниже — поставляемый файл без комментариев, и этот файл проходит python -m potato.validate_cli --strict без изменений:

yaml
annotation_task_name: "Review Sentiment (model training demo)"
 
data_files:
  - "data/reviews.json"
 
item_properties:
  id_key: "id"
  text_key: "text"
 
task_dir: "."
output_annotation_dir: "annotation_output"
 
require_password: false
admin_api_key: "demo-admin-key"
 
num_annotators_per_item: 1
 
annotation_schemes:
  - annotation_type: "radio"
    name: "sentiment"
    description: "Is this review positive or negative?"
    labels:
      - "positive"
      - "negative"
    sequential_key_binding: true
 
model_training:
  enabled: true
  writeback:
    schemas: ["sentiment"]
    include_unlabeled: true
    min_confidence: 0.6

Руководство определяют четыре настройки.

  • num_annotators_per_item: 1 даёт каждому отзыву одну метку. Три симулированных разметчика по 40 отзывов покрывают тогда 120 разных отзывов и оставляют 40 неразмеченными для модели.
  • require_password: false позволяет новому разметчику войти одним именем пользователя. Последний шаг входит именно так.
  • admin_api_key: "demo-admin-key" открывает админские страницы. На любом сервере, доступном другим людям, замените этот ключ.
  • model_training регистрирует маршруты /admin/training. Блок writeback показывает разметчикам предсказания для схемы sentiment, а раздел об обратной записи ниже объясняет каждый ключ.

Запуск сервера на порту 8000

Запустите Potato с примером конфигурации:

bash
potato start examples/ai-assisted/model-training/config.yaml -p 8000

Сервер загружает 160 отзывов и отдаёт страницу разметки по адресу http://localhost:8000. Если на вашей машине порт 8000 занят, передайте в -p другой порт и используйте его во всех адресах ниже.

Разметка 120 отзывов симулятором

Модели нужны человеческие метки, чтобы учиться. Симулятор пользователей заменяет трёх разметчиков. Каждый симулированный разметчик отвечает по файлу с эталонными метками и в большинстве случаев отвечает верно. Запустите симулятор во втором терминале из корня репозитория:

bash
python -m potato.simulator --server http://localhost:8000 --users 3 \
  --strategy gold_standard --competence good=1.0 --max-annotations 40 \
  --gold-file examples/ai-assisted/model-training/data/gold.json \
  --sequential --fast-mode --no-export

--strategy gold_standard заставляет каждого симулированного разметчика отвечать по gold.json, а --competence good=1.0 назначает всем трём разметчикам профиль good симулятора. Разметчик с профилем good получает точность от 0,80 до 0,90 и отвечает на каждый отзыв верно с такой вероятностью. Поэтому в метках есть ошибки, как и в метках настоящей команды. --sequential запускает трёх разметчиков один за другим, --fast-mode убирает паузы между ответами, а --no-export отключает запись собственных файлов результатов симулятора. Симулятор завершается примерно за две секунды и выводит сводку. Прежде чем двигаться дальше, убедитесь, что в сводке стоит Total annotations: 120. Отзывы можно также размечать вручную на http://localhost:8000. sklearn-text отказывается обучаться, если в выборке train меньше 10 размеченных объектов.

Открытие страницы Training с админским ключом

Для страницы Training нужна админская сессия. Откройте http://localhost:8000/admin, введите demo-admin-key, когда страница запросит ключ API, а затем откройте http://localhost:8000/admin/training.

Страница Training в Potato с выбранными тренером sklearn-text, схемой sentiment и локальным бэкендом над таблицей Runs, где перечислены два завершённых запуска с оценками на отложенных объектах 0,847 и 0,840Страница Training после двух запусков sklearn-text на учебном проекте

Панель Start a run вверху содержит всю настройку. Schema перечисляет единственную схему проекта, sentiment (radio). Trainer перечисляет все 38 тренеров, а у тренера, который проект запустить не может, рядом с названием стоит причина, например "not installed". Страница выбирает sklearn-text, когда sklearn-text подходит к схеме. Runs on показывает единственный бэкенд проекта, local (this machine).

Обучение sklearn-text

Оставьте Parameters пустым, чтобы использовать значения тренера по умолчанию, и нажмите Train now. Запуск сводит аннотации к одной метке на отзыв, делит 120 размеченных отзывов на выборки train, val и test и обучает модель в отдельном процессе. Наш запуск занял 1,5 секунды, и по его завершении на панели появилось "Run finished.".

По умолчанию sklearn-text берёт для признаков TfidfVectorizer из scikit-learn, а в качестве классификатора LogisticRegression. Если в выборке train 50 или больше объектов, sklearn-text также калибрует уверенность классификатора. Калибровка использует масштабирование Платта при числе обучающих объектов меньше 1000 и изотоническую регрессию начиная с 1000. Откалиброванная модель сохраняется, только если калибровка снижает точность на обучающей выборке не более чем на 0,05. Калибровка здесь важна, потому что шаг обратной записи сравнивает каждую уверенность с min_confidence.

Чтобы начать тот же запуск из скрипта, передайте админский ключ в заголовке X-API-Key:

bash
curl -X POST -H "X-API-Key: demo-admin-key" -H "Content-Type: application/json" \
  http://localhost:8000/admin/training/api/runs \
  -d '{"trainer": "sklearn-text", "schemas": ["sentiment"]}'

В ответе приходят новый run_id и "started": true.

Страница запуска и оценка на отложенных объектах

Завершённый запуск появляется в таблице Runs с размерами выборок train и val и колонкой Оценка на отложенных объектах. Щёлкните по идентификатору запуска, чтобы открыть страницу запуска по адресу /admin/training/runs/<run_id>. Страница запуска перечисляет статус, тренер, бэкенд, размеры выборок, начальное значение разбиения, оценку на отложенных объектах и параметры запуска, а затем таблицу всех метрик и журнал запуска.

По умолчанию запуск откладывает 15% размеченных объектов под val и 15% под test, а split_seed определяет, какие объекты попадут в какую выборку. Разбиение не меняется от запуска к запуску, пока split_seed сохраняет значение, поэтому два запуска на одних и тех же метках оцениваются на одних и тех же объектах. Оценка на отложенных объектах у запуска sklearn-text — это macro-F1 на val. Macro-F1 усредняет F1-меру по каждой метке, здесь по positive и negative. Запуск также записывает точность и macro-F1 на test. Точность на выборке train записывается как train_accuracy и никогда не используется как оценка. В нашем запуске журнал выглядел так:

text
[info] Read 76 labelled rows from the train split
[info] Applied sigmoid calibration over 5 folds
[info] Held-out val macro_f1: 0.725

Собственная документация Potato сообщает об одном запуске на том же проекте, и таблица ставит этот запуск рядом с нашим:

Документация PotatoНаш запуск
Размеченных отзывов120120
Объектов в train, val и testне указано76, 19 и 25
Оценка на отложенных объектах (macro-F1 на val)0,840,725
macro-F1 на testне указано0,826
Опубликовано предварительных меток8073
Предсказаний ниже min_confidence411

Ваши числа будут отличаться от обоих столбцов, потому что каждый симулированный разметчик случайно выбирает точность и ошибается в разных местах. В нашем запуске симулированные метки совпали с gold.json на 97 из 120 отзывов и на 15 из 19 отзывов val. Оценка на отложенных объектах измеряет согласие с метками ваших разметчиков, а не с каким-либо эталоном, поэтому ошибки разметчиков в val снижают оценку. Каждая из 73 предварительных меток, опубликованных нашим запуском, совпала с gold.json. В настоящем исследовании без файла с эталонными метками низкую оценку на отложенных объектах стоит читать как повод проверить согласованность разметчиков, прежде чем винить модель.

Включение обратной записи для схемы

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

yaml
model_training:
  enabled: true
  writeback:
    schemas: ["sentiment"]
    include_unlabeled: true
    min_confidence: 0.6

writeback.schemas называет схемы, предсказания для которых видят разметчики. По умолчанию список пуст, поэтому включение обучения ничего не меняет на странице разметки, пока вы не назовёте схему. include_unlabeled: true заставляет каждый запуск предсказывать и для отзывов, которые никто не размечал, а не только для отзывов val и test. Без include_unlabeled запуск предсказывает только для отзывов val и test, а у этих отзывов человеческая метка уже есть. min_confidence: 0.6 не пускает предсказание на страницу разметки, если уверенность модели ниже 0,6. Potato всё равно сохраняет это предсказание.

Обратная запись выполняется после каждого успешного запуска и пропускает любой объект из выборки train этого запуска. В нашем запуске модель предсказала для 84 отзывов (19 val, 25 test и 40 неразмеченных), 11 предсказаний оказались ниже 0,6, а остальные 73 запуск опубликовал. Поле writeback в GET /admin/training/api/status даёт те же числа со сводкой "Published 73 prediction(s) as prelabels.". Сохранённые предсказания записываются заново при запуске сервера, поэтому предварительные метки переживают перезапуск. Чтобы снять предварительные метки запуска с объектов, отправьте DELETE /admin/training/api/runs/<run_id>/predictions.

Предварительная метка глазами нового разметчика

Откройте http://localhost:8000 в приватном окне браузера и войдите под именем, которое никто не использовал, например newannotator. У каждого размеченного отзыва уже есть одна метка, поэтому новому разметчику назначаются 40 неразмеченных отзывов, и счётчик прогресса в нашем запуске показывал 0/40. Наш первый отзыв — "The toaster: Disappointed, it stopped working within a week. Much smaller than the photos suggest." — открылся с уже выбранным вариантом Negative при уверенности 0,68.

Страница разметки Potato с отзывом о тостере, на которой модель уже выбрала вариант Positive, а объект по-прежнему помечен как Not labeledОтзыв, который открывается с выбранным ответом модели до того, как разметчик что-либо сохранил

Предварительная метка не сохраняется, пока разметчик только смотрит на отзыв, и индикатор статуса показывает "Not labeled", пока разметчик не сохранит ответ. Ответ модели становится ответом разметчика, когда тот меняет выбор или нажимает Next. В нашем запуске 5 неразмеченных отзывов, предсказание для которых оказалось ниже min_confidence, открылись без выбранного варианта. Разметчик, отстранённый от машинной помощи через ai_support.holdout, не видит предварительных меток вообще. Предварительные метки склоняют разметчиков к ответу модели, поэтому включайте обратную запись, когда оценка на отложенных объектах достаточно высока, чтобы ей доверять, и следите за разметчиками, которые принимают все предварительные метки, с помощью проверок из материала обнаружение механически принятых предварительных меток.

Дальнейшие шаги

На том же проекте можно провести ещё несколько экспериментов, прежде чем переходить к своим данным.

  • Измените параметр. Введите {"vectorizer_kwargs": {"ngram_range": [1, 2]}} в Parameters и обучите заново, чтобы добавить в признаки пары слов. Наш второй запуск с парами слов дал 0,774 macro-F1 на val на той же выборке и опубликовал 74 предварительные метки. Имя параметра, которого sklearn-text не принимает, отклоняется со списком имён, которые тренер принимает.
  • Попробуйте трансформер. hf-text-classification (pip install "potato-annotation[train-text]") и setfit (pip install "potato-annotation[embeddings]") обучаются на той же схеме, а страница тренеров приводит параметры каждого тренера.
  • Замкните цикл. Модель в цикле добавляет очередь проверки, переобучение по мере поступления аннотаций через auto_retrain и сохранение выборок запуска как версии датасета.
  • Перенесите обучение на GPU. Обучение на GPU-сервере, кластере SLURM или машине за NAT отправляет те же запуски на другую машину.
  • Обучайте модели других видов. Руководства по дообучению LLM, моделям компьютерного зрения, аудиомоделям и научным моделям проходят те же шаги с другими тренерами и схемами.

Все использованные здесь ключи перечислены в справочнике по конфигурации обучения моделей. Начните первый запуск в своём проекте с копирования блока model_training выше в конфигурацию и указания своей схемы в writeback.schemas.

Дополнительные материалы