Рекрутеры используют всё более сложное ПО и инструменты для анализа и сопоставления присылаемых резюме с размещёнными вакансиями и описанием должностных обязанностей в них. Если в вашем резюме будет представлена только общая информация или если ваши ответы на описание должностных обязанностей будут указаны расплывчато и/или без всякой конкретики, такие инструменты сработают против вас. Ваш отклик на вакансию может быть отвергнут искусственным интеллектом. Да, это действительно так, и бьюсь об заклад, что вы об этом не знали, а если знали, то не верили!

В этой статье я хочу представить ряд техник, которые помогут повысить шансы вашего резюме на рассмотрение. В этом практическом примере мы будем использовать алгоритмы обработки текстов на естественных языках (Natural Language Processing, NLP), Python и ряд визуальных инструментов библиотеки Altair. Итак, готовы нанести ответный удар по кадровикам?


Предположим, что вы хотите получить хорошую должность, и, вот, вам встретилась в Интернете заманчивая вакансия. Сколько других людей, таких же, как вы, увидели эту вакансию? Имеют ли эти люди примерно такой же опыт и квалификацию, как и вы? Как вы полагаете, сколько претендентов откликнулись на эту вакансию? Десять, или, быть может, тысяча?

Далее давайте предположим, что отборочная комиссия отберёт только пять сильнейших претендентов и далее будет работать только с ними. Так как же вам не попасть в число несчастливых 995 претендентов, а остаться в рядах 5 сильнейших? Вот почему я говорю, что вам нужно повысить шансы, иначе судьба вашего резюме будет печальна!

Обработка 1 000 резюме (CV)

Я думаю, что такие "резюме" вначале делятся на стопки – по 3 или по 5 резюме в стопке. Резюме распечатывают и раздают другим людям, чтобы те их прочитали. Каждый из таких читателей отдаст обратно одно резюме из стопки. Если раздать резюме 5 читателям, то в итоге получится набор из 200 резюме –  из них предстоит выбрать лучшего одного или двух претендентов. Чтение всех этих резюме занимает много времени, и единственным результатом такого чтения будет лишь ответ на искомый вопрос "да" или "нет". А что если использовать Python, чтобы прочитать все такие резюме за считанные минуты?

В статье Как я использовал NLP (SpaCy) для отфильтровки резюме на получение работы в области интеллектуальной обработки данных, опубликованной здесь, в Medium, говорится, что имена файлов таких 1 000 резюме можно собрать, используя всего две строки кода.

#Function to read resumes from the folder one by one
mypath='D:/NLP_Resume/Candidate Resume' 
onlyfiles = [os.path.join(mypath, f) for f in os.listdir(mypath) 
             if os.path.isfile(os.path.join(mypath, f))]

Переменная onlyfiles представляет собой список Python, содержащий имена файлов всех резюме, которые были получены с использованием библиотеки Python os. Если внимательно прочитать эту статью, можно понять, что резюме можно ранжировать и исключать из рассмотрения, используя техники анализа ключевых слов. Так как мы пытаемся повысить шансы, нам необходимо сосредоточиться на описании должностных обязанностей и на информации, содержащейся в вашем текущем резюме. Совпадают ли они?

Сопоставление резюме и описания должностных обязанностей

Чтобы повысить шансы, необходимо проанализировать описание должностных обязанностей, содержание резюме и оценить степень их совпадения. В идеальном случае мы получим что-то вроде рекомендации, которую вы сможете использовать, чтобы "оставаться в игре".

Чтение документов

Поскольку речь идёт о резюме, то, по всей видимости, оно будет оформлено в виде файла в формате PDF или DOCX. Модули Python существуют для большинства форматов данных. На рисунке 1 показано, как можно считывать документы, сохраняя их содержимое в текстовом файле.

Рис. 1. Чтение текстовых файлов с диска и создание текстового объекта. Скриншот сделан автором из приложения Visual Studio Code – Jupyter Notebook.
Рис. 1. Чтение текстовых файлов с диска и создание текстового объекта. Скриншот сделан автором из приложения Visual Studio Code – Jupyter Notebook.

Первым шагом всегда должны быть открытие файла и считывание строк. На следующем этапе список строк преобразуется в единый текст, при этом выполняются определённые операции очистки. На рисунке 1 показано создание переменных jobContent и cvContent, представляющих собой строковый объект, включающий весь текст. Следующий фрагмент кода демонстрирует механизм непосредственного считывания документа Word.

import docx2txt
resume = docx2txt.process("DAVID MOORE.docx")
text_resume = str(resume)

Переменная text_resume представляет собой строковый объект, в котором, как и раньше, хранится весь текст резюме. Также с этой целью можно использовать библиотеку PyPDF2.

