Этот блог пост посвящен выступлению нашей команды 42 на хакатоне Moscow City Hack, который прошел с 11 по 14 Июня в режиме онлайн. В нашей команде было несколько новичков повыcтуплениям на хакатонах. Однако, команда выступила достойно, пройдя в финал, где заняла 10 место.
Задача трека
Наш трек включал задачу: развитие прототипа для образовательной платформы Нетология. Само задание подразумевало создание системы по оценке навыков пользователей и помощь в их дальнейшем развитие.
Ключевая идея проекта
Наш продакт-менеджер, Алексей Волков, предложил ключевую идею проекта. Он разделил задачу оценки навыков на три столпа: обучение, понимание и практика. В такой системе цель каждого пользователя состоит в том, чтобы балансировать на трех столпах.
Рекомендательная система
Для оценки каждого столпа мы решили использовать систему скоринга, которые популярны не только среди HR специалистов, но и в банковском секторе.
Cначала мы нарисовали окно с реультатом и рекомендациями для пользователя:
Парсер
Для того, чтобы понять какие данные мы можем использовать для настройки нашего приложения, в том числе и ML модели, мы прикрутии парсер HH. Входные параметры для него включают в себя текстовый запрос и более гранулярные параметры.
Библиотеки для парсера:
import requests
import json
import time
import pandas as pd
import numpy as np
from tqdm import tqdm
Следующая функция обращается к API hh и передает выбранные параметры: текст поиска и индекс страницы, с которой мы начинаем поиск в API:
def getPage(self, text, page = 0):
params = {
'text': f'NAME:{text}',
'area': 113,
'page': page,
'per_page': 100
}
req = requests.get('https://api.hh.ru/vacancies', params)
self.data = req.content.decode()
req.close()
Функция, сохраняющая данные из функции getPage в json:
def generate_pages(self, number=1):
for page in tqdm(range(0, number)):
js = json.loads(self.data)
self.jsObj.append(js)
if (js['pages'] - page) <= 1:
break
После того, как мы получили json, мы обрабатываем данные из него и вызоваем более детализированных данные через HeadHunter API. Кроме того, мы создаем DataFrame в pandas, в котором сохраняем наши данные:
def generate_vacancies(self, name ):
IDs = []
names = []
snippet = []
salary = []
skills_name=[]
for i in range(len(self.jsObj)):
for j in tqdm(range(len(self.jsObj[i]['items']))):
IDs.append(self.jsObj[i]['items'][j]['id'])
names.append(self.jsObj[i]['items'][j]['name'])
snippet.append(self.jsObj[i]['items'][j]['snippet']['requirement'])
skills=str()
req=requests.get(self.jsObj[i]['items'][j]['url'])
data = req.content.decode()
req.close()
jsVac = json.loads(data)
for skl in jsVac['key_skills']:
skills = skills + skl['name']+','
skills_name.append(skills[:-1])
try:
salary.append(self.jsObj[i]['items'][j]['salary']['from'])
except:
salary.append(np.nan)
time.sleep(0.25)
pd.DataFrame({'ids':IDs,'names':names,'skills':skills_name,'salary':salary},index=IDs).to_csv(f'{name}.csv', index=False)
Анализ полученных данных
Поскольку у нас было ограниченное время, мы решили сосредоточиться на трех языках программирования для нашего проекта: C ++, PHP и Python. Средняя и медианная заработная плата в российских рублях в месяц составила:
20 основных навыков, которые работодатели требуют от Python разработчиков в описании вакансий:

Механика наипростейшей ML рекомендательной системы
Мы решили попросить пользователей оценить свои способности от 1 до 5 среди самых популярных навыков по версии рекрутеров для каждого языка. В свою очередь, мы использовали оценку 1-3 как признак того, что пользователю не обладает навыком, а 4-5, — что он или она владеет данным навыком.
Мы обучили модель случайного леса на 600 вакансиях, оставив навыки в качестве фич и язык программирования в качестве целевой переменной. Оценка точности для нашего тестового сплита была невероятно высокой — 0,98.
После того, как пользователь проходит опрос, система возвращает учебный курс для языка программирования, который модель машинного обучения считает самым слабым.
Развертывание решения
Повозившись с файловой структурой и дополнительными файлами, необходимыми для Heroku, мы развернули наш проект на платформе во Flask.
Наш репозиторий на Github: https://github.com/Pfed-prog/Netology_Final/