随机梯度下降的批次大小是训练数据的长度,而不是1?

时间:2020-07-28 16:52:08

标签: python machine-learning keras neural-network gradient-descent

在尝试使用批梯度下降,随机梯度下降和小批量随机梯度下降时,我试图绘制不同的学习结果。

在任何地方,我都看到batch_size = 1与具有普通SGD相同,并且batch_size = len(train_data)与具有Batch梯度下降相同。

我知道随机梯度下降是指每次更新仅使用一个数据样本,而批量梯度下降使用整个训练数据集来计算目标函数/更新的梯度。

但是,当使用keras实现batch_size时,似乎正好相反。以我的代码为例,其中我将batch_size设置为与training_data的长度相等

input_size = len(train_dataset.keys())
output_size = 10
hidden_layer_size = 250
n_epochs = 250

weights_initializer = keras.initializers.GlorotUniform()

#A function that trains and validates the model and returns the MSE
def train_val_model(run_dir, hparams):
    model = keras.models.Sequential([
            #Layer to be used as an entry point into a Network
            keras.layers.InputLayer(input_shape=[len(train_dataset.keys())]),
            #Dense layer 1
            keras.layers.Dense(hidden_layer_size, activation='relu', 
                               kernel_initializer = weights_initializer,
                               name='Layer_1'),
            #Dense layer 2
            keras.layers.Dense(hidden_layer_size, activation='relu', 
                               kernel_initializer = weights_initializer,
                               name='Layer_2'),
            #activation function is linear since we are doing regression
            keras.layers.Dense(output_size, activation='linear', name='Output_layer')
                                ])
    
    #Use the stochastic gradient descent optimizer but change batch_size to get BSG, SGD or MiniSGD
    optimizer = tf.keras.optimizers.SGD(learning_rate=0.001, momentum=0.0,
                                        nesterov=False)
    
    #Compiling the model
    model.compile(optimizer=optimizer, 
                  loss='mean_squared_error', #Computes the mean of squares of errors between labels and predictions
                  metrics=['mean_squared_error']) #Computes the mean squared error between y_true and y_pred
    
    # initialize TimeStopping callback 
    time_stopping_callback = tfa.callbacks.TimeStopping(seconds=5*60, verbose=1)
    
    #Training the network
    history = model.fit(normed_train_data, train_labels, 
         epochs=n_epochs,
         batch_size=hparams['batch_size'], 
         verbose=1,
         #validation_split=0.2,
         callbacks=[tf.keras.callbacks.TensorBoard(run_dir + "/Keras"), time_stopping_callback])
    
    return history

train_val_model("logs/sample", {'batch_size': len(normed_train_data)})

运行此命令时,输出似乎显示每个时期的单个更新,即SGD Batch_size=len(input_data)

在每个时期下都可以看到它表示1/1,我认为这意味着一次更新迭代。另一方面,如果我将batch_size = 1设置为90000/90000,这就是我整个数据集的大小(在训练时间上这也很有意义)。

所以,我的问题是,batch_size = 1实际上是批处理梯度下降而不是随机梯度下降,而batch_size = len(train_data)实际上是随机梯度下降而不是批量梯度下降?

2 个答案:

答案 0 :(得分:1)

实际上有三(3)种情况:

  • batch_size = 1的确意味着随机梯度下降(SGD)
  • 等于全部训练数据的batch_size是(批量)梯度下降(GD)
  • 中间案例(实际上在实际中使用)通常称为小批量梯度下降

有关更多详细信息和参考,请参见A Gentle Introduction to Mini-Batch Gradient Descent and How to Configure Batch Size。事实是,在实践中,当我们说“ SGD”时,通常是指“小批量SGD”。

这些定义实际上完全符合您从实验中报告的内容:

  • 对于batch_size=len(train_data)(在GD情况下),确实确实希望每个时期进行一次更新(因为只有一个批次),因此在1/1指示中Keras输出。

  • 相反,对于batch_size = 1(SGD情况),您期望训练数据中的更新与样本一样多(因为这是现在的批次数量),即90000,因此{{ 1}}在Keras输出中显示。

即每个时期的更新次数(Keras表示)等于所使用的批次数量(并且 not 等于批次大小)。

答案 1 :(得分:0)

batch_size是每次更新的大小。

在这里,batch_size=1表示每次更新的大小为1个样本。根据您的定义,这将是SGD。

如果您有batch_size=len(train_data),则意味着权重的每次更新都需要整个数据集中的最终梯度。这实际上只是旧的梯度下降法。

批次梯度下降在中间的某个位置,其中batch_size不为1,并且批次大小不是您的整个训练数据集。以32为例。批梯度下降法每32个示例将更新一次权重,因此仅用一个示例就可以消除SGD的坚固性(异常值可能会产生很大的影响),但具有SGD优于常规梯度descne.t