【问题标题】:Tensorflow: There is a difference in gradient and loss for the same structureTensorflow:相同结构的梯度和损失存在差异
【发布时间】:2018-12-30 13:50:50
【问题描述】:

通过梯度和损失,我尝试了神经网络的学习过程。

我假设如果两个模型的学习条件(模型结构、初始化、批量输入流)相同,则学习过程(损失函数值、梯度值)相同。

在同样的初始化下,我以为每个模型计算的梯度和损失会是一样的,结果却不一样。

我运行的代码是最基本的学习代码,如下图。

(为了限制 dropout 的随机性,我只是停用了 dropout 层)

import tensorflow as tf
import numpy as np
#from pprint import pprint
from tensorflow.examples.tutorials.mnist import input_data

batch_size = 128
test_size = 256

def init_weights(shape):
    return tf.Variable(tf.random_normal(shape, stddev=0.01, seed=1))

def model(X, w, w2, w3, w4, w_o, p_keep_conv, p_keep_hidden):

    l1a = tf.nn.relu(tf.nn.conv2d(X, w,                       # l1a shape=(?, 28, 28, 32)
                        strides=[1, 1, 1, 1], padding='SAME'))
    l1 = tf.nn.max_pool(l1a, ksize=[1, 2, 2, 1],              # l1 shape=(?, 14, 14, 32)
                        strides=[1, 2, 2, 1], padding='SAME')
    #l1 = tf.nn.dropout(l1, p_keep_conv)

    l2a = tf.nn.relu(tf.nn.conv2d(l1, w2,                     # l2a shape=(?, 14, 14, 64)
                        strides=[1, 1, 1, 1], padding='SAME'))
    l2 = tf.nn.max_pool(l2a, ksize=[1, 2, 2, 1],              # l2 shape=(?, 7, 7, 64)
                        strides=[1, 2, 2, 1], padding='SAME')
    #l2 = tf.nn.dropout(l2, p_keep_conv)

    l3a = tf.nn.relu(tf.nn.conv2d(l2, w3,                     # l3a shape=(?, 7, 7, 128)
                        strides=[1, 1, 1, 1], padding='SAME'))
    l3 = tf.nn.max_pool(l3a, ksize=[1, 2, 2, 1],              # l3 shape=(?, 4, 4, 128)
                        strides=[1, 2, 2, 1], padding='SAME')
    l3 = tf.reshape(l3, [-1, w4.get_shape().as_list()[0]])    # reshape to (?, 2048)
    #l3 = tf.nn.dropout(l3, p_keep_conv)

    l4 = tf.nn.relu(tf.matmul(l3, w4))
    #l4 = tf.nn.dropout(l4, p_keep_hidden)

    pyx = tf.matmul(l4, w_o)
    return pyx


mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
trX, trY, teX, teY = mnist.train.images, mnist.train.labels, mnist.test.images, mnist.test.labels
trX = trX.reshape(-1, 28, 28, 1)  # 28x28x1 input img
teX = teX.reshape(-1, 28, 28, 1)  # 28x28x1 input img

X0 = tf.placeholder("float", [None, 28, 28, 1], name='input_0')
X1 = tf.placeholder("float", [None, 28, 28, 1], name='input_1')
Y  = tf.placeholder("float", [None, 10])

with tf.variable_scope('00'):
    w0_1 = init_weights([3, 3, 1, 32])       # 3x3x1 conv, 32 outputs
    w0_2 = init_weights([3, 3, 32, 64])     # 3x3x32 conv, 64 outputs
    w0_3 = init_weights([3, 3, 64, 128])    # 3x3x32 conv, 128 outputs
    w0_4 = init_weights([128 * 4 * 4, 625]) # FC 128 * 4 * 4 inputs, 625 outputs
    w0_o = init_weights([625, 10])         # FC 625 inputs, 10 outputs (labels)

with tf.variable_scope('01'):
    w1_1 = init_weights([3, 3, 1, 32])       # 3x3x1 conv, 32 outputs
    w1_2 = init_weights([3, 3, 32, 64])     # 3x3x32 conv, 64 outputs
    w1_3 = init_weights([3, 3, 64, 128])    # 3x3x32 conv, 128 outputs
    w1_4 = init_weights([128 * 4 * 4, 625]) # FC 128 * 4 * 4 inputs, 625 outputs
    w1_o = init_weights([625, 10])         # FC 625 inputs, 10 outputs (labels)


p_keep_conv = tf.placeholder("float")
p_keep_hidden = tf.placeholder("float")

py_x0 = model(X0, w0_1, w0_2, w0_3, w0_4, w0_o, p_keep_conv, p_keep_hidden)
py_x1 = model(X1, w1_1, w1_2, w1_3, w1_4, w1_o, p_keep_conv, p_keep_hidden)



cost0 = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=py_x0, labels=Y))
cost1 = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=py_x1, labels=Y))



