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

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

    Для сколько-нибудь осмысленного анализа этого мало. Важно не только выделить некие строки и пометить их тегами, но и определить, что за объекты кроются за ними.

    Живой пример (кусок 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?
    Поделиться публикацией
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама
    Комментарии 7
    • 0
      вообще потрясающе, я даже не знал, что есть системы, настолько узко заточенные. Расскажите, что кроме Sovren еще встречается? Ну и для английского тоже
      • 0
        Ещё есть RChili, раньше был сильно распиаренный Bright, который купил Linkedin и, похоже, похоронил. И множество in-house систем подобного назначения у разных HR и recruitment платформ. Но они чаще всего ограничиваются ФИО, контактами и полнотекстовым поиском.
        • 0
          У ЭВОЛА есть инструмент анализа резюме для SAP HR Human Capital Management с нашим ABBYY Compreno внутри. Он умеет автоматически анализировать входящие резюме, проверять, насколько они соответствуют открытым вакансиям, и выявлять значимую информацию о кандидатах. Информацию может извлекать самую разную, список длинный и может меняться\дополняться по потребностям пользователя. В общем виде это так (не обидитесь, если скопирую из пресс-релиза?):

          Личная информация (ФИО, пол, дата рождения/возраст, семейное положение, гражданство);
          • Контактная информация (телефон, e-mail, skype и др.);
          • Желаемая должность и пожелания по уровню дохода;
          • Опыт работы (период работы, название компании, сфера деятельности компании,
          • должность, отдел, обязанности, стаж);
          • Образование (год выпуска, название учебного учреждения, факультет, кафедра, специальность, специализация, квалификация);
          • Уровень владения иностранными языками;
          • Знание программного обеспечения и технологий;
          • Личные качества, хобби;
          • Рекомендации (ФИО, должность, компания).
          • 0
            Вот это круто! А происходит ли нормализация должностей, отделов и тд? Много ли времени ушло на создание модели (грамматики, графа или как это называется) для резюме в Compreno, и кто эту модель делал — ABBYY или ЭВОЛА сами?
            • 0
              «Нормализация» должностей и объектов к заранее заданным справочникам действительно требует учёта контекста и разрешения лингвистических явлений таких как анафорические связи, эллипсис и омонимия. Это может быть выполнено как с помощью чистого семантико-синтаксического разбора, так и гибридным подходом с использованием машинного обучения и семантических разборов. Оба этих подхода поддержаны в движке ABBYY Comrpeno на технологическом уровне.

              Информационную модель, которую необходимо получать на выходе парсинга разрабатывала Эвола. Алгоритмы извлечения (включённые в онтологии) разрабатывали специалисты ABBYY. Алгоритмы основаны на базовом семантическом разборе, который уже давно есть в Compreno.
        • НЛО прилетело и опубликовало эту надпись здесь
          • 0
            Да, есть такое дело — редкие сочетания могут ошибочно «отбраковаться». Но это происходит не со всеми редкими сочетаниями, а только с теми, у которых будет ещё и неоднозначность трактовки именно в этом «редком» месте. Ну и это легко исправится, как только появится пара-другая резюме с таким сочетанием признаков. При желании можно и вручную подправить счётчики для того или другого кортежа.

          Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.