Pull to refresh
887.51
Яндекс
Как мы делаем Яндекс

Агрегация ответов в краудсорсинге. Пример с открытой библиотекой Яндекса

Reading time4 min
Views2.7K
Краудсорсинг позволяет размечать данные для разных задач, но популярнее всего, конечно, задачи классификации объектов — текстов и картинок. Обычно в краудсорсинге несколько человек размечают каждый объект, что требует агрегации — выбора верного ответа из представленных. Под катом я покажу, как агрегировать результат разметки с помощью двух алгоритмов: голоса большинства и алгоритма Дэвида-Скина.

Я буду использовать Crowd-Kit — нашу открытую библиотеку вычислительных методов контроля качества в краудсорсинге, которая предлагает реализации разных методов агрегации ответов, оценки неопределённости и согласованности ответов и т. д. Но вы можете воспользоваться альтернативами: spark-crowd (использует Scala вместо Python), CEKA (Java вместо Python) или Truth Inference (использует Python, но предоставляет только категориальные и числовые ответы).

Что ещё есть в Crowd-Kit
Библиотека предлагает хорошо знакомые программистам структуры данных и API: она интегрируется с популярными библиотеками для анализа данных на Python, такими как NumPy, SciPy и pandas. Кроме того, она не зависит от конкретной краудсорсинговой платформы. Нужно только предоставить данные в виде таблицы исполнителей, задач и ответов, а Crowd-Kit выдаст качественные результаты независимо от того, на какой платформе эти данные получены.

Писать код буду в Google Colab, но любая другая среда для Python тоже подойдёт. Сначала нужно установить библиотеку Crowd-Kit из PyPI. Кроме того, мне понадобятся размеченные данные — буду использовать открытые данные Толоки о релевантности поисковых ответов с двумя категориями: релевантные и нерелевантные. Загрузчиком данных будет сам Crowd-Kit, чтобы скачать их в виде таблиц pandas. Опять же, вы можете использовать другой источник данных и собрать таблицы самостоятельно.

!pip install crowd-kit

from crowdkit.datasets import load_dataset

df, df_gt = load_dataset('relevance-2')

Итак, данные загружены — прежде чем двинуться дальше, давайте взглянем на них.
perfomer task label
0 w851 t30685 1
1 w6991 t30008 0
2 w2596 t36316 0
3 w5507 t15145 1
4 w2982 t44785 1
... ... ... ...
475531 w4660 t62250 1
475532 w6630 t46626 0
475533 w4605 t93513 1
475534 w1928 t29002 0
475535 w5375 t49052 1
475536 rows x 3 columns

df_gt

task
t30006    0
t33578    0
t22462    1
t52093    0
t26935    0
         ..
t57345    1
t81052    1
t7189     1
t80463    0
t93643    0
Name: label, Length: 10079, dtype: int64


Функция load_dataset возвращает пару элементов. Первый элемент — это таблица pandas с данными, полученными из краудсорсинга. Второй элемент (если он имеется) — это данные с верными ответами (ground truth). Таблица df содержит три столбца: исполнитель, задача и метка. Метка имеет значение 0, если исполнитель оценил документ как нерелевантный, в противном случае 1. Таблица df_gt — это последовательность pandas, которая содержит правильные ответы на задачи, помещенные в индекс.

Импортируем три класса агрегации: мнение большинства, Wawa и Дэвид-Скин. Давайте попробуем агрегировать с помощью мнения большинства — простого эвристического метода.

from crowdkit.aggregation import MajorityVote, Wawa, DawidSkene

Создадим экземпляр класса с реализацией мнения большинства и вызовем метод fit_predict, чтобы агрегировать наши данные.

agg_mv = MajorityVote().fit_predict(df)
agg_mv

task
t0       1
t1       1
t10      1
t100     0
t1000    0
        ..
t9995    1
t9996    0
t9997    0
t9998    0
t9999    1
Length: 99319, dtype: int64

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

Классический метод агрегации с помощью мнения большинства не учитывает навыки исполнителей. Но иногда полезно взвесить вклад каждого исполнителя в конечную метку с учётом их согласованности с агрегированным значением. Этот подход называется Wawa, и он тоже представлен в Crowd-Kit. Он вычисляет мнение большинства, а затем повторно взвешивает голоса исполнителей, используя долю ответов, совпавших с мнением большинства.

agg_wawa = Wawa().fit_predict(df)
agg_wawa

task
t0       1
t1       1
t10      1
t100     0
t1000    0
        ..
t9995    1
t9996    0
t9997    0
t9998    0
t9999    1
Length: 99319, dtype: int64

Теперь мы выполняем ту же операцию с помощью вероятностной модели Дэвида-Скина, реализованной в Crowd-Kit при помощи EM-алгоритма. Это еще один классический подход к агрегированию в краудсорсинге, который был первоначально разработан в 70-х для вероятностного моделирования медицинских обследований. Код практически тот же: мы создаём экземпляр, задаём количество итераций алгоритма, вызываем fit_predict и получаем агрегированные результаты.

agg_ds = DawidSkene(n_iter=10).fit_predict(df)
agg_ds

task
t30685    1
t30008    0
t36316    0
t15145    1
t44785    0
         ..
t95222    0
t83525    0
t49227    0
t96106    1
t16185    1
Length: 99319, dtype: int64

Давайте оценим качество агрегированных данных. Для этого мы используем хорошо известную F1-меру из библиотеки scikit-learn.

from sklearn.metrics import f1_score

В этом наборе данных верные ответы доступны только для подмножества заданий, поэтому оценивать будем только по ним. Это позволяет нам выбрать лучшую модель агрегации с использованием хорошо известных и надёжных инструментов, таких как pandas, scikit-learn и Crowd-Kit.

f1_score(df_gt, agg_mv[df_gt.index])

0.7621861152141802

f1_score(df_gt, agg_wawa[df_gt.index])

0.7610675039246467

f1_score(df_gt, agg_ds[df_gt.index])

0.7883762200532387

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

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

agg_ds.to_frame('label').to_csv('test.txt')

Давайте заглянем внутрь. Данные и ответы на месте, результаты агрегации тоже.



Мы получили агрегированные данные, написав всего несколько строк кода.
Tags:
Hubs:
Total votes 16: ↑16 and ↓0+16
Comments3

Articles

Information

Website
www.ya.ru
Registered
Founded
Employees
over 10,000 employees
Location
Россия