2016-04-20 3 views
2

Я использую shadoworflow для репликации нейронной сети для набора данных MNIST, ранее запрограммированного в skflow. Вот модель в skflow:Модель tensorflow имеет разные результаты, чем та же модель в skflow (оптимизатор)

import tensorflow.contrib.learn as skflow 
from sklearn import metrics 
from sklearn.datasets import fetch_mldata 
from sklearn.cross_validation import train_test_split 

mnist = fetch_mldata('MNIST original') 

train_dataset, test_dataset, train_labels, test_labels = train_test_split(mnist.data, mnist.target, test_size=10000, random_state=42) 

classifier = skflow.TensorFlowDNNClassifier(hidden_units=[1200, 1200], n_classes=10, optimizer="SGD", learning_rate=0.01, batch_size=128, steps=1000) 
classifier.fit(train_dataset, train_labels) 
score = metrics.accuracy_score(test_labels, classifier.predict(test_dataset)) 
print("Accuracy: %f" % score) 

Эта модель получает точность 0.950600.

Но модель, реплицируемая в тензорном потоке, получает nan в убытке fuction и не улучшается (я думаю, что это не связано с Tensorflow NaN bug?, так как я использую tf.nn.softmax_cross_entropy_with_logits).

Я не могу понять, почему, поскольку установка модели в тензорном потоке такая же, как в модели в skflow. Единственное, что я не уверен, что это то же самое, - это то, как skflow инициализирует весы сети, я искал эту часть в коде skflow, но я ее не нашел.

Вот код в tensorflow:

import numpy as np 
import tensorflow as tf 
from sklearn.cross_validation import train_test_split 
from sklearn.datasets import fetch_mldata 

mnist = fetch_mldata('MNIST original') 

num_labels = len(np.unique(mnist.target)) 
num_pixels = mnist.data.shape[1] 

#reshape labels to one hot encoding 
labels = (np.arange(num_labels) == mnist.target[:, None]).astype(np.float32) 

#create train_dataset of 60000 and test_dataset of 10000 elem 
train_dataset, test_dataset, train_labels, test_labels = train_test_split(mnist.data, labels, test_size=10000, random_state=42) 


def accuracy(predictions, labels): 
    return (100.0 * np.sum(np.argmax(predictions, 1) == np.argmax(labels, 1))/predictions.shape[0]) 


batch_size = 128 
graph = tf.Graph() 
with graph.as_default(): 

    # Input data. 
    tf_train_dataset = tf.placeholder(tf.float32, 
            shape=(batch_size, num_pixels)) 
    tf_train_labels = tf.placeholder(tf.float32, shape=(batch_size, num_labels)) 
    tf_test_dataset = tf.cast(tf.constant(test_dataset), tf.float32) 

    w_hidden = tf.Variable(tf.truncated_normal([num_pixels, 1200])) 
    b_hidden = tf.Variable(tf.zeros([1200])) 
    hidden = tf.nn.relu(tf.matmul(tf_train_dataset, w_hidden) + b_hidden) 

    w_hidden_2 = tf.Variable(tf.truncated_normal([1200, 1200])) 
    b_hidden_2 = tf.Variable(tf.zeros([1200])) 
    hidden2 = tf.nn.relu(tf.matmul(hidden, w_hidden_2) + b_hidden_2) 

    w = tf.Variable(tf.truncated_normal([1200, num_labels])) 
    b = tf.Variable(tf.zeros([num_labels])) 
    logits = tf.matmul(hidden2, w) + b 

    loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(
    logits, tf_train_labels)) 

    # Optimizer. 
    optimizer = tf.train.GradientDescentOptimizer(0.01).minimize(loss) 

    # Predictions for the training, and test data. 
    train_prediction = tf.nn.softmax(logits) 
    test_prediction = tf.nn.softmax(tf.matmul(tf.nn.relu(tf.matmul(tf.nn.relu(tf.matmul(tf_test_dataset, w_hidden) + b_hidden), w_hidden_2) + b_hidden_2), w) + b) 

num_steps = 1001 

