Analyse des postes vacants à l'aide du clustering

Cet article fournit une méthode d'analyse des postes vacants pour la requête de recherche «Python» à l'aide du modèle de clustering Gaussian Mixture Model (GMM). Pour chaque grappe en surbrillance, les compétences et l'échelle salariale les plus demandées seront affichées.



Quel était le but de cette étude? Je voulais savoir:



  • Dans quelles applications Python est-il utilisé
  • Quelles connaissances sont nécessaires: bases de données, bibliothèques, frameworks
  • Combien de spécialistes dans chaque direction sont demandés
  • Quels salaires sont offerts






Chargement des données



Emploi téléchargé à partir du site hh.ru , en utilisant l'API: dev.hh.ru . À la demande de "Python", les postes vacants de 1994 ont été téléchargés (région de Moscou), qui ont été divisés en suites de formation et de test, dans une proportion de 80% et 20% . La taille de l'ensemble d'apprentissage est de 1595 , la taille de l'ensemble de test est de 399 . L'ensemble de test ne sera utilisé que dans les sections Compétences Top / Antitop et Classification des emplois.



Panneaux



Sur la base du texte des offres d'emploi téléchargées, deux groupes de n-grammes de mots les plus courants ont été formés :



  • 2 grammes en cyrillique et en latin
  • 1 grammes en latin


Dans les postes vacants en TI, les compétences et technologies clés sont généralement rédigées en anglais, de sorte que le deuxième groupe comprenait des mots uniquement en latin.



Après la sélection de n-grammes, le premier groupe contenait 81 2 grammes et le second 98 1 grammes:

Non. n n-gramme Poids Postes vacants
1 2 en python huit 258
2 2 ci cd huit 230
3 2 compréhension des principes huit 221
4 2 connaissance de SQL huit 178
cinq 2 développement et neuf 174
... ... ... ... ...
82 1 sql cinq 490
83 1 Linux 6 462
84 1 postgresql cinq 362
85 1 docker sept 358
86 1 Java neuf 297
... ... ... ... ...


Il a été décidé de diviser les postes vacants en groupes selon les critères suivants par ordre de priorité:

Une priorité Critère Poids
1 Domaine (direction appliquée), poste, expérience

n-gram: "apprentissage automatique", "administration linux", "excellente connaissance"
7-9
2 Outils, technologies, logiciels.

n-grammes: "sql", "linux os", "pytest"
4-6
3 Autres compétences

n-gram: "enseignement technique", "anglais", "tâches intéressantes"
1-3


La détermination du groupe de critères auquel appartient le n-gramme et du poids à lui attribuer s'est déroulée de manière intuitive. Voici quelques exemples:

  1. À première vue, "Docker" peut être attribué au deuxième groupe de critères avec un poids de 4 à 6. Mais la mention de "Docker" dans le poste vacant signifie très probablement que le poste vacant concernera le poste "ingénieur DevOps". Par conséquent, "Docker" est tombé dans le premier groupe et a reçu un poids de 7.

  2. «Java» , .. «Java» Java- « Python». «-». , , , «Java» 9.



n- — .





Pour les calculs, chaque vacance a été transformée en un vecteur avec une dimension de 179 (le nombre de caractéristiques sélectionnées) d'entiers de 0 à 9, où 0 signifie que le i-ème n-gramme est absent de la vacance, et les nombres de 1 à 9 signifient la présence du i-ème n - grammes et son poids. Plus loin dans le texte, un point signifie une vacance représentée par un tel vecteur.

Exemple:

disons qu'une liste de n-grammes ne contient que trois valeurs:

Non. n n-gramme Poids Postes vacants
1 2 en python huit 258
2 2 compréhension des principes huit 221
3 1 sql cinq 490


Puis pour un poste vacant avec texte.



Exigences:



  • 3+ années d' expérience dans le développement de python .
  • Bonne connaissance de SQL


le vecteur est égal à [8, 0, 5].



Métrique



Pour travailler avec des données, vous devez les comprendre. Dans notre cas, je voudrais voir s'il existe des groupes de points, que nous considérerons comme des groupes. Pour ce faire, j'ai utilisé l'algorithme t-SNE pour traduire tous les vecteurs dans l'espace 2D. 



