Spark und Python und meine Vergangenheit

Ich habe jetzt zwei Wochen mit Spark und Python gespielt (oder eine Woche, es gab noch so was wie Feiertage und so was wie Arbeit) und verstehe jetzt wesentlich mehr.

Ich hatte schon geschrieben, dass das Datacamp Tutorial ein wesentliches Detail übersehen hat. Ich muss gestehen, dass ich das Tutorial nicht mehr viel benutzt habe.

In einer ersten Runde habe ich ausgehende vom Datacamp Tutorial unter Verwendung von derer Pyspark Cheatsheet und dem District Data Lab Tutorial einfach mal gespielt. Ich finde das ganze Konzept der ‚resilient distributed datasets‘  (RDD) interessant. In Prinzip baust Du einen ‚pipeline‘, wo Du durch Umwandlung und Filter zu Ergebnissen kommst.

Nachdem ich das etwas durchgekaut habe, habe ich angefangen, eine Anwendung zu schreiben, die meine Vergangenheit untersucht, oder eher die Rohdaten der Besucherstatistiken meiner Webseite auswertet. Das war so was wie eine Test von vielem, was ich in den letzten Monaten gemacht habe.

Ich war inspiriert durch einen Link im District Data Lab Tutorial auf eine Spark Reference Application. Die Referenzanwendung war dann nicht in Python, somit habe ich selber weitergesponnen.

Das erste Problem, dass ich hatte, war das gemischte Format meiner Logdateien. Mein Server hat etwas größere Logdateien ge-gzipped. Ich habe dann einen Generator geschrieben, die beide lesen kann. Für mich neu waren die zwei yield-Ausgänge, das hatte ich noch nie gemacht und ich wusste nicht, ob das geht, aber es geht. Die Funktion sieht so aus:

import gzip
from glob import glob

def yield_lines_from_directory(dir):
   files = glob('{}/*'.format(dir))
   for file in files:
      if file.endswith('.gz'):
         with gzip.open(file, mode='rt') as f:
            for line in f.readlines():
               yield line 
      else:
         with open(file, 'r') as f:
            for line in f.readlines():
               yield line

Ich habe dann entdeckt, dass die Logdateien ein Standardformat haben, dass hier beschrieben ist: https://httpd.apache.org/docs/1.3/logs.html. Mit diesen Informationen konnte ich die gelesene Zeilen interpretieren und in eine verwendbare Struktur verwandeln. Dabei sind 620967 – 620965 (=2) POST Requests auf der Strecke geblieben.

Jetzt bin ich so weit, dass ich einen Networkx Graph per Besucher male. Ich habe zwar über die Agent-Beschreibung Spiders und Bots ausgeschlossen, aber Yahoo oder Ask definieren sich anders. Das sieht dann nicht so übersichtlich aus.nx1

Das folgende Bild zeigt einen Besucher, der ein Mal auf der Webseite war, einmal über den Einstieg einer Suche und einmal über meine damals noch existente Wikispaces Seite.

nx2

Nicht immer ist so klar, was passiert ist. Beim nächsten Bild wäre zu überprüfen, was passiert ist. Ich weiß nicht, ob es hier drei komplett getrennte Besuche (0, 1, 2) gab oder ob es irgendwo anders holpert. Besuch 0 ist klar. Besuch 1, direkt auf meine famose error404.html Seite, was ist das? Und auch beim Besuch 2 gibt es so eine einsame error404. Dafür ist bei Besuch 2 klar zu verfolgen, welche Seiten nacheinander besucht wurden.

nx3

Ich will am Ende die Besuche auf eine Zeitachse abzubilden, aber das ist nicht so einfach, wenn es mehrere Besuche gibt. Es kann gut sein, dass Besuch 0 und Besuch 2 eine ganze Strecke auseinander liegen und dann nutzt eine lückenlose zeitliche Reihenfolge gar nichts.

