Очистка данных и очистка меток всегда являются сложными задачами, но хорошая среда для экспериментов упрощает задачу.
Повторяемые, независимо проверяемые эксперименты являются строительными блоками научного прогресса. Последние достижения в инструментах машинного обучения делают воспроизводимость проще, чем когда-либо прежде.
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.yaml
file.
Подготовить этап
На этапе подготовки мы собираем наши 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). [ссылка], [бумага]