L'essence de la méthode est de réduire la dimension des données, tout en préservant au maximum les proportions des distances entre les points de l'ensemble. Il est assez difficile de comprendre comment fonctionne t-SNE à partir des formules. Mais j'ai aimé un exemple trouvé quelque part sur Internet: disons que nous avons des balles dans un espace tridimensionnel. Nous connectons chaque balle avec toutes les autres balles par des ressorts invisibles, qui ne se croisent en aucune façon et n'interfèrent pas entre eux lors du croisement. Les ressorts agissent dans deux directions, c'est-à-dire ils résistent à la fois à la distance et à l'approche des balles les unes par rapport aux autres. Le système est dans un état stable, les balles sont stationnaires. Si nous prenons l'une des billes et la retirons, puis la relâchons, elle reviendra à son état d'origine en raison de la force des ressorts. Ensuite, nous prenons deux grandes assiettes et pressons les boules en une fine couche,tout en n'interférant pas avec les billes pour se déplacer dans le plan entre les deux plaques. Les forces des ressorts commencent à agir, les billes bougent et finissent par s'arrêter lorsque les forces de tous les ressorts s'équilibrent. Les ressorts agiront de sorte que les billes qui étaient proches les unes des autres restent relativement proches et plates. Aussi avec les balles retirées - elles seront retirées les unes des autres. À l'aide de ressorts et de plaques, nous avons converti l'espace tridimensionnel en deux dimensions, en préservant la distance entre les points sous une forme ou une autre!Aussi avec les balles retirées - elles seront retirées les unes des autres. À l'aide de ressorts et de plaques, nous avons converti l'espace tridimensionnel en deux dimensions, en préservant la distance entre les points sous une forme ou une autre!Aussi avec les balles retirées - elles seront retirées les unes des autres. À l'aide de ressorts et de plaques, nous avons converti l'espace tridimensionnel en deux dimensions, en préservant la distance entre les points sous une forme ou une autre!



L'algorithme t-SNE a été utilisé par moi uniquement pour visualiser un ensemble de points. Il a aidé à choisir une métrique et à sélectionner les pondérations des entités.



Si nous utilisons la métrique euclidienne que nous utilisons dans notre vie quotidienne, l'emplacement des postes vacants ressemblera à ceci:





La figure montre que la plupart des points sont concentrés au centre et qu'il y a de petites branches sur les côtés. Avec cette approche, les algorithmes de clustering qui utilisent la distance entre les points ne produiront rien de bon.



Il existe de nombreuses mesures (façons de déterminer la distance entre deux points) qui fonctionneront bien sur les données que vous explorez. J'ai choisi la distance de Jaccard comme mesure , en tenant compte des poids de n-grammes. La mesure de Jaccard est facile à comprendre, mais elle fonctionne bien pour résoudre le problème considéré.

:

1 n-: « python», «sql», «docker»

2 n-: « python», «sql», «php»

:

« python» — 8

«sql» — 5

«docker» — 7

«php» — 9

(n- 1- 2- ):  « python», «sql» = 8 + 5 = 13

( n- 1- 2- ):  « python», «sql», «docker», «php» = 8 + 5 + 7 + 9 = 29

=1 — ( / ) = 1 — (13 / 29) = 0.55


La matrice des distances entre toutes les paires de points a été calculée, la taille de la matrice est de 1595 x 1595. Au total, 1 271 215 distances entre des paires uniques. La distance moyenne s'est avérée être de 0,96, entre 619 659 la distance est de 1 (c'est-à-dire qu'il n'y a aucune similitude). Le graphique suivant montre que dans l'ensemble, il y a peu de similitude entre les emplois:





En utilisant la métrique Jaccard, notre espace ressemble maintenant à ceci:





Quatre zones de densité distinctes sont apparues et deux petits groupes de faible densité. Du moins, c'est ainsi que mes yeux voient!



Clustering



