0

Wenn wir neurale Netzwerke trainieren, verwenden wir normalerweise Gradientenabstieg, der auf einer kontinuierlichen, differenzierbaren reellen Kostenfunktion beruht. Die endgültige Kostenfunktion könnte beispielsweise den mittleren quadratischen Fehler annehmen. Oder anders gesagt, Gradientenabstieg setzt implizit voraus, dass das Endziel Regression ist - um ein reellwertiges Fehlermaß zu minimieren.Kostenfunktion Trainingsziel versus Genauigkeit gewünschtes Ziel

Manchmal wollen wir, dass ein neuronales Netzwerk eine Klassifizierung durchführt - bei einer Eingabe in zwei oder mehr diskrete Kategorien einordnen. In diesem Fall ist das Endziel, das dem Benutzer wichtig ist, die Klassifizierungsgenauigkeit - der Prozentsatz der Fälle, die korrekt klassifiziert wurden.

Aber wenn wir ein neuronales Netz zur Klassifizierung verwenden, obwohl unser Ziel Klassifikationsgenauigkeit ist, das ist nicht das, was das neuronale Netz zu optimieren versucht. Das neurale Netzwerk versucht immer noch, die reellwertige Kostenfunktion zu optimieren. Manchmal zeigen diese in die gleiche Richtung, manchmal aber auch nicht. Insbesondere bin ich auf Fälle gestoßen, in denen ein neuronales Netzwerk trainiert wurde, um die Kostenfunktion korrekt zu minimieren, eine Klassifizierungsgenauigkeit, die schlechter ist als ein einfacher handcodierter Schwellenwertvergleich.

Ich habe dies mit TensorFlow zu einem minimalen Testfall gekocht. Es erstellt ein Perzeptron (neuronales Netzwerk ohne versteckte Schichten), trainiert es auf einem absolut minimalen Datensatz (eine Eingangsvariable, eine binäre Ausgangsvariable), bewertet die Klassifikationsgenauigkeit des Ergebnisses und vergleicht es dann mit der Klassifikationsgenauigkeit einer einfachen Hand -kodierter Schwellenwertvergleich; Die Ergebnisse sind 60% bzw. 80%. Intuitiv ist dies der Fall, weil ein einzelner Ausreißer mit einem großen Eingangswert einen entsprechend großen Ausgangswert erzeugt, so dass der Weg zur Minimierung der Kostenfunktion darin besteht, besonders hart zu versuchen, diesen einen Fall zu berücksichtigen und dabei zwei weitere Fälle falsch zu klassifizieren. Das Perzeptron tut richtig, was es zu tun hatte; Es entspricht nur nicht dem, was wir eigentlich von einem Klassifikator erwarten. Die Klassifikationsgenauigkeit ist jedoch keine kontinuierliche differenzierbare Funktion, so dass wir sie nicht als Ziel für den Gradientenabfall verwenden können.

Wie können wir ein neuronales Netzwerk so trainieren, dass es die Klassifikationsgenauigkeit maximiert?

import numpy as np 
import tensorflow as tf 
sess = tf.InteractiveSession() 
tf.set_random_seed(1) 

# Parameters 
epochs = 10000 
learning_rate = 0.01 

# Data 
train_X = [ 
    [0], 
    [0], 
    [2], 
    [2], 
    [9], 
] 
train_Y = [ 
    0, 
    0, 
    1, 
    1, 
    0, 
] 

rows = np.shape(train_X)[0] 
cols = np.shape(train_X)[1] 

# Inputs and outputs 
X = tf.placeholder(tf.float32) 
Y = tf.placeholder(tf.float32) 

# Weights 
W = tf.Variable(tf.random_normal([cols])) 
b = tf.Variable(tf.random_normal([])) 

# Model 
pred = tf.tensordot(X, W, 1) + b 
cost = tf.reduce_sum((pred-Y)**2/rows) 
optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(cost) 
tf.global_variables_initializer().run() 

# Train 
for epoch in range(epochs): 
    # Print update at successive doublings of time 
    if epoch&(epoch-1) == 0 or epoch == epochs-1: 
     print('{} {} {} {}'.format(
      epoch, 
      cost.eval({X: train_X, Y: train_Y}), 
      W.eval(), 
      b.eval(), 
      )) 
    optimizer.run({X: train_X, Y: train_Y}) 

# Classification accuracy of perceptron 
classifications = [pred.eval({X: x}) > 0.5 for x in train_X] 
correct = sum([p == y for (p, y) in zip(classifications, train_Y)]) 
print('{}/{} = perceptron accuracy'.format(correct, rows)) 

# Classification accuracy of hand-coded threshold comparison 
classifications = [x[0] > 1.0 for x in train_X] 
correct = sum([p == y for (p, y) in zip(classifications, train_Y)]) 
print('{}/{} = threshold accuracy'.format(correct, rows)) 
+0

Je weniger Fehler, desto höher ist die Genauigkeit. Ist das nicht eine gültige Aussage? –

+0

