Zeichenfolgen als Merkmale im Entscheidungsbaum / zufälligen Wald


64

Ich mache einige Probleme bei der Anwendung von Decision Tree / Random Forest. Ich versuche, ein Problem zu lösen, bei dem sowohl Zahlen als auch Zeichenfolgen (z. B. der Name des Landes) als Merkmale verwendet werden. Jetzt nimmt die Bibliothek, scikit-learn, nur Zahlen als Parameter, aber ich möchte die Zeichenfolgen einschleusen, da sie eine erhebliche Menge an Wissen enthalten.

Wie gehe ich mit einem solchen Szenario um?

Ich kann einen String durch einen Mechanismus wie das Hashing in Python in Zahlen umwandeln. Ich würde aber gerne wissen, wie Zeichenfolgen in Entscheidungsbaumproblemen am besten gehandhabt werden.


Im Falle von sckitlearn habe ich gesehen, dass wir die kategorialen Variablen codieren müssen, sonst würde die Methode fit den Fehler ValueError auslösen: String konnte nicht in float konvertiert werden
Kar

Antworten:


56

In den meisten etablierten maschinellen Lernsystemen werden kategoriale Variablen auf natürliche Weise behandelt. In R würden Sie beispielsweise Faktoren verwenden, in WEKA würden Sie nominelle Variablen verwenden. Dies ist beim Scikit-Lernen nicht der Fall. Die in scikit-learn implementierten Entscheidungsbäume verwenden nur numerische Merkmale und diese Merkmale werden immer als kontinuierliche numerische Variablen interpretiert .

Das einfache Ersetzen der Zeichenfolgen durch einen Hash-Code sollte daher vermieden werden, da jede Codierung, die Sie verwenden, als fortlaufendes numerisches Merkmal eine Reihenfolge hervorruft, die in Ihren Daten einfach nicht vorhanden ist.

Ein Beispiel ist, ['rot', 'grün', 'blau'] mit [1,2,3] zu codieren, was seltsame Dinge hervorbringt, wie 'rot' ist niedriger als 'blau', und wenn Sie einen Durchschnittswert von 'rot' haben und ein "blau" erhalten Sie ein "grün". Ein weiteres subtileres Beispiel könnte auftreten, wenn Sie ['niedrig', 'mittel', 'hoch'] mit [1,2,3] codieren. Im letzteren Fall kann es vorkommen, dass es eine sinnvolle Reihenfolge gibt. Es kann jedoch zu subtilen Inkonsistenzen kommen, wenn „mittel“ nicht zwischen „niedrig“ und „hoch“ liegt.

Schließlich besteht die Antwort auf Ihre Frage darin, das kategoriale Merkmal in mehrere binäre Merkmale zu codieren . Beispielsweise könnten Sie ['rot', 'grün', 'blau'] mit 3 Spalten codieren, eine für jede Kategorie, wobei die Kategorie mit 1 übereinstimmt und die andere mit 0. Dies wird One-Hot-Codierung , Binärcodierung, One-of-K-Codierung oder was auch immer genannt. In der Dokumentation finden Sie Informationen zum Codieren kategorialer Features und zum Extrahieren von Features - Hashing und Dicts . Offensichtlich erweitert One-Hot-Encoding Ihren Platzbedarf und beeinträchtigt manchmal auch die Leistung.


2
Es ist die Scikit-Implementierung, die kategoriale Variablen nicht richtig verarbeitet. Eine Neukodierung, wie sie in dieser Antwort vorgeschlagen wird, ist wahrscheinlich das Beste, was Sie tun können. Ernsthaftere Benutzer suchen möglicherweise nach alternativen Paketen.
SmallChess

3
Man kann sklearn.preprocessing.LabelBinarizer für die One-Hot-Codierung von kategorialen Variablen verwenden.
GuSuku

@rapaio Ich denke, binäre Codierung ist nicht gleich eine heiße Codierung. Bei der binären Codierung werden 8 Kategorien mit 3 Spalten oder 9 bis 16 Kategorien mit 4 Spalten usw. dargestellt. Liege ich falsch?
Alok Nayak

Das Patsy-Python-Paket behandelt die One-Hot-Codierung von kategorialen Variablen. patsy.readthedocs.io/en/latest/quickstart.html
zhespelt

