5

Dopo aver completato i tutorial mnist/cifar ho pensato di sperimentare con tensorflow creando il mio "grande" insieme di dati e per semplicità ho optato per un nero su bianco forma ovale che modifica la sua altezza e larghezza in modo indipendente su una scala di 0.0-1.0 come un'immagine di 28x28 pixel (di cui ho 5000 immagini di allenamento, 1000 immagini di prova).Funzioni di costo e attivazione per più etichette indipendenti

mio codice utilizza il 'MNIST expert' esercitazione come base (ridimensionato per la velocità), ma sono passato in una funzione di costo basata squadrato errori e, sulla base del parere here, scambiato in una funzione sigmoidale per lo strato finale di attivazione, data che questa non è una classificazione, ma piuttosto un "best-fit" tra due tensori, y_ e y_conv.

Tuttavia, nel corso di> 100k iterazioni, l'uscita di perdita si deposita rapidamente in un'oscillazione compresa tra 400 e 900 (o, di conseguenza, 0,2-0,3 di una data etichetta mediata su 2 etichette in un lotto di 50), quindi immagino Sto solo facendo rumore. Forse mi sbaglio ma speravo di usare Tensorflow per convogliare le immagini in modo da dedurre forse 10 o più variabili indipendenti etichettate. Mi manca qualcosa di fondamentale qui?

def train(images, labels): 

# Import data 
oval = blender_input_data.read_data_sets(images, labels) 

sess = tf.InteractiveSession() 

# Establish placeholders 
x = tf.placeholder("float", shape=[None, 28, 28, 1]) 
tf.image_summary('images', x) 
y_ = tf.placeholder("float", shape=[None, 2]) 

# Functions for Weight Initialization. 

def weight_variable(shape): 
    initial = tf.truncated_normal(shape, stddev=0.1) 
    return tf.Variable(initial) 

def bias_variable(shape): 
    initial = tf.constant(0.1, shape=shape) 
    return tf.Variable(initial) 

# Functions for convolution and pooling 

def conv2d(x, W): 
    return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME') 

def max_pool_2x2(x): 
    return tf.nn.max_pool(x, ksize=[1, 2, 2, 1], 
         strides=[1, 2, 2, 1], padding='SAME') 

# First Variables 

W_conv1 = weight_variable([5, 5, 1, 16]) 
b_conv1 = bias_variable([16]) 

# First Convolutional Layer. 
h_conv1 = tf.nn.relu(conv2d(x, W_conv1) + b_conv1) 
h_pool1 = max_pool_2x2(h_conv1) 
_ = tf.histogram_summary('weights 1', W_conv1) 
_ = tf.histogram_summary('biases 1', b_conv1) 

# Second Variables 
W_conv2 = weight_variable([5, 5, 16, 32]) 
b_conv2 = bias_variable([32]) 

# Second Convolutional Layer 
h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2) 
h_pool2 = max_pool_2x2(h_conv2) 
_ = tf.histogram_summary('weights 2', W_conv2) 
_ = tf.histogram_summary('biases 2', b_conv2) 

# Fully connected Variables 
W_fc1 = weight_variable([7 * 7 * 32, 512]) 
b_fc1 = bias_variable([512]) 

# Fully connected Layer 
h_pool2_flat = tf.reshape(h_pool2, [-1, 7*7*32]) 
h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1)+b_fc1) 
_ = tf.histogram_summary('weights 3', W_fc1) 
_ = tf.histogram_summary('biases 3', b_fc1) 

# Drop out to reduce overfitting 
keep_prob = tf.placeholder("float") 
h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob) 

# Readout layer with sigmoid activation function. 
W_fc2 = weight_variable([512, 2]) 
b_fc2 = bias_variable([2]) 

with tf.name_scope('Wx_b'): 
    y_conv=tf.sigmoid(tf.matmul(h_fc1_drop, W_fc2)+b_fc2) 
    _ = tf.histogram_summary('weights 4', W_fc2) 
    _ = tf.histogram_summary('biases 4', b_fc2) 
    _ = tf.histogram_summary('y', y_conv) 

# Loss with squared errors 
with tf.name_scope('diff'): 
    error = tf.reduce_sum(tf.abs(tf.sub(y_,y_conv))) 
    diff = (error*error) 
    _ = tf.scalar_summary('diff', diff) 

# Train 
with tf.name_scope('train'): 
    train_step = tf.train.AdamOptimizer(1e-4).minimize(diff) 

# Merge summaries and write them out. 
merged = tf.merge_all_summaries() 
writer = tf.train.SummaryWriter('/home/user/TBlogs/oval_logs', sess.graph_def) 

# Add ops to save and restore all the variables. 
saver = tf.train.Saver() 

# Launch the session. 
sess.run(tf.initialize_all_variables()) 

# Restore variables from disk. 
saver.restore(sess, "/home/user/TBlogs/model.ckpt") 


for i in range(100000): 

    batch = oval.train.next_batch(50) 
    t_batch = oval.test.next_batch(50) 

    if i%10 == 0: 
     feed = {x:t_batch[0], y_: t_batch[1], keep_prob: 1.0} 
     result = sess.run([merged, diff], feed_dict=feed) 
     summary_str = result[0] 
     df = result[1] 

     writer.add_summary(summary_str, i) 
     print('Difference:%s' % (df) 
    else: 
     feed = {x:batch[0], y_: batch[1], keep_prob: 0.5} 
     sess.run(train_step, feed_dict=feed) 

    if i%1000 == 0: 
     save_path = saver.save(sess, "/home/user/TBlogs/model.ckpt") 

# Completion 
print("Session Done") 

Sono più preoccupato per come bordo tensore sembra dimostrare che i pesi sono a malapena cambiando di sorta, anche dopo ore e ore di formazione e un tasso di decomposizione di apprendimento (anche se non mostrato nel codice). La mia comprensione dell'apprendimento automatico è che, quando si convolgono le immagini, gli strati equivalgono effettivamente a livelli di rilevamento dei bordi ..... quindi sono confuso sul perché dovrebbero a malapena cambiare.

Le mie teorie al momento sono:
1. Ho trascurato/frainteso qualcosa riguardante la funzione di perdita.
2. Ho frainteso il modo in cui i pesi vengono inizializzati/aggiornati
3. Ho sottovalutato enormemente il tempo necessario per il processo ... anche se, di nuovo, la perdita sembra essere semplicemente oscillante.

Qualsiasi aiuto sarebbe molto apprezzato, grazie!

risposta

0

Da quello che posso vedere, la funzione di costo non è il solito errore quadratico medio.
Si sta ottimizzando tf.reduce_sum(tf.abs(tf.sub(y_,y_conv))) al quadrato. Questa funzione non è differenziabile in 0 (è il quadrato della norma l1). Questo può causare alcuni problemi di stabilità (specialmente nei passaggi di propagazione posteriore, non so quale tipo di sub-pendenza essi usano in questo caso).

Il solito errore quadratico medio può essere scritta come

residual = tf.sub(y_, y_conv) 
error = tf.reduce_mean(tf.reduce_sum(residual*residual, reduction_indices=[1])) 

(l'uso di media e somma è quello di evitare di avere valore dipende dalla dimensione del lotto). Questo è differenziabile e dovrebbe darti un comportamento migliore.