@AlexeyR. Der Punkt ist nicht die Terminologie, der Punkt ist, dass Gradientabstieg versucht, die Fehlerfunktion * real valued * zu minimieren, wohingegen der Benutzer sich Gedanken um Fehler im Sinne von * Prozent falsch klassifizierter Fälle macht * und dies sind zwei verschiedene Dinge. – rwallace

+0

Verwenden Sie einfach die [rechte Proxy-Funktion] (https://datascience.stackexchange.com/questions/13663/neural-networks-loss-and-accuracy-correlation). Quadratischer Fehler versagt hier sicher. – sascha

Antwort

1

Ich bin immer noch nicht sicher, ob dies ist eine gut gestellte Frage, geschweige denn angemessen für SO; Trotzdem werde ich es versuchen, und vielleicht finden Sie zumindest einige Elemente meiner Antwort hilfreich.

Wie können wir ein neuronales Netzwerk so trainieren, dass die Klassifikationsgenauigkeit maximiert wird?

Ich bin für eine Art und Weise zu fragen eine kontinuierliche Proxy-Funktion zu erhalten, die für die Genauigkeit näher ist

mit zu starten, dem Funktionsverlust heute für Klassifikationsaufgaben in (tief) neuronale Netze verwendet wurden nicht erfunden, mit sie, aber es geht mehrere Jahrzehnte zurück, und es kommt tatsächlich von den frühen Tagen der logistischen Regression.Hier ist die Gleichung für den einfachen Fall von binärer Klassifizierung:

enter image description here

Die Idee dahinter war genau das mit einer kontinuierlichen & differenzierbar Funktion zu kommen, so dass wir in der Lage sein würden, die (große auszubeuten und immer noch erweitert) Arsenal der konvexen Optimierung für Klassifikationsprobleme.

Es ist sicher zu sagen, dass die obige Verlustfunktion die beste ist, die wir so weit haben, angesichts der oben erwähnten mathematischen Einschränkungen.

Sollten wir dieses Problem (d. H. Bessere Annäherung an die Genauigkeit) als gelöst und beendet betrachten? Zumindest im Prinzip nein. Ich bin alt genug, um mich an eine Ära zu erinnern, als die einzigen praktisch verfügbaren Aktivierungsfunktionen tanh und sigmoid waren; Dann kam ReLU und gab dem Feld einen echten Schub. In ähnlicher Weise kann jemand schließlich eine bessere Verlustfunktion entwickeln, aber wohl wird dies in einer Forschungsarbeit passieren, und nicht als Antwort auf eine SO Frage ...

Das sagte, die Tatsache, dass die aktuelle Loss-Funktion kommt von sehr elementare Überlegungen der Wahrscheinlichkeits-und Informationstheorie (Felder, die, in scharfem Gegensatz zu dem aktuellen Bereich des Deep Learning, stehen auf festen theoretischen Grundlagen) schafft zumindest einige Zweifel, ob ein besserer Vorschlag für den Verlust kann gleich um die Ecke sein.


Es ist ein weiterer subtiler Punkt auf die Beziehung zwischen dem Verlust und Genauigkeit, was die letztere etwas qualitativ anderes als die ersteren macht, und in einem solchen Diskussionen häufig verloren. Lassen Sie mich ein wenig ausarbeiten ...

Alle Klassifizierer im Zusammenhang mit dieser Diskussion (d. H. Neuronale Netze, logistische Regression usw.) sind probabilistische Einsen; das heißt, sie geben keine harten Klassenmitgliedschaften (0/1) zurück, sondern Klassenwahrscheinlichkeiten (kontinuierliche reelle Zahlen in [0, 1]).

die Diskussion der Einfachheit halber auf den binären Fall Begrenzung, wenn eine Klasse Wahrscheinlichkeit auf eine (hart) Klassenzugehörigkeit Umwandlung werden wir eine Schwelle, in der Regel gleich 0,5, wie wenn p[i] > 0.5, dann class[i] = "1" implizit beteiligt ist. Jetzt können wir viele Fälle finden, in denen diese naive Standardschwellwertwahl nicht funktioniert (schwergewichtige Datensätze sind die ersten, die in den Sinn kommen), und wir müssen einen anderen wählen. Aber der wichtige Punkt für unsere Diskussion hier ist, dass diese Schwellwertauswahl, während sie von zentraler Bedeutung für die Genauigkeit ist, vollständig zu dem mathematischen Optimierungsproblem der Minimierung des Verlustes ist und als eine weitere "Isolationsschicht" zwischen ihnen dient, Kompromisse der vereinfachenden Ansicht, dass Verlust nur ein Proxy für die Genauigkeit ist (ist es nicht).


Erweiterung etwas eine bereits breite Diskussion: Können wir vielleicht völlig weg von der (sehr) begrenzten Einschränkung der mathematischen Optimierung der kontinuierlichen & differenzierbare Funktionen bewegen? Mit anderen Worten, können wir die Rückwärtsausbreitung und den Gradientenabstieg vermeiden?

Nun, wir tatsächlich tun, so schon, zumindest im Teilgebiet des Verstärkungslernens: 2017 war das Jahr, als new research from OpenAI auf etwas Evolutionsstrategienmade headlines genannt.Und als Extra-Bonus gibt es hier ein ultra-frisches (Dez 2017) paper by Uber zum Thema, das wiederum much enthusiasm in der Community generiert.


Dies sind meine Gedanken, basierend auf meinem eigenen Verständnis Ihrer Frage. Auch wenn dieses Verständnis nicht stimmt, hoffentlich finden Sie hier, wie ich bereits sagte, einige hilfreiche Elemente ...

1

Ich glaube, Sie vergessen, Ihre Ausgabe über ein Simgoid zu übergeben. Feste unter:

import numpy as np 
import tensorflow as tf 
sess = tf.InteractiveSession() 
tf.set_random_seed(1) 

# Parameters 
epochs = 10000 
learning_rate = 0.01 

# Data 
train_X = [ 
    [0], 
    [0], 
    [2], 
    [2], 
    [9], 
] 
train_Y = [ 
    0, 
    0, 
    1, 
    1, 
    0, 
] 

rows = np.shape(train_X)[0] 
cols = np.shape(train_X)[1] 

# Inputs and outputs 
X = tf.placeholder(tf.float32) 
Y = tf.placeholder(tf.float32) 

# Weights 
W = tf.Variable(tf.random_normal([cols])) 
b = tf.Variable(tf.random_normal([])) 

# Model 
# CHANGE HERE: Remember, you need an activation function! 
pred = tf.nn.sigmoid(tf.tensordot(X, W, 1) + b) 
cost = tf.reduce_sum((pred-Y)**2/rows) 
optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(cost) 
tf.global_variables_initializer().run() 

# Train 
for epoch in range(epochs): 
    # Print update at successive doublings of time 
    if epoch&(epoch-1) == 0 or epoch == epochs-1: 
     print('{} {} {} {}'.format(
      epoch, 
      cost.eval({X: train_X, Y: train_Y}), 
      W.eval(), 
      b.eval(), 
      )) 
    optimizer.run({X: train_X, Y: train_Y}) 

# Classification accuracy of perceptron 
classifications = [pred.eval({X: x}) > 0.5 for x in train_X] 
correct = sum([p == y for (p, y) in zip(classifications, train_Y)]) 
print('{}/{} = perceptron accuracy'.format(correct, rows)) 

# Classification accuracy of hand-coded threshold comparison 
classifications = [x[0] > 1.0 for x in train_X] 
correct = sum([p == y for (p, y) in zip(classifications, train_Y)]) 
print('{}/{} = threshold accuracy'.format(correct, rows)) 

Der Ausgang:

0 0.28319069743156433 [ 0.75648874] -0.9745011329650879 
1 0.28302448987960815 [ 0.75775659] -0.9742625951766968 
2 0.28285878896713257 [ 0.75902224] -0.9740257859230042 
4 0.28252947330474854 [ 0.76154679] -0.97355717420578 
8 0.28187844157218933 [ 0.76656926] -0.9726400971412659 
16 0.28060704469680786 [ 0.77650583] -0.970885694026947 
32 0.27818527817726135 [ 0.79593837] -0.9676888585090637 
64 0.2738055884838104 [ 0.83302218] -0.9624817967414856 
128 0.26666420698165894 [ 0.90031379] -0.9562843441963196 
256 0.25691407918930054 [ 1.01172411] -0.9567816257476807 
512 0.2461051195859909 [ 1.17413962] -0.9872989654541016 
1024 0.23519910871982574 [ 1.38549554] -1.088881492614746 
2048 0.2241383194923401 [ 1.64616168] -1.298340916633606 
4096 0.21433120965957642 [ 1.95981205] -1.6126530170440674 
8192 0.2075471431016922 [ 2.31746769] -1.989408016204834 
9999 0.20618653297424316 [ 2.42539024] -2.1028473377227783 
4/5 = perceptron accuracy 
4/5 = threshold accuracy 
+0

Danke! Es scheint vernünftig, dass das Sigmoid helfen könnte. Wenn ich deinen Code ausprobiere, funktioniert es immer noch nicht, aber ich denke, das liegt daran, dass dein TF eine andere Zufallszahlenfolge verwendet. Wenn ich deinen Start W/B versuche, funktioniert es ... – rwallace

+0

Mit meinem Start funktioniert es immer noch nicht, auch mit dem gleichen Code erreicht es einen anderen Endpunkt, aber das ist seltsam, Perceptrons sollen immer konvergieren zum globalen Optimum, sie sollen keine lokalen Optima haben. Ich versuche immer noch herauszufinden, was hier vor sich geht. – rwallace

+0

Okay, ich erinnerte mich, dass 'Perceptrons immer zum globalen Optimum konvergieren', vergaß aber die zweite Hälfte der korrekten Version 'wenn die Daten linear separierbar sind'. Das globale Optimum erreicht also tatsächlich 4/5 mit dem Sigmoid. – rwallace