Der Sommer ging zu Ende, der August war besonders kalt. Meine 11. Klasse begann und ich erkannte, dass jetzt die letzte Chance (Spoiler: nein) ist, meine berufliche Kompetenz irgendwie zu verbessern. Seit einigen Jahren arbeite ich fleißig an verschiedenen IT-Projekten, einige alleine, andere im Team. Aber jetzt machen alle
Söhne der Freundin meiner Mutter schon etwas Schönes. Vielleicht nutzlos, aber schön im Aussehen. Jemand macht eine klebrige Simulation von Partikeln in Form von Gifs, jemand taucht in maschinelles Lernen ein und führt alle Arten von Stilübertragungen durch. Und was bin ich schlimmer? Ich will auch!
Ein Beispiel für eine Simulation finden Sie auch unter Kat.Beispiel einer Partikelsimulation von einem Freund von mirMit diesem Gedanken begann mein Studium des Themas maschinelles Lernen. Und in Bezug auf die Ausbildung gab es für mich nichts Neues, wie in jedem anderen Bereich der IT, hier ist Übung erforderlich. Aber was ist, wenn ich nicht an Tonwertanalysatoren interessiert bin? Wir müssen etwas Eigenes erfinden.
Beim erneuten Durchblättern des VKontakte-Newsfeeds wurde mir klar, dass die Communitys dieses sozialen Netzwerks ein wahrer Schatz für die Datenwissenschaft sind. Wenn Sie Text, Memes in Form von Bildern oder Musik aus Sammlungen verarbeiten, erhalten Sie eine große Menge relevanter Informationen über moderne Menschen: populäre Musikgenres, Vokabeln oder die Tageszeit der Aktivitäten der meisten Menschen. Dies ist ein Feld für viele Entdeckungen.
Aber wie viel werden solche Statistiken für normale Menschen benötigt? Als ob ich meine Musik vermisse oder nicht auf den Bereich "Beliebt" zugreifen kann? Sie müssen sich also etwas Praktisches überlegen, das zumindest einen signifikanten Prozentsatz der Benutzer ansprechen kann.
Es ist erwähnenswert, dass ich ein paar Monate zuvor einen coolen Artikel über die
Erstellung meiner Home-Suchmaschine gelesen habe, der mich wirklich beeindruckt hat. Wie der Autor hatte ich ein großes Verlangen nach großen Projekten, die Tag und Nacht eine große Anzahl von Tausenden von Gigabyte an Informationen verarbeiten.

