Ich arbeite an einer Website, auf der ich die Ergebnisse von Schachspielen sammle, die Leute gespielt haben. Betrachtet man die Bewertungen des Spielers und den Unterschied zwischen seiner Bewertung und der seines Gegners, zeichne ich ein Diagramm mit Punkten, die Gewinn (grün), Unentschieden (blau) und Verlust (rot) darstellen.
Mit diesen Informationen habe ich auch einen logistischen Regressionsalgorithmus implementiert, um die Cutoffs für Gewinnen und Gewinnen / Zeichnen zu kategorisieren. Wenn ich die Bewertung und die Differenz als meine beiden Merkmale benutze, bekomme ich einen Klassifikator und zeichne dann die Grenzen auf dem Diagramm, wo der Klassifikator seine Vorhersage ändert.
Mein Code für Gradientenabfall, die Kostenfunktion und die Sigmoid-Funktion sind unten.
%Vor%Wenn ich dies auf dem Datensatz überprüfe, der mein eigenes Schachprofil repräsentiert, bekomme ich vernünftige Ergebnisse, mit denen ich glücklich sein kann:
Für eine Weile war ich glücklich. Alle Beispiele, die ich versuchte, ergaben interessante Diagramme. Dann probierte ich einen Spieler, Kevin Cao, der über 250 Turniere auf seinen Namen hatte, und somit 1000+ Spiele, für ein sehr großes Trainingsset. Das Ergebnis war offensichtlich falsch:
Nun, das war nicht gut. Also habe ich die anfängliche Lernrate von 1.0 auf 100.0 als erste Idee erhöht. Das hat die richtigen Ergebnisse für Kevin:
Leider habe ich, als ich es dann an mir selbst und an meinem kleineren Datensatz ausprobierte, das seltsame Phänomen, dass es für eine der Vorhersagen nur eine flache Linie bei 0 gab:
Ich überprüfte Theta, und es sagte, es war [[2.3707682771730836], [21.22408286825226], [-19081.906528679192]]. Die dritte Trainingsvariable (wirklich zweit, da x_0 = 1) ist der Unterschied in den Bewertungen. Wenn die Differenz also nur das kleinste Bit positiv ist, geht die Formel für die logistische Regression sehr negativ und die Sigmoidfunktion sagt y = 0 voraus Unterschied ist nur das ein bisschen positive, ähnlich springt es weit nach oben und sagt y = 1 voraus.
Ich habe die anfängliche Lernrate von 100.0 auf 1.0 reduziert und stattdessen beschlossen, sie langsamer zu reduzieren. Anstatt es um den Faktor zehn zu reduzieren, wenn die Kostenfunktion steigt, habe ich es um den Faktor zwei reduziert.
Leider hat dies das Ergebnis für mich überhaupt nicht verändert. Selbst wenn ich die Anzahl der Schleifen des Gradientenabfalls von 100 auf 1000 erhöht hätte, hätte ich immer noch das falsche Ergebnis vorhergesagt.
Ich bin immer noch ziemlich Anfänger in der logistischen Regression (ich habe gerade den Kurs zum maschinellen Lernen auf Kurs beendet und ich versuche zum ersten Mal, einen der Algorithmen, die ich dort gelernt habe, zu implementieren), also habe ich ungefähr das Ausmaß erreicht meine Intuition. Wenn mir jemand helfen würde, herauszufinden, was hier falsch läuft, was ich falsch mache und wie ich es beheben kann, wäre ich sehr dankbar.
EDIT: Ich habe es auch auf einem anderen Datensatz versucht, der ungefähr 300 Datenpunkte hatte, und wieder einmal eine flache grüne Linie und eine normale blaue Linie bekommen. Der Algorithmus ist im Grunde genommen der gleiche für beide, nur einige unterschiedliche Ergebnisse für y, weil ich Multi-Class-Klassifikation mache.
BEARBEITEN: Da die Leute danach gefragt haben, sind hier J, Alpha und Theta für jede Iteration des Gradientenabfalls für die Linie, die flach ist:
%Vor%Für denjenigen, der eine richtige Vorhersage erstellt:
%Vor%EDIT: Ich habe festgestellt, dass bei der ersten Iteration die Hypothese immer 0.5 voraussagt, da das Theta alles 0 ist. Aber danach sagt es immer 1 oder 0 voraus (0.00001 oder 0.99999, um Logarithmen zu vermeiden, die in meinem Code nicht existieren). Das erscheint mir nicht richtig - viel zu selbstbewusst - und ist wahrscheinlich der Schlüssel, warum das nicht funktioniert.
Es gibt ein paar Dinge über Ihre Implementierung, die ein wenig nicht standard sind.
Zunächst wird das logistische Regressionsziel typischerweise als Minimierungsproblem von
angegeben lr(x[n],y[n])=log(1+exp(-y[n]*dot(w[n],x[n])))
Dabei ist y[n]
entweder 1
oder -1
Sie scheinen die äquivalente Maximierungsproblemformulierung von
zu verwenden lr(x[n],y[n])=-y[n]*log(1+exp(-dot(w[n],x[n])))+(1-y[n])*(-dot(w[n],x[n])-log(1+exp(-dot(w[n],x[n])))
wobei y[n]
entweder 0 oder 1 ist (y [n] = 0 in dieser Formulierung ist das Äquivalent von y [n] = 1 in der ersten Formulierung).
Sie sollten also sicherstellen, dass Ihre Labels in Ihrem Dataset 0 oder 1 und nicht 1 oder -1 sind.
Als nächstes wird das LR-Ziel normalerweise nicht durch m
(die Größe des Datensatzes) geteilt. Dieser Skalierungsfaktor ist falsch, wenn Sie die logistische Regression als probabilistisches Modell betrachten.
Schließlich haben Sie vielleicht einige numerische Probleme mit Ihrer Implementierung (die Sie in der g-Funktion zu korrigieren versuchten). Leon Bottous sgd-Code (http://leon.bottou.org/projects/sgd) hat einige stabilere Berechnungen der Verlustfunktion und der Ableitung wie folgt (im C-Code - er verwendet die erste LR-Formulierung, die ich erwähne):
%Vor%Sie sollten auch eine l-bfgs-Standardroutine in Betracht ziehen (ich bin mit Ruby-Implementierungen nicht vertraut), damit Sie sich darauf konzentrieren können, die Ziel- und Gradientenberechnungen zu korrigieren und sich nicht um Lernraten zu kümmern.
ein paar Gedanken:
J()
und alpha
anzeigen könnten. Nehmen Sie eine Konstante (Bias) als Feature? Wenn ich mich richtig erinnere, wenn Sie dies nicht tun, wird Ihre (gerade) Zeile von h() == 0.5
gezwungen, durch Null zu gehen
Ihre Funktion J()
sieht so aus, als würde sie die negative Log-Wahrscheinlichkeit zurückgeben (die Sie daher minimieren ) möchten. Sie verringern jedoch die Lernrate if (oldJ < newJ)
, d.h. wenn J()
größer, d. H. Schlechter, wurde.
Versuchen Sie das? Equal
Vergleich zwischen Schwimmern macht keinen großen Sinn für mich.
Sie haben erwähnt, dass Sie zwei Funktionen verwenden, ich nehme an, dass sie die eigene Bewertung des Spielers und die Bewertung diff sind. Ist das richtig?
Erwägen Sie auch die Verwendung einer Skalierung von Features als Datenvorverarbeitungsschritt, z. B.
. oder Sie können die Standardisierungsmethode ausführen, indem Sie die Werte jedes Features in den Daten auf Null-Mittelwert und Einheiten-Varianz setzen.
Anstatt mit Ihrer Lernrate zu spielen, denke ich, dass Sie Ihren anfänglichen Datensatz mit Hilfe der Feature-Normalisierung ((X-mu) / sigma) normalisieren und dann die Operation ausführen müssen, die Sie durchführen möchten.
Ohne Feature-Normalisierung wird der Gradientenabstieg für große Datenmengen bei ungewöhnlichen Verhalten fehlerhaft.
Tags und Links ruby algorithm machine-learning statistics regression