Модерация резюме:
от людей к роботам
Ермаков Петр, HeadHunter
09.04.2016, AIST
HeadHunter - IT-компания
• Технический департамент > 70 человек
• 1 минута простоя hh.ru затрагивает 30.000
пользователей
• Более 3.000 RPS
Задачи анализа данных
HeadHunter
• Упрощение жизни пользователя
• Рекомендательные системы
• Автоматизация ручного труда
• Оптимизация продаж
Сайт hh.ru
Мы работаем, чтобы вы работали
Резюме на сайте
Как выглядит резюме
Процесс модерации
• 10-15 модераторов
• многостраничный гайд по модерации
• минимум 2000 резюме в сутки
• APPROVED, BLOCKED, DELETED
• APPROVED - 84%
• BLOCKED - 16%
• DELETED - 6000 за 2014-2015
Процесс модерации
Помимо конечного статуса, модераторы ставят
флаги “незаполненности” (нет рекомендаций,
плохая должность)
Флаги % из APPROVED
no_recommendation 52.21%
careless_key_skill_information 18.72%
careless_additional_information 11.54%
bad_function 5.96%
no_company_description 4.97%
bad_education 3.02%
Постановка задачи
• Бинарная классификация
• Пропускать или блокировать? Нет
• Пропускать или отдать человеку? Да
Как решать такую задачу?
1. Сформировать большую выборку истории
подтверждений/блокировок/удалений резюме
2. Превратить каждый объект выборки в набор чисел
фиксированной длины (выделить признаков)
3. Выбрать алгоритм машинного обучения, хорошо
справляющийся с задачей
4. Настроить модель максимизируя качество
5. Проверить качество в продакшене, если что-то

не так, вернуть к пункту 2
Обучающая выборка
• Выборка была составлена за трёхмесячную историю
подтверждений и блокировок резюме + все резюме,
удалённые за 2 года
169607 подтверждённых
33462 заблокированных
5945 удалённых
• Для подтвержденных резюме используется

версия резюме после модерации,

для заблокированных - до.
Модераторы: доля
блокирования
Обучающая выборка
• Выборка была составлена за трёхмесячную историю
подтверждений и блокировок резюме + все резюме,
удалённые за 2 года
169607 подтверждённых
33462 заблокированных
5945 удалённых
• Для подтвержденных резюме используется

версия резюме после модерации,

для заблокированных - до.
Модераторы: доля
проставления флага
Обучающая выборка:
допущения
Чтобы поддерживать разумное качество, пришлось
сделать две вещи:
• Обучаемся только но одном модераторе, их
поведение различается, что портит
статистическую природу данных
• Не предсказываем флаг
no_company_description
Выделение признаков
• В нашем случае объект обучения — резюме,
сложно структурированная сущность,
включающая в себя числовые параметры, текст,
признаки переменной длины (образования,
опыты) и т.д.
• В финальной модели одно резюме

представляется 6978 признаками
Выделение признаков
Текстовые признаки:
• TF-IDF по разным полям резюме

(название / опыты / образования / скиллы / о себе)
• кол-во слов в поле
• доля слов, не попавших в словарь
• параметры распределения длин слов

(перцентили, среднее, стандартное отклонение)
• фичи вида len(field) / len(resume)
• доля UPPERCASE
• доля alphanum
Выделение признаков
• кол-во пустых полей
• кол-во разделителей в названии
• возраст, общее время работы, их разница
• зарплата, пол, наличие фото
• начало карьеры / рабочая специальность / домашний персонал
• кол-во опытов / образований / ключевых навыков
• доля университетов / компаний из нашего справочника
• размер самой длинной последовательности из одинаковых цифр

в номере телефона
Многие признаки были навеяны правилами из инструкции для модераторов.
Target leak

в признаке null fields count
• Из-за поля moderationTime для всех подтверждённых резюме
количество пустых полей было на 1 больше
• Несмотря на то, что этот признак принимает разные значения,
небольшое смещение сильно улучшало (ложно) качество модели.
Какой алгоритм
выбрать?
Метрики и качество
target ROC_AUC
approve 0.95979
no_recommendation 0.97789
careless_key_skill_information 0.99855
careless_additional_information 0.98939
bad_function 0.97504
bad_education 0.96344
Метрики и качество
target Precision Recall
approve 0.99502 0.54794
no_recommendation 0.97647 0.90039
careless_key_skill_information 0.99036 0.95046
careless_additional_information 0.90004 0.88910
bad_function 0.75000 0.73520
bad_education 0.75009 0.65997
Важность признаков
Доля UPPPERCASE-а
log зарплаты
Доля слов в опыте не из словаря
log времени без работы
log от времени опыта работы
Доля alphanum текста
Доля описания обучения
Доля слов в образовании 