import PyPDF2

Не вдаваясь в подробности, отметим, что существует целый ряд возможностей, позволяющих специалисту-практику считывать документы, преобразовывая их в "чистый" текст. Такие документы могут быть очень пространными, трудно читаемыми и, откровенно говоря, скучными. Начать чтение можно с краткого изложения.

Обработка текста

Мне нравится скрипт Gensum, и я часто им пользуюсь.

from gensim.summarization.summarizer import summarize
from gensim.summarization import keywords

Прочитав файл Word, мы создали переменную resume_text. Теперь давайте составим краткое изложение резюме и объявления о приёме на работу.

print(summarize(text_resume, ratio=0.2))

Краткое изложение резюме создадим с помощью скрипта Gensim.summarization.summarizer.summarize

summarize(jobContent, ratio=0.2)

Теперь вы можете прочитать краткое изложение должностных обязанностей и ваше текущее резюме! Возможно, вы пропустили какую-то часть должностных обязанностей, на которой был сделан акцент в кратком изложении? Успешно подать себя вам помогут мелкие детали. Всем ли понятен ваш документ с кратким изложением, правильно ли в нём указаны ваши основные качества?

Возможно, одного лишь краткого изложения будет недостаточно. Теперь давайте поймём, насколько хорошо ваше резюме соответствует описанию должностных обязанностей. Код представлен на рисунке 2.

Рис. 2. Код для сопоставления двух документов выдаёт степень схожести.
Рис. 2. Код для сопоставления двух документов выдаёт степень схожести.

В общем случае мы составляем список наших текстовых объектов, а затем создаём экземпляр класса sklearn CountVectorizer() Мы также импортируем метрику cosine_similarity с помощью которой измеряется степень сходства двух документов. "Ваше резюме приблизительно на 69,44 % соответствует описанию должностных обязанностей". Звучит заманчиво, но пока не будем поддаваться эмоциям. Теперь можно прочитать краткое изложение документов и получить измеренное значение сходства. Шансы повышаются.

Далее можно проанализировать ключевые слова, встречающиеся в описании должностных обязанностей, и проверить, какие из них также встречаются в резюме. Но, возможно, мы пропустили несколько ключевых слов, которые могли бы довести степень совпадения до 100 %? Теперь переходим к spacy. Между прочим, заметили, какие красивые названия мы используем? Gensim, sklearn, а теперь и spacy! Надеюсь, у вас ещё не закружилась голова?

from spacy.matcher import PhraseMatcher
matcher = PhraseMatcher(Spnlp.vocab)
from collections import Counter
from gensim.summarization import keywords

Для определения степени соответствия важных фраз из описания должностных обязанностей содержанию резюме мы используем интегрированную в Spacy функцию PhraseMatcher В определении такого соответствия нам помогут ключевые слова Gensim. На рисунке 3 показано, как запустить скрипт соответствия.

Рис. 3. Использование ключевых слов и фраз для определения степени соответствия документов.
Рис. 3. Использование ключевых слов и фраз для определения степени соответствия документов.

Используя фрагмент кода, представленного на рисунке 3, можно получить список ключевых слов, для которых обнаружены совпадения. На рисунке 4 показано, как формируется список ключевых слов, для которых обнаружены совпадения. Воспользуемся словарём Counter из модуля Collections

Рис. 4. Использование модуля Collections. Словарь Counter осуществляет подсчет числа совпадений ключевых слов.
Рис. 4. Использование модуля Collections. Словарь Counter осуществляет подсчет числа совпадений ключевых слов.

Термин "составление отчётов" (reporting – в оригинале) содержится в описании должностных обязанностей, а в резюме обнаружены три случая употребления этого термина. Какие фразы или ключевые слова присутствуют в объявлении о приёме на работу, но отсутствуют в резюме? Можем ли мы что-нибудь добавить в резюме? Для ответа на этот вопрос я использовал библиотеку Pandas – результат представлен на рисунке 5.

Рис. 5. Ключевые слова в описании должностных обязанностей, не встречающиеся в резюме.
Рис. 5. Ключевые слова в описании должностных обязанностей, не встречающиеся в резюме.

Если это действительно так, то это тоже странно. Степень совпадений составила 69,44 % на уровне документов, но только посмотрите на этот длинный список ключевых слов, которые не встречаются в резюме. На рисунке 6 показаны встречающиеся в резюме ключевые слова.

Рис. 6. Ключевые слова, выявленные библиотекой Pandas.
Рис. 6. Ключевые слова, выявленные библиотекой Pandas.

