IT & Engineering

Maschinelles Lernen für alltägliche Aufgaben

Oft wird angenommen, dass maschinelles Lernen für alltägliche Entwicklungsaufgaben zu kompliziert ist. Wir assoziieren es oft mit Dingen wie Big Data, Data Mining, Data Science und künstlicher Intelligenz. Manchmal fühlt es sich etwa so an:
Bild für Maschinelles Lernen für alltägliche Aufgaben

Oft wird angenommen, dass maschinelles Lernen für alltägliche Entwicklungsaufgaben zu kompliziert ist. Wir assoziieren es oft mit Dingen wie Big Data, Data Mining, Data Science und künstlicher Intelligenz. Manchmal fühlt es sich etwa so an:

A brain made up of electrical points

Maschinelles Lernen ist schwer

Ich hatte schon immer das Gefühl, dass wir vom maschinellen Lernen für einfache Aufgaben, die wir regelmäßig erledigen, profitieren.

Ein Praxisbeispiel

Bei Mailgun arbeiten wir mit E-Mails und als Teil unseres Angebots parsen wir HTML-Zitate. Dadurch können Nutzer die neueste Antwort anstelle der gesamten Konversation abrufen, die als Teil unserer Webhook-Antwort zurückgegeben wird. Erfahren Sie mehr darüber, wie wir eingehende Nachrichten verarbeiten, in unserem Dokumentation.

Für alle, die es nicht wissen: So sieht das Parsen von HTML aus dem öffentlichen Internet aus:

Dirty Jeep stuck in the mud

Parsen von HTML aus dem öffentlichen Internet

Es ist unübersichtlich und manchmal bleiben Prozesse hängen.

Ein Wechsel der Parsing-Bibliothek ist hilfreich, löst das Problem jedoch nicht vollständig, da jede Bibliothek ihre Grenzen hat. Sie müssen das Parsen auf ein vernünftiges Maß beschränken.

Cluster-Analyse als Rettung

Aber was sollten die Kriterien und der Schwellenwert sein? Sollten wir nach HTML-Länge oder Tag-Anzahl begrenzen? Vielleicht beides? Vielleicht durch etwas anderes? Das Ziel ist offensichtlich, so viele Nachrichten wie möglich zu verarbeiten, ohne sich selbst ins Bein zu schießen. Der Weg dorthin ist jedoch nicht ganz klar.

Genau hier sind Cluster-Analyse und statistische Klassifizierung nützlich. Für die Untersuchung nutzte ich R, aber abhängig von Ihrer Aufgabe und Ihren persönlichen Einstellungen verwenden Sie vielleicht etwas anderes – scikit-learnWekaMOA usw.

Datensatz sammeln

Zuerst haben wir HTML-Länge, Tag-Anzahl und Verarbeitungszeit der Nachricht protokolliert und in einer CSV-Datei gespeichert:

                                

                                    htmllen,tagscount,took rn2893762,85527,34.300139904 rn31378,518,0.0368919372559 rn19105,413,0.0545339584351 rn...
                                
                            

Die überwiegende Mehrheit der Nachrichten wird in Sekundenbruchteilen verarbeitet. Deshalb mussten wir beim Sammeln des Datensatzes sicherstellen, dass wir genügend „langsame“ Nachrichten haben.

Letztendlich hatten wir zwei CSV-Dateien, die an verschiedenen Tagen gesammelt wurden. Eine hatte 13.831 Zeilen und war für die Analyse und das Modell-Training reserviert (der Trainingsdatensatz). Eine andere hatte 12.149 Zeilen und war für die Modell-Validierung reserviert (der Validierungsdatensatz).

Generell benötigen Sie mindestens zwei Datensätze – einen für das Training und einen für die Validierung. Andernfalls könnte das Problem des Overfittings auftreten, bei dem Ihr Modell zwar gut an die Trainingsdaten angepasst ist, in der Praxis jedoch versagt.

Anzahl der Cluster bestimmen

Um die Daten zu visualisieren und nach Mustern zu suchen, K-Means-Clustering wurde zuerst ausprobiert:

                                

                                    messages <- read.csv(file="messages080816.csv", sep=",", head=TRUE) rn    mydata <- matrix(messages$took, ncol=1) rnrn    ## Determine the number of clusters rn    wss <- (nrow(mydata)-1)*sum(apply(mydata,2,var)) rn    for (i in 2:15) wss[i] <- sum(kmeans(mydata, rn        centers=i)$withinss) rn    plot(1:15, wss, type="b", xlab="Number of Clusters", rn        ylab="Within groups sum of squares")
                                
                            