Le modèle de mélange gaussien (GMM) a été choisi comme algorithme de clustering . L'algorithme reçoit des données sous forme de vecteurs en entrée, et le paramètre n_components est le nombre de clusters dans lesquels l'ensemble doit être divisé. Vous pouvez voir comment fonctionne l'algorithme ici (en anglais). J'ai utilisé une implémentation GMM prête à l'emploi de la bibliothèque scikit-learn: sklearn.mixture.GaussianMixture .



Notez que GMM n'utilise pas de métrique, mais sépare les données uniquement par un ensemble d'entités et leurs pondérations. Dans l'article, la distance Jaccard est utilisée pour visualiser les données, calculer la compacité des clusters (j'ai pris la distance moyenne entre les points des clusters pour la compacité) et déterminerle point central du cluster (vacance typique) - le point avec la plus petite distance moyenne par rapport aux autres points du cluster. De nombreux algorithmes de clustering utilisent exactement la distance entre les points. La section Autres méthodes abordera d'autres types de clustering qui sont basés sur des métriques et donnent également de bons résultats.



Dans la section précédente, il a été déterminé à l'œil nu qu'il y aura probablement six grappes. Voici à quoi ressemblent les résultats du clustering avec n_components = 6:







Dans la figure avec la sortie des clusters séparément, les clusters sont classés par ordre décroissant du nombre de points de gauche à droite, de haut en bas: le cluster 4 est le plus grand, le cluster 5 est le plus petit. La compacité de chaque cluster est indiquée entre parenthèses.



Le clustering ne semble pas très bon, même si vous considérez que l'algorithme t-SNE n'est pas parfait. Lors de l'analyse des clusters, le résultat n'était pas non plus encourageant.



Pour trouver le nombre optimal de clusters n_components, nous utiliserons les critères AIC et BIC, que vous pouvez lire ici . Le calcul de ces critères est intégré à la méthode sklearn.mixture.GaussianMixture . Voici à quoi ressemble le graphique des critères:





Lorsque n_composants = 12, le critère BIC a la valeur la plus basse (meilleure), le critère AIC a également une valeur proche du minimum (minimum lorsque n_composants = 23). Divisons les postes vacants en 12 groupes:







Les clusters sont désormais plus compacts, tant en apparence qu'en termes numériques. Au cours de l'analyse manuelle, les postes vacants ont été divisés en groupes caractéristiques pour comprendre une personne. La figure montre les noms des clusters. Les clusters numérotés 11 et 4 sont marqués comme <Corbeille 2>:



  1. Dans le cluster 11, toutes les entités ont approximativement les mêmes poids totaux.
  2. Le cluster 4 est dédié à Java. Néanmoins, il y a peu de postes vacants pour le poste de Développeur Java dans le cluster, la connaissance de Java est souvent requise car «sera un plus».


Clusters



Après avoir supprimé deux clusters non informatifs numérotés 11 et 4, le résultat est 10 clusters:





Pour chaque cluster, il existe un tableau des caractéristiques et 2 grammes que l'on retrouve le plus souvent dans les postes vacants du cluster.



Légende:



S - la proportion de postes vacants dans laquelle le trait est trouvé, multipliée par le poids du trait

% - le pourcentage de postes vacants dans lesquels le trait / 2 grammes se trouve

Poste vacant typique de la grappe - vacance, avec la plus petite distance moyenne par rapport aux autres points de la grappe



Analyste de données



Nombre d'emplois: 299 Emploi



typique: 35805914

Non. Signer avec poids S Signe % 2 grammes %
1 exceller 3.13 sql 64,55 connaissance de SQL 18,39
2 r 2,59 exceller 34,78 en développement 14.05
3 sql 2,44 r 28,76 python r 14.05
4 connaissance de SQL 1,47 bi 19,40 avec grand 13,38
cinq l'analyse des données 1,17 tableau 15,38 développement et 13,38
6 tableau 1,08 Google 14,38 l'analyse des données 13.04
sept avec grand 1,07 vba 13.04 connaissance de python 12,71
huit développement et 1,07 science 9,70 entrepôt analytique 11,71
neuf vba 1,04 dwh 6,35 expérience de développement 11,71
Dix connaissance de python 1,02 oracle 6,35 bases de données 11,37