.plt

 

 

Spark auf Windows

Um Spark auf Windows zum Laufen zu kriegen brauchte ich genau diese Unterstützung, die in diesem Linux-lastigen Tutorial gefehlt hat. Jetzt kann es los gehen mit Spark und Python.

Meilenstein

Pünktlich zum Abschluss meiner dreimonatlichen ‚Studienzeit‘ konnte ich den neuen DataCanp Track ‚Data Scientist with Python‘ abschließen. (Gleichzeitig habe ich die Tracks ‚Data Analyst with Python‘ und ‚Python Developer‘. abgeschlossen. Es fehlte einen Kurs für den 3 Tracks.).

Das macht schon zufrieden. Es ist immer noch so, dass ich nicht glaube, richtig große Aufgaben angehen zu können. Mein letztes Kaggle-Problem habe ich noch nicht in Griff; der Erste richtige Durchlauf habe ich vor 14 Stunden gestartet und lauft immer noch. Ich vermute, dass das sich über den Tag ziehen wird und das Ergebnis grausam sein wird. Aber ich habe viel gelernt 🙂 was ich nicht in DataCamp Kurse gelernt hätte.

Kaggle Wettbewerb: wann sind Fragen identisch?

Ich spiele jetzt mit einem neuen Kaggle Wettbewerb. Es geht darum, zwei Fragen, die  auf Quora gestellt wurden, mit einander zu vergleichen und dann zu entscheiden, ob es hier um die gleiche Frage geht.

Das ist spannend, es geht nicht nur um Zahlen sondern auch um die Verarbeitung von Sprache. Als Mr. Selfmademan arbeite ich mich jetzt durch Foren, Webseiten und dem Buch ‚Text Analytics with Python‚ und kriege ein vage Idee, wie ich das Problem lösen könnte. Die Idee ist so vage, dass ich noch keine Lösung eingestellt habe. (Auch ist mein Rechner nicht auf diese Datenmengen gebaut.)

Starten mit KERAS

Vor 6 Tage habe ich über ein  KERASTutorial  geschrieben. Inzwischen bin ich weiter mit dem Thema. Es läuft zumindest:

easy4

Hier einige Hinweise für Tutorials:

  1. Installationen sind immer eine Fummelei. Jeder bräuchte einen persönlichen Admin, der ihr/ihm diese Sorge abnimmt.
  2. DataCamp hat (zumindest demnächst, zum jetzigen Tag ist der Kurs noch in der Betatestphase) ein Deep Learning mit Python Kurs im Angebot. Das nette am Kurs ist, dass die erste Hälfte Hintergrundinformationen vermittelt, die zweite Hälfte dann die Grundlagen von KERAS vermittelt.
  3. KERAS hält viele Beispiele auf GitHub bereit. Aber passt auf: die Beispiele sind immer für die neueste  KERAS-Version gedacht und zumindest die Anaconda-Version für Python 3.5 auf Win64 ist NICHT die neueste Version. Dann muss man sich eben durch die Geschichte wühlen, dass ist das schöne an GitHub.
  4. Das erwähnte Tutorial auf EliteDataScience.com ist gut.
  5. Viel mehr Tutorials findest Du aber auf Machine Learning Mastery. (Zumindest habe ich da mehrere gefunden.)

[Edit] Das Skript ist wunderbar durchgelaufen mit den vorgegebenen Parameter, aber jetzt versuche ich eine Optimierung mit GridSearchCV und kann die Heizung wieder ausdrehen, sehe seit über eine halbe Stunde Folgendes (und kann dementsprechend berechnen, dass ich noch mindestens 1152 * 1/2 Stunde == 576 Stunden == 24 Tage warten muss, was ich wahrscheinlich nicht mach):

easy5

KERAS – easy, huh? :-)

Ich spiele gerade das KERASTutorial  von ‚Elite Datascience‘ durch. Das wirkt erst mal easy, obwohl ich noch längst nicht verstehe, was ich mach 🙂 Steht auch so beschrieben im Schritt 9:

easy1

So sieht es in meinem Jupyter aus, nach mindestens 10, gefühlt schon 20 Minuten:

easy2

Ich habe 10 Epochen definiert, dann werde ich jetzt erst mal kochen und was essen.

Ach ja, in Schritt 4 steht Folgendes 🙂

MNIST is a great dataset for getting started with deep learning and computer vision. It’s a big enough challenge to warrant neural networks, but it’s manageable on a single computer.

Update 1: lecker gegessen, aber am Rechner ist die Lage wie vor anderthalb Stunden.

Update 2: Wieder zwei Stunden später ohne wirkliche Verbesserung habe ich mich jetzt entschieden, diese Warnung ernst zu nehmen:

easy3

Ich habe cygwin installiert und Theano erkennt g++ aber findet noch nicht alle notwendige Headerdateien. Wahrscheinlich wird das heute nichts mehr. Stackoverflow meint übrigens, dass es meine eigene Schuld ist.

Update 3: inzwischen habe ich gelernt, dass ich mingw und nicht cygwin benutzen soll, dass Mingw selbstverständlich 64bits sein soll, wenn Python das ist UND dass ich die Datei .theanoc in mein Homeverzeichnis liegen haben soll und nichtirgendwo im Anacondabaum. Theano wird jetzt mit g++-Unterstützung importiert und … braucht immer noch lange. Seufz.

Kaggle 3: die harte Gangart

Nachdem ich einiges ausprobiert hab im Titanic Wettbewerb, versuch ich jetzt, in einem anderen Wettbewerb nach vorne zu kommen. Dabei stolpere ich jetzt knallhart über die Realität.

In diesem Wettbewerb gibt es sowohl numerische Daten als auch Text. Sklearn hat ein wunderbares Konzept um Daten auseinander zu ziehen und nachher wieder zusammenzufügen, sehr wiederverwendbar und clean, aber die Details sind dann doch schlecht vorhersehbar für ein Grünschnabel wie mir.
Das Konzept ist der Pipeline. Du definierst einmal, welche Schritte nacheinander durchgeführt werden und dann kann das Training und die tatsächliche Vorhersage nacheinander durchgeführt werden. Das geht auch, weil die verschiedene Werkzeuge im sklearn Werkzeugkasten alle die Methoden Methoden wie fit, transform und predict
haben.
Heute ging das aber schief – die Eingangsparameter und Ergebnisse sind doch nicht so verschaltbar wie ich es erwartet hatte.

So sieht es aus:

pl = Pipeline([
        ('union', FeatureUnion(
            transformer_list = [
                ('numeric_features', Pipeline([
                    ('selector', get_numeric_data),
                    ('imp', Imputer()),
                    ('scale', StandardScaler())
                ])),
                ('text_features', Pipeline([
                    ('selector', get_text_data),
                    ('vectorizer', CountVectorizer()),
                    ('dim_red', SelectKBest(chi2, 300))
                ]))
             ])
        ),
        ('clf', SVC(gamma=my_gamma, C=my_C, kernel=my_kernel, probability=True))
    ])

pl.fit(X_train, y_train)
y_val_pred = pl.predict_proba(X_val)

Die Probleme:

  • Der Unterpipeline 'numeric_features' arbeitet mit einem Pandas DataFrame, .während 'text_features' mit einem Pandas Series Struktur arbeitet.
  • 'text_features' liefert dann einen ’sparse matrix‘ Struktur zurück, wo nicht alle ('clf') Classifier mit umgehen können. Deswegen gerade den Resourcenfressenden Support Vector Machine, obwohl das Ergebnis wahrscheinlich suboptimal sein wird. Ich warte mal ab, was weiter passiert, das ganze läuft jetzt seit 2 Stunden, die Trainingsphase ist durch, jetzt ist das pl.fit für die aktuelle Vorhersage dran.