model_0_vars = [tensor for tensor in tf.trainable_variables() if '00/' in tensor.name]
model_1_vars = [tensor for tensor in tf.trainable_variables() if '01/' in tensor.name]

#pprint(model_0_vars)
#pprint(model_1_vars)


train_op_model_0_grad = tf.train.RMSPropOptimizer(0.001, 0.9).compute_gradients(cost0, var_list = model_0_vars)
train_op_model_0_apply= tf.train.RMSPropOptimizer(0.001, 0.9).apply_gradients(train_op_model_0_grad)


train_op_model_1_grad = tf.train.RMSPropOptimizer(0.001, 0.9).compute_gradients(cost1, var_list = model_1_vars)
train_op_model_1_apply= tf.train.RMSPropOptimizer(0.001, 0.9).apply_gradients(train_op_model_1_grad)


predict_op_0 = tf.argmax(py_x0, 1)
predict_op_1 = tf.argmax(py_x1, 1)



# Launch the graph in a session
with tf.Session() as sess:
    # you need to initialize all variables
    tf.initialize_all_variables().run()



    step = 0
    for i in range(2):
        #check_weight_tmp = sess.run([model_0_vars, model_1_vars])
        #check_weight.append(check_weight_tmp)

        training_batch = zip(range(0, len(trX), batch_size),
                             range(batch_size, len(trX)+1, batch_size))


        for start, end in training_batch:
            step +=1

            grad0, grad1 = \
            sess.run([train_op_model_0_grad, train_op_model_1_grad], 
                     feed_dict={X0: trX[start:end], X1: trX[start:end], Y: trY[start:end],
                                p_keep_conv: 0.8, p_keep_hidden: 0.5})


            cost0_r, cost1_r = \
            sess.run([cost0, cost1], 
                     feed_dict={X0: trX[start:end], X1: trX[start:end], Y: trY[start:end],
                                p_keep_conv: 0.8, p_keep_hidden: 0.5})

            sess.run([train_op_model_0_apply, train_op_model_1_apply],
                      feed_dict={X0: trX[start:end], X1: trX[start:end], Y: trY[start:end],
                                 p_keep_conv: 0.8, p_keep_hidden: 0.5})


            print("STEP: {0:5d}, {1:3.6f}, {2:3.6f}, {3:3.6f}".format(step, cost0_r, cost1_r, cost0_r - cost1_r))



        #test_indices = np.arange(len(teX)) # Get A Test Batch
        #np.random.shuffle(test_indices)
        #test_indices = test_indices[0:test_size]

        #print(i, np.mean(np.argmax(teY[test_indices], axis=1) ==
        #                 sess.run(predict_op_0,
        #                          feed_dict={X: teX[test_indices],
        #                                     Y: teY[test_indices],
        #                                     p_keep_conv: 1.0,
        #                                     p_keep_hidden: 1.0})))

与第 200 个 epoch 的损失有明显差异。

我想我错过了,但我花了很长时间看它也想不通。

如果你能告诉我我缺少什么,我将不胜感激。

【问题讨论】:

  • 在不仔细查看代码的情况下,您是否尝试在一个模型完全训练后将随机生成器重置为种子?有关详细信息,请参阅tf.set_random_seed()
  • 据我所知,上传代码的 tf.random_normal(shape, stddev=0.01, seed=1) 中的“种子”实际上是强制random_normal生成器生成相同的序列,而这个与使用 tf.set_random_seed("seed") 完全相同。但是,无论如何我都会尝试 tf.set_random_seed() 来检查 tf.random_seed() 和正态分布的特定随机值生成器之间是否存在差异。
  • 我试过你提到的 tf.set_random_seed() ,而不是修复随机生成器的种子,但结果是一样的。尽管如此,我还是无法弄清楚为什么两个模型的每个梯度和损失是不同的,而不是相同的。
  • 是的,您的 random_normal 中的种子也已被记录,但您永远不知道 TensorFlow 在哪里使用了随机性。您是否还比较了第一个模型在不同运行中的值?他们是一样的吗?那么确实是 where 你设置了 random_seed 的问题
  • 我发现了一些与这个问题相关的问题,似乎他们称之为稳定结果问题。 stackoverflow.com/questions/42156296/…> stackoverflow.com/questions/36288235/…> 有人指出并行计算由于独立于循环的先前值而导致结果不稳定。 (我没有完全理解这意味着什么,但可能是计算 mini-batch 的梯度导致了问题?)

标签: python tensorflow gradient


【解决方案1】:

当程序已经训练自己识别数据并且现在过度概括输入时,可能会由于过度拟合而发生这种损失差异。我在训练音频工具时亲身体验过。

【讨论】:

    猜你喜欢
    • 2021-08-17
    • 2018-04-13
    • 2020-05-03
    • 1970-01-01
    • 1970-01-01
    • 2022-01-07
    • 2019-12-14
    • 1970-01-01
    • 2021-02-24
    相关资源
    最近更新 更多