Développeur C ++



Nombre d'emplois: 139 Emploi

typique: 39955360

Non. Signer avec poids S Signe % 2 grammes %
1 c ++ 9h00 c ++ 100,00 expérience de développement 44,60
2 Java 3.30 Linux 44,60 c c ++ 27,34
3 Linux 2,55 Java 36,69 c ++ python 17,99
4 c # 1,88 sql 23.02 en c ++ 16,55
cinq aller 1,75 c # 20,86 développement sur 15,83
6 développement sur 1,27 aller 19,42 structures de données 15.11
sept bonne connaissance 1,15 unix 12,23 expérience d'écriture 14,39
huit structures de données 1,06 tensorflow 11,51 programmation sur 13,67
neuf tensorflow 1,04 frapper 10.07 en développement 13,67
Dix expérience de programmation 0,98 postgresql 9,35 langages de programmation 12,95


Ingénieur Linux / DevOps



Nombre d'emplois: 126 Emploi type

: 39533926

Non. Signer avec poids S Signe % 2 grammes %
1 ansible 5,33 Linux 84,92 ci cd 58,73
2 docker 4,78 ansible 76,19 expérience en administration 42,06
3 frapper 4,78 docker 74,60 bash python 33,33
4 ci cd 4.70 frapper 68,25 ip tcp 39,37
cinq Linux 4,43 Prométhée 58,73 expérience de personnalisation 28,57
6 Prométhée 4.11 zabbix 54,76 surveillance et 26,98
sept nginx 3,67 nginx 52,38 prométhée grafana 23,81
huit expérience en administration 3,37 Grafana 52,38 systèmes de surveillance 22,22
neuf zabbix 3,29 postgresql 51,59 avec docker 16,67
Dix wapiti 3,22 kubernetes 51,59 gestion de la configuration 16,67


Développeur Python



Nombre d'offres d'emploi: 104 Emploi type

: 39705484

Non. Signer avec poids S Signe % 2 grammes %
1 en python 6,00 docker 65,38 en python 75,00
2 Django 5,62 Django 62,50 développement sur 51,92
3 ballon 4,59 postgresql 58,65 expérience de développement 43,27
4 docker 4,24 ballon 50,96 flacon de Django 04.24
cinq développement sur 4.15 redis 38,46 reste api 23.08
6 postgresql 2,93 Linux 35,58 python de 21,15
sept aiohttp 1,99 lapinmq 33,65 bases de données 18,27
huit redis 1,92 sql 30,77 expérience d'écriture 18,27
neuf Linux 1,73 mongodb 25,00 avec docker 17,31
Dix lapinmq 1,68 aiohttp 22.12 avec postgresql 16,35


Data scientist



Nombre de postes vacants: 98 Poste

vacant type: 38071218

Non. Signer avec poids S Signe % 2 grammes %
1 pandas 7,35 pandas 81,63 apprentissage automatique 63,27
2 engourdi 6,04 engourdi 75,51 pandas numpy 43,88
3 apprentissage automatique 5,69 sql 62,24 l'analyse des données 29,59
4 pytorche 3,77 pytorche 41,84 science des données 26,53
cinq ml 3,49 ml 38,78 connaissance de python 25,51
6 tensorflow 3,31 tensorflow 36,73 scipy engourdi 24,49
sept l'analyse des données 2,66 étincelle 32,65 pandas python 23,47
huit scikitlearn 2,57 scikitlearn 28,57 en python 21,43
neuf science des données 2,39 docker 27,55 statistiques mathématiques 20,41
Dix étincelle 2,29 hadoop 27,55 algorithmes de machine 20,41


Développeur frontal



Nombre d'emplois: 97 Emploi

typique: 39681044