Und jetzt kehren wir zum August zurück, der etwas wärmer wurde als zu Beginn des Artikels. Als ich merkte, dass ich jetzt eine riesige Informationsquelle habe, wurde mir klar, dass es Zeit war. Es ist Zeit für unser eigenes monströses System. Die Hauptfrage blieb jedoch einige Tage später - was soll ich mit all dem anfangen? Was kann der Benutzer anbieten? Ich werde den Leser nicht quälen, ich werde Ihnen nur sagen, dass es für mich, wie für einige meiner Freunde, sehr schwierig ist, nach neuen VKontakte-Gruppen zu suchen, die mir gefallen könnten. Jetzt hat jedes erste Publikum einen Namen - eine zufällige Reihe von Wörtern. Administratoren versuchen, es zum absurdesten zu machen, wahrscheinlich ist dies eine Art Rasse, die nur für sie verständlich ist.
Und dann habe ich beschlossen, einen Dienst zu schreiben, der dem Benutzer bei der Auswahl der Communitys hilft und empfiehlt, was Sie abonnieren können. Also kam meine Idee auf.
Die Einführung war lange nicht zufällig, sie sollte meine Gefühle vermitteln und zeigen, dass die Idee nicht aus heiterem Himmel erschien. Eigentlich wie alle anderen Ideen zu Habré.
Mein Dienst ist noch in Betrieb, er läuft seit mehr als vier Monaten (wenn Sie vom Moment des ersten erfolgreichen Experiments an zählen). Aber ich habe bereits Erfahrungen, die ich mit Ihnen teilen möchte. Jetzt wird es eine kurze, präzise Beschreibung des Projekts geben. Als nächstes werde ich einige wichtige Punkte skizzieren. Und wenn der Artikel Habrayuzer besonders anspricht, wird seine Fortsetzung herauskommen, in der es rein technische Informationen und Code geben wird.
Alles besteht aus drei Teilen:
- Suchbot (wenn du es so nennen kannst)
- Datenverarbeitungs-Engine
- Website für Benutzer (mit einem Kontroll- und Überwachungsfeld für Administratoren)
Die Funktionalität des Bots umfasst das Suchen nach neuen Gruppen und das "Entfernen" von Text und anderen Informationen in die Datenbank. Die Engine ist mit der Weiterverarbeitung dieser Daten beschäftigt, über die ich weiter unten schreiben werde. Und die Site ermöglicht es den Benutzern einfach, all dies zu nutzen.
Suche bot
Hier gibt es nichts Neues. Ich nehme einfach das Profil einer Person auf VK und erhalte eine Liste der Gruppen und seiner Freunde von ihm. All dies geschieht mit der VK-API. Und wenn dieser IPA es schafft, eine Liste der Gruppen des Benutzers und seiner Freunde zu erhalten, schafft er es nicht, den Inhalt der Gruppen zu erhalten ... Ich bin nur auf eine Einschränkung gestoßen und das war's. Dann erinnerte ich mich, dass VKontakte vor einiger Zeit ihr cooles System nur für solche Dinge bewarb. Der Name dieses Systems lautet Streaming API.
Streaming API - ein Tool zum Abrufen einer zufälligen Auswahl von Datensätzen von VK. Auf der Beschreibungsseite steht, dass Sie nur bis zu 1% aller Informationen erhalten können. Um bis zu hundert zu erhalten, müssen Sie dem Support schreiben und ihm Ihre Absichten erklären.
Es scheint, dass alles wunderbar ist. Aber nein. Ich habe, wie wahrscheinlich viele, das wichtigste Wort in der obigen Beschreibung übersehen. Und das ist die Präposition „vorher“. Niemand wird Ihnen alle 100% der Daten geben. Dies ist nur eine schöne obere Leiste und das wars. In der Tat bekommen wir so:
Hoffe, Agent # 365 wird mich nicht alle 365 Tage im Jahr für diesen Screenshot hassenDas heißt, ich kann nur 30.000 Ereignisse pro Tag erhalten. Und diese Nummer enthält Kommentare und nur Reposts. Es ist auch notwendig, einige Tag-Wörter anzugeben, es werden nur Nachrichten mit ihnen kommen. Einige der verbleibenden Beiträge interessieren mich einfach nicht, da sie an der Wand der Benutzer stehen. Bleibt ziemlich viel. Als Referenz kann ich in meiner aktuellen Implementierung in wenigen Tagen unvollständiger Betriebszeit bis zu 8,5 Millionen Datensätze empfangen (insgesamt etwa 10 Stunden, aber es gab keine genauen Messungen).
Hier muss ich zu einer Regel sagen, die ich aus diesem ganzen Experiment identifiziert habe. Beurteile eine Gruppe niemals nach einem Beitrag. Besonders wenn Sie eine künstliche Intelligenz sind, die für solche Geräusche anfällig ist. Sie benötigen also mindestens einige Beiträge, um eine objektive Beschreibung der Öffentlichkeit zu erstellen. Lassen Sie uns nun schätzen, dass einige Gruppen mit wirklich hochwertigen Inhalten diese alle paar Wochen veröffentlichen. Und selbst dann kann ich es aufgrund der unvollständigen Streaming-API überspringen. Und wenn ich es bekomme, wie lange sollte ich den Inhalt Stück für Stück sammeln?
Ich entschied das zu lange und ging in die andere Richtung. Da ich von VKontakte im JSON-Format keine eindeutige Antwort erhalten kann, analysiere ich die Wände von Communitys. Ja, die Aufgabe ist etwas kompliziert und ihre Lösung verlangsamt sich, aber ich habe keine Alternative. So fing ich an, den ersten Block meines Systems zu schreiben. Ich habe es übrigens in Java mit Jsoup geschrieben, einer Bibliothek, die es sehr bequem macht, Inhalte aus HTML-Text zu extrahieren. Ich habe nicht vergessen, das Veröffentlichungsdatum des letzten Beitrags zu verarbeiten. Ich brauche keine toten Communities. Ich indiziere sie einfach nicht. Mit Werbung getaggte Beiträge werden ebenfalls verworfen. Nicht alle Administratoren machen solche Notizen, aber dieses Problem ist nicht so einfach zu lösen. Ich konnte keinen geeigneten Filter für Werbung erstellen und lehne diese Filterung vorerst ab.
Motor
Dies ist wahrscheinlich der interessanteste Teil des Projekts, aber ich werde in dieser Veröffentlichung nicht alles im Detail beschreiben. Wenn sich jemand für die Details interessiert, fragen Sie mich auf alle möglichen Arten.
Die einfachste aller Möglichkeiten, Text in einem für ein neuronales Netzwerk verständlichen Format darzustellen, ist eine Wortsammlung.

