Тестовое задание: Crowd / Технический менеджер проектов

Анализ лога краудсорсингового проекта по бинарной разметке URL (workflow REGION_MARKUP). Цель — оценить качество разметки, найти проблемные контрольные задания и посчитать ключевые метрики проекта.

Записей в логе: 21 437 Заданий: 203 963 Исполнителей: 2 258 Контрольных URL: 13 358 Стек: Python 3.14 · pandas · matplotlib

Содержание

  1. Задание 1. Привести данные к удобному формату
  2. Задание 2. «Сложные» и «неоднозначные» контрольные задания
  3. Задание 3. Дополнительные метрики проекта
  4. Итоговый вывод
  5. Код и артефакты

Задание 1. Привести данные к удобному формату

Исходный TSV-файл содержит JSON-поля, «сжатые» в строки, и Unix-таймстемпы. Чтобы данные стали пригодны для анализа, нужно: распарсить JSON, перевести времена в datetime и развернуть страницы-ассайменты в длинный формат «одна строка = одно микро-задание».

Ключевые шаги

# 1. Загрузка
df = pd.read_csv(SRC, sep="\t")

# 2. Unix-секунды -> datetime
for col in ("assignment_skip_time", "assignment_start_time", "assignment_submit_time"):
    df[col] = df[col].apply(lambda ts: pd.to_datetime(int(ts), unit="s", utc=True)
                            if pd.notna(ts) else pd.NaT)

# 3. Длительность работы над страницей
df["duration_sec"] = (df["assignment_submit_time"] - df["assignment_start_time"]).dt.total_seconds()

# 4. JSON-поля
df["solutions_parsed"] = df["assignment_raw_solutions"].apply(json.loads)
df["tasks_parsed"]     = df["task_suite_raw_tasks"].apply(json.loads)

# 5. Длинный формат: одна строка = одно задание внутри страницы
rows = []
for _, r in df.iterrows():
    for i, task in enumerate(r["tasks_parsed"]):
        url   = task["input_values"]["input"]["view"]["data"]["region_markup"]["url"]
        known = task.get("known_solutions")
        gold  = known[0]["output_values"]["result"] if known else None
        ans   = r["solutions_parsed"][i]["output_values"].get("result") if i < len(r["solutions_parsed"]) else None
        rows.append({
            "assignment_id": r["assignment_assignment_id"],
            "worker_id":     r["worker_id"],
            "task_index":    i,
            "url":           url,
            "is_honeypot":   bool(known),
            "gold_answer":   gold,
            "worker_answer": ans,
            "is_correct":    None if not known else (ans == gold),
        })
tasks_long = pd.DataFrame(rows)

Сводка по данным

ПоказательЗначение
Страниц в логе21 437
Микро-заданий203 963
Из них контрольных (ханипотов)31 063 (15,2%)
Уникальных контрольных URL13 358
Исполнителей2 258
Распределение ответовyes 94 335 / no 72 604 / not_working 9 060 / NaN 27 964
Вывод по заданию 1. Получены две таблицы: assignments_clean.csv (по странице) и tasks_long.csv (по микро-заданию). Длинная таблица — основа всех расчётов на шагах 2–3. Уже на этом шаге заметно, что (1) у воркеров есть третья кнопка not_working помимо да/нет; (2) число пустых ответов (27 964) почти точно равно 10 × число EXPIRED-страниц (2 815) — то есть на истёкших страницах ответов нет вовсе.

Задание 2. «Сложные» и «неоднозначные» контрольные задания

Контрольное задание идентифицируем по URL. Группируем все показы ханипота, считаем долю верных ответов и баланс «yes/no». Чтобы статистика не шумела, фильтруем URL с ≥ 5 показов — таких 268.

Метрики

Распределение accuracy по контрольным URL
Рис. 1. Распределение accuracy по контрольным URL (≥5 показов). Розовая зона — «сложные», оранжевая — «неоднозначные».
Бакет accuracyURLДоля
0–20%3211,9%
20–40%166,0%
40–60%228,2%
60–80%3613,4%
80–100%15859,0%

Доля «сложных» (acc < 50%): 17,9%. Доля «неоднозначных» (40–60% yes): 10,1%.

Топ «сложных» (примеры из 32 URL с 0% accuracy)

URLGoldПоказов yesnonot_working accuracy
svarka-piter.runo66000%
food-service.ruyes60600%
vip-phones.runot_working55000%
faridkamal.pronot_working66000%
gazballon-nizhniy-tagil.runo88000%
efsmoscow.runo77000%
myshop-bei517.myinsales.runot_working66000%

Полный список — honeypot_hardest.csv.

Топ «неоднозначных» (yes/no близко к 50/50)

URLGold yesno yes_shareentropy, бит
giftarcher.runo3350%1.00
tvoya-vaza.runo3350%1.00
бир.рфyes3350%1.00
klassikashop.ruyes4357%0.99
myxbag.runo3443%0.99

Полный список — honeypot_most_ambiguous.csv.

Вывод по заданию 2. Найдено 48 «сложных» ханипотов с accuracy < 50% (из них 32 — с абсолютным 0%) и 27 «неоднозначных» с расщеплением 40–60%. Очень показательно, что в группе 0% исполнители почти единодушно дают противоположный gold ответ (например, 8 из 8 нажимают «yes» там, где gold «no»). Это типичный признак некорректного gold, а не «плохих воркеров»: либо инструкция допускает разное толкование сайта, либо контроль протух (сайт изменился). Ханипоты с gold = not_working, на которых все воркеры ставят yes, — кандидаты на удаление в первую очередь, т.к. они штрафуют добросовестную работу.

