Парсинг резюме

Ті хто стикався з завданнями автоматизованого аналізу резюме, представляють сучасний стан справ в цій області — існуючі парсери в основному обмежуються виділенням контактних даних та ще кількох полів, таких як «посада» і «місто».

Для скільки-небудь осмисленого аналізу цього мало. Важливо не тільки виділити якісь рядки і позначити їх тегами, але і визначити, що за об'єкти криються за ними.

Живий приклад (шматок 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?
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.