2017-05-05 6 views
2

In einem Klassifikationsproblem mit vielen Klassen schlägt Tensorflow docs vor, sampled_softmax_loss über eine einfache softmax zu verwenden, um Trainingslaufzeit zu reduzieren.Tensorflow Sampled Softmax Verlust Korrekte Verwendung

Nach der docs und source (Linie 1180), für sampled_softmax_loss die Anrufmuster:

tf.nn.sampled_softmax_loss(weights, # Shape (num_classes, dim)  - floatXX 
        biases,  # Shape (num_classes)   - floatXX 
        labels,  # Shape (batch_size, num_true) - int64 
        inputs,  # Shape (batch_size, dim)  - floatXX 
        num_sampled, # - int 
        num_classes, # - int 
        num_true=1, 
        sampled_values=None, 
        remove_accidental_hits=True, 
        partition_strategy="mod", 
        name="sampled_softmax_loss") 

Es ist unklar, (zumindest für mich), wie ein reale Welt Problem in die Formen zu konvertieren, dass dieser Verlust Funktion erfordert. Ich denke, das Feld "Eingaben" ist das Problem.

Hier ist ein Beispiel für eine Copy-Paste-ready-Minimalfunktion, die beim Aufruf der Verlustfunktion einen Matrixmultiplikations-Formfehler auslöst.

import tensorflow as tf 

# Network Parameters 
n_hidden_1 = 256 # 1st layer number of features 
n_input = 784  # MNIST data input (img shape: 28*28) 
n_classes = 10 # MNIST total classes (0-9 digits)  

# Dependent & Independent Variable Placeholders 
x = tf.placeholder("float", [None, n_input]) 
y = tf.placeholder("float", [None, n_classes]) # 

# Weights and Biases 
weights = { 
    'h1': tf.Variable(tf.random_normal([n_input, n_hidden_1])), 
    'out': tf.Variable(tf.random_normal([n_hidden_1, n_classes])) 
} 
biases = { 
    'b1': tf.Variable(tf.random_normal([n_hidden_1])), 
    'out': tf.Variable(tf.random_normal([n_classes])) 
} 

# Super simple model builder 
def tiny_perceptron(x, weights, biases): 
    layer_1 = tf.add(tf.matmul(x, weights['h1']), biases['b1']) 
    layer_1 = tf.nn.relu(layer_1) 
    out_layer = tf.matmul(layer_1, weights['out']) + biases['out'] 
    return out_layer 

# Create the model 
pred = tiny_perceptron(x, weights, biases)  

# Set up loss function inputs and inspect their shapes 
w = tf.transpose(weights['out']) 
b = biases['out'] 
labels = tf.reshape(tf.argmax(y, 1), [-1,1]) 
inputs = pred 
num_sampled = 3 
num_true = 1 
num_classes = n_classes 

print('Shapes\n------\nw:\t%s\nb:\t%s\nlabels:\t%s\ninputs:\t%s' % (w.shape, b.shape, labels.shape, inputs.shape)) 
# Shapes 
# ------ 
# w:  (10, 256) # Requires (num_classes, dim)  - CORRECT 
# b:  (10,)  # Requires (num_classes)   - CORRECT 
# labels: (?, 1)  # Requires (batch_size, num_true) - CORRECT 
# inputs: (?, 10) # Requires (batch_size, dim)  - Not sure 

loss_function = tf.reduce_mean(tf.nn.sampled_softmax_loss(
        weights=w, 
        biases=b, 
        labels=labels, 
        inputs=inputs, 
        num_sampled=num_sampled, 
        num_true=num_true, 
        num_classes=num_classes)) 

Die letzte Zeile löst und Valueerror, die besagt, dass Sie mehrfach Tensoren mit Form kippen (? 10) und (?, 256). In der Regel stimme ich dieser Aussage zu. Voll Fehler unten:

ValueError: Dimensions must be equal, but are 10 and 256 for 'sampled_softmax_loss_2/MatMul_1' (op: 'MatMul') with input shapes: [?,10], [?,256]. 

Wenn der ‚dim‘ Wert von tensorflow docs soll, konstant sein, entweder die ‚Gewichte‘ oder ‚Eingänge‘ Variablen in die Verlustfunktion gehen falsch.

Alle Gedanken wären toll, ich bin völlig ratlos, wie man diese Verlustfunktion korrekt verwendet & es hätte einen großen Einfluss auf die Trainingszeit für das Modell, das wir es verwenden (500k Klassen). Vielen Dank!

--- EDIT ---

Es ist möglich, die Probe oben ohne Fehler auszuführen, indem Sie mit den Parametern spielen gezeigt zu bekommen und das Ignorieren der sampled_softmax_loss erwarteten Eingaben Ruf Muster. Wenn Sie dies tun, führt dies zu einem trainierbaren Modell, das die Vorhersagegenauigkeit beeinträchtigt (wie Sie es erwarten würden).

