L'été se terminait, août était particulièrement froid. Ma 11e année a commencé et j'ai réalisé que c'était la dernière chance (spoiler: non) d'améliorer d'une manière ou d'une autre mes compétences professionnelles. Depuis plusieurs années, je fais avec diligence divers projets informatiques, certains seuls, d'autres dans l'équipe. Mais maintenant, tous les
fils de la petite amie de ma mère font déjà quelque chose de beau. Peut-être inutile, mais belle en apparence. Quelqu'un fait une simulation collante de particules sous forme de gifs, quelqu'un plonge dans l'apprentissage automatique et fait toutes sortes de transferts de style. Et qu'est-ce que je suis pire? Je veux aussi!
Un exemple de simulation est également sous cat.Exemple de simulation de particules d'un de mes amisC'est avec cette pensée que mon étude du sujet de l'apprentissage automatique a commencé. Et en termes de formation pour moi, il n'y avait rien de nouveau, comme dans tout autre domaine de l'informatique, la pratique est nécessaire ici. Mais que se passe-t-il si je ne suis pas intéressé par des analyseurs de tonalité? Nous devons inventer quelque chose qui nous est propre.
En parcourant à nouveau le fil d'actualité de VKontakte, j'ai réalisé que les communautés de ce réseau social sont un véritable trésor pour la science des données. Si vous traitez du texte, des mèmes sous forme d'images ou de musique à partir de collections, vous pouvez obtenir une énorme quantité d'informations pertinentes sur les gens modernes: les genres musicaux populaires, le vocabulaire ou l'heure de la journée de la plupart des gens. C'est un domaine pour de nombreuses découvertes.
Mais combien ces statistiques seront-elles nécessaires pour les gens ordinaires? Comme si ma musique me manquait ou que je ne pouvais pas accéder à la section "Populaire"? Donc, vous devez penser à quelque chose de pratique, quelque chose qui peut plaire à au moins un pourcentage significatif d'utilisateurs.
Il convient de noter que quelques mois auparavant, j'ai lu un article sympa sur la
création de mon moteur de recherche , qui m'a vraiment frappé. Comme l'auteur, j'ai ressenti une grande envie d'énormes projets qui traitent jour et nuit un grand nombre de milliers de gigaoctets d'informations.

