Praxiseinstieg Machine Learning mit Scikit-Learn, Keras und TensorFlow. Aurélien Géron
Abbildung 2-15: Diese Scatterplot-Matrix zeigt jedes numerische Attribut gegen jedes andere numerische Attribut und dazu ein Histogramm.
Das am meisten Erfolg versprechende Merkmal zur Vorhersage des mittleren Immobilienwerts ist das mittlere Einkommen. Daher zoomen wir in den entsprechenden Scatterplot hinein (siehe Abbildung 2-16):
housing.plot(kind="scatter", x="median_income", y="median_house_value",
alpha=0.1)
Abbildung 2-16: Mittleres Einkommen gegen mittleren Immobilienwert
Dieses Diagramm verdeutlicht einige Dinge. Erstens ist die Korrelation in der Tat recht stark; Sie können den Trend nach oben klar sehen, und die Punkte sind nicht allzu verstreut. Zweitens erkennen wir die weiter oben beobachtete obere Preisbegrenzung deutlich als horizontale Linie bei 500.000 USD. Das Diagramm zeigt aber auch weniger offensichtliche gerade Linien: eine horizontale Linie bei etwa 450.000 USD und eine zweite bei 350.000 USD, eventuell auch eine bei 280.000 USD und darunter noch weitere. Möglicherweise sollten Sie versuchen, die entsprechenden Bezirke aus dem Datensatz zu entfernen, um zu verhindern, dass Ihre Algorithmen diese Artefakte im Datensatz reproduzieren.
Experimentieren mit Kombinationen von Merkmalen
Hoffentlich hat Ihnen der vorige Abschnitt einige Ideen geliefert, mit denen Sie die Daten erkunden und Erkenntnisse gewinnen können. Sie haben ein paar Artefakte identifiziert, die Sie eventuell entfernen sollten, bevor Sie die Daten in einen Machine-Learning-Algorithmus einspeisen. Sie haben auch einige interessante Korrelationen entdeckt, insbesondere mit der Zielgröße. Sie haben außerdem bemerkt, dass einige Merkmale eine rechtsschiefe Verteilung aufweisen. Daher kann es nötig sein, diese zu transformieren (z.B. durch Logarithmieren). Natürlich unterscheidet sich der nötige Aufwand von Projekt zu Projekt beträchtlich, aber die Grundideen sind die gleichen.
Bevor Sie die Daten für Machine-Learning-Algorithmen vorbereiten, sollten wir als letzten Punkt noch einige Kombinationen von Merkmalen ausprobieren. Beispielsweise ist die Anzahl der Räume in einem Distrikt nicht besonders aussagekräftig, wenn Sie nicht wissen, wie viele Haushalte es dort gibt. Was Sie wirklich benötigen, ist die Anzahl der Räume pro Haushalt. In ähnlicher Weise ist die Gesamtzahl der Schlafzimmer nicht sehr nützlich, Sie sollten diese mit der Anzahl der Zimmer vergleichen. Auch die Bewohner pro Haushalt könnten eine interessante Kombination von Merkmalen hergeben. Erstellen wir diese neuen Merkmale:
housing["rooms_per_household"] = housing["total_rooms"]/housing["households"]
housing["bedrooms_per_room"] = housing["total_bedrooms"]/housing["total_rooms"]
housing["population_per_household"]=housing["population"]/housing["households"]
Nun betrachten wir die Korrelationsmatrix erneut:
>>> corr_matrix = housing.corr()
>>> corr_matrix["median_house_value"].sort_values(ascending=False)
median_house_value 1.000000
median_income 0.687160
rooms_per_household 0.146285
total_rooms 0.135097
housing_median_age 0.114110
households 0.064506
total_bedrooms 0.047689
population_per_household -0.021985
population -0.026920
longitude -0.047432
latitude -0.142724
bedrooms_per_room -0.259984
Name: median_house_value, dtype: float64
Nicht schlecht! Das neue Merkmal bedrooms_per_room korreliert wesentlich stärker mit dem mittleren Immobilienwert als die Anzahl der Zimmer oder Schlafzimmer. Anscheinend sind Häuser mit einem niedrigeren Verhältnis von Schlafzimmern zu Zimmern teurer. Die Anzahl Räume pro Haushalt ist ebenfalls aufschlussreicher als die Gesamtzahl Räume in einem Bezirk – natürlich sind Häuser umso teurer, je größer sie sind.
Dieser Teil der Untersuchung muss nicht extrem gründlich sein; es geht darum, an der richtigen Stelle zu beginnen und schnell einige Erkenntnisse zu sammeln, die für einen halbwegs guten Prototyp ausreichen. Der Prozess ist insgesamt iterativ: Sobald Ihr Prototyp läuft, können Sie dessen Ausgabe untersuchen, weitere Erkenntnisse daraus ziehen und zur Erkundung zurückkehren.
Bereite die Daten für Machine-Learning-Algorithmen vor
Es ist an der Zeit, die Daten für Ihre Machine-Learning-Algorithmen vorzubereiten. Es gibt mehrere gute Gründe, dafür Funktionen zu schreiben, anstatt es manuell zu probieren:
Sie können die entsprechenden Transformationen leicht auf beliebigen Datensätzen reproduzieren (z.B. auf dem nächsten frischen Datensatz, den Sie bekommen).
Sie bauen nach und nach eine Bibliothek von Transformationsfunktionen auf, die Sie in zukünftigen Projekten nutzen können.
Sie können diese Funktionen in Ihrer Produktionsumgebung nutzen, um neue Daten vor der Eingabe in Ihre Algorithmen zu transformieren.
Dadurch können Sie unterschiedliche Transformationen leichter ausprobieren und prüfen, welche Kombinationen am besten funktionieren.
Aber kehren wir zunächst zu einem sauberen Trainingsdatensatz zurück (indem wir strat_train_set noch einmal kopieren) und trennen wir die Merkmale und Labels voneinander. Wir möchten nämlich nicht unbedingt die gleichen Transformationen auf die Merkmale zur Vorhersage und die Zielwerte anwenden (beachten Sie, dass drop() eine Kopie der Daten erzeugt und strat_train_set nicht verändert):
housing = strat_train_set.drop("median_house_value", axis=1)
housing_labels = strat_train_set["median_house_value"].copy()
Aufbereiten der Daten
Die meisten Machine-Learning-Algorithmen können mit fehlenden Merkmalen nicht umgehen. Deshalb werden wir einige Funktionen schreiben, die sich darum kümmern. Sie haben bereits bemerkt, dass beim Attribut total_bedrooms einige Werte fehlen. Um diesen Umstand zu beheben, haben Sie drei Möglichkeiten:
1 die entsprechenden Bezirke entfernen
2 das Merkmal komplett verwerfen
3 die Werte auf einen bestimmten Wert setzen (null, den Median o.Ä.)
Sie können alle drei leicht mit den Methoden dropna(), drop() und fillna() eines DataFrames umsetzen:
housing.dropna(subset=["total_bedrooms"]) # Option 1
housing.drop("total_bedrooms", axis=1) # Option 2
median = housing["total_bedrooms"].median() # Option 3
housing["total_bedrooms"].fillna(median, inplace=True)
Wenn Sie sich für die dritte Möglichkeit entscheiden, sollten Sie den Median des Trainingsdatensatzes berechnen und die fehlenden Werte mit diesem auffüllen. Sie sollten aber auch daran denken, den berechneten Wert zu sichern. Sie werden ihn später benötigen, um fehlende Werte im Testdatensatz zu ersetzen, wenn Sie Ihr System