Для сколько-нибудь осмысленного анализа этого мало. Важно не только выделить некие строки и пометить их тегами, но и определить, что за объекты кроются за ними.
Живой пример (кусок XML результата анализа резюме от одного из лидеров области Sovren):
<EmployerOrg>
<EmployerOrgName>ООО Звезда-DSME</EmployerOrgName>
<PositionHistory positionType="directHire">
<Title>Ведущий специалист отдела развития информационных систем</Title>
<OrgName>
<OrganizationName>ООО Звезда-DSME</OrganizationName>
</OrgName>
Парсер Sovren прекрасно справился с выделением полей. Ребята не зря занимаются этим делом без малого 20 лет!
Но что дальше делать с «Ведущий специалист отдела развития информационных систем»? Как понять, что же это за должность, насколько опыт работы этого человека релевантен для той или иной вакансии?
Если ваша задача — поиск сотрудника под требования вакансии или наоборот — вакансии под опыт и пожелания кандидата, то поиск ключевых слов, сравнение bag of words дают посредственные результаты. Для объектов, которым соответствует множество возможных синонимичных наименований такой подход не сработает.
Для начала нужно нормализовать наименования, превратить «специалистов в чём-либо» в программистов, сисадминов и прочих отоларингологов.
Для этого придётся составить базу знаний, таксономию объектов. Причём специфика такова, что недостаточно описать, например только строителей — люди меняют области деятельности и в резюме строителя могут встречаться и другие, не связанные со строительством места работы.
И если таксономия будет описывать только строительство — в текстах, относящихся к другим областям деятельности, будут ложные срабатывания. В строительстве «архитектор» — это одно, а в IT — совсем другое. «Операция», «Акция», «Объект» и множество словосочетаний, содержащих эти слова — примеры неоднозначностей, которые необходимо разрешать.
Простая нормализация тоже не спасёт отца русской демократии. Фантазия людей пишущих резюме и составляющих штатные расписания не перестаёт удивлять. К сожалению для нас, разработчиков, это значит, что в общем случае из строки описывающей объект идентифицировать этот объект нельзя. То есть вы конечно можете попытаться обучить какой-нибудь классификатор, скармливая ему поле и желаемую должность.
И он даже будет работать. На «бухгалтерах», «секретарях», «программистах».
Только вот в резюме люди пишут «специалист отдела N» и понять, бухгалтер он или секретарь, можно лишь по контексту, набору выполняемых обязанностей.
Казалось бы — хорошо, учтём контекст, пусть классификатор обучается ещё и на обязанностях. Так, да не так — при определении набора обязанностей та же проблема: неоднозначность трактовки, всякие непонятные анафоры).
Мы решили применить вероятностный (байесовский) подход:
Анализируя исходный текст, для всех строк (например, «архитектор», «работа
с клиентами») мы определяем множество всех возможных трактовок
(например, для «архитектора» это будет «архитектор зданий», «архитектор программного
обеспечения» и т.д.). В результате получается набор множеств трактовок. Затем
ищем такое сочетание трактовок из всех множеств, чтобы его правдоподобность
была максимальной.
Например:
- 2007-2009 ООО Umbrella corp. Старший менеджер. Работа с ключевыми клиентами, поиск новых клиентов, переговоры, оформление сделок;
- 2001-2007 ООО Рога и копыта. Менеджер по работе с клиентами. Консультирование покупателей по всем возникающим вопросам, оформление покупок, наличный и безналичный расчёт.
В обоих местах работы используется слово «менеджер» для обозначения совсем разных должностей. По контексту можно понять, что в первом случае должность действительно менеджерская, а во втором правильнее было бы назваться продавцом.
Для того, чтобы выбрать между «менеджером по работе с клиентами» и «продавцом» мы оцениваем правдоподобность сочетания этих должностей с найденными в этом месте работы навыками. При этом навыки могут таким же образом выбираться из нескольких вариантов, поэтому задача состоит в выборе наиболее правдоподобного сочетания из множества найденных в тексте объектов.
Количество объектов разных типов (навыки, должности, отрасли, города и пр.) очень большое (сотни тысяч в нашей базе знаний), поэтому пространство, которому принадлежат резюме очень-очень многомерное. Для обучения большинства machine learning алгоритмов понадобится астрономическое количество примеров.
Мы решили резать. То есть кардинально сокращать количество параметров и использовать результат обучения только там, где у нас есть достаточное количество примеров.
Для начала мы стали собирать статистику по сочетаниям кортежей признаков, например: должность-отрасль, должность-отдел, должность-навык. На основе этой статистики мы оцениваем правдоподобность новых, ещё не встречаемых ранее, сочетаний
объектов и выбираем лучшее сочетание.
В примере выше набор навыков склоняет парсер в сторону менеджера в первом случае и в сторону продавца во втором.
Использование простых счётчиков и оценки вероятности по Байесу позволяет получать хорошие результаты при небольшом количестве примеров. В нашей базе знаний сейчас около ста тысяч размеченных специалистами вакансий и резюме, и это позволяет разрешать большинство неоднозначностей для распространённых объектов.
На выходе мы получаем JSON объект, описывающий вакансию или резюме в терминах нашей базы знаний, а не в тех, которые придумал соискатель или работодатель.
Это представление можно использовать для точного поиска по параметрам, оценки («скоринга») резюме соискателя или сопоставления пар «резюме-вакансия».
Мы сделали простой интерфейс, в котором можно загрузить резюме (doc, docx, pdf (не картинкой) и другие форматы) и получить его представление в JSON. Только не забывайте про 152ФЗ! Не надо эксперементировать с резюме с реальными персональными данными :)
Например вот такое резюме:
г. Омск
тел +7923123321123
Ответственный и трудолюбивый менеджер по продажам.
Опыт работы
- 2001-2002: ООО Бытдомуправ. Уборщик территории во дворе. Особенно добросовестно выполнял работы по уборке снега.
- С 12.03.2005 по 30.01.2007 Магазин «Надежда». Старший киоскёр по продаже колбасы. Увеличил продажи колбасы на 146% за 2 месяца.
- 2002-2003: ООО Кузремонт Жестянщик-кузовщик в автомастерской. Переделывал «Запорожцы» в «Мерседесы».
Дополнительно
Физически сильный, умный, красивый. Есть собственный автомобиль Range Rover Sport и права категории B.
Превращается в следующий JSON:
{
"url": null,
"name": "Менеджер по продажам, г. Омск",
"skill_ids": [
{
"cv_skill_id": 5109999,
"skill_name": "ответственность",
"skill_id": 91,
"skill_level_id": 1,
"skill_level_name": "Базовый"
},
{
"cv_skill_id": 5110000,
"skill_name": "трудолюбие",
"skill_id": 596,
"skill_level_id": 1,
"skill_level_name": "Базовый"
},
{
"cv_skill_id": 5109998,
"skill_name": "осуществление уборки",
"skill_id": 1474,
"skill_level_id": 1,
"skill_level_name": "Базовый"
},
{
"cv_skill_id": 5109997,
"skill_name": "наличие автомобиля",
"skill_id": 2688,
"skill_level_id": 2,
"skill_level_name": "Средний"
}
],
"description": "Описание отсутствует",
"ts": "2016-09-14 06:00:51.136898",
"jobs": [
{
"employer_id": null,
"description": ": ООО Бытдомуправ. Уборщик территории во дворе. Особенно добросовестно выполнял работы по уборке снега",
"department_id": null,
"company_size_id": null,
"industry_id": null,
"start_date": "2001-01-01",
"cv_job_id": 1812412,
"company_size_name": null,
"employer_name": null,
"job_id": 336,
"department_name": null,
"industry_name": null,
"end_date": "2002-01-01",
"job_name": "Дворник"
},
{
"employer_id": null,
"description": ": ООО Кузремонт Жестянщик-кузовщик в автомастерской. Переделывал \"Запорожцы\" в \"Мерседесы\". Дополнительно Физически сильный, умный, красивый. Есть собственный автомобиль Range Rover Sport и права категории B",
"department_id": null,
"company_size_id": null,
"industry_id": null,
"start_date": "2002-01-01",
"cv_job_id": 1812414,
"company_size_name": null,
"employer_name": null,
"job_id": 268,
"department_name": null,
"industry_name": null,
"end_date": "2003-01-01",
"job_name": "Рабочий автосервиса"
},
{
"employer_id": null,
"description": "С 12.03.2005 по 30.01.2007 Магазин \"Надежда\". Старший киоскёр по продаже колбасы. Увеличил продажи колбасы на 146% за 2 месяца",
"department_id": null,
"company_size_id": null,
"industry_id": 39,
"start_date": "2005-03-12",
"cv_job_id": 1812413,
"company_size_name": null,
"employer_name": null,
"job_id": 354,
"department_name": null,
"industry_name": "Розничная торговля",
"end_date": "2007-01-30",
"job_name": "Продавец"
}
],
"cv_file_id": 16598,
"favorite_industries": [
{
"name": "Розничная торговля",
"industry_id": 39
}
],
"wage_min": null,
"cv_id": 1698916,
"favorite_areas_data": [
[
{
"id": 198830,
"name": "Российская Федерация",
"level": 1
},
{
"id": 10005,
"name": "Сибирский федеральный округ",
"level": 2
},
{
"id": 88,
"name": "Омская область",
"level": 3
},
{
"id": 727,
"name": "г. Омск",
"level": 4
}
]
],
"certificate_ids": [
{
"certificate_name": "Водительское удостоверение категории B",
"certificate_id": 118,
"cv_certificate_id": 604445
}
],
"cv_owner": "own",
"favorite_jobs": [
{
"name": "Менеджер по продажам",
"job_id": 112
}
],
"cv_status_id": 2,
"filename": "test_resume.odt"
}
Извлечение персональных данных в парсере отключено, не ищите их в JSON.
На мой предвзятый взгляд, результат интересный и применений ему — множество. Хотя до точности распознавания объектов, сравнимой с человеческой, ещё очень далеко. Нужно развивать базу знаний, обучать алгоритм на примерах, вводить дополнительные эвристики и, возможно, узкоспециализированные классификаторы, например для определения отраслей.
Интересно, какие методики используете или использовали бы Вы? Особенно интересно, использует ли кто-нибудь семантический подход а-ля Compreno от ABBYY?
Комментарии (4)
Novosedoff
13.10.2016 06:27<<< Для начала мы стали собирать статистику по сочетаниям кортежей признаков, например: должность-отрасль, должность-отдел, должность-навык. На основе этой статистики мы оцениваем правдоподобность новых, ещё не встречаемых ранее, сочетаний объектов и выбираем лучшее сочетание. >>>
— — — Подход конечно академический, только применительно к реальной жизни всё равно нелепый :-)
А Вы знаете, дорогой автор, что зачастую у самих работодателей <правдоподобность>, т.е. <реальная достижимость> их требований к кандидитам ни в какие ворота не лезет? Иными словами, опираясь на требования таких работодателей, в целевую выборку при поиске должны попадать как раз те самые кандидаты, которых ваш поиск забракует как раз таки по причине <неправдоподобности> сочетаний навыков в их опыте?CPro
13.10.2016 06:38Да, есть такое дело — редкие сочетания могут ошибочно «отбраковаться». Но это происходит не со всеми редкими сочетаниями, а только с теми, у которых будет ещё и неоднозначность трактовки именно в этом «редком» месте. Ну и это легко исправится, как только появится пара-другая резюме с таким сочетанием признаков. При желании можно и вручную подправить счётчики для того или другого кортежа.
ganqqwerty
вообще потрясающе, я даже не знал, что есть системы, настолько узко заточенные. Расскажите, что кроме Sovren еще встречается? Ну и для английского тоже
CPro
Ещё есть RChili, раньше был сильно распиаренный Bright, который купил Linkedin и, похоже, похоронил. И множество in-house систем подобного назначения у разных HR и recruitment платформ. Но они чаще всего ограничиваются ФИО, контактами и полнотекстовым поиском.