2016-07-19 53 views
6

的問題

我有,爲了做到二元分類使用TensorFlow創建多層感知網絡(與輟學)的Python腳本。儘管我一直很小心地設置Python和TensorFlow種子,但我得到了不可重複的結果。如果我跑一次然後再跑,我會得到不同的結果。我甚至可以運行一次,退出Python,重新啓動Python,再次運行並獲得不同的結果。TensorFlow:非可重複的結果

我已經試過

我知道有些人發佈有關獲取非重複的結果中TensorFlow問題(例如,"How to get stable results...""set_random_seed not working...""How to get reproducible result in TensorFlow"),答案往往變成是一個不正確的使用/理解tf.set_random_seed()。我已經確保實施給出的解決方案,但是這並沒有解決我的問題。

一個常見的錯誤是沒有意識到tf.set_random_seed()只是一個圖形級別的種子,並且多次運行腳本會改變圖形,解釋不可重複的結果。我用下面的語句打印出整個圖,並驗證(通過差異)即使結果不同,圖也是一樣的。

print [n.name for n in tf.get_default_graph().as_graph_def().node] 

我也用函數調用像tf.reset_default_graph()tf.get_default_graph().finalize()避免對圖中的任何改變,即使這可能是矯枉過正。

的(相關)代碼

我的腳本〜360線長,所以這裏是相關的線(與文檔片斷代碼所示)。 ALL_CAPS中的任何項目都是在我的Parameters塊中定義的常量。

import numpy as np 
import tensorflow as tf 

from copy import deepcopy 
from tqdm import tqdm # Progress bar 

# --------------------------------- Parameters --------------------------------- 
(snip) 

# --------------------------------- Functions --------------------------------- 
(snip) 

# ------------------------------ Obtain Train Data ----------------------------- 
(snip) 

# ------------------------------ Obtain Test Data ----------------------------- 
(snip) 

random.seed(12345) 
tf.set_random_seed(12345) 

(snip) 

# ------------------------- Build the TensorFlow Graph ------------------------- 

tf.reset_default_graph() 

with tf.Graph().as_default(): 

    x = tf.placeholder("float", shape=[None, N_INPUT]) 
    y_ = tf.placeholder("float", shape=[None, N_CLASSES]) 

    # Store layers weight & bias 
    weights = { 
     'h1': tf.Variable(tf.random_normal([N_INPUT, N_HIDDEN_1])), 
     'h2': tf.Variable(tf.random_normal([N_HIDDEN_1, N_HIDDEN_2])), 
     'h3': tf.Variable(tf.random_normal([N_HIDDEN_2, N_HIDDEN_3])), 
     'out': tf.Variable(tf.random_normal([N_HIDDEN_3, N_CLASSES])) 
    } 

    biases = { 
     'b1': tf.Variable(tf.random_normal([N_HIDDEN_1])), 
     'b2': tf.Variable(tf.random_normal([N_HIDDEN_2])), 
     'b3': tf.Variable(tf.random_normal([N_HIDDEN_3])), 
     'out': tf.Variable(tf.random_normal([N_CLASSES])) 
    } 