Non. Signer avec poids S Signe % 2 grammes %
1 javascript 9h00 javascript 100 html css 27,84
2 Django 2,60 html 42,27 expérience de développement 25,77
3 réagir 2,32 postgresql 38,14 en développement 17,53
4 nodejs 2.13 docker 37,11 connaissance de javascript 15,46
cinq l'extrémité avant 2.13 css 37,11 et support 15,46
6 docker 2,09 Linux 32,99 python et 14,43
sept postgresql 1,91 sql 31,96 css javascript 13,40
huit Linux 1,79 Django 28,87 bases de données 12,37
neuf html css 1,67 réagir 25,77 en python 12,37
Dix php 1,58 nodejs 23,71 conception et 11,34


Développeur backend



Nombre d'emplois: 93 Emploi type

: 40226808

Non. Signer avec poids S Signe % 2 grammes %
1 Django 5,90 Django 65,59 python django 26,88
2 js 4,74 js 52,69 expérience de développement 25,81
3 réagir 2,52 postgresql 40,86 connaissance de python 20,43
4 docker 2,26 docker 35,48 en développement 18,28
cinq postgresql 2,04 réagir 27,96 ci cd 17,20
6 compréhension des principes 1,89 Linux 27,96 connaissance confiante 16,13
sept connaissance de python 1,63 backend 22,58 reste api 15.05
huit backend 1,58 redis 22,58 html css 13,98
neuf ci cd 1,38 sql 20,43 capacité à comprendre 10,75
Dix l'extrémité avant 1,35 mysql 19,35 chez un inconnu 10,75


Ingénieur DevOps



Nombre d'emplois: 78 Emploi type

: 39634258

Non. Signer avec poids S Signe % 2 grammes %
1 devops 8,54 devops 94,87 ci cd 51,28
2 ansible 5,38 ansible 76,92 bash python 30,77
3 frapper 4,76 Linux 74,36 expérience en administration 24,36
4 Jenkins 4,49 frapper 67,95 et support 23.08
cinq ci cd 4.10 Jenkins 64,10 docker kubernetes 20,51
6 Linux 3,54 docker 50,00 développement et 17,95
sept docker 2,60 kubernetes 41.03 expérience d'écriture 17,95
huit Java 2,08 sql 29,49 et personnalisation 17,95
neuf expérience en administration 1,95 oracle 25,64 développement et 16,67
Dix et support 1,85 OpenShift 24,36 script 14.10


Ingénieur de données



Nombre d'emplois: 77 Emploi

typique: 40 008 757

Non. Signer avec poids S Signe % 2 grammes %
1 étincelle 6,00 hadoop 89,61 traitement de l'information 38,96
2 hadoop 5,38 étincelle 85,71 Big Data 37,66
3 Java 4,68 sql 68,83 expérience de développement 23,38
4 ruche 4,27 ruche 61,04 connaissance de SQL 22.08
cinq scala 3,64 Java 51,95 développement et 19,48
6 Big Data 3,39 scala 51,95 étincelle hadoop 19,48
sept etl 3,36 etl 48,05 java scala 19,48
huit sql 2,79 flux d'air 44,16 qualité des données 18,18
neuf traitement de l'information 2,73 kafka 42,86 et traitement 18,18
Dix kafka 2,57 oracle 35,06 ruche hadoop 18,18


Ingénieur QA



Nombre d'emplois: 56 Emploi

typique: 39630489

Non. Signer avec poids S Signe % 2 grammes %
1 automatisation des tests 5,46 sql 46,43 automatisation des tests 60,71
2 expérience de test 4,29 qa 42,86 expérience de test 53,57
3 qa 3,86 Linux 35,71 en python 41,07
4 en python 3,29 sélénium 32,14 expérience d'automatisation 35,71
cinq développement et 2,57 la toile 32,14 développement et 32,14
6 sql 2,05 docker 30,36 expérience de test 30,36
sept Linux 2,04 Jenkins 26,79 expérience d'écriture 28,57
huit sélénium 1,93 backend 26,79 test sur 23,21
neuf la toile 1,93 frapper 21,43 tests automatisés 21,43
Dix backend 1,88 ui 19,64 ci cd 21,43




Les salaires



Les salaires ne sont indiqués que dans 261 (22%) postes vacants sur 1 167 dans les grappes.



