Очистка данных и очистка меток всегда являются сложными задачами, но хорошая среда для экспериментов упрощает задачу.

Повторяемые, независимо проверяемые эксперименты являются строительными блоками научного прогресса. Последние достижения в инструментах машинного обучения делают воспроизводимость проще, чем когда-либо прежде.

DVC означает Data Version Control, и это служебная библиотека Python, которая делает больше, чем просто помогает вам получать доступ и управлять большими наборами данных и изменениями. Это также помогает вам легко управлять, отслеживать и сравнивать эксперименты без зависимости от внешнего сервера. С ним легко начать, и я покажу вам, как использовать его возможности на рабочем, нетривиальном примере. Наш набор данных и проблема связаны с НЛП, но принцип очистки данных с помощью Cleanlab для анализа вероятностей предсказания перекрестной проверки обычно применим ко всем типам данных.

Давайте быстро взглянем на демо-код этой статьи в действии, вот краткий asciiccast выборки и сравнения экспериментов демо с использованием git и DVC:



Очистка меток данных — проблема сегодняшнего и завтрашнего дня

Случайно помеченные данные обычно доступны во многих источниках: Викиданные, наборы данных Kaggle, документы с академическими данными, отдельные сообщения в блогах и т. д. Мы описываем их как «случайные», потому что часто качество меток может варьироваться от нормального до сомнительного, и, как правило, нет. доступны показатели качества.

Auto-ML, который автоматически правильно классифицирует данные, произойдет завтра — как в «Завтра бесплатная еда» — то есть, вероятно, никогда и уж точно никогда не будет бесплатным! Однако мы можем немного продвинуться в этом направлении, поскольку случайная выборка данных и меток — плохой механизм отбора, а оценка человеком — утомительна и дорога. Лучше использовать неконтролируемое обучение для оценки и ранжирования данных и меток в соответствии с их предсказанными вероятностями, также известными как оценки достоверности. Однако, поскольку у нас нет априорного золотого ярлыка для оценки наших оценок достоверности, мы будем использовать обработку Cleanlab предсказанных вероятностей из сегментов перекрестной проверки, чтобы получить разумное приближение для набора золотых этикеток. Таким образом, мы можем уменьшить бремя последующей оценки человеком, автоматически находя и перемаркируя худших исполнителей.

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

Цели демонстрации и этой статьи

  • Демонстрация воспроизводимого машинного обучения
  • Используйте DVC для создания пайплайна и отслеживания экспериментов
  • Автоматически переименовывать зашумленные метки данных с помощью Cleanlab
  • Используйте вложения подслов FastText для неконтролируемой классификации
  • Настройка гиперпараметров с отслеживанием экспериментов
  • Подготовьте небрежно помеченные данные для моделей и оценки человеком

Проблема и данные

Для нашей рабочей демонстрации мы очистим некоторые из слегка зашумленных и грязных ярлыков, которые можно найти в записях о людях в Викиданных, а именно атрибуты для работодателей и профессий. Наши исходные метки данных были собраны с использованием json-дампа Викиданных, набора данных Викиданных Kensho и этого скрипта блокнота для извлечения данных.

Набор данных похож на многие реальные проблемы: зашумленные метки; и туманные границы классов меток. Метки зашумлены, потому что обычно их вводят добровольцы Викиданных или инженеры, импортирующие необработанные данные в Викиданные из устаревших источников без особой очистки. Обычные веб-браузеры и читатели энциклопедий терпимы к ошибкам и туманным границам, но модели машинного обучения страдают при обучении на ошибочных данных. Самый простой способ повысить производительность и надежность модели — это тренироваться на более качественных данных и с меньшим количеством ошибок.

Наши ярлыки основных классов, работодателей и профессий, имеют туманные границы: baker (профессия) может нанять carpenter (профессия), и тогда технически верно, что этот baker на самом деле является работодателем; но такой пример на самом деле просто игра слов; в реальном мире мы обычно ожидаем, что люди описывают свою профессию в общих чертах наиболее распространенного использования, то же самое для employers - bakery (работодатель) обычно использует bakers.