не из словаря
Название не из словаря
Разница между возрастом и опытом
Длина текста резюме
Количество разделителей

в заголовке
Навыки не из словаря
Размер слов в навыках
Возраст
Длина фамилии
Университеты не из словаря
Проблемы внедрения
• Некоторые правила алгоритм выучил недостаточно точно
• нельзя размещать резюме возрастом >= 30 лет в
профобласти “студенты/начало карьеры”
• в опыте работы обязательно должен быть описан опыт
последних 2-3х лет за исключением случаев, когда
причина отсутствия этого опыта изложена в поле “о себе”
• Некоторые вещи мы пока что не умеем модерировать
(портфолио)
• Пришлось писать ручные if’ы, чтобы закрыть самые

критичные проблемы (с точки зрения отдела модерации)
Проблемы внедрения
• Самая серьёзная проблема, выявившаяся в
продакшене состоит в неточном моделировании задачи
• При проектировании не учитывалось редактирование
резюме модератором при подтверждении =>
некоторые не совсем валидные резюме алгоритм
воспринимает как “хорошие”
• Это не только увеличивает real-time ошибку, но и
мешает оценить её точно (мы не можем запретить
модераторам редактировать резюме для

честного эксперимента)
Онлайн мониторинг работы
Внедрение
Фронтенд Бизнес-логика
Сервис с
моделью
Очередь
new new
new
decision
decision
Побочные артефакты
• Выявление “хитрого” модератора
• Выключение робомодератора заметили
модераторы
• “Качество” работы модераторов лучше в
выходные
• Попробовали решать обратную задачу
Слепое тестирование
n1=7+8+183+106=304 n2=7+9+183+15=214
p1=(7+8)/304=4.9% p2=(7+9)/214=7.5%
Слепое тестирование
• p*=(n1*p1+n2*p2)/(n1+n2)=6.0%.
• z-stat = (p1-p2)/sqrt(p*(1-p*)(1/n1+1/n2))=1.20.
Для одностороннего теста с уровнем
достоверности 95% z_кр=1.64
• То есть разница между роботом и человеком
статистически незначима.
и в продакшн!