Vektorisierungsprozess und mehr über BOWIch bereite im Voraus ein Wörterbuch aller gebräuchlichen Wörter vor (ohne zu vergessen, dass häufig vorkommende Wörter wie „a“, „was“, „was“ und andere ausgeschlossen werden; sie unterscheiden ihren Text nicht vom Hintergrund anderer). Jedes Wort hat seine eigene Nummer. Wenn ich dann den Text mit einem neuronalen Netzwerk verarbeiten muss, erhalte ich die Nummer jedes Wortes aus dem Wörterbuch (falls vorhanden) und einen Vektor (auch bekannt als Array in der Programmierung). Dies ist ein solcher geordneter Satz von Zahlen, bei dem anstelle jeder Wortnummer aus dem Text eine Einheit steht (siehe Abbildung oben). Es stellt sich heraus, dass ein Datentyp für das Netzwerk durchaus verständlich ist. Ich habe die Länge jedes Vektors 30.000, ungefähr so viele adäquate Wörter, die ich in den ersten Entwicklungsstadien gesammelt habe.
Es ist auch wichtig, nicht zu vergessen, dass zum Beispiel die Wörter "habr" und "(c) habr" für das Verständnis fast gleich sind. Für den oben beschriebenen Algorithmus sind dies jedoch völlig andere Wörter. Um dies zu beheben, verwende ich den morphologischen Analysator
JMorphy2 . Dies ist der Port des ursprünglichen PyMorphy2 für Java. Er kann viele coole Dinge tun, zum Beispiel die Form eines Wortes ändern (Groß- und Kleinschreibung, Geschlecht, Zahl usw.). Ich brauche es, um die ursprüngliche Form des Wortes zu erhalten. Wie Sie wissen, sind die Anfangsformen von "identischen" Wörtern dieselben. Und das löst das obige Problem.
6929 21903 25126 11441 7374 1925 1626 23128 6241 25584
Ein Beispiel für eine Liste von Wörtern in einem Wörterbuch und deren Nummern (durch ein Leerzeichen getrennt)Die obige Liste zeigt, dass das Wort "Drache" nicht zu "Drache" wurde. Das ist ein bisschen falsch, aber selbst eine solche Textvorverarbeitung ist genug. Im Allgemeinen weist diese Bibliothek viele Fehler auf, die meisten wirken sich jedoch nicht auf den Betrieb des Systems aus.
Der Service richtet sich an ein russischsprachiges Publikum. Der Einfachheit halber wird derzeit nur Russisch verarbeitet. Alle Zeichen (Buchstaben darunter) aus anderen Alphabeten werden weggeworfen, wie Satzzeichen, Zahlen, Emojis ... Nochmals Vereinfachung. Vergessen Sie auch nicht, Wörter aus Sprachen herauszufiltern, die teilweise das russische Alphabet verwenden, sondern fügen Sie ihre eigenen Buchstaben hinzu (z. B. Ukrainisch).
Aber ich werde von dem Moment an fortfahren, in dem sich ein Beitrag von VKontakte bereits in einen Vektor verwandelt hat (ich nenne ihn Vektorisierung). Hier ist folgende Verbindung verbunden: ein neuronales Netzwerk. Ich habe mich für es entschieden, weil es für mich interessant war und es geschafft hat, eine geeignete Architektur für meine Aufgabe zu finden. Der
erste Artikel aus der Serie „Auto Encoder in Keras“ hat mir dabei geholfen. Und ja, ich habe mich für den gängigsten Auto-Encoder entschieden, da dieser in Bezug auf Geschwindigkeit und Training von Vorteil ist. Aber reden wir über alles in Ordnung.
Wie bei allen anderen Autoencodern müssen Sie zwei neuronale Netze (Encoder und Decoder) erstellen und zu einem kombinieren. Ich habe es wie folgt gemacht:
from keras.layers import Input, Dense, Flatten, Reshape from keras.models import Model
Aber warum brauchen wir zwei Netzwerke? Wie auch immer, der Autor, Sie haben nicht beschrieben, warum das
alles ist !
Ruhig, jetzt wird alles sein. Zum Beispiel ist es unmöglich, nur einen Encoder zu trainieren - es wird einfach nicht klar sein, wie richtig die Vorhersage ist, die er gemacht hat. Und dafür trainieren wir das zweite Netzwerk, das den Ausgang des ersten (Decoders) sofort decodiert. Die gleichen Eingabe- und Ausgabedaten werden ebenfalls verwendet. Eine Reihe von zwei Netzwerken (Autoencoder genannt) lernt, aus den Eingabedaten dasselbe zu erhalten. Alle Daten durchlaufen jedoch einen engen „Engpass“ in Form von 64 Neuronen. Dadurch werden die unnötigsten Informationen verworfen. Auf diese Weise lernen neuronale Netze, wichtige Informationen über den Text mit maximaler Qualität zu übertragen und das gesamte Rauschen zu beseitigen. Dann entferne ich einfach den Decoder und das wars. Sie können ein besseres Ergebnis erzielen, müssen dann aber entweder die Dimension der Ausgangsschicht des Codierers / Eingangsdecodierers vergrößern. Dann müssen mehr Werte in der Datenbank gespeichert werden, es wird mehr gewogen + alle Operationen an langen Vektoren werden länger sein (dazu später mehr). Oder Sie können Schichten / Neuronen hinzufügen, aber dann werden Training und Vektorisierung länger dauern.
Mit dem Encoder selbst können Sie "die Dimension des Vektors komprimieren". Erinnern Sie sich an diesen Vektor von Nullen und Einsen? Mit dem Encoder können Sie also seine Größe von 30 KB auf 64 KB ändern, ohne dass wichtige Informationen verloren gehen. Nach diesem Schritt können Sie normalerweise die beiden Vektoren vergleichen, um ihre Ähnlichkeit zu bestimmen ...
Wir betrachten jedoch die Arbeit des Dienstes auf Empfehlung der VK-Gemeinschaften und nicht einzelne Aufzeichnungen. Dies bedeutet, dass wir irgendwie den Vektor der gesamten Öffentlichkeit erhalten müssen. Dies ist sehr einfach, Mathematik in der fünften Klasse. Dies ist eine etwas grobe Methode, aber sie funktioniert. Ich nehme einfach alle Datensatzvektoren aus einer Community und füge sie hinzu (zum Beispiel drei kleine Vektoren {1, 2, 3}, {2, 3, 4}, {0, 4, 2}, wir erhalten den Vektor {3, 9, 9 }). Und ich dividiere jedes Element davon durch die Anzahl der Vektoren (wir erhalten den Vektor {1, 3, 3}). Das ist alles, wir haben alle Datensätze der Gruppe zu einem zusammengefasst. In Zukunft müssen Sie sich etwas Schwierigeres einfallen lassen, damit Sie beispielsweise Geräusche in Form von Posts mit Werbung werfen können. Aber jetzt ist das genug.
Wir wenden uns dem mathematischen Teil selbst zu, aber da jeder aus irgendeinem Grund Angst davor hat, werde ich ihn so oft wie möglich unterschreiben. Beginnen wir mit Vektoren im mathematischen Sinne. Vektor ist ein gerichtetes Segment. Dies ist so etwas, das die Koordinaten des Anfangs (es ist am bequemsten, sie mit Nullen zu nehmen) und die Koordinaten des Endes hat. Letztere sind in geschweiften Klammern angegeben. Zum Beispiel sind die Koordinaten des Endes des Vektors {1, 0, 1}
youtube ein Punkt mit Koordinaten (1, 0, 1). Wir werden aber zwei zweidimensionale Vektoren betrachten,
{5, 2} und
{5, 0}. Bauen wir sie in einem Koordinatensystem auf:

Lass den Vektor
rosa
- gelb. Dann ist nach der mathematischen Tatsache der neunten Klasse der Kosinus des Winkels zwischen ihnen gleich dem Verhältnis ihres Skalarprodukts zum Produkt ihrer Module.
Skalarprodukt <
,
> gleich der Summe der Produkte der entsprechenden Elemente haben wir
.
Das Vektormodul wird durch die folgende Formel gefunden:
Wo
und
Dies ist der erste bzw. zweite Wert des Vektors a. Also:
Wenn wir alles nach der Formel kombinieren, erhalten wir:
Die Richtigkeit der Berechnungen kann durch die trigonometrischen Funktionen des gebildeten rechtwinkligen Dreiecks überprüft werden. Im Projekt werden alle Berechnungen nach solchen Formeln durchgeführt, aber nur die Koordinaten des Vektorendes sind nicht zwei, sondern vierundsechzig.
Was geben diese Informationen? Wie sich herausstellte, sind die Texte, die den Vektoren entsprechen, umso ähnlicher, je größer der Kosinuswert ist (je kleiner der Winkel). Die Aufgabe, die Gruppe zu finden, die der Gruppe A am ähnlichsten ist, besteht also darin, den Kosinus des Winkels zwischen dem Vektor dieser Gruppe und allen anderen zu finden. Dann verlässt der Motor alle Gruppen, für die der Kosinuswert zusammen mit A größer als beispielsweise 0,99 ist. In diesem Stadium können Sie einfach das Ergebnis anzeigen, wie ich es zuvor getan habe. Aber dieser Prozess ist in 100.000 Gemeinden bereits sehr lang, und was wird beispielsweise bei 1 Million passieren?
Um dieses Problem zu lösen, verwende ich die Grafik. Alle Gruppen werden als ihre Eckpunkte dargestellt, und zwei Punkte werden verbunden, wenn der Kosinus des Winkels zwischen den ihnen entsprechenden Vektoren größer als 0,99 ist. Wenn Sie die Struktur mit dem Namen des Diagramms jedoch nicht verstehen, können Sie sich vorstellen, dass ich die ähnlichsten Community-Paare in der Datenbank vorberechnete und speichere. Und ich vergesse nicht, das Diagramm zu aktualisieren, wenn der Datenbank neue Gruppen hinzugefügt werden. Ja, es ist eine sehr lange Zeit, aber für den Benutzer immer noch einfacher als zuvor.
Website
Ich werde nicht alles über die Seite malen, da dies der einfachste und langweiligste Teil ist. Ich habe noch nie Websites von Grund auf neu geschrieben, ich habe immer verschiedene vorgefertigte Engines verwendet. Aber in diesem Projekt wurde mir klar, dass es einfacher sein würde, einen Samopis herzustellen. Daher wird die Site-Engine in Python 3 mit Flask geschrieben. Außerdem wird die Ninja2-Vorlagen-Engine verwendet, die es einfacher macht, dynamische Werte in statischem HTML- (und js-) Code zu ersetzen. Ich habe die Autorisierung durch VKontakte nicht vergessen, da dies die optimalste Option ist. Der Designer, wie auch der Layout-Designer, ist einfach schrecklich von mir, wenn jemand dem Projekt beitreten möchte - willkommen.
Die erste Ergebniszeile der SiteDie Probleme
Ich bin auf einige unangenehme Situationen gestoßen, die ich erfolgreich gelöst habe. Das Problem mit der VK-API wurde oben beschrieben und seine Lösung war für den Dienst besonders unangenehm, da die Geschwindigkeit sehr stark abnahm. Wenn ich vorher hundert Beiträge in einer Anfrage erhalten habe, muss ich jetzt ein paar Downloads von großem HTML-Code durchführen, ihn analysieren und erst danach verarbeiten. Jetzt gibt es ein Problem mit der Einschränkung, Benutzer, ihre Freunde und Gruppen zu erhalten, aber diese Begrenzung stört derzeit nicht wirklich. Dann müssen Sie es genauso lösen wie das erste.
Text im modernen Internet verliert von Tag zu Tag an Bedeutung. VKontakte hat seit vielen Jahren viele Gruppen mit Videos, Bildern und Musik. Und um gute Empfehlungen zu erhalten, müssen Sie diese verarbeiten.