Морфология представляет собой еще одну туманную границу: в приведенном выше примере пекарьсотрудник работает в пекарне — здесь жирным шрифтом показано, как морфология указывает на профессию и работодателя — однако, поскольку carpenter не используется carpentry, и многие другие примеры нарушают парадигму морфологии. Таким образом, мы будем использовать контекстуальные вложения слов для сбора информации о границах, чтобы мы могли лучше группировать, классифицировать и очищать зашумленные метки.

Формат ввода данных

Файлы CSV, разделенные табуляцией, с полями:

  • text_data — Элемент, который необходимо пометить (одно слово или короткая группа слов)
  • class_type — Метка класса
  • context — любой текст, который окружает поле text_data in situ или другими словами определяет элемент text_data.
  • count — количество вхождений этой метки; насколько часто это появляется в существующих данных.

Исходные данные: профессии и работодатели

Пример данных Викиданных о занятиях:

Этот небольшой образец размеченных данных о занятиях выглядит нормально, но в файле 12 755 записей, и мы скоро увидим, где что-то может пойти не так.

Пример данных о работодателях Викиданных:

Даже с небольшой выборкой данных о работодателях мы можем видеть проблемы: ни bibliography, ни computer science, ни poetry не являются работодателями, а classification system встречается только один раз, так что это даже не поддерживается должным образом. Примеры с одним экземпляром почти всегда вызывают подозрение, поскольку они являются выбросами. Они могут быть действительными, но чаще всего являются ошибочными суждениями.

Использование экземпляра count в качестве грубой эвристики для определения достоверности элемента само по себе ненадежно, но эту функцию стоит рассмотреть. Поле context происходит из описания поля text_data, или для многих наборов данных это может быть предложение, в котором используется элемент text_data. Можно попытаться объединить поле context с полем text_data, чтобы создать более сильный сигнал для использования во время маркировки и кластеризации типов классов.

Формат вывода данных

  • (те же параметры, что и для ввода данных плюс)
  • class_type — Обновлена ​​метка
  • previous_class_type — Предыдущая метка class_type
  • mislabeled_rank — ранг достоверности Cleanlab до перемаркировки
  • date_updated — Когда метка была обновлена

Этапы конвейера

Конвейер DVC состоит из этапов, определенных в файле dvc.yaml и настроенных в файле params.yaml. Конвейер запущен, начните и закончите, просто вызвав dvc repro (следуйте вместе с README.md репозитория кода). Если какой-либо из параметров изменен в файле params.yaml или если какие-либо зависимости были обновлены (исходный код или данные), то этот этап снова запускается с нуля. Давайте посмотрим на наши этапы:

  • fetch.py — Эта программа вызывается для загрузки моделей и данных. Модель встраивания FastText составляет несколько гигабайт.
  • prepare.py — эта программа вызывается для обработки CSV-файлов в каталоге data/raw с использованием загруженных вложений и модели определения языка.
  • train.py — Эта программа создает классификатор для групповой маркировки данных.
  • relabel.py — Эта программа использует гиперпараметры, настроенные на этапе train, и данные, выводимые на этапе prepare, а также функциональные возможности служебной библиотеки Cleanlab для обучения моделей с использованием перекрестной проверки, чтобы предсказать, какие экземпляры неправильно помечены. Данные перемаркированы и экспортированы в каталог data/final.

Этапы пайплайна связаны конфигурацией файла dvc.yaml. Мы кратко рассмотрим каждый этап и изучим, как они настроены. Вы можете увидеть визуальное представление этого, если наберете: dvc dag

Этап выборки

Обычно проекты DVC хранят большие файлы в облачном хранилище и загружают их локально для обработки. Однако, поскольку одной из целей этого демонстрационного конвейера является определение того, какое встраивание лучше всего использовать, я выделил шаг доступа к данным в отдельный автоматизированный этап, вместо того, чтобы требовать от пользователей настройки доступа к облачному хранилищу и импорта файла в их Конфигурация ДВК.