+0

Ich könnte falsch liegen, aber versuchen Sie, Ihre Gewichte mit Form definieren '[num_hidden_1, num_input]' und '[num_classes, num_hidden_1]'. Es scheint, als ob Ihre Daten nicht wie erwartet von Ihren vollständig verbundenen Schichten umgewandelt werden ... – Engineero

+0

@Engineero Danke fürs Wiegen.Die versteckten Gewichte zwischen aufeinanderfolgenden Schichten des Modells werden miteinander multipliziert, so dass (256, 784) und (10, 256) die nicht kompatibel sind. Um sicherzustellen, dass der Rest des Codes korrekt ist, wird die Einstellung 'n_hidden_1' bis 10 (wie' n_classes') erfolgreich sein. Das macht natürlich nichts produktives, da es auf die falschen Kriterien optimiert! Nur ein kleiner Test. –

+0

Interessant. Ich dachte an die Operationen: 'h = W1 * x',' y = W2 * h', in diesem Fall würden Sie Ihre Gewichtsmatrizen mit den vorgeschlagenen Dimensionen benötigen. Ich denke, es implementiert das Gegenteil: 'h = x * W1' und' y = h * W2'. ** Edit: ** Jetzt sehe ich, wo du dein Netzwerk definierst. Mein Fehler. – Engineero

Antwort

1

In Ihrer softmax Ebene, die Sie Ihr Netzwerk Prognosen multiplizieren, die Dimension (num_classes,) durch Ihre w Matrix hat, die Dimension hat (num_classes, num_hidden_1), so dass Sie am Ende versuchen, Ihr Ziel Etiketten der Größe (num_classes,) etwas zu vergleichen, die jetzt (num_hidden_1,) Größe ist. Ändern Sie Ihr kleines Perzeptron, um stattdessen layer_1 auszugeben, und ändern Sie dann die Definition Ihrer Kosten. Der folgende Code könnte den Trick machen.

def tiny_perceptron(x, weights, biases): 
    layer_1 = tf.add(tf.matmul(x, weights['h1']), biases['b1']) 
    layer_1 = tf.nn.relu(layer_1) 
    return layer_1 

layer_1 = tiny_perceptron(x, weights, biases) 
loss_function = tf.reduce_mean(tf.nn.sampled_softmax_loss(
        weights=weights['h1'], 
        biases=biases['b1'], 
        labels=labels, 
        inputs=layer_1, 
        num_sampled=num_sampled, 
        num_true=num_true, 
        num_classes=num_classes)) 

Wenn Sie Ihr Netzwerk mit einigen Optimierer trainieren, werden Sie sagen, es loss_function zu minimieren, was bedeuten soll, dass es beide Sätze von Gewichtungen und Bias anpassen.

+1

Wenn Sie diese Lösung so ändern, dass die letzte Zeile 'weights ['h1']' und 'biases ['b1']' anstelle von 'weights ['out]' und 'biases [' out ']' verwendet, wird die übergeben Build Schritt & wird sogar ausgeführt. Aber laut den Dokumenten sollte der Wert für Gewichte '(num_classes, dim) 'sein, was' (10,?) 'Wäre. Sie können bestätigen, dass etwas nicht stimmt, indem Sie ein vollständiges Modell trainieren. Der Verlust wird schön abnehmen, aber die Genauigkeit ist zufällig oder schlechter als zufällig. Ich werde den Beitrag aktualisieren, um den vollständigen Trainingscode zur Veranschaulichung zu enthalten –

+0

Das macht keinen Sinn. Ich werde versuchen, es noch etwas genauer zu betrachten, aber die Dimensionen in diesem Fall ergeben für mich keinen Sinn. Es scheint, als ob ich vorzeitig geantwortet habe ... – Engineero

+0

Danke für Ihre Hilfe. Das Stück, das ich nicht verstanden habe, war, dass sampled_softmax die finale softmax Schicht abreißt und sie innerhalb der Verlustfunktion ersetzt. –

0

Der entscheidende Punkt ist, die richtige Form von Gewicht, Vorspannung, Eingabe und Beschriftung zu übergeben. Die Form von Gewicht, die an sampled_softmax übergeben wird, ist nicht die gleiche mit der allgemeinen Situation. Zum Beispiel logits = xw + b, rufen Sie sampled_softmax wie folgt auf: sampled_softmax(weight=tf.transpose(w), bias=b, inputs=x), NICHT sampled_softmax(weight=w, bias=b, inputs=logits) !! Außerdem ist Label keine One-Hot-Darstellung. Wenn Ihre Etiketten heiß dargestellt werden, übergeben Sie labels=tf.reshape(tf.argmax(labels_one_hot, 1), [-1,1])

Verwandte Themen