Man kann viel über Data Analysis und Machine Learning lesen. Um wirklich zu verstehen, wie es funktioniert und wo die Probleme sind, muss man selbst Hand anlegen. Genau das war eines der Ziele, die wir mit dem DataLab erreichen wollten.
Leider ist es gar nicht so einfach einen Anwendungsfall zu finden, für den genügend frei verfügbare Daten vorhanden sind, der interessant genug ist, um Spaß bei der Arbeit zu haben und der nicht schon von 100 anderen durchgerechnet und damit langweilig ist.
Nach Brainstorming, Mails, Chats, Hangouts und einigem Hin-und-Her konnten wir uns auf eine Idee einigen:
Wir wollen vorhersagen, wer im Sommer die Fußball-Weltmeisterschaft gewinnt!
Zugegeben, die Idee ist nicht sehr originell. Tatsächlich gibt es eine ganze Menge Webseiten, die sich mit der Vorhersage von Sportereignissen beschäftigen (z.B. dataminingsoccer.com ). Aber davon ließen wir uns nicht aufhalten. Wir sind alle begeisterte Fußball-Fans und es macht einfach mehr Spaß in den Daten vergangener Weltmeisterschaften zu wühlen, als die Länge und Breite von Schwertlilien zu untersuchen. Außerdem beschäftigen sich die meisten Online-Vorhersagen eher mit nationalen Ligen als mit internationalen Turnieren. Es besteht also noch die Möglichkeit, etwas Neues zu entdecken.
Der Weg ist das Ziel
Doch ohne konkretes Ziel findet man den Weg eher schlecht. Der erste Schritt war also, aus der eher vagen Idee „Lasst uns die WM vorhersagen“ konkrete Ziele abzuleiten. Dabei wurde recht bald klar, dass die Vorhersage des Weltmeisters eher einem Raten gleichkommt. Wesentlich aussagekräftigere Ergebnisse sind dagegen zu erwarten, wenn man sich nur einzelne Partien vornimmt. Damit war das erste Ziel gefunden:
Aus den Daten vergangener Länderspiele soll das Ergebnis eines beliebigen zukünftigen Länderspiels vorhergesagt werden.
Mit „Ergebnis“ ist dabei im einfachsten Fall nur „Heimsieg“, „Unentschieden“ oder „Auwärtssieg“ gemeint. Bei den „Daten vergangener Länderspiele“ waren wir nicht wählerisch. Am interessantesten war natürlich immer der Ausgang der Spiele (also z.B. geschossene Tore oder Tordifferenz).
Daten sammeln
In guter Big-Data-Manier war unser Ansatz sehr simpel: Einfach alles sammeln, was wir kriegen können. Datenformat egal. Quelle egal (solange legal). Alles ist erlaubt, was nicht verboten ist. Hauptsache, wir haben Daten mit denen wir arbeiten können. Um das Säubern der Daten können wir uns später kümmern.
Als gute Datenquelle hat sich (wieder einmal) Wikipedia herausgestellt. Auch wenn es etwas aufwendig ist, die Spielergebnisse aus dem HTML zu extrahieren. Unter www.rsssf.com findet man auch vorgefertigte Datensätze für Länderspiele. Allerdings ist die Seite etwas unübersichtlich. Eine sehr gute und sehr saubere Quelle sind auch verschiedene Anbieter von Sportwetten. Einziger Nachteil: Der Zugriff auf die REST-Schnittstellen ist nicht ganz billig. Letztendlich hat jeder von uns gesammelt, was er für sinnvoll hielt. Es waren sogar einige Buchmacherquoten dabei.
Die gesammelten Daten sowie unseren R, Python, Groovy und Java-Code gibt es wie immer frei zugänglich in einem GitHub-Repository: Soccer 2014 .
Daten zusammenführen und säubern
Ohne besondere Absprache war das Format der Daten schon in allen Fällen CSV. Aber CSV ist nicht gleich CSV. Die Spaltennamen waren unterschiedlich (teils englisch, teils deutsch). Die Formate (v.a. Datumsformate) waren unterschiedlich. Um daraus eine gemeinsame saubere Datenbasis zu generieren, gingen wir wie folgt vor:
Unterschiedliche Datumsformate
Das war noch das einfachste Problem. Die R-Funktionen strptime und format leisten hier gute Dienste.
1# Eingabeformat z.B. 21.11.1999 2INPUTFORMAT <- "%d.%m.%Y" 3# Ausgabeformat z.B. 1999-11-21 4OUTPUTFORMAT <- "%Y-%m-%d" 5 6data <- read.csv2("input.csv") 7data$date <- format(strptime(data$date, format=INPUTFORMAT), format=OUTPUTFORMAT) 8write.csv2(data, "output.csv")
Unterschiedliche Teamnamen
Ländernamen sind eindeutig. Möchte man meinen. Doch Ländernamen können deutsch oder englisch sein. Um nun die Ergebnisse aus unterschiedlichen Datenquellen zusammenzuführen, verwendeten wir ISO-Ländercodes. Die Vorteile liegen auf der Hand: Für alle benötigten Sprachen gibt es Tabellen, die Ländernamen auf ISO-Codes abbilden. Die ISO-Codes sind einheitlich. Außerdem wirken die Daten mit ISO-Codes aufgeräumter und übersichtlicher. Durch die Umwandlung in ISO-Codes kamen auch einige Rechtschreibfehler zum Vorschein, die auch schnell behoben werden konnten.
1# CSV-Datei mit Ländernamen (erste Spalte) und ISO-Codes (zweite Spalte) 2iso_code_data <- read.csv2("iso-codes.csv") 3 4# Lookup-Tabelle für Zuordnung Ländername -> ISO-Code 5iso_codes_by_country <- iso_code_data[,1] 6names(iso_codes_by_country) <- iso_code_data[,2] 7 8data <- read.csv("data.csv") 9data$team_a <- sapply(data$team_a, function(country) { 10 return(iso_codes_by_country[as.character(country)]) 11})
Widersprüchliche Daten
Natürlich gab es Unstimmigkeiten in den Daten. Nachdem alle Quellen auf ein einheitliches Format gebracht wurden, war es auch nicht schwer, diese Unstimmigkeiten zu finden (das R-Kommando merge leistet hier wertvolle Dienste). Bei Nachforschungen kamen auch recht interessante Fakten heraus: So gab es im Laufe der Geschichte Spiele, die aus unterschiedlichen Gründen abgesagt oder abgebrochen wurden. Unter anderem fand das Spiel Spanien-UdSSR im Jahr 1960 niemals statt. Franco verweigerte der Mannschaft der UdSSR die Einreise nach Spanien. Das Spiel wurde als Sieg für die UdSSR gewertet und die UdSSR wurde anschließend Europameister.
Das Zusammenführen, Vereinheitlichen, Bereinigen und Auflösen von Konflikten übernimmt ein kleines Python-Skript . Das Ergebnis ist ein Datensatz mit 6487 Spielen verteilt über die Zeit von Juli 1930 bis Januar 2014. Davon 3276 Heimsiege, 1864 Auswärtssiege und 1347 Unentschieden. Einen ersten Eindruck der Daten geben auch die folgenden Histogramme:
Automatisierung
Daten sind nicht statisch. Nach der WM ist vor der WM. Neue Länderspiele können in die Analyse mit aufgenommen werden. Der Wiki-Analyse-Job kann jederzeit verbessert und neu angestoßen werden. Auch die Skripte zur Datensäuberung werden stetig weiterentwickelt. Deshalb ist es nötig, so viel wie möglich zu automatisieren. Im Idealfall ist nach jeder Änderung nur ein Knopfdruck nötig, um die ganze Pipeline von Datensäuberung, Datenzusammenführung, Feature-Extraktion, Training und Validierung anzustoßen.
Da wir im Laufe des Projekts viele verschiedene Programmiersprachen und Tools eingesetz haben (curl, wget, python, groovy, R, …) entschieden wir uns für einen pragmatischen Ansatz: Good old Makefiles. Die Verwendung dieser Makefiles, sowie die Ausgabe eines Beispieldurchlaufs, finden sich im GitHub-Repository Soccer-Prediction-2014 .
Fazit
Ich kann nun verstehen, warum bei Data Analysis Projekten oft davon die Rede ist, dass die Vorbereitung der Daten wesentlich aufwändiger ist, als die eigentliche Analyse. Wir mussten eine Menge Arbeit investieren um an Daten zu kommen und die Daten zu säubern. Nachdem das geschafft war, kam der interessante Teil: Die Berechnung von sinnvollen Features, die Bewertung dieser Features und letztendlich das Trainieren eines Modells und die Vorhersage des Fußball-Weltmeisters 2014. Das sind auch die Themen für die kommenden Blog-Posts. Stay tuned…
Weitere Artikel der Data Analytics Serie
Teil 1 – Daten sammeln und bereinigen
Teil 2 – Ist Deutschland eine Turniermannschaft?
Teil 3 – Feature Engineering
Teil 4 – Feature Selection
Teil 5 – Logistische Regression und Random Forest
Teil 6 – Die Heimspielproblematik und Vorhersagen für die KO-Runde
Weitere Beiträge
von Michael Lex
Dein Job bei codecentric?
Jobs
Agile Developer und Consultant (w/d/m)
Alle Standorte
Gemeinsam bessere Projekte umsetzen.
Wir helfen deinem Unternehmen.
Du stehst vor einer großen IT-Herausforderung? Wir sorgen für eine maßgeschneiderte Unterstützung. Informiere dich jetzt.
Hilf uns, noch besser zu werden.
Wir sind immer auf der Suche nach neuen Talenten. Auch für dich ist die passende Stelle dabei.
Blog-Autor*in
Michael Lex
Du hast noch Fragen zu diesem Thema? Dann sprich mich einfach an.
Du hast noch Fragen zu diesem Thema? Dann sprich mich einfach an.