with tf.Session(graph=graph) as session: 
    tf.initialize_all_variables().run() 
    print("Initialized") 
    for step in range(num_steps): 
     # Pick an offset within the training data, which has been randomized. 
     offset = (step * batch_size) % (train_labels.shape[0] - batch_size) 

     # Generate a minibatch. 
     batch_data = train_dataset[offset:(offset + batch_size), :] 
     batch_labels = train_labels[offset:(offset + batch_size), :] 

     # Prepare a dictionary telling the session where to feed the minibatch. 
     feed_dict = {tf_train_dataset: batch_data, tf_train_labels: batch_labels} 
     _, l, predictions = session.run([optimizer, loss, train_prediction], feed_dict=feed_dict) 
     if (step % 100 == 0): 
      print("Minibatch loss at step %d: %f" % (step, l)) 
      print("Minibatch accuracy: %.1f%%" % accuracy(predictions, batch_labels)) 
    print("Test accuracy: %.1f%%" % accuracy(test_prediction.eval(), test_labels)) 

Я невежественный на то, что может быть проблемой. Какие-либо предложения?

Отредактировано 1: Как мне предложили, я попытался заменить tf.Variable звонки с tf.get_variable ("w_hidden", [num_pixels, 1200]), но я получил Nans.

Кроме того, я использовал skflow.ops.dnn op для выполнения слоев и использовал свои собственные потери и т. Д., И до сих пор получил Nans.

Отредактировано 2: Оказывается, это не проблема инициализации веса. Кажется, что градиенты слишком неустойчивы (в модели тензорного потока) и приводят к тому, что потеря становится NaN. Как и в Adding multiple layers to TensorFlow causes loss function to become Nan, я замедлял скорость обучения на порядок, и это сработало.

Теперь я не понимаю, что отличается между оптимизатором SGD skflow и выше. Или что объясняет, что они «кажутся» равными, но им нужны разные учебные курсы?

ответ

0

Инициализация в skflow основана на tf.get_variable инициализации по умолчанию - uniform_unit_scaling_initializer (см. this для подробного описания).

Вы можете попробовать заменить свои звонки tf.Variable примерно на tf.get_variable("w_hidden", [num_pixels, 1200]).

Альтернатива, чтобы начать с помощью skflow.ops.dnn оп, который будет делать слои для вас, но вы по-прежнему делать свои собственные потери и т.д.

Также, пожалуйста, дайте мне знать, если вы там ясно UseCase, что заставил вас переписать вещи в чистом TensorFlow вместо использования skflow - я бы с удовольствием рассмотрел его. Вы всегда можете написать собственную модель, пройдя model_fn в TensorFlowEstimator и по-прежнему пользуйтесь функциями обучения/пакетной/экономии и т. Д.

+0

Привет @ilblackdragon Я попытался заменить tf.Variable вызовы во всех весах, а затем в весах и смещениях, но я все еще получаю nans в функции потерь. Цель репликации модели в тензорном потоке заключается в следующем: я пытаюсь реплицировать результаты Distill Knowledge в наборе данных MNIST, я начал развиваться с помощью skflow, потому что я больше знаком с миром sklearn, но в skflow у меня нет ту же свободу играть с функцией loss/softmax или с ярлыками, потому что я нуждаюсь в них как вероятности. – Ismael

+0

привет @ilblackdragon, я снова, но с плохими новостями, теперь я пробовал использовать skflow.ops.dnn op, хороший hack btw, но я все еще получаю nan в функции потерь. Теперь я очень беспокоился об этом, поэтому я попробовал другую настройку, на этот раз только используя один скрытый слой (relu) с 1200 нейронами как в skflow, так и в тензорном потоке (используя dnn op), и я неожиданно получил то, что ожидалось, одинаковая точность в обеих моделях (около 0,93 без nans). Поэтому снова я не знаю, что может быть проблемой при использовании [1200, 1200] в качестве скрытых слоев. – Ismael

+0

@ismael Вы можете использовать 'predict_proba' для получения исходной вероятности. Вы также можете определить свою собственную функцию потерь и передать ее в пользовательскую функцию модели, как указано в приведенном выше ответе. –

Смежные вопросы