5
Verwenden Sie nicht LabelBinarizer, sondern sklearn.preprocessing.OneHotEncoder . Wenn Sie Ihre Daten mit Pandas importieren und vorverarbeiten , können Sie dies auch direkt mit pandas.get_dummies tun . Es ist schade, dass scikit-learn keine kategorialen Variablen unterstützt.
Ricardo Cruz

11

Sie müssen Ihre Zeichenfolgen als numerische Features codieren, die sci-kit für die ML-Algorithmen verwenden kann. Diese Funktionalität wird im Vorverarbeitungsmodul behandelt (siehe z. B. sklearn.preprocessing.LabelEncoder für ein Beispiel).


3
rapaio erklärt in seiner Antwort , warum dies ein falsches Ergebnis erhalten würde
Keith

7

Normalerweise sollten Sie kategoriale Variablen für Scikit-Learn-Modelle, einschließlich zufälliger Gesamtstrukturen, einmalig codieren . Zufällige Gesamtstrukturen funktionieren häufig ohne One-Hot-Codierung, erzielen jedoch normalerweise eine bessere Leistung, wenn Sie One-Hot-Codierungen durchführen. One-Hot-Codierung und "Dummying" -Variablen bedeuten in diesem Zusammenhang dasselbe. Scikit-learn hat sklearn.preprocessing.OneHotEncoder und Pandas hat pandas.get_dummies , um dies zu erreichen.

Es gibt jedoch Alternativen. Der Artikel "Beyond One-Hot" bei KDnuggets liefert eine hervorragende Erklärung, warum Sie kategoriale Variablen und Alternativen zur One-Hot-Codierung codieren müssen.

Es gibt alternative Implementierungen von Zufallsgesamtstrukturen, die keine One-Hot-Codierung erfordern, z. B. R oder H2O. Die Implementierung in R ist rechenintensiv und funktioniert nicht, wenn Ihre Features viele Kategorien haben . H2O funktioniert mit einer großen Anzahl von Kategorien. Continuum hat H2O in Anaconda Python verfügbar gemacht.

Es wird ständig versucht, dass Scikit-Learn direkt mit kategorialen Funktionen umgeht .

Dieser Artikel enthält eine Erläuterung des in H2O verwendeten Algorithmus. Es verweist auf die wissenschaftliche Arbeit A Streaming Parallel Decision Tree Algorithm und eine längere Version derselben Arbeit.


5

2018 Update!

Sie können einen Einbettungsraum (dichten Vektorraum) für Ihre kategorialen Variablen erstellen. Viele von Ihnen sind mit word2vec und fastext vertraut, die Wörter in einen aussagekräftigen, dichten Vektorraum einbetten. Dieselbe Idee hier - Ihre kategorialen Variablen werden einem Vektor mit einer gewissen Bedeutung zugeordnet.

Aus dem Guo / Berkhahn-Papier :

Entity-Einbettung reduziert nicht nur die Speichernutzung und beschleunigt neuronale Netze im Vergleich zur One-Hot-Codierung, sondern enthüllt vor allem die intrinsischen Eigenschaften der kategorialen Variablen, indem sie ähnliche Werte nahe beieinander im Einbettungsraum abbilden. Wir haben es kürzlich bei einem Kaggle-Wettbewerb erfolgreich eingesetzt und konnten mit relativ einfachen Features den dritten Platz erreichen.

Die Autoren stellten fest, dass die Darstellung kategorialer Variablen auf diese Weise die Wirksamkeit aller getesteten Algorithmen für maschinelles Lernen, einschließlich der Zufallsgesamtstruktur, verbesserte.

Das beste Beispiel könnte die Anwendung der Technik von Pinterest sein, um verwandte Pins zu gruppieren:

Bildbeschreibung hier eingeben

Die Leute bei fastai haben kategorische Einbettungen implementiert und einen sehr schönen Blog-Beitrag mit begleitendem Demo-Notizbuch erstellt .

Zusätzliche Details und Erläuterungen

Ein neuronales Netz wird verwendet, um die Einbettungen zu erstellen, dh jedem kategorialen Wert einen Vektor zuzuweisen. Sobald Sie die Vektoren haben, können Sie sie in jedem Modell verwenden, das numerische Werte akzeptiert. Jede Vektorkomponente wird zu einer Eingangsvariablen. Wenn Sie beispielsweise 3-D-Vektoren zum Einbetten Ihrer kategorialen Farbliste verwenden, erhalten Sie möglicherweise Folgendes: Rot = (0, 1,5, -2,3), Blau = (1, 1, 0) usw. Sie würden drei verwenden Eingabevariablen in Ihrer zufälligen Gesamtstruktur, die den drei Komponenten entsprechen. Für rote Dinge ist c1 = 0, c2 = 1,5 und c3 = -2,3. Für blaue Dinge ist c1 = 1, c2 = 1 und c3 = 0.