Lors du calcul des salaires:



  1. Si la plage "de ... à ..." a été spécifiée, la valeur moyenne a été utilisée
  2. Si seulement "de ..." ou seulement "à ..." était indiqué, alors cette valeur était prise
  3. Les calculs ont utilisé (ou ont été donnés) le salaire après impôts (NET)


Sur le graphique:



  1. Les grappes sont classées par ordre décroissant du salaire médian
  2. Barre verticale dans la boîte - médiane
  3. Boîte - plage [Q1, Q3], où Q1 (25%) et Q3 (75%) sont des centiles. Ceux. 50% des salaires tombent dans la boîte
  4. La «moustache» comprend les salaires de la fourchette [Q1 - 1,5 * IQR, Q3 + 1,5 * IQR], où IQR = Q3 - Q1 - intervalle interquartile
  5. Les points individuels sont des anomalies qui ne sont pas tombées dans la moustache. (Il y a des anomalies non incluses dans le diagramme)




Compétences Top / Antitop



Les graphiques ont été créés pour tous les postes vacants téléchargés en 1994. Les salaires sont indiqués dans 443 (22%) postes vacants. Pour le calcul de chaque fonctionnalité, les postes vacants ont été sélectionnés lorsque cette fonctionnalité est présente, et sur leur base, le salaire médian a été calculé.







Classification des emplois



Le regroupement pourrait être beaucoup plus facile sans recourir à des modèles mathématiques complexes: pour compiler les principaux noms des postes vacants et les diviser en groupes. Ensuite, analysez chaque groupe pour les n-grammes les plus élevés et les salaires moyens. Il n'est pas nécessaire de mettre en évidence les caractéristiques et de leur attribuer des pondérations.



Cette approche fonctionnerait bien (dans une certaine mesure) pour une requête "Python". Mais pour la demande "1C Programmer" cette approche ne fonctionnera pas, car pour les programmeurs 1C dans les noms des postes vacants, les configurations 1C ou les domaines d'application sont rarement indiqués. Et il existe de nombreux domaines où 1C est utilisé: comptabilité, calcul des salaires, calcul des taxes, calcul des coûts dans les entreprises industrielles, comptabilité d'entrepôt, budgétisation, systèmes ERP, commerce de détail, comptabilité de gestion, etc.



Pour moi, je vois deux tâches pour analyser les postes vacants:



  1. Comprenez où un langage de programmation que je connais peu est utilisé (comme dans cet article).
  2. Filtrer les nouvelles offres d'emploi publiées.


Le clustering convient pour résoudre le premier problème, pour résoudre le second - divers classificateurs, forêts aléatoires, arbres de décision, réseaux de neurones. Néanmoins, je voulais évaluer la pertinence du modèle choisi pour le problème de classification des emplois.



Si vous utilisez la méthode prédire () intégrée à sklearn.mixture.GaussianMixture , rien de bon ne se passe. Il attribue la plupart des postes vacants à de grandes grappes, et deux des trois premières grappes ne sont pas informatives. J'ai utilisé une approche différente: 



  1. Nous prenons le poste vacant que nous voulons classer. Nous le vectorisons et obtenons un point dans notre espace.
  2. Nous calculons la distance entre ce point et tous les clusters. Sous la distance entre un point et un cluster, j'ai pris la distance moyenne entre ce point et tous les points du cluster.
  3. La grappe avec la plus petite distance est la classe prévue pour le poste vacant sélectionné. La distance au cluster indique la fiabilité d'une telle prédiction.
  4. Pour augmenter la précision du modèle, j'ai choisi 0,87 comme distance seuil, c'est-à-dire si la distance à la grappe la plus proche est supérieure à 0,87, le modèle ne classe pas le poste vacant.


Pour évaluer le modèle, 30 postes vacants ont été sélectionnés au hasard dans l'ensemble de test. Dans la colonne verdict:



N / a: le modèle n'a pas classé le poste (distance> 0,87)

+: classification correcte

-: classification incorrecte  

