为什么Softmax分类器的梯度要除以批次大小(CS231n)?

5

问题

在 CS231 中 使用反向传播计算解析梯度,首先实现了一个 Softmax 分类器,从 (softmax + log loss) 得到的梯度被批次大小(在训练中用于正向成本计算和反向传播的数据数量)所除。

请帮我理解为什么需要除以批次大小。

enter image description here

链式法则用于获取梯度,应该如下所示。我应该在哪里加入除法?

enter image description here

enter image description here

enter image description here

编码

N = 100 # number of points per class
D = 2 # dimensionality
K = 3 # number of classes
X = np.zeros((N*K,D)) # data matrix (each row = single example)
y = np.zeros(N*K, dtype='uint8') # class labels

#Train a Linear Classifier

# initialize parameters randomly
W = 0.01 * np.random.randn(D,K)
b = np.zeros((1,K))

# some hyperparameters
step_size = 1e-0
reg = 1e-3 # regularization strength

# gradient descent loop
num_examples = X.shape[0]
for i in range(200):

  # evaluate class scores, [N x K]
  scores = np.dot(X, W) + b

  # compute the class probabilities
  exp_scores = np.exp(scores)
  probs = exp_scores / np.sum(exp_scores, axis=1, keepdims=True) # [N x K]

  # compute the loss: average cross-entropy loss and regularization
  correct_logprobs = -np.log(probs[range(num_examples),y])
  data_loss = np.sum(correct_logprobs)/num_examples
  reg_loss = 0.5*reg*np.sum(W*W)
  loss = data_loss + reg_loss
  if i % 10 == 0:
    print "iteration %d: loss %f" % (i, loss)

  # compute the gradient on scores
  dscores = probs
  dscores[range(num_examples),y] -= 1
  dscores /= num_examples                      # <---------------------- Why?

  # backpropate the gradient to the parameters (W,b)
  dW = np.dot(X.T, dscores)
  db = np.sum(dscores, axis=0, keepdims=True)

  dW += reg*W # regularization gradient

  # perform a parameter update
  W += -step_size * dW
  b += -step_size * db
2个回答

0

这是因为您在平均梯度而不是直接取所有梯度的总和。

当然,您可以不进行大小划分,但这种划分具有许多优点。主要原因是它是一种正则化方法(避免过拟合)。较小的梯度使权重不能增长得过于夸张。

这种标准化方法允许比较不同实验中批量大小的不同配置(如果它们依赖于批量大小,如何比较两个批量的性能?)

如果您按照该大小划分梯度总和,则可以使用更高的学习速率,以使培训更快。

交叉验证社区中的这个答案非常有用。


谢谢您的跟进,但我仍然不清楚。softmax输出p(k)介于0和1之间,这是dscore的每个元素,它是一个形状为(num_samples, 3)的矩阵。如果将dscore除以num_samples,则会将矩阵中的每个元素除以它,因此除以p(k)会导致非常小的值。仍然困惑为什么要这样做。 - mon

0
注意到在梯度计算的代码 dW = np.dot(X.T, dscores) 中,dot 表示对 W 的梯度是对 num_sample 个实例的 Σ。由于 dscore即 softmax 输出的概率已经除以了 num_samples,所以一开始没有理解这是对 dotsum 部分进行归一化。现在明白了必须要除以 num_sample(如果学习率训练得好,可能不需要归一化也能正常工作)。
我认为下面的代码更能说明问题。
# compute the gradient on scores
dscores = probs
dscores[range(num_examples),y] -= 1

# backpropate the gradient to the parameters (W,b)
dW = np.dot(X.T, dscores) / num_examples
db = np.sum(dscores, axis=0, keepdims=True) / num_examples

enter image description here


dscores是梯度,不是softmax的纯输出(dscores[range(num_examples),y] -= 1)。你在对梯度求平均,而不是概率。 - Nikaido

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接