В действительности ключевых слов, совпадающих с описанием должностных обязанностей, очень мало, и именно это стало причиной моего скептицизма по отношению к значению косинусного коэффициента 69,44 %. Тем не менее наши шансы увеличиваются, так как в описании должностных обязанностей встречаются ключевые слова, которых нет в резюме. Чем меньше будет совпадений с ключевыми словами, тем вероятнее, что ваше резюме будет отправлено в корзину. Поняв, каких ключевых слов нет в резюме, можно подправить резюме и запустить анализ заново. Однако не стоит действовать "в лоб" и переписывать резюме, просто подставляя в него ключевые слова, тут необходимо быть крайне осторожным. Вполне возможно, что вы сумеете пройти этап первоначального отсева, но возможное отсутствие письменных навыков (умения писать грамотно) на следующих этапах выдаст вас с головой. Поэтому то, что нам нужно сейчас, – это ранжировать фразы и сосредоточиться на основных темах или словах, которые встречаются в описании должностных обязанностей.

Давайте взглянем на ранжированный список фраз. Для этого упражнения я использую собственный класс NLP и некоторые ранее используемые мною методы.

from nlp import nlp as nlp
LangProcessor = nlp()
keywordsJob = LangProcessor.keywords(jobContent)
keywordsCV = LangProcessor.keywords(cvContent)

Используя собственный класс, я восстановил ранжированные фразы из ранее созданных объектов описания должностных обязанностей и резюме. Приведённый ниже фрагмент кода определяет метод. Для извлечения строк ranked_phrases и scores теперь будем использовать модуль rake.

def keywords(self, text):
 keyword = {}
 self.rake.extract_keywords_from_text(text)
 keyword['ranked phrases'] = self.rake.get_ranked_phrases_with_scores()
 return keyword

На рисунке 7 показан результат вызова метода.

Рис. 7 – Ранжированные фразы из объявления о приёме на работу.
Рис. 7 – Ранжированные фразы из объявления о приёме на работу.

Фраза "Методология проектного управления – проектное управление" (в оригинале – project management methodology — project management) соответствует рангу 31.2, поэтому будем считать, что в объявлении о приёме на работу – это самое важное квалификационное требование. Надо учитывать, что важные фразы в резюме также могут представлены с незначительными вариациями.

for item in keywordsCV['ranked phrases'][:10]:
 print (str(round(item[0],2)) + ' - ' + item[1] )

Читая самые часто встречающиеся фразы как в резюме, так и в объявлении о приёме на работу, спросим себя, есть ли в них совпадения или сходство? Естественно! И мы можем выяснить его с помощью кода. Следующий код устанавливает соответствие между ранжированными фразами в объявлении о приёме на работу и в резюме.

sims = []
phrases = []
for key in keywordsJob['ranked phrases']:
 rec={}
 rec['importance'] = key[0]
 texts = key[1]
 sims=[]
 avg_sim=0
 for cvkey in keywordsCV['ranked phrases']:
  cvtext = cvkey[1]
  sims.append(fuzz.ratio(texts, cvtext))
  #sims.append(lev.ratio(texts.lower(),cvtext.lower()))
  #sims.append(jaccard_similarity(texts,cvtext))
 count=0
 for s in sims:
 count=count+s
 avg_sim = count/len(sims)
 rec['similarity'] = avg_sim
 rec['text'] = texts
 phrases.append(rec)

Обратите внимание, что при использовании механизма сопоставления мы использовали опцию поиска по сходству (приближённого поиска). В коде также использованы коэффициент Левенштейна и функция jaccard_similarity (коэффициент Жаккара). На рисунке 8 показано, как выглядит результат.

Рис. 8. Код, устанавливающий соответствие между фразами в описании должностных обязанностей и в резюме.
Рис. 8. Код, устанавливающий соответствие между фразами в описании должностных обязанностей и в резюме.

Переменная importance представляет собой рейтинговую оценку фразы из резюме. Переменная similarity – рейтинговую оценку результатов поиска по сходству. Термину методология проектного управления присвоен ранг 31.2, соответствующие ему ранжированные фразы резюме набрали в среднем 22.5 балла. Несмотря на то что главным квалификационным требованием в объявлении о приёме на работу является "проектное управление", наибольшее количество рейтинговых баллов в резюме получили различные технические аспекты. Из этого примера можно понять, как искусственный интеллект работает против вашего резюме.

На рисунке 9 эта же ситуация представлена с другой точки зрения. Работа с лексемами (словами) показывает важность каждого слова в описании должностных обязанностей по сравнению с количеством совпадений в резюме: чем чаще встречается в документе конкретное слово, тем большую значимость оно имеет. Фраза "финансы" (finance) не имеет большой важности в описании должностных обязанностей, однако имеет большую значимость в резюме. Кто это там ищет работу в сфере IT? Финансист? Хе-хе. Не шутите с искусственным интеллектом, он может буквально интерпретировать ваши слова!

