TensorFlow: Resultados não repetíveis

O problema

Eu tenho um script Python que usa o TensorFlow para criar uma rede perceptron multicamada (com abandono) para fazer a classificação binária. Embora tenha sido cuidadoso ao definir as sementes Python e TensorFlow, obtenho resultados não repetíveis. Se eu corro uma vez e depois corro novamente, obtenho resultados diferentes. Posso até executar uma vez, sair do Python, reiniciar o Python, executar novamente e obter resultados diferentes.

O que eu tentei

Sei que algumas pessoas postaram perguntas sobre como obter resultados não repetíveis no TensorFlow (por exemplo,"Como obter resultados estáveis ...", "set_random_seed não está funcionando ...", "Como obter resultado reproduzível no TensorFlow"), e as respostas geralmente acabam sendo um uso / entendimento incorretos detf.set_random_seed(). Fiz questão de implementar as soluções fornecidas, mas isso não resolveu o meu problema.

Um erro comum é não perceber quetf.set_random_seed() é apenas uma semente no nível do gráfico e que a execução do script várias vezes alterará o gráfico, explicando os resultados não repetíveis. Usei a seguinte declaração para imprimir o gráfico inteiro e verifiquei (via diff) que o gráfico é o mesmo, mesmo quando os resultados são diferentes.

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

Eu também usei chamadas de função comotf.reset_default_graph() etf.get_default_graph().finalize() para evitar alterações no gráfico, mesmo que isso seja provavelmente um exagero.

O Código (Relevante)

Meu script tem ~ 360 linhas, então aqui estão as linhas relevantes (com o código destacado indicado). Todos os itens que estão em ALL_CAPS são constantes definidas no meuParameters bloco abaixo.

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()
O que não é repetível

Como você pode ver, estou exibindo resultados durante cada época em um arquivo e também imprimindo números de precisão no final. Nenhuma delas corresponde de uma corrida para outra, mesmo que eu acreditei ter definido as sementes corretamente. Eu usei ambosrandom.seed(12345) etf.set_random_seed(12345)

Informe-me se precisar fornecer mais informações. E obrigado antecipadamente por qualquer ajuda.

-DG

Detalhes de configuração

TensorFlow versão 0.8.0 (apenas CPU)
Enthought Canopy versão 1.7.2 (Python 2.7, não 3. +)
Mac OS X versão 10.11.3

questionAnswers(3)

yourAnswerToTheQuestion