Poste vacant Cluster le plus proche Distance Verdict
37637989 Ingénieur Linux / DevOps 0,9464 N / a
37833719 Développeur C ++ 0,8772 N / a
38324558 Ingénieur de données 0.8056 +
38517047 Développeur C ++ 0,8652 +
39053305 Poubelle 0,9914 N / a
39210270 Ingénieur de données 0,8530 +
39349530 Développeur frontal 0,8593 +
39402677 Ingénieur de données 0,8396 +
39415267 Développeur C ++ 0,8701 N / a
39734664 Ingénieur de données 0,8492 +
39770444 Développeur backend 0,8960 N / a
39770752 Data scientist 0,7826 +
39795880 Analyste de données 0,9202 N / a
39947735 Développeur Python 0,8657 +
39954279 Ingénieur Linux / DevOps 0,8398 -
40008770 Ingénieur DevOps 0,8634 -
40015219 Développeur C ++ 0,8405 +
40031023 Développeur Python 0,7794 +
40072052 Analyste de données 0,9302 N / a
40112637 Ingénieur Linux / DevOps 0,8285 +
40164815 Ingénieur de données 0.8019 +
40186145 Développeur Python 0,7865 +
40201231 Data scientist 0,7589 +
40211477 Ingénieur DevOps 0,8680 +
40224552 Data scientist 0,9473 N / a
40230011 Ingénieur Linux / DevOps 0,9298 N / a
40241704 Corbeille 2 0,9093 N / a
40245997 Analyste de données 0,9800 N / a
40246898 Data scientist 0,9584 N / a
40267920 Développeur frontal 0,8664 +


Total: 12 postes vacants sont sans résultat, 2 postes vacants - classement erroné, 16 postes vacants - classement correct. Exhaustivité du modèle - 60%, précision du modèle - 89%.



Côtés faibles



Le premier problème - prenons deux postes vacants:

Poste vacant 1 - "Lead C ++ Programmer"

"Conditions requises:



  • Plus de 5 ans d'expérience en développement C ++.
  • La connaissance de Python sera un atout supplémentaire. "


Poste vacant 2 - "Lead Python Programmer"

"Conditions requises:

  • Plus de 5 ans d'expérience en développement Python.
  • La connaissance de C ++ sera un atout supplémentaire "
Du point de vue du modèle, ces vacances sont identiques. J'ai essayé d'ajuster les poids des entités selon leur ordre d'apparition dans le texte. Cela n'a abouti à rien de bon.



Le deuxième problème est que GMM regroupe tous les points dans un ensemble, comme de nombreux algorithmes de clustering. Les clusters non informatifs ne sont pas un problème en eux-mêmes. Mais les clusters informatifs contiennent également des valeurs aberrantes. Cependant, cela peut être facilement résolu en effaçant les clusters, par exemple en supprimant les points les plus atypiques qui ont la plus grande distance moyenne au reste des points de cluster.



Autres méthodes



La page de comparaison de cluster illustre bien les divers algorithmes de clustering. GMM est le seul à avoir donné de bons résultats.

Le reste des algorithmes n'a pas fonctionné ou a donné des résultats très modestes.



Parmi ceux que j'ai mis en œuvre, de bons résultats étaient dans deux cas:



  1. Des points à forte densité ont été sélectionnés dans un certain voisinage, situés à une distance éloignée les uns des autres. Les points sont devenus les centres des grappes. Puis, sur la base des centres, le processus de formation de grappes a commencé - la jonction des points voisins.
  2. Le clustering agglomératif est une fusion itérative de points et de clusters. La bibliothèque scikit-learn présente ce type de clustering, mais cela ne fonctionne pas bien. Dans mon implémentation, j'ai changé la matrice de jointure après chaque itération de la fusion. Le processus s'est arrêté lorsque certains paramètres limites ont été atteints - en fait, les dendrogrammes n'aident pas à comprendre le processus de fusion si 1500 éléments sont regroupés.


Conclusion



La recherche que j'ai faite m'a donné les réponses à toutes les questions au début de l'article. J'ai acquis une expérience pratique du clustering tout en implémentant des variantes d'algorithmes connus. J'espère vraiment que l'article motivera le lecteur à mener ses recherches analytiques et aidera d'une certaine manière dans cette leçon passionnante.



All Articles