Как решать такую задачу?
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 больше
• Несмотря на то, что этот признак принимает разные значения,
небольшое смещение сильно улучшало (ложно) качество модели.
Важность признаков
Доля UPPPERCASE-а
log зарплаты
Доля слов в опыте не из словаря
log времени без работы
log от времени опыта работы
Доля alphanum текста
Доля описания обучения
Доля слов в образовании
не из словаря
Название не из словаря
Разница между возрастом и опытом
Длина текста резюме
Количество разделителей
в заголовке
Навыки не из словаря
Размер слов в навыках
Возраст
Длина фамилии
Университеты не из словаря
Проблемы внедрения
• Некоторые правила алгоритм выучил недостаточно точно
• нельзя размещать резюме возрастом >= 30 лет в
профобласти “студенты/начало карьеры”
• в опыте работы обязательно должен быть описан опыт
последних 2-3х лет за исключением случаев, когда
причина отсутствия этого опыта изложена в поле “о себе”
• Некоторые вещи мы пока что не умеем модерировать
(портфолио)
• Пришлось писать ручные if’ы, чтобы закрыть самые
критичные проблемы (с точки зрения отдела модерации)
Проблемы внедрения
• Самая серьёзная проблема, выявившаяся в
продакшене состоит в неточном моделировании задачи
• При проектировании не учитывалось редактирование
резюме модератором при подтверждении =>
некоторые не совсем валидные резюме алгоритм
воспринимает как “хорошие”
• Это не только увеличивает real-time ошибку, но и
мешает оценить её точно (мы не можем запретить
модераторам редактировать резюме для
честного эксперимента)
Слепое тестирование
• 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
• То есть разница между роботом и человеком
статистически незначима.