Verbessere die Klassifizierung mit vielen kategorialen Variablen


37

Ich arbeite an einem Datensatz mit mehr als 200.000 Stichproben und ungefähr 50 Merkmalen pro Stichprobe: 10 kontinuierliche Variablen und die anderen ~ 40 sind kategoriale Variablen (Länder, Sprachen, wissenschaftliche Gebiete usw.). Für diese kategorialen Variablen haben Sie beispielsweise 150 verschiedene Länder, 50 Sprachen, 50 wissenschaftliche Bereiche usw.

Bisher ist mein Ansatz:

  1. Nehmen Sie für jede kategoriale Variable mit vielen möglichen Werten nur die mit mehr als 10000 Stichproben, die diesen Wert annehmen. Dies reduziert sich auf 5-10 statt 150 Kategorien.

  2. Erstellen Sie für jede Kategorie eine Dummy-Variable (wenn 10 Länder, dann fügen Sie für jede Stichprobe einen Binärvektor der Größe 10 hinzu).

  3. Versorgen Sie einen zufälligen Gesamtstrukturklassifizierer (überprüfen Sie die Parameter usw.) mit diesen Daten.

Gegenwärtig schaffe ich es mit diesem Ansatz nur, eine Genauigkeit von 65% zu erreichen, und ich habe das Gefühl, dass mehr getan werden kann. Insbesondere bin ich mit meiner 1) nicht zufrieden, da ich der Meinung bin, dass ich die "am wenigsten relevanten Werte" nicht willkürlich entsprechend der Anzahl der Stichproben entfernen sollte, da diese weniger repräsentierten Werte diskriminierender sein könnten. Andererseits kann es sich mein RAM nicht leisten, 500 Spalten * 200000 Zeilen zu den Daten hinzuzufügen, indem alle möglichen Werte beibehalten werden.

Hätten Sie einen Vorschlag, mit diesen vielen kategorialen Variablen umzugehen?


2
Wenn Sie immer noch interessiert sind, können Sie meine Antwort zur Dimensionsreduzierung und meine Antwort zur hierarchischen Klassifizierung überprüfen .
Aleksandr Blekh

1
Wenn Sie "Dummy-Variable für jede Kategorie erstellen" sagen , hört sich das so an, als würden Sie Python verwenden, nicht R? R randomforest kann nativ mit kategorialen Elementen umgehen, auch mit der daraus resultierenden Speicherreduzierung. Versuchen Sie R.
smci

Antworten:


20

1) Zufällige Gesamtstrukturen sollten in der Lage sein, kategoriale Werte nativ zu verarbeiten. Suchen Sie daher nach einer anderen Implementierung, damit Sie nicht alle diese Funktionen codieren und Ihren gesamten Speicher verbrauchen müssen.

2) Das Problem bei kategorialen Merkmalen mit hoher Kardinalität besteht darin, dass es leicht ist, sie zu stark anzupassen. Möglicherweise verfügen Sie über genügend Daten, sodass dies kein Problem darstellt. Achten Sie jedoch darauf.

3) Ich schlage vor, die zufällige Auswahl von forstbasierten Merkmalen entweder mit der von Brieman vorgeschlagenen Methode oder mit künstlichen Kontrasten zu untersuchen . Die künstliche Kontrastmethode (Artificial Contrasts Method, ACE) ist interessant, weil sie die Wichtigkeit des Features mit der Wichtigkeit einer gemischten Version von sich selbst vergleicht, die einige der Probleme mit hoher Kardinalität bekämpft. Es gibt eine neue Veröffentlichung "Module Guided Random Forests", die interessant sein könnte, wenn Sie über viel mehr Features verfügen, da sie eine Feature-Auswahlmethode verwendet, die Gruppen von stark korrelierten Features berücksichtigt.

4) Eine andere Option, die manchmal verwendet wird, besteht darin, den Algorithmus so zu optimieren, dass er die Out-of-Bag-Cases verwendet, um die endgültige Feature-Auswahl zu treffen, nachdem die Splits an den In-Bag-Cases angebracht wurden.

Es ist eine fast vollständige Ass Umsetzung hier und ich habe eine mehr Speicher effichent / schnell rf Implementierung dass Griffe kategorische Variablen nativ hier ... die -evaloob Option unterstützt die Option 4 Ich arbeite an dem Hinzufügen der Unterstützung für ACE und ein paar anderen rf Es ist noch nicht abgeschlossen.


4
All diese Vorschläge sind interessant, ich stimme zu, dass zufällige Gesamtstrukturen nativ kategoriale Variablen behandeln sollten, aber Scikit-Learn nicht ... Ich denke, das ist einer der Hauptfehler von Scikit. Ich werde Ihren Code anhand meiner Daten testen, um zu sehen, was passiert, und ich werde Ihre anderen Vorschläge prüfen!
Bertrand R

