2015-11-24 13 views
6

Sto mirando a fare grandi cose con TensorFlow, ma sto cercando di iniziare in piccolo.TensorFlow - perché questa regressione sofmax non apprende nulla?

Ho piccoli quadrati in scala di grigi (con un po 'di rumore) e voglio classificarli in base al loro colore (ad esempio 3 categorie: nero, grigio, bianco). Ho scritto una piccola classe Python per generare quadrati e vettori 1-hot e modificato il loro esempio di base MNIST per nutrirli.

Ma non imparerà nulla - ad es. per 3 categorie si azzecca sempre ≈33% corretto.

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}) 

mio generatore di dati simile a questa:

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 

risposta

2

Mentre le risposte di dga e syncd erano utili, ho provato a utilizzare l'inizializzazione del peso diverso da zero e dataset più grandi, ma senza risultati. La cosa che alla fine ha funzionato è stata l'utilizzo di un diverso algoritmo di ottimizzazione.

ho sostituito:

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

con

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

Ho inoltre integrato la formazione per il ciclo in un altro ciclo for per allenarsi per diverse epoche, con conseguente convergenza in questo modo:

===# 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 

MODIFICA - PERCHE 'FUNZIONA: Suppongo che il problema è che non ho scelto manualmente un buon piano di apprendimento e Adam è stato in grado di crearne uno migliore automaticamente.

3

Per cominciare, provare l'inizializzazione tua matrice W con valori casuali e non zeri - non stai dando il nulla ottimizzatore di lavorare con quando l'uscita è tutti zeri per tutti gli input.

Invece di:

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

Prova:

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

ora sto usando 'tf.truncated_normal()' e 'tf.constant()' per i miei pesi e bias come suggerito da te e il loro [tutorial] (http://tensorflow.org/tutorials/mnist/pros/index.html#weight-initialization). Ma ancora nessun cambiamento: indovina a caso. :( –

+0

Sei sicuro che non ci sia un bug con i tuoi dati? Ds [0] 100 articoli? ds = data_generator.generate_data (10000) xs = ds [0] xs = xs.reshape (100, 100, 28 * 28) Sarebbe più comodo se xs avesse il numero giusto prima di essere rimodellato ... – dga

+0

Ciao. Il nparray xs inizia come forma (10000, 784), quindi viene ridimensionato a (100, 100, 784). Ho cambiato il mio post per includere la classe che crea i dati in modo che tu possa provarlo se vuoi Grazie! –

2

problema che è che le vostre pendenze sono in aumento/diminuzione senza limiti, causando la funzione di perdita di diventare nan.

Date un'occhiata a questa domanda: Why does TensorFlow example fail when increasing batch size?

Inoltre, assicurarsi che si esegue il modello per un numero sufficiente di punti. Lo si esegue solo una volta attraverso il set di dati del treno (100 volte * 100 esempi) e questo non è sufficiente per farlo convergere. Aumentalo a qualcosa come 2000 al minimo (eseguendo 20 volte il tuo set di dati).

Modifica (non posso commentare, quindi aggiungo i miei pensieri qui): Il punto del post che ho collegato è che è possibile utilizzare GradientDescentOptimizer, a patto che il tasso di apprendimento diventi qualcosa come 0.001. Questo è il problema, il tuo tasso di apprendimento era troppo alto per la funzione di perdita che stavi usando.

In alternativa, utilizzare una funzione di perdita diversa, che non aumenta/riduce i gradienti tanto. Utilizzare tf.reduce_mean anziché tf.reduce_sum nella definizione di crossEntropy.

0

Trovato questa domanda quando stavo avendo un problema simile ... Ho risolto il mio ridimensionando le funzionalità.

Un po 'di sottofondo: stavo seguendo il tutorial di tensorflow, tuttavia volevo usare i dati di Kaggle (see data here) per fare la modellazione, ma all'inizio ho accettato lo stesso problema: il modello non apprende ..dopo i round di trouble-shooting, mi sono reso conto che i dati di Kaggle erano su una scala completamente diversa. Pertanto, ho ridimensionato i dati in modo che condividesse la stessa scala (0,1) del set di dati MNIST di tensorflow.

solo pensato che vorrei aggiungere i miei due centesimi caso here..in alcuni principianti che stanno cercando di seguire le impostazioni del tutorial di rimanere bloccati come ho fatto io =)

+0

Sì - per l'apprendimento del trasferimento è essenziale verificare che i nuovi dati siano preelaborati allo stesso modo di i dati di allenamento originali del modello che stai trasferendo. Tieni presente che questo problema riguardava il tasso di apprendimento e stavo formando un modello da zero con dati artificiali generati nell'intervallo [0, 1]. –