【问题标题】:TensorFlow TrainingTensorFlow 训练
【发布时间】:2016-03-09 22:10:39
【问题描述】:

假设我有一个非常简单的神经网络,比如多层感知器。对于每一层,激活函数都是 sigmoid,网络是全连接的。

在 TensorFlow 中,这可能是这样定义的:

    sess = tf.InteractiveSession()

    # Training Tensor
    x = tf.placeholder(tf.float32, shape = [None, n_fft])
    # Label Tensor
    y_ = tf.placeholder(tf.float32, shape = [None, n_fft])

    # Declaring variable buffer for weights W and bias b
    # Layer structure [n_fft, n_fft, n_fft, n_fft]
    # Input -> Layer 1
    struct_w = [n_fft, n_fft]
    struct_b = [n_fft]
    W1 = weight_variable(struct_w, 'W1')
    b1 = bias_variable(struct_b, 'b1')
    h1 = tf.nn.sigmoid(tf.matmul(x, W1) + b1)

    # Layer1 -> Layer 2
    W2 = weight_variable(struct_w, 'W2')
    b2 = bias_variable(struct_b, 'b2')
    h2 = tf.nn.sigmoid(tf.matmul(h1, W2) + b2)

    # Layer2 -> output
    W3 = weight_variable(struct_w, 'W3')
    b3 = bias_variable(struct_b, 'b3')
    y = tf.nn.sigmoid(tf.matmul(h2, W3) + b3)

    # Calculating difference between label and output using mean square error
    mse = tf.reduce_mean(tf.square(y - y_))

    # Train the Model
    # Gradient Descent
    train_step = tf.train.GradientDescentOptimizer(0.3).minimize(mse)

此模型的设计目标是将n_fft 点 fft 频谱图映射到另一个 n_fft 目标频谱图。假设训练数据和目标数据的大小均为[3000, n_fft]。它们存储在变量spec_trainspec_target 中。

现在问题来了。对于 TensorFlow,这两种训练有什么区别吗?

培训1:

for i in xrange(200):
        train_step.run(feed_dict = {x: spec_train, y_: spec_target})

培训2:

for i in xrange(200):
        for j in xrange(3000):
            train = spec_train[j, :].reshape(1, n_fft)
            label = spec_target[j, :].reshape(1, n_fft)
            train_step.run(feed_dict = {x: train, y_: label})

非常感谢!

【问题讨论】:

    标签: neural-network tensorflow


    【解决方案1】:

    在第一个训练版本中,您是一次训练整批训练数据,这意味着spec_train 的第一个和第 3000 个元素将使用相同的模型参数在一个步骤中进行处理。这称为(批量)梯度下降

    在第二个训练版本中,您一次从训练数据中训练一个示例,这意味着spec_train 的第 3000 个元素将使用自第一个元素最频繁更新以来已更新 2999 次的模型参数进行处理最近处理的。这称为随机梯度下降(或者如果元素是随机选择的)。

    一般而言,TensorFlow 用于处理太大而无法一次处理的数据集,因此小批量 SGD(其中一个示例的子集在一个步骤中处理)更受青睐。一次处理单个元素在理论上是可取的,但本质上是顺序的并且具有很高的固定成本,因为矩阵乘法和其他操作的计算密集度不高。因此,一次处理小批量(例如 32 或 128 个)示例是通常的方法,多个副本在不同批次上并行训练。

    请参阅此Stats StackExchange question,了解有关何时应使用一种方法与另一种方法的更多理论讨论。

    【讨论】:

    • 这是我从你的帖子中得到的。在版本 1 中,在程序将整批数据输入模型之前,不会更新权重和偏差。这意味着 3000 个数据点将产生一个很大的权重调整。对于版本 2,就像我使用这 3000 个数据点来更新权重 3000 次,进行 3000 次小的权重调整。它是否正确?谢谢。
    • 没错,是的。如果您进行 3000 次单独更新,以后的更新将使用更多最新版本的参数,这将有助于提高收敛性(每个训练数据点)。
    • @mrry 你能解释一下为什么“理论上一次处理一个元素是可取的”吗?我一直认为批量越大越好。
    • 通过一次处理单个元素,您会更频繁地更新权重,因此,后期计算可以利用更多“进化”的网络权重,可能会导致更好的收敛(更好的准确性)。然而,单元素处理对 GPU 计算的占用率较低,导致计算吞吐量较差,因此训练时间较长。相比之下,更大的batch,pro:训练速度快; con:更差的收敛性(更差的准确性)。
    • 嗨,我只是想知道更新的详细工作原理。如果我批量运行训练数据,它们是否都按顺序计算,然后计算梯度并处理更新?还是并行完成,批处理中的数据在多个线程中同时处理,直到可以计算梯度(和(同步?)更新)?如果我在每个训练数据之后更新模型,我假设它是同步完成的?
    【解决方案2】:

    是的,有区别。我认为第二种方式的损失函数可能有点混乱。这更像是在线培训。对于整个批次中的每个数据点,您都会更新所有参数。但在第一种方式中,它被称为批量梯度,一次取一个批次并取平均损失,然后更新参数。

    请参考此链接 https://stats.stackexchange.com/questions/49528/batch-gradient-descent-versus-stochastic-gradient-descent 这个链接的第一个答案真的很好

    【讨论】:

      猜你喜欢
      • 2020-08-05
      • 1970-01-01
      • 2017-03-30
      • 2017-08-21
      • 2018-05-22
      • 2018-11-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多