1
Probieren Sie die R-Implementierung aus. Laufen ist ein Einzeiler. Das Lesen der Daten ist extrem einfach und es gibt eine neue Paralell-Implementierung, die blitzschnell und speichereffizient ist: r-bloggers.com/… Auf der anderen Seite. Sind Ihre Klassen unausgewogen? In der r-Implementierung können Sie jeden Baum aus einem ausgewogenen Bootstrap-Beispiel wachsen lassen. sampsize = c (x, x). Dies hat für mich zu besseren binären Klassifikationen geführt. Mit den Ausgängen der OOB-Verwirrungsmatrix R können Sie ganz einfach mit den Größen herumspielen und die Klassifizierung anpassen.
JEquihua

2
Die randomForest-Implementierung von R ermöglicht Faktoren mit maximal 32 Ebenen. scikit-learn ist weniger restriktiv, vorausgesetzt, Sie erstellen zunächst Dummy-Variablen (siehe die pandas.get_dummiesFunktion). Die Implementierung von Random Forest in H2O hat sich für mich sehr gut bewährt (siehe 0xdata.com/docs/master/model/rf ).
Alex Woolford

1
Es gibt eine neuere und schnellere Implementierung von Random Forest, das Paket heißt Ranger. Wirklich großartiges Zeug. Größenordnungen schneller und hat nicht das Limit von 32 Levels.
Marbel

6

Warum sollten Sie nicht einfach eine einzige numerische Variable für jede Kategorie verwenden, anstatt Ihre Kategorien zu dummifizieren? Im Zusammenhang mit zufälligen Wäldern habe ich mich oft gefragt, welche Konsequenzen dies hat (da ich der Meinung bin, dass es verdächtig klingt, Ordinalitäten in kategoriale Daten einzuführen, mit denen, wenn auch oft, dies keinen Sinn ergibt), aber in der Praxis (zumindest) Bei der Implementierung von RFs, die ich bereits verwendet habe, habe ich oft festgestellt, dass dies keinen Einfluss auf die Ergebnisse hat (ich bin mir jedoch nicht sicher, warum).


1
Dies ist in Ordnung für kategoriale Features mit n <= 3, da Sie dieselben Teilungen generieren können, als würden Sie das Feature nativ als kategorial betrachten. Für größere n können Teilungssätze erzielt werden, die der kategorialen Teilung entsprechen, aber der Algorithmus kann sie möglicherweise nicht so effizient finden. Wenn Sie jedoch das Merkmal in n numerische Merkmale aufteilen, verringern Sie auch die Effizienz, mit der Der Algorithmus kann Splits finden. Jemand muss der Implementierung von Scikit-Learn Unterstützung für kategoriale Variablen hinzufügen, da dies ansonsten großartig ist.
Ryan Bressler

Ich stimme Ihnen zu, wenn Sie sagen, dass es verdächtig klingt, Ordinalität in kategoriale Daten einzuführen ... Ich würde es lieber nicht tun müssen, aber ich kann es zumindest versuchen und sehen, was passiert!
Bertrand R

4
Ich hatte eine lange Diskussion über diese Frage auf der sklearn-Mailingliste (Teile davon können Sie hier nachlesen : mail-archive.com/scikit-learn-general@lists.sourceforge.net/… ). Einer der Implementierer war der Meinung, dass ordinalcodierte kategoriale Merkmale bei ausreichend tiefen Bäumen (zusätzlich zu einer höheren Recheneffizienz) einigermaßen gut funktionieren könnten. Wenn Sie es trotzdem versuchen, würde ich mich sehr über Ihre Ergebnisse / Schlussfolgerungen freuen, da ich immer wieder auf dieses Problem stoße.
Cjauvin

1
Also habe ich versucht, eine einzige numerische Variable für die kategorialen zu behalten, und es funktioniert tatsächlich überraschend gut und viel besser als das Hinzufügen einer großen Anzahl von Binäreinträgen ... Ich habe auch versucht, die Werte nach ihrem Mittelwert bezüglich des Ziels zu sortieren . Und es funktioniert auch gut
Bertrand R

Das überrascht mich eigentlich nicht. Es stimmt mit dem überein, was ich in ein paar verschiedenen Einstellungen beobachtet habe, auch wenn es nach der Anzahl der positiven Stimmen zu urteilen ist, ist dies eine eher kontraproduktive Idee.
Cjauvin

5

Ich denke, Sie sollten eine / mehrere variable Reduktionstechnik (en) in Betracht ziehen . Es wird die nicht so einflussreichen Prädiktoren los.

Ich habe viel über Datenvorverarbeitung gelesen und es ist eine großartige Lösung, um die Anzahl Ihrer Variablen zu reduzieren.

