2015-11-24 6 views
6

Ich möchte große Dinge mit TensorFlow machen, aber ich versuche klein anzufangen.TensorFlow - warum lernt diese Sofmax-Regression nichts?

Ich habe kleine Graustufenquadrate (mit ein wenig Rauschen) und ich möchte sie nach ihrer Farbe klassifizieren (z. B. 3 Kategorien: schwarz, grau, weiß). Ich schrieb eine kleine Python-Klasse, um Quadrate und 1-Hot-Vektoren zu erzeugen, und modifizierte ihr grundlegendes MNIST-Beispiel, um sie einzufügen.

Aber es wird nichts lernen - z.B. Für 3 Kategorien rät es immer zu 33% richtig.

import tensorflow as tf 
import generate_data.generate_greyscale 

data_generator = generate_data.generate_greyscale.GenerateGreyScale(28, 28, 3, 0.05) 
ds = data_generator.generate_data(10000) 
ds_validation = data_generator.generate_data(500) 
xs = ds[0] 
ys = ds[1] 
num_categories = data_generator.num_categories 

x = tf.placeholder("float", [None, 28*28]) 
W = tf.Variable(tf.zeros([28*28, num_categories])) 
b = tf.Variable(tf.zeros([num_categories])) 
y = tf.nn.softmax(tf.matmul(x,W) + b) 
y_ = tf.placeholder("float", [None,num_categories]) 
cross_entropy = -tf.reduce_sum(y_*tf.log(y)) 
train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy) 
init = tf.initialize_all_variables() 
sess = tf.Session() 
sess.run(init) 

# let batch_size = 100 --> therefore there are 100 batches of training data 
xs = xs.reshape(100, 100, 28*28) # reshape into 100 minibatches of size 100 
ys = ys.reshape((100, 100, num_categories)) # reshape into 100 minibatches of size 100 

for i in range(100): 
    batch_xs = xs[i] 
    batch_ys = ys[i] 
    sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys}) 

correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1)) 
accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float")) 

xs_validation = ds_validation[0] 
ys_validation = ds_validation[1] 
print sess.run(accuracy, feed_dict={x: xs_validation, y_: ys_validation}) 

Meine Datengenerator wie folgt aussieht:

import numpy as np 
import random 

class GenerateGreyScale(): 
    def __init__(self, num_rows, num_cols, num_categories, noise): 
     self.num_rows = num_rows 
     self.num_cols = num_cols 
     self.num_categories = num_categories 
     # set a level of noisiness for the data 
     self.noise = noise 

    def generate_label(self): 
     lab = np.zeros(self.num_categories) 
     lab[random.randint(0, self.num_categories-1)] = 1 
     return lab 

    def generate_datum(self, lab): 
     i = np.where(lab==1)[0][0] 
     frac = float(1)/(self.num_categories-1) * i 
     arr = np.random.uniform(max(0, frac-self.noise), min(1, frac+self.noise), self.num_rows*self.num_cols) 
     return arr 

    def generate_data(self, num): 
     data_arr = np.zeros((num, self.num_rows*self.num_cols)) 
     label_arr = np.zeros((num, self.num_categories)) 
     for i in range(0, num): 
      label = self.generate_label() 
      datum = self.generate_datum(label) 
      data_arr[i] = datum 
      label_arr[i] = label 
     #data_arr = data_arr.astype(np.float32) 
     #label_arr = label_arr.astype(np.float32) 
     return data_arr, label_arr 

Antwort

2

Während dga und syncd die Antworten hilfreich waren, habe ich versucht, nicht-Null-Gewicht-Initialisierung und größere Datensätze aber vergeblich. Die Sache, die schließlich funktionierte, war die Verwendung eines anderen Optimierungsalgorithmus.

I ersetzt:

train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)

mit

train_step = tf.train.AdamOptimizer(0.0005).minimize(cross_entropy)

ich auch die Ausbildung für Schleife in einer anderen für Schleifen eingebettet für mehrere Epochen zu trainieren, wie dies in der Konvergenz resultierenden:

===# EPOCH 0 #=== 
Error: 0.370000004768 
===# EPOCH 1 #=== 
Error: 0.333999991417 
===# EPOCH 2 #=== 
Error: 0.282000005245 
===# EPOCH 3 #=== 
Error: 0.222000002861 
===# EPOCH 4 #=== 
Error: 0.152000010014 
===# EPOCH 5 #=== 
Error: 0.111999988556 
===# EPOCH 6 #=== 
Error: 0.0680000185966 
===# EPOCH 7 #=== 
Error: 0.0239999890327 
===# EPOCH 8 #=== 
Error: 0.00999999046326 
===# EPOCH 9 #=== 
Error: 0.00400000810623 