Теперь, я полагаю, картина для вас стала ясна. Использование инструментов и библиотек NLP может помочь по-настоящему понять описание должностных обязанностей и измерить степень относительных совпадений. Эти инструменты, естественно, не вполне надёжны и не являются истиной в последней инстанции, но, тем не менее, их можно использовать, чтобы повысить шансы вашего резюме. То, что сказано вами в резюме, естественно, сыграет свою роль, но вы не должны тупо переносить ключевые слова в резюме. Поступите проще – составьте действительно сильное резюме и отправьте отклик на вакансию, которая вам подходит. Обработка и интеллектуальный анализ текста – это неисчерпаемая тема. Мы только слегка приоткрыли завесу того, что можно сделать с помощью алгоритмов искусственного интеллекта. Лично я считаю алгоритмы интеллектуального анализа текста и модели машинного обучения на базе текста весьма точными инструментами. Давайте напоследок посмотрим на некоторые визуальные инструменты, предлагаемые библиотекой Altair, а затем подведём итог.

Визуальные инструменты Altair

В последнее время я часто пользуюсь библиотекой Altair – гораздо чаще, чем библиотеками Seaborn или Matplotlib. Грамматика в Altair как будто создана для меня. В качестве вспомогательных материалов, которые можно использовать при обсуждении, я создал три визуальных инструмента – на рисунке 10 изображены такие параметры, как важность и значимость ключевых слов в резюме. Применив цветовую шкалу, мы видим, что такое слово, как "внедрение", встречается в резюме дважды, однако оно имеет более низкий приоритет в объявлении о приёме на работу.

Рис. 10. Визуальный инструмент Altair. Слова по важности и значимости в резюме.
Рис. 10. Визуальный инструмент Altair. Слова по важности и значимости в резюме.

На рисунке 11 показаны соответствия ранжированных тем, обнаруженных в объявлениях о приёме на работу, и тем, обнаруженных в резюме. Самая важная фраза в объявлении о приёме на работу – "проектное управление…", однако в рейтинге фраз резюме эта фраза стоит не на первом месте.

Рис. 11. Линейчатая диаграмма, на которой показаны ранжированные фразы и взаимосвязь между резюме и объявлением о приёме на работу.
Рис. 11. Линейчатая диаграмма, на которой показаны ранжированные фразы и взаимосвязь между резюме и объявлением о приёме на работу.

На рисунке 12 показаны сходные слова. Слово "финансы" в резюме встречается 10 раз, однако ни разу не встречается в объявлении о приёме на работу. Слово "проект" встречается и в резюме, и в объявлении о приёме на работу.

Рис. 12. Результат анализа повторяемости ключевых слов в обоих документах.
Рис. 12. Результат анализа повторяемости ключевых слов в обоих документах.

Если посмотреть на эти диаграммы, можно прийти к выводу, что содержания резюме и описания должностных обязанностей сочетаются друг с другом не очень хорошо. Общих для двух документов ключевых слов крайне мало, ранжированные фразы выглядят очень по-разному. И именно это сыграет роковую роль – ваше резюме будет отправлено в корзину!

Заключение

Чтение этой статьи может показаться больше похожим на сценарий высокобюджетного голливудского фильма со спецэффектами "Пристрели их всех". В голливудских блокбастерах, как правило, в главных ролях снимаются известные актёры. Так и здесь – в этой статье главную роль сыграли крупные NLP-библиотеки, а некоторые библиотеки даже выступили в роли камео –  как более старые, более опытные и более зрелые инструменты, например библиотека NLTK. Мы использовали такие библиотеки, как Gensim, Spacy, sklearn, и получили представление о том, как их применять. Используя специально созданный собственный класс, в котором я объединил библиотеки NLTK, rake, textblob и множество других модулей, я получил инструмент, с помощью которого неопределённые догадки можно облечь в форму поддающегося анализу текста и с помощью которого вы получите шанс получить работу своей мечты.

Получение работы мечты требует ясного понимания и неослабного внимания к деталям и крайне аккуратной подготовки отклика на вакансию, резюме и сопроводительного письма. Использование алгоритмов обработки текстов на естественных языках, естественно, не превратит вас в претендента номер один на получение заветного места. Тут всё зависит от вас! Но это может повысить ваши шансы на прохождение хотя бы первого этапа, на котором с помощью систем искусственного интеллекта отсеиваются "непроходные" резюме.

Любой рыбак знает – без жирной наживки никакой рыбы не поймать!

Узнайте подробности, как получить Level Up по навыкам и зарплате или востребованную профессию с нуля, пройдя онлайн-курсы SkillFactory со скидкой 40% и промокодом HABR, который даст еще +10% скидки на обучение.

Другие профессии и курсы