Where Have All the Singletons Gone?

Schöne Serie von Artikel über die Verwendung von Singletons. Fast 10 Jahre alt, aber ich habe die Diskussionen nicht so verfolgt. Jetzt dachte ich aber einen Singleton zu brauchen 🙂

Quelle: Singletons are Pathological Liars

Quelle: Where Have All the Singletons Gone?

Quelle: Root Cause of Singletons

Thoughtful Machine Learning with Python

Mir gefällt das Buch ist ‚Thoughtful Machine Learning with Python‚ immer mehr.

Wie beschrieben, ist es das erste Buch, dass ich zu Python und Data Science in Händen kriege, dass auch Unittests behandelt.

Aber auch die Machine Learning Inhalte werden sehr sorgfältig behandelt. Das erste inhaltliche Kapitel (3) zu KNearestNeigbors habe ich jetzt ein mal gelesen und ein mal durchgearbeitet. Ich weiß immer noch nicht genau, was ein KDTree macht, aber weiter habe ich wohl noch Neues gelernt. Das folgende Kapitel (4) arbeite ich jetzt durch.

Die Codebeispiele im Repository für Kapitel 3 sind Python3-kompatibel, im Buch nicht ganz. Für Kapitel 4 muss man auch noch ein kleines Bisschen am Code aus dem Repository schrauben. Aber, hey, dafür testet man doch! Das sind dann die Übungen für die Streber 🙂

TDD und Data Science

Nachdem ich jetzt einige Python Data Science Bücher [u.A. 1, 2, 3, 4] und alle DataCamp Python Kurse durchgearbeitet habe, habe ich mich gefragt, warum immer nur in hack-style gearbeitet und das sogar als Heldentat verbucht wird. Also habe ich gesucht.

Und ich habe was gefunden! Es gibt ein Buch, dass sich mit Python, TDD und Machine Learning beschäftigt. Schön dünn ist es eine Einführung in Machine Learning unter Anwendung von Tests. Unit Tests in Test First Approach, neben den öfters angewendeten Cross Validations und visuellen Tests.

Das Buch ist ‚Thoughtful Machine Learning with Python‚, von Matthew Kirk. (Es gibt eine Rezension, die besagt, dass der Code nicht mit Python 3 funktioniert. Wie immer: man hat ein eigenes Hirn dabei, man kann es auch benutzen.)

Jetzt brauch ich ’nur‘ noch Disziplin, um wirklich Test First zu arbeiten, weil hack-style mir nicht fremd ist.

‚Schlechtes‘ Buch das mich sehr genutzt hat.

Diese Amazon-Rezension zu ‚Spark for Python Developers‚ habe ich erst gelesen, als ich das Buch schon bestellt habe. Die Rezension ist trotz drei Sterne abschreckend, trifft völlig zu oder ist eher noch untertrieben und trotzdem fand ich das Buch extrem nützlich. Ich liebe es, so zu sagen :-), gerade in seiner Unvollkommenheit.

Das Fazit zuerst: wer gerne nach Rezept kocht, wird dieses Buch nicht mögen. Wer improvisiertes Kochen aus eine gut gefüllte Vorratskammer schätzt, wird seien Freude haben.

Die einzelne Kritikpunkte von Rezensent TDL:

First, the code as presented (at least in the ebook) is in serious need of formatting

Nicht nur im eBook, kann ich ergänzen. Auch im Buch. Und auch in den ‚Quelltexten‘, die von der Webseite verfügbar sind. Es heißt zwar ‚Quelltext‘, ist aber eine Kopie vom IPython notebook, inklusive Ausgaben, Nummerierung, Zwischentexte etc, dazu noch durcheinander nummeriert. Das bedeutet, das Copy and Paste nicht funktioniert. Das ist blöd,aber da ich faul bin, hat es den Lerneffekt zienlich erhöht.

Second, it is not clear that this book was well edited.

Ich würde sagen, dass es klar ist, dass der Lektor geschlafen hat. Oder aber gar nicht eingeschaltet wurde, um das Buch schnell am Markt zu kriegen.

Why isn't the code available online? Github & Bitbucket both have free public repos.

Die Frage habe ich eigentlich schon beantwortet: es gibt keinen Code, beim Autor gab es nur ein Notebook. Und das ist verfügbar beim Verlag. Und vielleicht ist es Verlagspolitik.

Andere Rezensenten hatten andere Probleme:

The author skims over important details in setting up the environments he describes

oder auch

dreadfully confusing

Man muss sich schon selber auf den Weg machen, die Onlinehilfen zu Hilfe rufen, vielleicht StackOverflow. Aber es lohnt sich. (Es hat sich für mich gelohnt.)