Sie nicht wirklich brauchen ein neuronales Netzwerk verwenden Einbettungen zu erstellen (obwohl ich nicht empfehlen shying von der Technik entfernt). Es steht Ihnen frei, Ihre eigenen Einbettungen von Hand oder auf andere Weise zu erstellen, wenn dies möglich ist. Einige Beispiele:

  1. Ordnen Sie Farben RGB-Vektoren zu.
  2. Ordnen Sie Standorte Lat / Long-Vektoren zu.
  3. Ordnen Sie in einem politischen Modell der USA Städte einigen Vektorkomponenten zu, die Links- / Rechtsausrichtung, Steuerbelastung usw. darstellen.

OK, cool, aber es sei denn, ich habe etwas verpasst. Wie erstellen wir eine Einbettung und übergeben diese Einbettung dann an einen Forrest? Ich nehme an, Sie müssen ein ganzes Netz mit allen Funktionen trainieren und dann die ersten Schichten nehmen und diese als Eingabefunktion für Ihren Forrest verwenden. Es ist nicht klar, wie dies geschehen würde.
Keith

@Keith Mit einem neuronalen Netz werden die Einbettungen erstellt, dh jedem kategorialen Wert wird ein Vektor zugewiesen. Sobald Sie die Vektoren haben, können Sie sie in jedem Modell verwenden, das numerische Werte akzeptiert. Jede Vektorkomponente wird zu einer Eingangsvariablen. Wenn Sie beispielsweise 3D-Vektoren zum Einbetten Ihrer kategorialen Farbliste verwenden, erhalten Sie möglicherweise Folgendes: Rot = (0, 1.5, -2.3), Blau = (1, 1, 0)usw. Sie würden drei Eingabevariablen in Ihrer zufälligen Gesamtstruktur verwenden, die den drei Komponenten entsprechen. Für rote Dinge ist c1 = 0, c2 = 1,5 und c3 = -2,3. Für blaue Dinge ist c1 = 1, c2 = 1 und c3 = 0.
Pete

Ich verstehe das Konzept total, da es ziemlich einfach ist. Ich meine, wie würde das in der Implementierung gemacht werden? Das fast.ai-Demo-Notizbuch, das Sie verknüpfen, hat am Ende etwas mit einem RandomForestRegressor zu tun, aber ich sehe nicht wirklich, wie sich dies in den Einbettungen auswirkt.
Keith

Ich denke, dies ist ein gutes Beispiel für Code in Keras github.com/entron/entity-embedding-rossmann
Keith

3

In solchen Szenarien können Sie Dummy-Variablen verwenden. Mit panda's können panda.get_dummiesSie Dummy-Variablen für Zeichenfolgen erstellen, die Sie in Decision Tree oder Random Forest einfügen möchten.

Beispiel:

import pandas as pd
d = {'one' : pd.Series([1., 2., 3.,4.], index=['a', 'b', 'c','d']),'two' :pd.Series(['Paul', 'John', 'Micheal','George'], index=['a', 'b', 'c', 'd'])}
df = pd.DataFrame(d)

df_with_dummies= pd.get_dummies(df,columns=["two"],drop_first=False)
df_with_dummies

2

Verwandeln Sie sie in Zahlen, zum Beispiel für jedes Land, das eine eindeutige Nummer hat (wie 1,2,3 und ...).

auch Sie nicht verwenden müssen , um One-Hot - Codierung (auch bekannt als Dummy - Variablen) , wenn sie mit zufälligem Wald arbeiten, weil Bäume wie anderer Algorithmus nicht funktionieren (wie lineare / logistische Regression) und sie funktionieren nicht von ferne (sie Arbeiten Sie daran, eine gute Aufteilung für Ihre Funktionen zu finden. Sie brauchen also kein One-Hot-Encoding


1
Es hängt tatsächlich von dem speziellen Algorithmus ab, der den Baum trainiert. Insbesondere unterstützt scikit KEINE kategorialen Variablen.
Chuse
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.