22

Die Textdaten sind als Vektor mit 20.000 Elementen wie [2, 1, 0, 0, 5, ..., 0] organisiert. i-tes Element zeigt die Häufigkeit des i-ten Worts in einem Text an.Multilabel-Textklassifizierung mit TensorFlow

Die Daten der Grundwahrheitsbeschriftung werden ebenfalls als Vektor mit 4.000 Elementen dargestellt, wie [0, 0, 1, 0, 1, ..., 0]. i-tes Element gibt an, ob das i-te Etikett eine positive Bezeichnung für einen Text ist. Die Anzahl der Etiketten für einen Text ist je nach Text unterschiedlich.

Ich habe einen Code für die Ein-Label-Textklassifizierung.

Wie kann ich den folgenden Code für die Klassifizierung von Multilabel-Texten bearbeiten?

Besonders möchte ich folgende Punkte wissen.

  • So berechnen Sie die Genauigkeit mit TensorFlow.
  • So legen Sie einen Schwellenwert fest, der beurteilt, ob eine Beschriftung positiv oder negativ ist. Wenn die Ausgabe beispielsweise [0,80, 0,43, 0,21, 0,01, 0,32] ist und die Grundwahrheit [1, 1, 0, 0, 1] ist, sollten die Markierungen mit Werten über 0,25 als positiv bewertet werden.

Danke.

import tensorflow as tf 

# hidden Layer 
class HiddenLayer(object): 
    def __init__(self, input, n_in, n_out): 
     self.input = input 

     w_h = tf.Variable(tf.random_normal([n_in, n_out],mean = 0.0,stddev = 0.05)) 
     b_h = tf.Variable(tf.zeros([n_out])) 

     self.w = w_h 
     self.b = b_h 
     self.params = [self.w, self.b] 

    def output(self): 
     linarg = tf.matmul(self.input, self.w) + self.b 
     self.output = tf.nn.relu(linarg) 

     return self.output 

# output Layer 
class OutputLayer(object): 
    def __init__(self, input, n_in, n_out): 
     self.input = input 

     w_o = tf.Variable(tf.random_normal([n_in, n_out], mean = 0.0, stddev = 0.05)) 
     b_o = tf.Variable(tf.zeros([n_out])) 

     self.w = w_o 
     self.b = b_o 
     self.params = [self.w, self.b] 

    def output(self): 
     linarg = tf.matmul(self.input, self.w) + self.b 
     self.output = tf.nn.relu(linarg) 

     return self.output 

# model 
def model(): 
    h_layer = HiddenLayer(input = x, n_in = 20000, n_out = 1000) 
    o_layer = OutputLayer(input = h_layer.output(), n_in = 1000, n_out = 4000) 

    # loss function 
    out = o_layer.output() 
    cross_entropy = -tf.reduce_sum(y_*tf.log(out + 1e-9), name='xentropy')  

    # regularization 
    l2 = (tf.nn.l2_loss(h_layer.w) + tf.nn.l2_loss(o_layer.w)) 
    lambda_2 = 0.01 

    # compute loss 
    loss = cross_entropy + lambda_2 * l2 

    # compute accuracy for single label classification task 
    correct_pred = tf.equal(tf.argmax(out, 1), tf.argmax(y, 1)) 
    accuracy = tf.reduce_mean(tf.cast(correct_pred, "float")) 

    return loss, accuracy 
+0

Ich denke, es könnte eine bessere Verlustfunktion verwenden neben Quer Entropie. – Aaron

+0

Es gibt viele verschiedene Genauigkeitsmessungen für ein Multilabel-Klassifizierungsproblem: Einfehlergenauigkeit, Rangverlust, durchschnittliche Durchschnittsgenauigkeit usw.Ich lerne immer noch TensorFlow selbst und habe es noch nicht geschafft, sie richtig zu implementieren. Aber vielleicht hilft Ihnen dieses Papier: http://arxiv.org/pdf/1312.5419v3.pdf Lassen Sie mich wissen, wenn Sie Fortschritte machen! –

+0

Für eine bessere Vorstellung der Genauigkeit erwägen Sie, Präzision und Rückruf zu berechnen. –

Antwort

8

Reluktanz zu Sigmoid der Ausgabeschicht ändern. Ändern Kreuzentropie Verlust explizite mathematische Formel von S-förmige Quer Entropieverlust (explicit Verlust wurde in meinem Fall/Version tensorflow Arbeits)

import tensorflow as tf 

# hidden Layer 
class HiddenLayer(object): 
    def __init__(self, input, n_in, n_out): 
     self.input = input 

     w_h = tf.Variable(tf.random_normal([n_in, n_out],mean = 0.0,stddev = 0.05)) 
     b_h = tf.Variable(tf.zeros([n_out])) 

     self.w = w_h 
     self.b = b_h 
     self.params = [self.w, self.b] 

    def output(self): 
     linarg = tf.matmul(self.input, self.w) + self.b 
     self.output = tf.nn.relu(linarg) 

     return self.output 