Dies ist jedoch kein Text, und es wird wirklich ernsthafte Rechenleistung benötigt. Dies ist beispielsweise eine Top-End-Grafikkarte, aber jetzt habe ich keine und ich möchte für all dies keinen Server nehmen (es ist zu früh). Im Allgemeinen habe ich jedoch bereits die Best Practices für die neuronale Netzwerkarchitektur für diese Aufgabe. Ich werde ein Neuron verwenden, um Bilder zu klassifizieren und den oberen Teil davon "abzuschneiden", der für die Klassifizierung von Objekten verantwortlich ist. Alles, was bleibt, wird das sein, was die Zeichen des Bildes abbildet. Ich kann diese Karte mit einem anderen Encoder quetschen und das ist alles, alle nachfolgenden Operationen ähneln denen von "Text".
Es bleibt eine weitere ungelöste Frage, wie viele Anfragen an die VKontakte-Site ich pro Zeiteinheit stellen kann. Oder an einem Tag. Jetzt bin ich nicht auf diese Einschränkung gestoßen, aber es kann im ungünstigsten Moment passieren.
Zukunftspläne
Ich brauche dringend ein schönes Bedienfeld und Statistiken. Es befindet sich bereits im Ausgangszustand, muss jedoch fertiggestellt werden. Daraus möchte ich den Start / Stopp von Microservices (nämlich die Engine besteht aus ihnen), die Größe der Warteschlangen, die Verarbeitungsgeschwindigkeit und all das steuern. Nun, Statistiken, wer würde nicht auf ihre Zahlen schauen wollen? Natürlich muss ich alles optimieren und für Benutzer geeignet machen, insbesondere muss ich den externen Teil der Website wiederholen, da er nicht meinen Komfortstandards entspricht.
Fazit
Ich habe es geschafft, einen Dienst mit einer interessanten Struktur (zumindest für mich) zu schaffen, die ich für einen der Wettbewerbe verwenden werde, die es mir ermöglichen, die beste russische Universität zu betreten (ich werde nicht sagen, um welche Art von erster nicht klassischer es sich handelt). Ich denke, wenn Sie noch arbeiten, können Sie etwas Interessanteres daraus herausholen, z. B. einen Analysator für die Qualität von Veröffentlichungen, einen Analysedienst für die Community-Verwaltung oder etwas anderes.
Ich bin zum ersten Mal auf viele Dinge aus dem obigen Text gestoßen. Das bedeutet, dass ich etwas falsch machen könnte. Wenn meine Leser wissen, was verbessert / behoben werden kann, wo ich möglicherweise andere Probleme habe usw., schreiben Sie dies bitte im Kommentar. Und ich bitte Sie, Kritik an der Qualität des Artikels zu üben, damit ich ihn beim nächsten Mal verbessern kann. Vielen Dank.