BEARBEITEN - WARUM ES FUNKTIONIERT: Ich nehme an, das Problem war, dass ich nicht manuell einen guten Zeitplan für die Lernrate gewählt habe und Adam konnte automatisch einen besseren erstellen.

3

Für den Anfang, versuchen Sie Ihr W-Matrix mit Zufallswerten initialisiert wird, nicht Nullen - du bist nicht der Optimierer etwas geben mit, wenn der Ausgang zu arbeiten ist nur Nullen für alle Eingaben.

Statt:

W = tf.Variable(tf.zeros([28*28, num_categories])) 

Versuchen:

W = tf.Variable(tf.truncated_normal([28*28, num_categories], 
            stddev=0.1)) 
+0

ich jetzt mit 'tf.truncated_normal()' und 'tf.constant()' für meine Gewichte und Verzerrungen, wie von Ihnen und ihrem [Tutorial] vorgeschlagen (http://tensorflow.org/tutorials/mnist/pros/index.html#weight-initialization). Aber immer noch keine Veränderung: Vermutungen sind zufällig. :( –

+0

Sind Sie sicher, dass es keinen Fehler mit Ihren Daten gibt? Ist ds [0] 100 Elemente? ds = data_generator.generate_data (10000) xs = ds [0] xs = xs.reshape (100, 100, 28 * 28) Ich wäre bequemer, wenn xs die richtige Zahl hatte, bevor Sie umgestaltet ... – dga

+0

Hi. Das Nparray xs beginnt als Form (10000, 784), dann wird die Größe auf (100, 100, 784) habe meinen Beitrag geändert, um die Klasse einzuschließen, die Daten erstellt, damit du sie ausprobieren kannst, danke! –

2

Sie Problem ist, dass die Ihre Gradienten erhöhen/ohne Grenzen abnimmt, was den Verlust Funktion nan werden.

Werfen Sie einen Blick auf diese Frage: Why does TensorFlow example fail when increasing batch size?

Darüber hinaus stellen Sie sicher, dass Sie das Modell für eine ausreichende Anzahl von Schritten ausgeführt werden. Sie führen es nur einmal durch Ihren Zugdatensatz (100 Mal * 100 Beispiele), und dies ist nicht genug, um es zu konvergieren. Erhöhen Sie den Wert auf mindestens 2000 (20 Mal durch Ihren Datensatz).

Bearbeiten (kann nicht kommentieren, also werde ich meine Gedanken hier): Der Punkt des Beitrags ich verlinkt ist, dass Sie GradientDescentOptimizer verwenden können, solange Sie die Lernrate etwas wie 0,001 machen. Das ist das Problem, Ihre Lernrate war zu hoch für die Verlustfunktion, die Sie verwendeten.

Alternativ kann eine andere Verlustfunktion verwendet werden, die die Gradienten nicht so stark erhöht/verringert. Verwenden Sie tf.reduce_mean anstelle von tf.reduce_sum in der Definition von crossEntropy.

0

Diese Frage gefunden, als ich ein ähnliches Problem hatte .. Ich reparierte meine, indem ich die Funktionen skalierte.

Ein kleiner Hintergrund: Ich folgte dem Tensorflow Tutorial, aber ich wollte die Daten von Kaggle (see data here) für die Modellierung verwenden, aber am Anfang hatte ich das gleiche Problem: das Modell lernt einfach nicht Nach den Runden der Fehlersuche wurde mir klar, dass die Kaggle-Daten in einem völlig anderen Maßstab lagen. Daher skalierte ich die Daten so, dass sie denselben Maßstab (0,1) wie der MIST-Datensatz des Tensorflusses haben.

dachte nur, dass ich meine zwei Cent here..in Fall addieren würden einige Anfänger, die das Tutorial Einstellungen zu folgen versuchen, stecken wie ich =)

+0

Ja - für das Transferlernen ist es wichtig zu prüfen, ob Ihre neuen Daten auf die gleiche Weise wie vorverarbeitet werden die ursprünglichen Trainingsdaten des Modells, das Sie übertragen. Bitte beachten Sie, dass dieses Problem, das ich hatte, mit der Lernrate zu tun hatte, und ich ein Modell von Null mit künstlichen Daten trainierte, die im Intervall [0, 1] erzeugt wurden. –