Very little of the first few chapters actually deal with Spark, except for some brief examples that are not explained in detail.

Es gibt eine Riesenlatte an Tools, die in den ersten Kapitteln installiert werden. Alle drei bis vier Seiten eine neue Installation. Da bleibt wenig Platz für Spark. Wer nur etwas zu Spark/ Pyspark wissen will, sollte sich ein anderes Buch suchen. Für mich war es ausgesprochen nützlich, Spark in seinem Kontext kennen zu lernen, überlegungen zu der Wahl zwischen MongoDB und Cassandra mitzukriegen, mit Kafka zu spielen.

Wichtig ist noch, dass das Buch auf Python 2.7 aufsetzt (meistens).

Inherentes Apache Spark Problem

Ich versuche gerade ein interessantes Problem zu lösen. Hier und hier habe ich beschrieben, wie ich den Performance von Spark und Pandas vergleichen will auf die Daten vom Kaggle Quora Wettbewerb.

Dabei stoße ich auf ein interessantes Phänomen. Solange der Zugriff zeilenweise stattfindet, ist Spark OK. Jetzt will ich aber das Maximum einer Spalte berechnen. Das geht erstaunlich schlecht. Ich vermute, dass das mit der verteilte Struktur von Spark zu tun hat, würde es aber gerne verstehen wollen.

Meine Frage nach dem ‚Warum‘ auf Stack Overflow wurde beantwortet mit ‚benutze Spark nur, wenn es absolut notwendig ist, nimm ansonsten Pandas‘. Obwohl das auch meine Schlussfolgerung ist, ist es keine Antwort.

Es gibt verschiedene Arten, das Maximum zu suchen. Alle brauchen mehr als 20 Minuten. Wenn Du diesen Code siehst, verstehst Du, wie merkwürdig das ist.

df.createOrReplaceTempView("kaggle")
biggest = spark.sql("SELECT MAX(levenshtein) FROM kaggle")
biggest.collect()

Das Maximum aus 400.000 Einträgen zu suchen, dauert bei einem Datenbankzugriff keine Sekunde. Und hier 25 Minuten. Es gibt noch mehr Lösungen auf StackOverflow und bei Databricks. Alles Banane. Irgendwann wird die Antwort kommen.

[Edit: 2. Mai] Das Problem saß mal wieder vor dem Bildschirm. Aber schon seit Tage 😦

Es eht um ein inherentes Apache Spark Feature: Lazy Evaluation. Ich habe das Ausmaß des Laziness unterschätzt. Ich hatte gedacht, dass ich die Berechnung der levenshtein-Spalte schon erzwungen hatte, aber dem war nicht so. Also werden jetzt alle Werte berechnet, bevor das MAX geholt werden kann. Also

  1. Dauert die Berechnung des Maximums nicht so lange und
  2. War meine Freude, dass die zeilenweise Berechnungen so flott durchliefen, nicht so angebracht. Die liefen schön flott noch nicht durch.

Inzwischen habe ich aber die Accumulator und AccumulatorParam Klassen kennengelernt, dass ist auch was schönes 🙂

[Edit2: 2. Mai] Trotzdem sollte man den Accumulator benutzen. Ansonsten wird die ganze Berechnung noch mal wiederholt, wenn man den Codeblock oben aufruft.

# create the accumulator to capture the maximum levnshtein
from pyspark.accumulators import AccumulatorParam

class MaxAccumulatorParam(AccumulatorParam):
    def zero(self, value):
        return 0
    def addInPlace(self, val1, val2):
        # this method defines what happens with 
        # the value sent to the accumulator
        return max(val1, val2)
    
# create an Accumulator object
max_levenshtein = sc.accumulator(0,MaxAccumulatorParam())

from nltk.metrics import edit_distance

def levenshtein(question1, question2):
    result = edit_distance(question1, question2)
    global max_levenshtein
    # the following call calls the addInPlace method
    # from the MaxAccumulatorParam object
    max_levenshtein += result
    return result

# and create the pyspark.sql.UserDefinedFunction
from pyspark.sql.functions import udf
from pyspark.sql.types import IntegerType
udf_levenshtein = udf(levenshtein, IntegerType())

 

Gestern war ein schöner Tag

Gestern war ein schöner Tag, weil ich den ganzen Tag erfolgreich mit Sparks’s RDDs experimentiert hatte. Leider habe ich dann gestern Abend spät festgestellt, dass die Zukunft den DataSets (und DataFrames) gehört und nicht den RDDs 😦

Damit war ich heute noch nicht so erfolgreich. Ich hänge auf eine User Defined Function, wobei ich die Fehlermeldung in der Console kenne – ich arbeite wieder mit den Kaggle Quora Daten.

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.)