Meine Vorschläge sind wie folgt:

  • Ersetzen Sie bei qualitativen Variablen fehlende Werte durch die Kategorie "missing". Es kann Verzerrungen hervorrufen, wenn die Daten nicht zufällig fehlen, aber Sie haben zumindest alle Ihre Beobachtungen intakt und die fehlende Seite könnte ein anderes Verhalten erkennen lassen.
  • Eliminieren Sie Null-Varianz-Prädiktoren oder Fast-Null-Varianz-Prädiktoren (achten Sie darauf, dass Sie keine Dummy-Variablen mit stark unausgeglichenen Kategorien entfernen, die Ihr Y effizient trennen können. Erstellen Sie einige Diagramme für die Variablen, die Sie für wichtig halten.). In R können Sie die 'nzv'Funktion aus dem 'caret'Paket verwenden. Dadurch wird Ihre Datendimension erheblich reduziert.
  • Korrelierte Prädiktoren eliminieren . Verwenden Sie die Kendall-Korrelationsmatrix, da sie sich besser für das Konstruieren mit kategorialen Variablen eignet. Der Nachteil ist, dass Sie alle Ihre nominalen Variablen in kategoriale umwandeln müssen.
  • Es gibt Feature-Auswahlmethoden , die die Anzahl der Features noch weiter reduzieren (Clustering - Sie wählen einen einzelnen Vertreter jedes Clusters, die LASSO-Regression usw.). Ich hatte noch keine Gelegenheit, sie zu testen, weil die anderen Schritte meine Variablen auf unter 100 reduziert haben.

Außerdem würde ich vorschlagen, den AdaBoost-Algorithmus anstelle des RF zu verwenden. Persönlich ergaben die von mir durchgeführten Untersuchungen für beide Methoden sehr ähnliche Gini-Koeffizienten. Das Gute an AdaBoost ist, dass in R fehlende Beobachtungen behandelt werden. Sie können also den ersten Schritt dieser Liste überspringen

Ich hoffe es hat ein wenig geholfen. Viel Glück


4

Möglicherweise möchten Sie Modelle mit gemischten Effekten in Betracht ziehen. Sie sind in den Sozialwissenschaften aufgrund ihrer Leistung bei kardinalitätsbezogenen kategorialen Daten beliebt. Ich habe sie verwendet, um großartige Vorhersagemodelle zu erstellen, die gängige Ansätze für maschinelles Lernen wie gradientenverstärkte Bäume, zufällige Wälder und regulierte logistische Regression mit elastischem Netz übertreffen. Die bekannteste Implementierung ist das lme4-Paket von R; Die Funktion, die Sie für die Klassifizierung verwenden würden, ist glmer, wodurch eine logistische Regression mit gemischten Effekten implementiert wird. Möglicherweise haben Sie Probleme mit der Skalierung Ihres Datasets, aber ich habe 80.000 Zeilen mit 15 Features ohne allzu große Schwierigkeiten erstellt.


2
  1. Wenn Sie "Dummy-Variable für jede Kategorie erstellen" sagen , hört sich das so an, als würden Sie Python verwenden, nicht R? R randomforest kann nativ mit kategorialen Elementen umgehen, auch mit der daraus resultierenden Speicherreduzierung. Versuchen Sie R.

  2. Als nächstes müssen Sie die kategorialen Ebenen nicht manuell beschneiden / zusammenführen, was sich nach einem großen Schmerz anhört. Und selbst wenn ja, kann nicht garantiert werden, dass die bevölkerungsreichsten Kategorien die aussagekräftigsten sind. Kontrollieren Sie die Komplexität des Zufallswalds mit Parameter Nodesize : Beginnen Sie mit einer großen Knotengröße und reduzieren Sie diese schrittweise (dies ist die Hyperparametersuche).

  3. Variablenauswahl wird nützlich sein. @lorelai gibt gute Empfehlungen. Versuchen Sie, nutzlose (unwichtige oder stark korrelierte) Funktionen zu eliminieren. Die Baumkonstruktion ist im Verhältnis zur Anzahl der Features quadratisch. Wenn Sie also ein Drittel eliminieren, zahlt sich dies aus.


0

Sie sollten sich das Paket H2O.ai ansehen . Es behandelt kategoriale Variablen ohne Kodierung (stellen Sie sicher, dass die Variablen Faktoren sind).

Die Implementierung von Gradient Boosted Machine (GBM) gefällt mir besonders gut, da Sie die variable Wichtigkeit nach dem Erstellen des Modells betrachten können. GBMs haben auch die nette Eigenschaft, gegen Überanpassung beständig zu sein.

Wenn Sie andere Modelle erforschen möchten, haben sie: GLM, Random Forest, Naive Bayes, Deep Learning, etc.

Siehe: http://docs.h2o.ai/h2o/latest-stable/h2o-docs/data-science/gbm.html

Es ist auch einfach zu installieren (Windows, Linux, Mac) und mit APIs unter Verwendung von R, Python, Java und Scala einfach auszuführen.

Es kann mehrere Kerne verwenden, um die Dinge zu beschleunigen.

In naher Zukunft werden sie GPUs unterstützen.

Es ist auch Open Source und kostenlos (es gibt Enterprise-Support).

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.