Назад
54

CleanLab: помощь в разметке классификации

54

CleanLab — это вспомогательная либа для задач классификации. Она поможет вам автоматически сделать следующее:

  • найти сэмплы со спорными метками в наборе данных;
  • каким-то образом оценить качество меток вашего датасета для каждого из классов;
  • найти пересекающиеся классы для объединения их впоследствии в один класс;
  • сгенерировать подробный health-report о состоянии вашего набора данных для возможности отслеживания прогресса улучшения этого датасета (если вас вдруг заставят заниматься DataOps’ом 🙂).

Изнутри CleanLab базируется на confident learning’e. Его математика подробно описана в статье авторами самой либы. В нашем посте мы не будем разбирать матан, а просто посмотрим, как можно быстро прикрутить либу к вашим задачам. Если кратко: метод основан на подсчете двух матриц:

  • \( C_{\tilde{y}, y^{\star}} \) — целочисленная матрица встречаемости истинного класса \( y^{\star} \), предсказанного как класс \( \tilde{y} \);
  • \( \hat{Q}_{\tilde{y}, y^{\star}} \) — оценка матрицы совместного распределения \( p(\tilde{y} = i, y^{\star} = j) \),

где \( p(\tilde{y} = i, y^{\star} = j) \) — совместная вероятность зашумленной метки \( i \) и истинной метки \( j \) и различных манипуляций над этими матрицами.

Как установить либу? Нужно лишь прописать pip install cleanlab в вашем виртуальном окружении.

Поиск проблемных меток

Поиграемся с библиотекой на игрушечном датасете MNIST. Искать проблемы с метками можно исключительно на out-of-training примерах (примерах, отсутствующих в тренировочной выборке). Поэтому давайте представим: мы провели кросс-валидацию на MNIST’e и получили \( K \) моделей, которыми мы можем посчитать \( K \) out-of-fold вероятностей. Пусть y_true — истинные метки, а y_hat_probas — предсказанные вероятности. Для поиска проблемных меток воспользуемся функцией find_label_issues . На вход ей нужно подать y_true , y_hat_probasи указать, каким способом искать сэмплы с проблемными метками и как их сортировать. Приведем пример:

from cleanlab.filter import find_label_issues

y_true = ...         # GT-метки валидационной выборки.
y_hat_probas = ...   # Предсказанные вероятности размера (N_samples, 10).

# label_issues - это список с индексами сэмплов, которые по
# мнению cleanlab являются проблемными.
label_issues = find_label_issues(
	labels=y_true,
	pred_probs=y_hat_probas,
	filter_by="prune_by_noise_rate",
	return_indices_ranked_by="self_confidence",
)

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

Например, если выполнить код, представленный выше, а затем посмотреть на сэмплы с индексами из функции find_label_issues, то можно получить следующие результаты:

Рисунок 1. Найденные сэмплы с неправильными метками в MNIST

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

Оценка качества меток для классов

cleanlab позволяет оценить качество меток для каждого из представленных в вашем наборе данных классов. Сделать это можно таким образом:

from cleanlab.dataset import rank_classes_by_label_quality

rank_classes_by_label_quality(
	y_true,
	y_hat_probas,
	class_names=range(10),
	multi_label=False,
)

В результате вы получите следующее:

Рисунок 2. Оценка качества меток для классов в MNIST

Теперь расскажем подробнее о значениях колонок:

  • Label issues показывает количество сэмплов, у которых предсказанный класс не совпадает с истинным;
  • Inverse label issues показывает количество сэмплов, которые по мнению cleanlab должны иметь метку, отличную от истинной;
  • Label noise — доля label issues среди примеров данного класса;
  • Inverse label noise — доля inverse label issues среди примеров данного класса;
  • Label quality score — доля примеров в данном классе, у которых предсказанная и истинная метки совпадают.

Поиск пересекающихся классов

При помощи cleanlab можно оценить степень пересечения классов друг с другом. Пересечение классов — ситуация, при которой обученная вами модель или ассессоры не могут различить какие-либо два класса между собой. Как это делается:

from cleanlab.dataset import find_overlapping_classes

find_overlapping_classes(
	y_true,
	y_hat_probas,
	class_names=range(10),
	multi_label=False,
)

Данная функция возвращает pandas.DataFrame-объект с такими метриками:

  • Num overlapping examples — число примеров, для которых классы пересекаются;
  • Joint probability — доля пересекающихся примеров у данных двух классов среди всех примеров в наборе данных.

Например, на том же MNIST’e можно увидеть следующую картинку:

Рисунок 3. Отчет о пересекающихся классах в MNIST

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

  1. Один класс — подмножество другого класса;
  2. Совпадение классов;
  3. Примеры, на которых пересекающиеся классы всегда встречаются вместе (а-ля мультилейбл);
  4. Сэмплы, на которых эти классы встречаются вместе, принадлежат другому классу;
  5. и так далее.

К каждой из перечисленных ситуаций стоит пристальнее присмотреться и посоветоваться с экспертами в прикладной области по поводу объединения или выделения совершенно иных классов (как в случаях 3-4). Это упростит работу вашей модели, потому что ей не придется разделять неразделяемое.

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

Health-report

Общая оценка качества меток в вашем наборе данных может быть подсчитана как след матрицы \( \hat{Q}_{\tilde{y}, y^{\star}} \) следующим образом:

from cleanlab.dataset import overall_label_health_score

overall_label_health_score(
	y_true,
	y_hat_probas,
	multi_label=False,
)

Данная функция выдаст вам одно число, которое можно как раз-таки интепретировать как общую оценку качества меток. Для MNIST’a, например, число равно 0.9978571428571429 .

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

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

from cleanlab.dataset import health_summary

health_summary(
	y_true,
	y_hat_probas,
	class_names=range(10),
	multi_label=False,
)

Например, для MNIST’a мы получим такой результат:

Дополнительно

У cleanlab есть еще куча разных применений (например, обучения на шумных метках). С ними вы можете ознакомиться в примерах здесь. Также на текущий момент отсутствует поддержка задачи обнаружения объектов, однако авторы либы работают над этим.

Еще есть такой аналог как doubtlab , который делает примерно то же самое, но немного другими методами.

Личный опыт

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

Телеграм-канал

DeepSchool

Короткие посты по теории ML/DL, полезные
библиотеки и фреймворки, вопросы с собеседований
и советы, которые помогут в работе

Открыть Телеграм

Увидели ошибку?

Напишите нам в Telegram!