# Construct model 
    pred = multilayer_perceptron(x, weights, biases, USE_DROP_LAYERS, DROP_KEEP_PROB) 

    mean1 = tf.reduce_mean(weights['h1']) 
    mean2 = tf.reduce_mean(weights['h2']) 
    mean3 = tf.reduce_mean(weights['h3']) 

    cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(pred, y_)) 

    regularizers = (tf.nn.l2_loss(weights['h1']) + tf.nn.l2_loss(biases['b1']) + 
        tf.nn.l2_loss(weights['h2']) + tf.nn.l2_loss(biases['b2']) + 
        tf.nn.l2_loss(weights['h3']) + tf.nn.l2_loss(biases['b3'])) 

    cost += COEFF_REGULAR * regularizers 

    optimizer = tf.train.GradientDescentOptimizer(LEARNING_RATE).minimize(cost) 

    out_labels = tf.nn.softmax(pred) 

    sess = tf.InteractiveSession() 
    sess.run(tf.initialize_all_variables()) 

    tf.get_default_graph().finalize() # Lock the graph as read-only 

    #Print the default graph in text form  
    print [n.name for n in tf.get_default_graph().as_graph_def().node] 

    # --------------------------------- Training ---------------------------------- 

    print "Start Training" 
    pbar = tqdm(total = TRAINING_EPOCHS) 
    for epoch in range(TRAINING_EPOCHS): 
     avg_cost = 0.0 
     batch_iter = 0 

     train_outfile.write(str(epoch)) 

     while batch_iter < BATCH_SIZE: 
      train_features = [] 
      train_labels = [] 
      batch_segments = random.sample(train_segments, 20) 
      for segment in batch_segments: 
       train_features.append(segment[0]) 
       train_labels.append(segment[1]) 
      sess.run(optimizer, feed_dict={x: train_features, y_: train_labels}) 
      line_out = "," + str(batch_iter) + "\n" 
      train_outfile.write(line_out) 
      line_out = ",," + str(sess.run(mean1, feed_dict={x: train_features, y_: train_labels})) 
      line_out += "," + str(sess.run(mean2, feed_dict={x: train_features, y_: train_labels})) 
      line_out += "," + str(sess.run(mean3, feed_dict={x: train_features, y_: train_labels})) + "\n" 
      train_outfile.write(line_out) 
      avg_cost += sess.run(cost, feed_dict={x: train_features, y_: train_labels})/BATCH_SIZE 
      batch_iter += 1 

     line_out = ",,,,," + str(avg_cost) + "\n" 
     train_outfile.write(line_out) 
     pbar.update(1) # Increment the progress bar by one 

    train_outfile.close() 
    print "Completed training" 


# ------------------------------ Testing & Output ------------------------------ 

keep_prob = 1.0 # Do not use dropout when testing 

print "now reducing mean" 
print(sess.run(mean1, feed_dict={x: test_features, y_: test_labels})) 

print "TRUE LABELS" 
print(test_labels) 
print "PREDICTED LABELS" 
pred_labels = sess.run(out_labels, feed_dict={x: test_features}) 
print(pred_labels) 

output_accuracy_results(pred_labels, test_labels) 

sess.close() 

什麼是不可重複的

正如你所看到的,我輸出每個時期到一個文件中的結果,並在最後打印出精確的數字。儘管我相信我已經正確設置了種子,但這些都不會從運行到運行。我用過random.seed(12345)tf.set_random_seed(12345)

請讓我知道是否需要提供更多信息。並提前感謝任何幫助。

-DG

建立細節

TensorFlow版本0.8.0(僅CPU)
Enthought篷版本1.7.2(Python 2.7版,而不是3 +)
Mac OS X版本10.11.3

回答

5

您需要設置操作水平種子除了繪製一級的種子,即

tf.reset_default_graph() 
a = tf.constant([1, 1, 1, 1, 1], dtype=tf.float32) 
graph_level_seed = 1 
operation_level_seed = 1 
tf.set_random_seed(graph_level_seed) 
b = tf.nn.dropout(a, 0.5, seed=operation_level_seed) 
+0

哇。你是否需要爲_every_操作設置操作級別的種子?所有的'tf.placeholder','tf.Variable','tf.reduce_mean'等等? – DojoGojira

+2

不,只是那些有隨機性的人 –

+1

@Yaroslav我不明白:我會假設'tf.set_random_seed()'的作用是影響圖中的所有隨機操作,所以你不必設置爲每個隨機運算符手動創建一個種子它有什麼用途?從[doc](https://www.tensorflow.org/versions/r0.11/api_docs/python/constant_op.html#set_random_seed)中的示例中,他們只設置全局種子以獲得可重複的結果。 – toto2

5

看到這張圖流github issue。 GPU上的一些操作並不完全確定(速度與精度)。

我還觀察到,對於種子產生任何影響,tf.set_random_seed(...)必須調用創建Session之前。此外,您應該在每次運行代碼時徹底重新啓動python解釋器,或者在開始時調用tf.reset_default_graph()

0

只需添加到Yaroslav的答案,除了操作和圖形級種子之外,還應該設置numpy種子,因爲一些後端操作依賴於numpy。這對我來說訣竅np.random.seed()Tensorflow V 1.1.0