# Fetch stage of dvc.yaml
  fetch:
    cmd:
      - python src/fetch.py --param_group fetch_data
      - python src/fetch.py --param_group fetch_model
    always_changed: True
    deps:
      - src/fetch.py
    params:
      - fetch_data.file
      - fetch_data.uri
      - fetch_model.file
      - fetch_model.uri
    cmd:
      - python src/fetch.py --param_group fetch_data
      - python src/fetch.py --param_group fetch_model
    always_changed: True
    deps:
      - src/fetch.py
    params:
      - fetch_data.file
      - fetch_data.uri
      - fetch_model.file
      - fetch_model.uri

Примечание: вы можете вызвать команду с более чем одной целью и передать разные параметры, как это сделано выше, однако эти параметры не предназначены для обновления здесь, и все изменения параметров должны происходить в файле params.yamlfile.

Подготовить этап

На этапе подготовки мы собираем наши text_data элементов и class_type меток, а также создаем и сохраняем встраиваемое представление для каждого элемента. Наши вложения подслов FastText генерируются с использованием двоичных моделей встраивания FastText (т.е. crawl-300d-2M-subword.binвместо crawl-300d-2M-subword.vec). Это позволяет нам генерировать вложения на основе последовательностей символов/подслов, составляющих слово. С практической точки зрения, если бы я столкнулся с неологизмом, таким как пекарня, бинарная модель FastText создала бы вложение, очень похожее на слово пекарня, с некоторыми дополнительными значениями встраивания, найденными рядом со словами, оканчивающимися на арама, говоря образно. Использование модели бинарного встраивания, такой как FastText, позволяет нам создать более надежную стадию подготовки, которая должна генерировать вложения, которые несколько терпимы к орфографическим ошибкам и неологизмам, и это может помочь нашей модели обобщать и лучше работать с невидимыми данными.

Если в элементе text_data несколько слов, мы:

  • отбросить любые стоп-слова
  • взвешивать отдельные вложения слов, используя словарь IDF (если параметр tfidf_dict_pickle_file был предоставлен вparams.yaml ).
  • усреднить взвешенные вложения

Описанный выше подход подробно объясняется в статье Простая, но непростая базовая линия для встраивания предложений.

# Prepare stage of dvc.yaml
prepare:
  cmd: python src/prepare.py
  deps:
    - src/prepare.py
    - data/raw
  outs:
    - data/prepared/data.all.csv
  metrics:
    - reports/prepare.metrics.json:
        cache: false
  params:
    - fetch_data.file
    - prepare.embeddings_dim
    - prepare.filter_lang_bool
    - prepare.filter_lang
    - prepare.lang_detect_model
    - prepare.stopwords_filter_lang
    - prepare.filter_count_gteq
    - prepare.tfidf_dict_pickle_file

Выходной файл был указан для этапа подготовки, и если этот выходной файл существует на момент запуска этапа, он удаляется; и когда cmd завершится, если этот файл не был воссоздан, стадия не удалась, и DVC попытается запуститься со следующим вызовом dvc repro.

Также сообщаются метрики, и должен быть сгенерирован файл reports/prepare.metrics.json, иначе этап помечен как неудачный. Зависимостью этапа deps являются только исходный код файла и необработанный каталог — обычно файлы данных будут перечислены здесь, и если эти файлы изменятся, DVC сравнит контрольные суммы и при необходимости перезапустит этап подготовки, однако, поскольку fetch stage позволяет пользователям гибко указывать любые файлы, которые они хотят, зависимость файла данных не жестко запрограммирована.

На этапе подготовки также используется языковая модель FastText для обнаружения и фильтрации по любому языку, который вы хотите указать. Параметр filter_count_gteq является целым числом и используется для фильтрации записей, в которых атрибут данных count меньше этого значения; если в строке данных нет атрибута count, то он не применяется.