Задание 3. Дополнительные метрики проекта

5 метрик, главная (M1) — качество разметки.

M1. Honeypot accuracy — главная метрика качества

ПоказательЗначение
Project accuracy (yes/no, без not_working)74,4%
Project accuracy (строгая, с not_working)71,9%
Медиана accuracy по воркерам (n=1 061 с ≥10 ханипотами)78%
Доля воркеров с accuracy < 70% (кандидаты на бан)16,6%
Доля воркеров с accuracy ≥ 90% (доверенные)2,9%
Гистограмма honeypot accuracy по воркерам
Рис. 2. Распределение honeypot accuracy по воркерам.

Польза: прямой индикатор корректности разметки. 74% — это средне-низко для бинарной задачи; обычно проект считается «здоровым» при ≥85%. Гистограмма унимодальная (мода ~80%), без явного второго пика «ботов» у нуля — массового мошенничества нет, но левый хвост (≈170 воркеров с acc < 70%) тянет среднее вниз.

M2. Status mix — здоровье воркфлоу

Распределение статусов страниц
Рис. 3. Распределение статусов страниц-ассайментов.
СтатусСтраницДоля
APPROVED18 57986,7%
EXPIRED2 81513,1%
SKIPPED430,2%

Польза: EXPIRED-rate 13% — ощутимая утечка. SUBMITTED/REJECTED отсутствуют — значит, отдельной модерации после автоприёма по ханипотам нет. Это означает, что 86,7% APPROVED не равно 86,7% хороших ответов: сюда же попадают страницы воркеров с accuracy 60–70%.

M3. Throughput — производительность

Распределение секунд на задание
Рис. 4. Распределение скорости работы (секунд на одно задание, отсечён 99-й перцентиль).
ПоказательЗначение
Медиана длительности страницы (10 заданий)349 сек
Медиана сек/задание36,8 сек
90-й перцентиль сек/задание82 сек
Доля страниц с < 3 сек/задание (random clicking)0,36%

Польза: показывает, что задание реально трудоёмкое (~37 сек на URL — успеть открыть сайт и оценить). Подозрительно быстрых страниц мало — массового «кликания» нет, проблема качества лежит в плоскости понимания задачи, а не скорости.

M4. Worker concentration — устойчивость пула

Парето: концентрация работы по воркерам
Рис. 5. Накопленная доля сделанных страниц от доли воркеров (Парето).
ПоказательЗначение
Воркеров делает 50% объёма465 (20,6%)
Воркеров делает 80% объёма1 098 (48,6%)
Топ-1 воркер114 страниц = 0,5% объёма

Польза: работа размазана — bus-factor низкий, нет «ключевых» воркеров, потеря которых сломает проект. Это плюс с точки зрения устойчивости, но минус с точки зрения управляемости качеством: каждый воркер делает в среднем 9,5 страниц — мало для надёжной оценки accuracy на новичках.

M5. Honeypot density

ПоказательЗначение
Доля ханипотов в показанных заданиях15,2%
Ханипотов на страницу: медиана / среднее / max1 / 1,45 / 2

Польза: проверка корректности настройки контроля. 15% — стандартное значение (обычно 10–20%); у нас есть достаточно сигнала для оценки воркеров (в среднем 1–2 контрольных на 10 заданий).

Сводная таблица всех метрик

МетрикаЗначениеСигнал
M1. Honeypot accuracy (проект)74,4%низковато (норма 85%+)
M1. Доля воркеров с accuracy < 70%16,6%требуется чистка
M2. APPROVED rate86,7%OK
M2. EXPIRED rate13,1%повышенный
M3. Median sec/task36,8 секнорма
M3. < 3 сек/task (фрод)0,36%OK
M4. 80% работы делают49% воркеровздоровое распределение
M5. Honeypot density15,2%в норме
Вывод по заданию 3. Главная метрика — honeypot accuracy 74,4%; остальные метрики (status mix, throughput, концентрация воркеров, плотность ханипотов) показывают, что инфраструктура и пул в норме, а провисает именно качество разметки.

Итоговый вывод

  1. Данные приведены к удобному формату: два CSV (assignments_clean.csv, tasks_long.csv) с распарсенными JSON и человекочитаемыми временами; готовы для любых groupby и визуализации.
  2. Сложные/неоднозначные ханипоты найдены: 48 URL с accuracy < 50% (из них 32 с 0% — с большой вероятностью неверный gold) и 27 URL с расщеплением 40–60%. Эти 75 URL — приоритет для ревизии командой контроля качества.
  3. Качество проекта 74% — ниже бенчмарка (~85%). Главные рычаги для роста:
    1. ревизия gold у проблемных ханипотов уберёт ложные штрафы и поднимет accuracy воркеров без их участия;
    2. бан/перенаправление 16,6% слабых воркеров поднимет среднее;
    3. сокращение 13% EXPIRED-страниц через более короткие тайм-ауты или более привлекательную оплату ускорит конвейер.
    Фрод (рандом-клик) практически отсутствует — проблема в понимании задания, а не в злом умысле.

Код и артефакты

Полный код, исходный TSV и промежуточные CSV — в репозитории. Скрипты разбиты по заданиям:

Артефакты в data/: metrics_summary.csv · honeypot_hardest.csv · honeypot_most_ambiguous.csv · worker_quality.csv · honeypot_stats_all.csv · assignments_clean.csv