Et maintenant, nous revenons à août, qui est devenu un peu plus chaud qu'au début de l'article. Quand j'ai réalisé que j'avais maintenant une énorme source d'informations, j'ai réalisé qu'il était temps. Le temps est venu pour notre propre système monstrueux. Mais la question principale est restée quelques jours plus tard - que dois-je faire avec tout cela? Que proposer à l'utilisateur? Je ne tourmenterai pas le lecteur, je vous dirai seulement qu'il est très difficile pour moi, comme certains de mes amis, de rechercher de nouveaux groupes VKontakte qui pourraient me plaire. Désormais, chaque premier public a un nom - un ensemble aléatoire de mots. Les administrateurs essaient d'en faire le plus absurde, probablement c'est une sorte de race, compréhensible seulement pour eux.
Et puis j'ai décidé d'écrire un service qui aidera l'utilisateur avec le choix des communautés, recommander ce à quoi vous pouvez vous abonner. Donc, mon idée est venue.
L'introduction n'a pas été longue par hasard, elle était censée transmettre mes émotions et montrer que l'idée n'est pas apparue à l'improviste. En fait, comme toutes les autres idées sur Habré.
Mon service est toujours opérationnel, il dure depuis plus de quatre mois (si vous comptez dès le premier essai réussi). Mais j'ai déjà une expérience que je veux partager avec vous. Maintenant, il y aura une description courte et très concise du projet. Ensuite, je vais souligner quelques points clés. Et si l'article plaira particulièrement aux habrayuzers, alors sa suite sortira, dans laquelle il y aura plus d'informations purement techniques et de code.
Tout se compose de trois parties:
- bot de recherche (si vous pouvez l'appeler ainsi)
- moteur de traitement des données
- site pour les utilisateurs (avec un panneau de contrôle et de surveillance pour les administrateurs)
La fonctionnalité du bot comprend la recherche de nouveaux groupes et le «retrait» du texte et d'autres informations dans la base de données. Le moteur est engagé dans un traitement ultérieur de ces données, dont je parlerai ci-dessous. Et le site permet simplement aux utilisateurs d'utiliser tout cela.
Recherche bot
Rien de nouveau ici. Je prends simplement le profil d'une personne sur VK et j'obtiens une liste de groupes et de ses amis. Tout cela se produit avec l'API VK. Et si cet IPA parvient à obtenir une liste des groupes de l'utilisateur et de ses amis, alors il ne parvient pas à obtenir le contenu des groupes ... Je rencontre juste une restriction et c'est tout. Puis je me suis souvenu qu'il y a quelque temps, VKontakte faisait la promotion de son système cool juste pour de telles choses. Et le nom de ce système est Streaming API.
Streaming API - un outil pour obtenir une sélection aléatoire d'enregistrements de VK. Il est écrit sur la page de description que c'est juste que vous pouvez obtenir jusqu'à 1% de toutes les informations, pour obtenir jusqu'à une centaine, vous devez écrire au support et leur expliquer vos intentions.
Il semblerait que tout soit merveilleux. Mais non. Comme probablement beaucoup, j'ai raté le mot le plus important dans la description ci-dessus. Et c'est la préposition «avant». Personne ne vous donnera 100% des données. C'est juste une belle barre supérieure et c'est tout. En fait, nous obtenons comme ceci:
J'espère que l'agent # 365 ne me détestera pas 365 jours par an pour cette capture d'écranAutrement dit, je ne peux obtenir que 30 000 événements par jour. Et ce nombre comprend des commentaires et des reposts seulement. Il est également nécessaire d'indiquer certains mots-clés, seuls les messages avec eux viendront. Certains des messages restants ne m'intéressent tout simplement pas, car ils sont sur le mur des utilisateurs. Reste un peu. Pour référence, dans mon implémentation actuelle, je peux recevoir jusqu'à 8,5 millions d'enregistrements en quelques jours de temps de disponibilité incomplet (au total - environ 10 heures, mais il n'y avait pas de mesures précises).
Ici, je dois dire à propos d'une règle que j'ai identifiée à partir de toute cette expérience. Ne jugez jamais un groupe sur un seul post. Surtout si vous êtes une intelligence artificielle sensible à un tel bruit. Donc, vous avez besoin d'au moins quelques articles pour créer une description objective du public. Estimons maintenant que certains groupes avec un contenu de très haute qualité le publient toutes les quelques semaines. Et même alors, je peux l'ignorer en raison de l'API de streaming imparfaite. Et si je l'obtiens, combien de temps dois-je collecter le contenu petit à petit?
J'ai décidé cela trop longtemps et je suis allé dans l'autre sens. Étant donné que je ne peux pas obtenir une réponse claire de VKontakte au format JSON, je vais analyser les murs des communautés. Oui, la tâche est un peu compliquée, et sa solution ralentit, mais je n'ai pas d'alternative. C'est ainsi que j'ai commencé à écrire le premier bloc de mon système. Je l'ai d'ailleurs écrit en Java en utilisant Jsoup, une bibliothèque qui rend très pratique l'extraction de contenu à partir de texte HTML. Je n'ai pas oublié de traiter la date de publication du dernier message, je n'ai pas besoin de communautés mortes, je ne les indexe tout simplement pas. Les messages marqués de publicités sont également supprimés. Tous les administrateurs ne prennent pas de telles notes, mais ce problème n'est pas si simple à résoudre, je n'ai pas pu créer un filtre adéquat pour la publicité et pour cette raison, pour l'instant, je refuse ce filtrage.
Moteur
C'est probablement la partie la plus intéressante du projet, mais je ne décrirai pas tout en détail dans cette publication. Si quelqu'un s'intéresse aux détails, demandez-le-moi de toutes les manières possibles.
La manière la plus simple de présenter un texte dans un format compréhensible par un réseau de neurones est le sac de mots.

Processus de vectorisation et plus sur BOWJe prépare à l'avance un dictionnaire de tous les mots courants (sans oublier d'exclure les mots simples et fréquents, tels que «a», «quoi», «qui» et d'autres; ils ne distinguent pas leur texte de l'arrière-plan des autres), chaque mot a son propre numéro. Ensuite, lorsque j'ai besoin de traiter le texte avec un réseau de neurones, j'obtiens le numéro de chaque mot du dictionnaire (s'il est là) et j'obtiens un vecteur (alias tableau en programmation). Il s'agit d'un tel ensemble ordonné de nombres, dans lequel il y a une unité à la place de chaque numéro de mot du texte (voir l'image ci-dessus). Il s'avère qu'un type de données est tout à fait compréhensible pour le réseau. J'ai la longueur de chaque vecteur est de 30 000, environ autant de mots adéquats que j'ai recueillis aux premiers stades de développement.
Il est également important de ne pas oublier que, par exemple, les mots "habr" et "(c) habr" sont presque les mêmes pour la compréhension. Mais pour l'algorithme décrit ci-dessus, ce sont des mots complètement différents. Pour résoudre ce problème, j'utilise l'analyseur morphologique
JMorphy2 . Il s'agit du port du PyMorphy2 d'origine pour Java. Il peut faire beaucoup de choses sympas, par exemple, changer la forme d'un mot (cas, sexe, nombre, etc.). J'en ai besoin pour obtenir la forme initiale du mot. Comme vous le savez, les formes initiales des mots "identiques" sont les mêmes. Et cela résout le problème ci-dessus.
6929 21903 25126 11441 7374 1925 1626 23128 6241 25584
Un exemple de liste de mots dans un dictionnaire et leurs nombres (séparés par un espace)La liste ci-dessus montre que le mot "dragon" n'est pas devenu "dragon". C'est un peu faux, mais même un tel prétraitement de texte suffit. En général, cette bibliothèque contient de nombreuses erreurs, mais la plupart d'entre elles n'affectent pas le fonctionnement du système.
Le service s'adresse à un public russophone. Et pour simplifier, seul le russe est en cours de traitement. Tous les caractères (lettres parmi eux) des autres alphabets sont jetés, comme les signes de ponctuation, les chiffres, les emojis ... Encore une fois, la simplification. N'oubliez pas non plus de filtrer les mots des langues qui utilisent partiellement l'alphabet russe, mais ajoutez leurs propres lettres (ukrainien par exemple).
Mais je vais continuer à partir du moment où un message de VKontakte est déjà devenu un vecteur (je l'appelle vectorisation). Ici le lien suivant est connecté: un réseau de neurones. J'ai décidé de l'utiliser car c'était intéressant pour moi et j'ai réussi à trouver une architecture adaptée à ma tâche. Le
premier article de la série «Auto Encoders in Keras» m'a aidé avec cela. Et oui, j'ai décidé d'utiliser l'encodeur automatique le plus courant, car il est bénéfique en termes de vitesse et d'entraînement. Mais parlons de tout dans l'ordre.
Comme pour tous les autres encodeurs automatiques, vous devez créer deux réseaux de neurones (encodeur et décodeur) et les combiner en un seul. Je l'ai fait comme suit:
from keras.layers import Input, Dense, Flatten, Reshape from keras.models import Model
Mais pourquoi avons-nous besoin de deux réseaux? Quoi qu'il en soit, l'auteur, vous n'avez pas expliqué pourquoi c'est
tout !
Calme, maintenant tout sera. Pour former, par exemple, seul un encodeur est impossible - il ne sera tout simplement pas clair à quel point la prédiction qu'il a faite est correcte. Et pour cela, nous formons le deuxième réseau, qui décodera immédiatement la sortie du premier (décodeur). Les mêmes données d'entrée et de sortie sont également utilisées. Un groupe de deux réseaux (appelé autoencoder) apprend à obtenir la même chose à partir des données d'entrée. Mais toutes les données passent par un «goulot d'étranglement» étroit sous la forme de 64 neurones. Cela supprime les informations les plus inutiles. Ainsi, les réseaux de neurones apprennent à transmettre des informations importantes sur le texte avec une qualité maximale et à rejeter tout le bruit. Ensuite, je viens de retirer le décodeur et c'est tout. Vous pouvez obtenir un meilleur résultat, mais vous devez alors augmenter la dimension de la couche de sortie du codeur / décodeur d'entrée. Ensuite, il faudra stocker plus de valeurs dans la base de données, cela pèsera plus + toutes les opérations sur les vecteurs longs seront plus longues (plus à ce sujet plus tard). Ou vous pouvez ajouter des couches / neurones, mais l'entraînement et la vectorisation seront plus longs.
L'encodeur lui-même vous permet de "compresser la dimension du vecteur". Rappelez-vous ce vecteur de zéros et de uns? Ainsi, l'encodeur vous permet de changer sa taille de 30K à 64 sans trop de perte d'informations importantes. Après cette étape, vous pouvez normalement comparer les deux vecteurs pour déterminer leur similitude ...
Mais nous regardons le travail du service sur la recommandation des communautés VK, et non des enregistrements individuels. Cela signifie que nous devons en quelque sorte obtenir le vecteur de l'ensemble du public. Cela se fait très facilement, les mathématiques au cinquième niveau. C'est une méthode un peu grossière, mais ça marche. Je viens de prendre et d'ajouter tous les vecteurs d'enregistrement d'une communauté (par exemple, prendre trois petits vecteurs {1, 2, 3}, {2, 3, 4}, {0, 4, 2}, nous obtenons le vecteur {3, 9, 9 }). Et j'en divise chaque élément par le nombre de vecteurs (on obtient le vecteur {1, 3, 3}). C'est tout, nous avons combiné tous les enregistrements du groupe en un seul. À l'avenir, vous devrez trouver quelque chose de plus délicat, afin de pouvoir émettre des bruits sous la forme de messages avec de la publicité, par exemple. Mais maintenant ça suffit.
Nous passons à la partie mathématique elle-même, mais comme tout le monde en a peur pour une raison quelconque, je vais la signer autant que possible. Commençons par les vecteurs au sens mathématique. Le vecteur est un segment dirigé. C'est une chose qui a les coordonnées du début (il est plus pratique de les prendre avec des zéros) et les coordonnées de la fin. Ce sont ces derniers qui sont enregistrés entre accolades. Par exemple, les coordonnées de la fin du vecteur {1, 0, 1}
youtube est un point avec des coordonnées (1, 0, 1). Mais nous considérerons deux vecteurs bidimensionnels,
{5, 2} et
{5, 0}. Construisons-les dans un système de coordonnées:

Laissez le vecteur
rose
- jaune. Ensuite, par le fait mathématique de la neuvième classe, le cosinus de l'angle entre eux est égal au rapport de leur produit scalaire au produit de leurs modules.
Produit scalaire <
,
> égal à la somme des produits des éléments correspondants, nous avons
.
Le module vectoriel est trouvé par la formule suivante:
O Where
et
c'est la première et la deuxième valeur du vecteur a, respectivement. Donc:
En combinant tout selon la formule, nous obtenons:
La justesse des calculs peut être vérifiée grâce aux fonctions trigonométriques du triangle rectangle formé. Dans le projet, tous les calculs sont effectués selon de telles formules, mais seules les coordonnées de la fin du vecteur ne sont pas deux, mais soixante-quatre.
Que donnent ces informations? Il s'est avéré que plus la valeur du cosinus était grande (plus l'angle était petit), plus les textes correspondant aux vecteurs étaient similaires. Ainsi, la tâche de trouver le groupe le plus similaire au groupe A revient à trouver le cosinus de l'angle entre le vecteur de ce groupe et tous les autres. Ensuite, le moteur quitte tous les groupes pour lesquels la valeur du cosinus avec A sera supérieure à, disons, 0,99. À ce stade, vous pouvez simplement afficher le résultat, comme je l'avais fait auparavant. Mais ce processus est déjà très long dans les communautés de 100 000 habitants, et que se passera-t-il, disons, à 1 million?
Pour résoudre ce problème, j'utilise le graphique. Tous les groupes sont représentés comme ses sommets et deux points sont connectés si le cosinus de l'angle entre les vecteurs qui leur correspondent est supérieur à 0,99. Mais si vous ne comprenez pas la structure avec le nom du graphique, vous pouvez simplement imaginer que je pré-calcule les paires de communautés les plus similaires dans la base de données et les enregistre. Et je n'oublie pas de mettre à jour le graphique à mesure que de nouveaux groupes sont ajoutés à la base de données. Oui, c'est très long, mais toujours plus facile pour l'utilisateur qu'auparavant.
Le site
Je ne peindrai pas tout sur le site, car c'est la partie la plus simple et la plus ennuyeuse. Je n'ai jamais écrit de sites à partir de zéro, j'ai toujours utilisé différents moteurs prêts à l'emploi. Mais dans ce projet, j'ai réalisé qu'il serait plus facile de faire des samopis. Ainsi, le moteur du site est écrit en Python 3 à l'aide de Flask. Et le moteur de modèle Ninja2 est utilisé, ce qui rend plus pratique la substitution de valeurs dynamiques dans du code HTML (et js) statique. Je n'ai pas oublié l'autorisation via VKontakte, car c'est l'option la plus optimale. Le concepteur, comme le concepteur de la mise en page, est tout simplement horrible de ma part, si quelqu'un veut rejoindre le projet - bienvenue.
La première ligne de résultats du siteLes problèmes
J'ai rencontré des situations désagréables que j'ai résolues avec succès. Le problème avec l'API VK a été écrit ci-dessus et sa solution était particulièrement désagréable pour le service, car la vitesse a beaucoup baissé. Si avant, je recevais une centaine de messages en une seule demande, maintenant je dois faire quelques téléchargements de gros code HTML, l'analyser, et seulement après ce processus. Maintenant, il y a un problème avec la restriction sur l'obtention d'utilisateurs, de leurs amis et de groupes, mais cette limite n'interfère pas vraiment à ce stade. Ensuite, vous devez le résoudre de la même manière que le premier.
Le texte sur Internet moderne perd chaque jour moins d'importance. Depuis de nombreuses années, VKontakte a de nombreux groupes avec des vidéos, des photos et de la musique. Et pour obtenir de bonnes recommandations, vous devez les traiter.

Mais ce n'est pas du texte, et une puissance de calcul vraiment sérieuse est nécessaire. Par exemple, c'est une carte vidéo haut de gamme, mais maintenant je n'en ai pas, et je ne veux pas prendre de serveur pour tout ça (c'est trop tôt). Mais en général, j'ai déjà les meilleures pratiques pour l'architecture de réseau neuronal pour cette tâche. Je vais utiliser un neurone pour classer les images, en "coupant" la partie supérieure de celui-ci, qui est responsable de la classification des objets. Il ne restera plus que celui qui tracera les signes de l'image. Je peux serrer cette carte avec un autre encodeur et c'est tout, toutes les opérations suivantes sont similaires à celles "textuelles".
Il reste une autre question non résolue concernant le nombre de demandes au site VKontakte que je peux faire par unité de temps. Ou en un jour. Maintenant, je n'ai pas rencontré cette restriction, mais cela peut arriver au moment le plus inopportun.
Plans futurs
J'ai besoin de toute urgence d'un beau panneau de contrôle et de statistiques. Il est déjà dans son état initial, mais il doit être terminé. De là, je veux contrôler le démarrage / arrêt des microservices (à savoir, le moteur en est composé), la taille des files d'attente, la vitesse de traitement et tout ça. Eh bien, les statistiques, qui ne voudrait pas regarder leurs chiffres? Bien sûr, je dois tout optimiser et le rendre adapté aux utilisateurs, en particulier, je dois refaire la partie externe du site, car il ne répond pas à mes normes de confort.
Conclusion
J'ai réussi à m'engager sur la voie de la création d'un service avec une structure intéressante (au moins pour moi) que je vais utiliser pour l'un des concours qui me permettront d'entrer dans la meilleure université russe (je ne dirai pas quel genre de première université non classique c'est). Je pense que si vous travaillez toujours, vous pouvez en tirer quelque chose de plus intéressant, par exemple, un analyseur de la qualité des publications, faire un service d'analyse pour l'administration communautaire ou autre chose.
Je suis tombé sur beaucoup de choses du texte ci-dessus pour la première fois. Cela signifie que je pourrais faire quelque chose de mal. Si mes lecteurs savent ce qui peut être amélioré / corrigé, où je peux avoir d'autres problèmes et ainsi de suite - veuillez en parler dans le commentaire. Et je vous demande de critiquer la qualité même de l'article, afin que je puisse l'améliorer la prochaine fois. Je vous remercie