Последнее, но, возможно, самое важное, этап подготовки помечает любые повторяющиеся элементы text_data как неизвестные с помощью тега UNK. Это позволяет нам избежать ложной дихотомии, которая возникает, когда у вас есть только две метки в данных, но в реальном мире вы находите элементы вне любого типа класса, например. есть много вещей, которые не являются ни профессией, ни ни работодателем. Пометка коллизий как неизвестных позволит шагам модели и перекрестной проверки иметь безопасную корзину для сбора элементов с низкой достоверностью.

Стадия поезда

На этапе обучения вы можете указать классификатор: опорный вектор или KNeighbors (или другие могут быть добавлены). Выходные данные этапа позволяют пользователю проверять и настраивать гиперпараметры модели. Для нашей демонстрации мы создаем классификатор опорных векторов, который был выбран потому, что он хорошо работает для обнаружения и выявления границ и максимальных границ между данными (дополнительную информацию см. в документах, перечисленных в конце этой статьи).

# train stage of dvc.yaml
train:
  cmd: python src/train.py
  deps:
  - data/prepared/data.all.csv
  - src/train.py
  outs:
  - model/svm.model.pkl
  metrics:
  - model/train.metrics.json:
      cache: false
  plots:
  - model/class.metrics.csv:
      cache: false
  params:
  - train.class_types
  - train.svm_degree
  - train.svm_dual
  - train.svm_gamma
  - train.svm_kernel
  - train.svm_loss
  - train.model_type
  - train.svm_penalty
  - train.svm_regularization_C
  - train.seed
  - train.split
  - train.knc_n_neighbors
  - train.knc_weights
  - train.knc_algorithm
  - train.knc_leaf_size
  - train.knc_p
  - train.knc_metric
  - train.num_components
  - train.use_pca

Одна небольшая неприятность заключается в том, что трудно сгруппировать параметры, которые принадлежат друг другу. Например, модели LinearSVC и SVC принимают параметр регуляризации C, но тогда LinearSVC принимает параметры penalty, loss, dual, а SVC принимает параметры, определяющие kernel, degree, gamma. Нет простого способа сгруппировать их; в демонстрационном коде мы позволяем экспериментаторам переключаться между моделями, указав параметр model_type.

Стадия перемаркировки

На этапе перемаркировки используется библиотека Cleanlab и все настройки этапа обучения.

# The relabel stage of dvc.yaml
relabel:
  cmd: python src/relabel.py
  deps:
    - src/relabel.py
    - data/prepared/data.all.csv
    - model/svm.model.pkl
  outs:
    - data/final/data.csv
  metrics:
    - reports/relabel.metrics.json:
        cache: false
  plots:
  - data/final/class.metrics.csv:
      cache: false
  params:
  - prepare.unknown_tag
  - train.class_types
  - train.svm_degree
  - train.svm_dual
  - train.svm_gamma
  - train.svm_kernel
  - train.svm_loss
  - train.model_type
  - train.svm_penalty
  - train.svm_regularization_C
  - train.seed
  - train.split
  - train.knc_n_neighbors
  - train.knc_weights
  - train.knc_algorithm
  - train.knc_leaf_size
  - train.knc_p
  - train.knc_metric
  - relabel.num_crossval_folds
  - relabel.min_distance_decision
  - relabel.max_distance_decision

Использование библиотеки Cleanlab для очистки меток требует, чтобы мы создавали значения вероятности для прогнозов, например, предоставляемые методом predict_proba класса Scikit-Learn. Механика алгоритма Cleanlab выходит за рамки этой статьи, но любознательные умы захотят ознакомиться с документом Confident Learning и другими документами, перечисленными в репозитории Cleanlab на github.

Результаты

Чтобы перемаркировать, сначала мы используем метод скрытой оценки Cleanlab:cross_val_predict, который вычисляет прогнозируемую вероятность вне выборки [P(s=k|x)] для каждого примера в X с использованием перекрестной проверки. Затем мы используем метод Cleanlab Pruning: find_label_issues, который возвращает индексы наиболее вероятных (уверенных) ошибок меток в y-hat.