# output Layer 
class OutputLayer(object): 
    def __init__(self, input, n_in, n_out): 
     self.input = input 

     w_o = tf.Variable(tf.random_normal([n_in, n_out], mean = 0.0, stddev = 0.05)) 
     b_o = tf.Variable(tf.zeros([n_out])) 

     self.w = w_o 
     self.b = b_o 
     self.params = [self.w, self.b] 

    def output(self): 
     linarg = tf.matmul(self.input, self.w) + self.b 
     #changed relu to sigmoid 
     self.output = tf.nn.sigmoid(linarg) 

     return self.output 

# model 
def model(): 
    h_layer = HiddenLayer(input = x, n_in = 20000, n_out = 1000) 
    o_layer = OutputLayer(input = h_layer.output(), n_in = 1000, n_out = 4000) 

    # loss function 
    out = o_layer.output() 
    # modified cross entropy to explicit mathematical formula of sigmoid cross entropy loss 
    cross_entropy = -tf.reduce_sum(( (y_*tf.log(out + 1e-9)) + ((1-y_) * tf.log(1 - out + 1e-9))) , name='xentropy')  

    # regularization 
    l2 = (tf.nn.l2_loss(h_layer.w) + tf.nn.l2_loss(o_layer.w)) 
    lambda_2 = 0.01 

    # compute loss 
    loss = cross_entropy + lambda_2 * l2 

    # compute accuracy for single label classification task 
    correct_pred = tf.equal(tf.argmax(out, 1), tf.argmax(y, 1)) 
    accuracy = tf.reduce_mean(tf.cast(correct_pred, "float")) 

    return loss, accuracy 
11

Sie müssen Variationen der Kreuz-Entropie-Funktion in anderen verwenden, um Multilabel-Klassifizierung zu unterstützen. Wenn Sie weniger als eintausend Ausgänge haben, sollten Sie sigmoid_cross_entropy_with_logits verwenden, in Ihrem Fall, dass Sie 4000 Ausgänge haben, können Sie candidate sampling betrachten, da es schneller als das vorherige ist.

So berechnen Sie die Genauigkeit mit TensorFlow.

Dies hängt von Ihrem Problem und was Sie erreichen möchten. Wenn Sie kein Objekt in einem Bild vermissen wollen, sollte der Klassifizierer bis auf eins Eins erhalten, dann sollten Sie das ganze Bild als Fehler betrachten. Sie können auch in Betracht ziehen, dass ein fehlgeschlagenes oder fehlklassifiziertes Objekt ein Fehler ist. Letzteres wird von sigmoid_cross_entropy_with_logits unterstützt.

So legen Sie einen Schwellenwert fest, der entscheidet, ob ein Etikett positiv ist oder negativ ist. Wenn die Ausgabe beispielsweise [0,80, 0,43, 0,21, 0,01, 0,32] lautet und die Grundwahrheit [1, 1, 0, 0, 1] lautet, sollten die Markierungen mit Werten über 0,25 als positiv gewertet werden.

Threshold einen Weg zu gehen, haben Sie entschieden, welche. Aber das ist eine Art Hack, keine echte multilaterale Klassifikation. Dafür brauchen Sie die vorherigen Funktionen, die ich vorher gesagt habe.

+1

Ich weiß nicht, warum Leute 'sigmoid_cross_entropy_with_logits' vorschlagen. Wenn es ist, was sein Name suggeriert -Y * ln (Sigmoid (logits)). Dann wird es den Verlust minimieren, indem jeder Klasse hohe Wahrscheinlichkeit gegeben wird, und in der Tat gab es das in meinem Fall. –

+0

Diese Funktion gibt keine Wahrscheinlichkeit zurück. Und ich sehe nicht, wie es den Verlust minimieren wird, indem man einen hohen Wert gibt. Wenn Sie für Ihre Klassen 1 und 0 angeben, wenn die Klasse nicht vorhanden ist, gibt das Netzwerk Werte nahe 0, wenn das Objekt nicht im Bild ist, und Werte nahe 1 oder größer (sogar 2 oder 3), wenn das Objekt vorhanden ist das Bild. Ich benutze es und funktioniert ziemlich gut. – jorgemf

+0

Es wird den Verlust minimieren, indem jeder Klasse ein hoher Wert gegeben wird, da es keine Strafe (oder 0 Verlust) gibt, um Klassen mit der Bezeichnung 0 einen hohen Wert zu geben. Also muss man den Entropieverlust mit binärer Kreuzentropie modifizieren (y *). ln (sigmoid (logits)) + 1-y * ln (sigmoid (1-logits))). sigmoid_cross_entropy_with_logits implementiert intern keine binäre Kreuzentropie. Ich bin überrascht, warum es in Ihrem Fall funktioniert, verwenden Sie theano usw. –