代码之家  ›  专栏  ›  技术社区  ›  I. A Ziang Yan

即使设置了随机种子,也无法复制TensorFlow结果

  •  0
  • I. A Ziang Yan  · 技术社区  · 6 年前

    为了能够执行超参数优化,我想最好设置随机种子,这样我们将更好地比较模型。因此,我在TensorFlow-Through中设置了随机种子: tf.set_random_seed(mseed) ,并且我创建了初始值设定项as: kernel_initializer=tf.glorot_normal_initializer(seed=mseed) wherei passed the later into the lstm. cell。所以模型如下:

    导入tensorflow as tf 将numpy导入为np def lstm_模型(lstm_模型(输入、单元格大小1、内核初始值设定项、m_dtype、退出、IS_培训、使用_窥视孔、mseed、num_类): 使用tf.变量_scope(“lstm_model”): cell=tf.nn.rnn_cell.lstmcell(cell_size1,initializer=kernel_initializer) 初始_状态=cell.zero_状态(34如果是_training else 14,dtype=tf.float32) 输出,新的状态=tf.nn.dynamic\u rnn(单元格,输入,数据类型=m\u dtype,初始\u状态=初始\u状态) 使用tf.variable_scope(“输出”): 输出=tf.整形(输出,形状=[-1,单元格大小1]) 输出=tf.layers.close(输出,单位=num_类, kernel_initializer=内核_initializer) 如果ISSL培训: output=tf.remote(输出,shape=[34,-1,num_类]) 其他: output=tf.remote(输出,shape=[14,-1,num_类]) 返回输出,新状态,初始状态,模型摘要 def模型(inputs…,mseed,kernel_initializer,reuse=false): 使用tf.variable_scope(“模型”,重用=重用): 输出,新_状态,初始_状态,模型_摘要=lstm_模型(输入,num_单位, 内核初始值设定项, tf.float32,退出,不重用,真, mseed,num_classes=num_类) #现在我计算损失,并在培训的情况下使用优化器… 返回输出,新状态,初始状态,模型摘要 M种子=123 种子(种子) tf.设置随机种子(毫秒) 内核初始值设定项=tf.glorot正常初始值设定项(seed=mseed) #在这里,我将数据作为numpy数组加载… #在这里我创造了占位符… #T代表火车,D代表发展 output_t,new_state_t,init_state_t=模型(inputs_t…,mseed,kernel_initializer,reuse=false) output_d,new_state_d,init_state_d=模型(inputs_d…,mseed,kernel_initializer,reuse=true) 训练_模型()… < /代码>

    因此,代码总结为只包含其中的重要部分。

    现在,即使在设置随机种子并在创建内核时使用 mseed

    这里是一个屏幕截图的准确性和损失随着时间的推移。我们可以看到,这些值在开始时几乎是相同的,然后变得不同。

    我想知道哪里可能出错,或者至少知道代码的调试部分。最后,请注意,通过out训练,我将把最后一个隐藏状态反馈到每个批次的初始状态。如下:

    new_state_train_py=sess.run(initiale_state_train)
    对于范围内的i(num_迭代次数):
    _,summary_t,new_state_train_py=sess.run([训练步骤,summary_train,new_state_train],
    feed_dict=train_x_ph:train_x[:,i*时间步数:(i+1)*时间步数,:],
    列车速度:列车速度[:,i*时间步数:(i+1)*时间步数,:]
    初始状态训练:新状态训练
    
    训练编写器。添加摘要(摘要,epoch*num_iterations+i)
    < /代码> 
    
    

    到目前为止,我所知道的是,主要问题应该在模型定义中,因为这个定义了整个模型中的任何随机性,这就是使同一个模型的不同运行之间的预测不同的原因。如果我弄错了,请纠正我。

    调试后,我注意到,当我将图表中每个op的数据类型更改为tf.float64时,我发现两条曲线完全相交,除了在结尾处,曲线中还有一个细微的变化。是什么导致了这种行为?

    非常感谢您的帮助!!TensorFlow中的种子通过:tf.set_random_seed(mseed),我创建了一个初始值设定项,如下所示:kernel_initializer = tf.glorot_normal_initializer(seed=mseed)后来我通过了LSTM细胞。因此模型如下:

    import tensorflow as tf
    import numpy as np
    
    
    def lstm_model(lstm_model(inputs, cell_size1, kernel_initializer, m_dtype, dropout, is_training, use_peepholes, mseed, num_classes):
    
        with tf.variable_scope('lstm_model'):
    
            cell = tf.nn.rnn_cell.LSTMCell(cell_size1, initializer=kernel_initializer)
            initial_state = cell.zero_state(34 if is_training else 14, dtype=tf.float32)
    
            output, new_state = tf.nn.dynamic_rnn(cell, inputs, dtype=m_dtype, initial_state=initial_state)
    
    
        with tf.variable_scope("output"):
            output = tf.reshape(output, shape=[-1, cell_size1])
            output = tf.layers.dense(output, units=num_classes,
                                     kernel_initializer=kernel_initializer)
    
            if is_training:
                output = tf.reshape(output, shape=[34, -1, num_classes])
            else:
                output = tf.reshape(output, shape=[14, -1, num_classes])
    
            return output, new_state, initial_state, model_summary
    
    
    def model(inputs..., mseed, kernel_initializer, reuse=False):
        with tf.variable_scope('model', reuse=reuse):
    
            output, new_state, initial_state, model_summary = lstm_model(inputs, num_units,
                                                                         kernel_initializer,
                                                                         tf.float32, dropout, not reuse, True,
                                                                         mseed, num_classes=num_classes)
    
        # Now I calculate the loss and used an optimizer in case of training...
        return output, new_state, initial_state, model_summary
    
    mseed = 123
    seed(mseed)
    tf.set_random_seed(mseed)
    kernel_initializer = tf.glorot_normal_initializer(seed=mseed)
    
    # here I loaded the data as numpy arrays...
    # Here I created the placeholders...
    
    # t for train, and d for development
    output_t, new_state_t, init_state_t = model(inputs_t..., mseed, kernel_initializer, reuse=False)
    output_d, new_state_d, init_state_d = model(inputs_d..., mseed, kernel_initializer, reuse=True)
    
    train_model()...
    

    因此,代码被总结为只包含其中的重要部分。

    现在,即使在设置随机种子并使用mseed当创建内核时,我不能复制相同的结果。

    这里是一个屏幕截图的准确性和损失随着时间的推移。我们可以看到,这些值在开始时几乎是相同的,然后变得不同。

    enter image description here

    enter image description here

    我想知道哪里可能出错,或者至少知道代码的调试部分。最后,请注意,通过out训练,我将把最后一个隐藏状态反馈到每个批次的初始状态。如下:

    new_state_train_py = sess.run(initiale_state_train)
        for i in range(num_iterations):
            _, summary_t, new_state_train_py = sess.run([train_step, summary_train, new_state_train],
                                    feed_dict={train_x_ph: train_x[:, i*time_steps: (i + 1) * time_steps, :],
                                               train_y_ph: train_y[:, i*time_steps: (i + 1) * time_steps, :],
                                               initiale_state_train: new_state_train_py})
    
            train_writer.add_summary(summary_t, epoch * num_iterations + i)
    

    到目前为止,我所知道的是,主要问题应该在模型定义中,因为这个定义了整个模型中的任何随机性,这就是使同一个模型的不同运行之间的预测不同的原因。如果我弄错了,请纠正我。

    在调试之后,我注意到,当我将图中每个op的数据类型更改为tf.float64时,我发现两条曲线完全相交,除了在末尾,曲线中还有一个微小的变化。是什么导致了这种行为?

    enter image description here enter image description here

    非常感谢您的帮助!!

    1 回复  |  直到 6 年前
        1
  •  1
  •   Kilian Batzner    6 年前

    如果您在GPU上运行代码,很可能是由于CUDN的不确定性行为(请参见 this thread 了解更多详细信息)。由于性能优化,在GPU上执行某些操作的顺序可能是随机的。这意味着舍入误差也会以不同的顺序出现,这会导致这些操作结果的细微差异。在您的案例中,这些细微的差异在培训过程中累积起来,这会导致在几个培训步骤之后已经有显著不同的行为。

    舍入误差的大小取决于GPU使用的浮点精度。用 float64 ,四舍五入误差加起来要比加起来明显长得多。 float32 .

    在CPU上,当Python的 numpy S和 tensorflow 的随机种子是固定的。因此,如果您在CPU上运行代码,那么每次运行都应该得到相同的结果(当然,这需要更长的时间)。

    推荐文章