[Edit 1, 8. März:] Wenn man das problem richtig aussprechen kann, kann Google unterstützen bei der Lösungsfindung. Es gibt eine Bibliothek, mlxtend, die eine Funktion bereitstellt, um einen sparse matrix in einen dense matrix zu verwandeln. Das funktioniert, bringt aber meinen Rechner an den Grenzen seiner Speicherkapazitäten. Hier muss ich an der eine Seite vielleicht einige Dienste abschalten, an der andere Seite im Skript was machen.

Es hat sich aber (sei es minimal, aber ich bin noch nicht am Ende!) gelohnt:

climbing_the_ranks.3

[Edit 2, 8. März] Inzwischen bin ich sogar bei 0,60419 und habe ich einen ersten Durchlauf gestartet, wo ich auch die Beschreibung mitnehme, ein langes Freitextfeld. Ich hoffe, dass ich dann mit folgender Pipeline unter 0.6 komme:

 
pl = Pipeline([
        ('union', FeatureUnion(
            transformer_list = [
                ('numeric_features', Pipeline([
                    ('selector', get_numeric_data),
                    ('imp', Imputer()),
                    ('scale', StandardScaler())
                ])),
                ('text_feature1', Pipeline([
                    ('selector', get_text_data),
                    ('vectorizer', CountVectorizer()),
                    ('dim_red', SelectKBest(chi2, 100))
                ])),
                ('text_feature2', Pipeline([
                    ('selector', get_description),
                    ('vectorizer', vectorizer),
                    ('dim_red', SelectKBest(chi2, 100))
                ]))
             ])
        ),
        ('to_dense', DenseTransformer()),
        ('clf', GradientBoostingClassifier(n_estimators = 1000))
    ])
pl.fit(X_train, y_train)

Kaggle 2: climbing the ranks

Ich spiele erst mal in dem einfachsten Kaggle-Wettbewerb rum, die Aufgabe mit den Fischen ist für diese Woche zu hoch gegriffen. Ausgehende von der Lösung, die im DataCamp Kaggle Tutorial entwickelt werden, klettere ich jetzt mit einer SVM Lösung die Rangliste hoch. Mal sehen, was die Neuronale Netze bringen.

climbing_the_ranks

Nach wie vor bräuchte ich ein reales Projekt, aber so geht es auch.

(Dass die Rangliste mit 100% Scores angeführt wird, halte ich übrigens für unglaubwürdig, also entweder geschummelt oder aber reine Glückstreffer. )

Kaggle

Ich habe jetzt Kaggle entdeckt. Nachdem ich keinen Respons bekommen habe auf meinen Aufruf für ein Projekt, und März naht, werde ich mir da eine Spielwiese aussuchen.

Erst werde ich mal zu hoch greifen und versuchen, mir diesem Wettbewerb anzuschließen. Das scheint mir ein sehr sinnvolles Projekt. Ich habe nur gar keine Ahnung von Bilderkennung von Videomaterial. Gar nicht. Bilderkennung war noch Teil eines Kurses und eines Tutorials bei DataCamp, aber Video-Erkennung gab es gar nicht als Übung. (Eigentlich die gleiche Übung als Gesichter auf Überwachungskameras erkennen, sollte also schon längst vorhanden sein!)

Danach werde ich dann mit beiden Füßen auf die Erde zurückkehren und ein oder zwei Anfängerwettbewerbe durchackern.

An sich finde ich zumindest die Idee spannend, in ein Wettbewerb einzusteigen, damit ich meine Lösung auch mit der Lösung anderer vergleichen kann.

Fertig! (mit DataCamp Python Curriculum)

Ich bin durch mit dem DataCamp Python Curriculum. Zeit für Real Life Erfahrungen. Bald ist auch März, und das war die Planung für März. (Was fehlt ist Textmining.)status