Петр Ермаков, HeadHunter - Модерация резюме: от людей к роботам. Машинное обучение в компании HeadHunter

  • 1.
    Модерация резюме: от людейк роботам Ермаков Петр, HeadHunter 09.04.2016, AIST
  • 2.
    HeadHunter - IT-компания •Технический департамент > 70 человек • 1 минута простоя hh.ru затрагивает 30.000 пользователей • Более 3.000 RPS
  • 3.
    Задачи анализа данных HeadHunter •Упрощение жизни пользователя • Рекомендательные системы • Автоматизация ручного труда • Оптимизация продаж
  • 4.
    Сайт hh.ru Мы работаем,чтобы вы работали
  • 5.
  • 6.
  • 7.
    Процесс модерации • 10-15модераторов • многостраничный гайд по модерации • минимум 2000 резюме в сутки • APPROVED, BLOCKED, DELETED • APPROVED - 84% • BLOCKED - 16% • DELETED - 6000 за 2014-2015
  • 8.
    Процесс модерации Помимо конечногостатуса, модераторы ставят флаги “незаполненности” (нет рекомендаций, плохая должность) Флаги % из APPROVED no_recommendation 52.21% careless_key_skill_information 18.72% careless_additional_information 11.54% bad_function 5.96% no_company_description 4.97% bad_education 3.02%
  • 9.
    Постановка задачи • Бинарнаяклассификация • Пропускать или блокировать? Нет • Пропускать или отдать человеку? Да
  • 10.
    Как решать такуюзадачу? 1. Сформировать большую выборку истории подтверждений/блокировок/удалений резюме 2. Превратить каждый объект выборки в набор чисел фиксированной длины (выделить признаков) 3. Выбрать алгоритм машинного обучения, хорошо справляющийся с задачей 4. Настроить модель максимизируя качество 5. Проверить качество в продакшене, если что-то
 не так, вернуть к пункту 2
  • 11.
    Обучающая выборка • Выборкабыла составлена за трёхмесячную историю подтверждений и блокировок резюме + все резюме, удалённые за 2 года 169607 подтверждённых 33462 заблокированных 5945 удалённых • Для подтвержденных резюме используется
 версия резюме после модерации,
 для заблокированных - до.
  • 12.
  • 13.
    Обучающая выборка • Выборкабыла составлена за трёхмесячную историю подтверждений и блокировок резюме + все резюме, удалённые за 2 года 169607 подтверждённых 33462 заблокированных 5945 удалённых • Для подтвержденных резюме используется
 версия резюме после модерации,
 для заблокированных - до.
  • 14.
  • 15.
    Обучающая выборка: допущения Чтобы поддерживатьразумное качество, пришлось сделать две вещи: • Обучаемся только но одном модераторе, их поведение различается, что портит статистическую природу данных • Не предсказываем флаг no_company_description
  • 16.
    Выделение признаков • Внашем случае объект обучения — резюме, сложно структурированная сущность, включающая в себя числовые параметры, текст, признаки переменной длины (образования, опыты) и т.д. • В финальной модели одно резюме
 представляется 6978 признаками
  • 17.
    Выделение признаков Текстовые признаки: •TF-IDF по разным полям резюме
 (название / опыты / образования / скиллы / о себе) • кол-во слов в поле • доля слов, не попавших в словарь • параметры распределения длин слов
 (перцентили, среднее, стандартное отклонение) • фичи вида len(field) / len(resume) • доля UPPERCASE • доля alphanum
  • 18.
    Выделение признаков • кол-вопустых полей • кол-во разделителей в названии • возраст, общее время работы, их разница • зарплата, пол, наличие фото • начало карьеры / рабочая специальность / домашний персонал • кол-во опытов / образований / ключевых навыков • доля университетов / компаний из нашего справочника • размер самой длинной последовательности из одинаковых цифр
 в номере телефона Многие признаки были навеяны правилами из инструкции для модераторов.
  • 19.
    Target leak
 в признакеnull fields count • Из-за поля moderationTime для всех подтверждённых резюме количество пустых полей было на 1 больше • Несмотря на то, что этот признак принимает разные значения, небольшое смещение сильно улучшало (ложно) качество модели.
  • 20.
  • 21.
    Метрики и качество targetROC_AUC approve 0.95979 no_recommendation 0.97789 careless_key_skill_information 0.99855 careless_additional_information 0.98939 bad_function 0.97504 bad_education 0.96344
  • 22.
    Метрики и качество targetPrecision Recall approve 0.99502 0.54794 no_recommendation 0.97647 0.90039 careless_key_skill_information 0.99036 0.95046 careless_additional_information 0.90004 0.88910 bad_function 0.75000 0.73520 bad_education 0.75009 0.65997
  • 23.
    Важность признаков Доля UPPPERCASE-а logзарплаты Доля слов в опыте не из словаря log времени без работы log от времени опыта работы Доля alphanum текста Доля описания обучения Доля слов в образовании 
 не из словаря Название не из словаря Разница между возрастом и опытом Длина текста резюме Количество разделителей
 в заголовке Навыки не из словаря Размер слов в навыках Возраст Длина фамилии Университеты не из словаря
  • 24.
    Проблемы внедрения • Некоторыеправила алгоритм выучил недостаточно точно • нельзя размещать резюме возрастом >= 30 лет в профобласти “студенты/начало карьеры” • в опыте работы обязательно должен быть описан опыт последних 2-3х лет за исключением случаев, когда причина отсутствия этого опыта изложена в поле “о себе” • Некоторые вещи мы пока что не умеем модерировать (портфолио) • Пришлось писать ручные if’ы, чтобы закрыть самые
 критичные проблемы (с точки зрения отдела модерации)
  • 25.
    Проблемы внедрения • Самаясерьёзная проблема, выявившаяся в продакшене состоит в неточном моделировании задачи • При проектировании не учитывалось редактирование резюме модератором при подтверждении => некоторые не совсем валидные резюме алгоритм воспринимает как “хорошие” • Это не только увеличивает real-time ошибку, но и мешает оценить её точно (мы не можем запретить модераторам редактировать резюме для
 честного эксперимента)
  • 26.
  • 27.
  • 28.
    Побочные артефакты • Выявление“хитрого” модератора • Выключение робомодератора заметили модераторы • “Качество” работы модераторов лучше в выходные • Попробовали решать обратную задачу
  • 29.
  • 30.
    Слепое тестирование • p*=(n1*p1+n2*p2)/(n1+n2)=6.0%. •z-stat = (p1-p2)/sqrt(p*(1-p*)(1/n1+1/n2))=1.20. Для одностороннего теста с уровнем достоверности 95% z_кр=1.64 • То есть разница между роботом и человеком статистически незначима.
  • 31.