Wie Sie sehen, gibt es bis zu 4 Clustern eine deutliche Leistungssteigerung. Danach gibt es keinen wirklichen Schub mehr.

Clustering

Der nächste Schritt bestand darin, herauszufinden, wie sich die Datenpunkte auf die Cluster verteilen:

                                

                                     ## K-Means Clustering with 4 clustersrn    fit <- kmeans(mydata, 4) rnrn    ## Cluster Plot against 1st 2 principal components rn    ## vary parameters for most readable graph rn    library(cluster) rn        clusplot(mydata, fit$cluster, color=TRUE,rn           shade=TRUE, labels=2, lines=0)
                                
                            
A clusplot graph

Das Problem lässt sich bereits ein wenig erahnen: Die Cluster bilden sich durch das Abtrennen der weit entfernten Datenpunkte, während das Intervall, an dem wir interessiert sind (1–20 Sek.), genau in der Mitte liegt. Das Problem besteht auch bei Erhöhung der Cluster-Anzahl weiter.

Darüber hinaus gibt es eine deutliche Überschneidung zwischen den Clustern in dem Intervall:

                                

                                     ## get clusters mean, min, max rn    mean <- aggregate(mydata,by=list(fit$cluster),FUN=mean) rn    min <- aggregate(mydata,by=list(fit$cluster),FUN=min) rn    max <- aggregate(mydata,by=list(fit$cluster),FUN=max)
                                
                            
A list of clusters code

Vergleichen Sie Cluster Nummer 1 und 4. Das Problem besteht auch bei Erhöhung der Cluster-Anzahl weiter.

An diesem Punkt entschieden wir uns für einen anderen Ansatz und betrachteten die Perzentile der Verarbeitungszeit der Nachricht:

                                

                                     percentiles <- quantile(messages$took, seq(0.5, 0.99, 0.01)) rn    plot(seq(0.5, 0.99, 0.01), percentile)
                                
                            
A graph of percentiles

Wie Sie sehen, steigt die Verarbeitungszeit nach dem 78. Perzentil schnell an. Hier war unser erster Schwellenwert – das 78. Perzentil, das 6,5 Sekunden entsprach.

Alle Datenpunkte, die weniger als 6,5 Sek. dauerten, wurden als „schnell“ und andere als „langsam“ markiert.

Klassifizierung

Für die Klassifizierung probierten wir SVM (Support Vector Machines), Random Forests  genannt, und CART(Classification And Regression Tree).

CART lieferte für diese Aufgabe etwas bessere Ergebnisse. Der Hauptvorteil besteht jedoch darin, dass es einen Entscheidungsbaum bietet, der leicht zu verstehen, zu erklären und zu implementieren ist, im Gegensatz zu SVM oder Random Forests, die wie eine Black-Box funktionieren und den Einsatz umfangreicher ML-Bibliotheken in der Produktion erfordern.

So klassifizieren Sie mit CART:

                                

                                    x <- subset(messages, select=-took) rnlibrary(rpart) rnrn# grow tree rnfit <- rpart(x$cls ~., method="class", data=x) rnrn## display the results rnprintcp(fit)rnrn# detailed summary of splits rnsummary(fit) rnrn# plot tree rnplot(fit, uniform=TRUE, rn    main="Classification Tree for message processing time") rntext(fit, use.n=TRUE, all=TRUE, cex=.8) 
                                
                            

Hier ist der Entscheidungsbaum:

Classification tree for message processing time

Und so sieht die Implementierung aus:

                                

                                    def html_too_big(s): rn    return s.count('<') > _MAX_TAGS_COUNT
                                
                            

Ist das nicht wunderbar? Die gesamte Komplexität der Untersuchung in einer einzigen Zeile.

Validierung

Zur Auswertung nahmen wir den Validierungsdatensatz und versuchten, die Klassifizierung mit unserem Modell vorherzusagen:

                                

                                     validate <- read.csv(file="messages080916.csv", sep=",", head=TRUE) rn    validate <- subset(validate, select=-took) rn    xv <- subset(validate, select=-cls) rn    y <- predict(fit, xv, type="class") rn    table(validate$cls, y)
                                
                            

Hier ist die Konfusionsmatrix und einige gängige Klassifizierungsmetriken:

Evaluation code

Erkenntnisse

Maschinelles Lernen ist nicht nur für Data Scientists. Sogar bei einfachen Entscheidungen, die durch ML unterstützt werden, profitieren Sie. Machen Sie sich mit Ihren Daten vertraut. Verlassen Sie sich nicht blind auf wissenschaftliche Algorithmen und Modelle.

Viel Spaß beim maschinellen Lernen und Data Mining.