Когда программа relabel.py запускается, она выводит 20 лучших элементов, которые возвращает Cleanlab в порядке возрастания достоверности (то есть первый — худший). Поскольку случайные начальные значения фиксированы, а эксперименты повторяемы, они дают интересные и поучительные сравнения.

Здесь мы видим, что каждый тип ядра (линейный, полиномиальный, радиальный) по-разному определяет вектор вложения и изучает разные границы, так что каждая модель обеспечивает свой взгляд на данные. Для нашего конкретного набора данных (где UNK является очевидным несбалансированным классом) кажется более приемлемым, что неопределенные прогнозы моделей имеют тенденцию помечать больше значений как UNK, что предпочтительнее, чем они галлюцинируют неправильную маркировку.

Запустив наш демонстрационный код, мы видим, что наш первоначальный набор данных о профессиях и работодателях Викиданных сокращается с помощью эвристики качества данных, определения языка, пороговых значений и отбрасывания дубликатов. Работодатели сократились с 66 880 до 27 734 записей, а количество занятий сократилось с 10 975 до 6 280 записей, а необработанные размеченные данные были дедуплицированы, что привело к 33 103 элементам данных и меткам. Наш конвейер и алгоритм Cleanlab обнаружили от 1354 до 1993 проблем с метками (в зависимости от используемого классификатора), которые затем были перемаркированы или перемещены в неизвестную категорию для дальнейшего изучения.

Дальнейшие наблюдения

  • Для перемаркировки и очистки важно иметь более двух меток и указывать метку UNK для: неизвестно; ярлыки, охватывающие несколько групп; или поддержка с низким уровнем доверия; часто двоичный набор меток слишком ограничен, чтобы зафиксировать текущее состояние имеющейся у нас информации.
  • Стандартизация форматов входных данных позволяет пользователям гибко использовать множество различных источников данных.
  • Определение языка — важная часть очистки данных, хотя и проблематичная, потому что:
    — Современные языки иногда «заимствуют» слова из других языков (но не любые слова!)
    — Модели определения языка плохо выполняют вывод с ограниченным данные, особенно одно слово.
    - Утилиты нормализации, такие как unidecode, бесполезны; (неправильное слово в более читаемых буквах все равно неправильное слово).
  • Экспериментальные параметры часто имеют взаимозависимости, которые делают простой комбинаторный поиск по сетке неэффективным.

Заключение

Демонстрационный конвейер производит достаточно автоматически перемаркированных данных, чтобы можно было оценить и сравнить выходные данные нескольких моделей, и это остается в качестве упражнения для читателя. Каждый классификатор, вероятно, предоставляет полезную информацию, или, возможно, другое специальное ядро ​​может дать лучшие результаты для ваших данных. Классификаторы могли голосовать вместе, и голоса могли быть взвешены. Тонкости использования методов ансамбля выходят за рамки этой статьи, но заинтересованные читатели могут начать с практического руководства Кунапули Методы ансамбля для машинного обучения. Есть много вариантов, которые можно рассмотреть для следующего этапа конвейера автоматической маркировки.

Источники

https://github.com/todd-cook/auto-label-pipeline



https://fasttext.cc/docs/en/english-vectors.html
Уверенное обучение: оценка неопределенности в метках наборов данных Кертис Г. Норткатт, Лу Цзян, Исаак Л. Чуанг, 31 октября 2019 г., [arxiv]
Простая, но непростая базовая линия для встраивания предложений, Санджив Арора, Иньюй Лян, Тенгью Ма, ICLR 2017, [бумага ]
Кластеризация опорных векторов, Аса Бен-Гур, Дэвид Хорн, Хава Т. Сигельманн, Владимир Вапник, ноябрь 2001 г. Журнал исследований машинного обучения 2 (12): 125–137, DOI :10.1162/15324430260185565, [бумага]
Кластеризация SVM Винтерс-Хилт, С., Мерат, С. Биоинформатика BMC 8, S18 (2007). [ссылка], [бумага]