这是深度学习笔记第一篇,完整的笔记目录可以点击这里查看。
  
  有两种方法来计算梯度:一种是计算速度慢,近似的,但很简单的方法(数值梯度),另一种是计算速度快,精确的,但更容易出错的方法,需要用到微积分(解析梯度)。

1. Numerical gradient

  数值梯度就是根据导数的定义来求解梯度:
在这里插入图片描述
  在具体实现的时候,只要保证h很小,就可以近似求出精确的梯度值了。下面的这段python代码实现的是一个通用的数值梯度求解方法,它接受一个函数f和一个向量x来计算梯度,并返回fx处的梯度:

def eval_numerical_gradient(f, x):
  """
  a naive implementation of numerical gradient of f at x
  - f should be a function that takes a single argument
  - x is the point (numpy array) to evaluate the gradient at
  """

  fx = f(x) # evaluate function value at original point
  grad = np.zeros(x.shape)
  h = 0.00001

  # iterate over all indexes in x
  it = np.nditer(x, flags=['multi_index'], op_flags=['readwrite'])
  while not it.finished:

    # evaluate function at x+h
    ix = it.multi_index
    old_value = x[ix]
    x[ix] = old_value + h # increment by h
    fxh = f(x) # evalute f(x + h)
    x[ix] = old_value # restore to previous value (very important!)

    # compute the partial derivative
    grad[ix] = (fxh - fx) / h # the slope
    it.iternext() # step to next dimension

  return grad

  按照上面所给的梯度公式,上面的代码一个接一个地迭代所有维度,沿着该维度做一个小的改变h,并通过观察函数改变的程度来计算损失函数沿着该维度的偏导数。变量grad最终存储了所有维度的梯度计算值。
  需要注意的是,在导数定义中,h是用极限来定义的,但在实践中,使用非常小的值(比如1e-5)通常就足够了。此外,在实践中,使用中心差分公式 [f(x+h)−f(x−h)]/2h 计算数值梯度通常效果更好,可以参考另一篇博客梯度检验

2. Analytic gradient

  使用有限差分近似计算数值梯度非常简单,但缺点是它是近似的(因为我们必须选择一个小的h值,而真正的梯度定义为h为零时的极限),并且计算起来非常耗时。第二种计算梯度的方法是使用微积分进行分析,它允许我们推导出梯度的直接公式(无近似),计算速度也非常快。但是,与数值梯度不同,它更容易出现错误,这就是为什么在实践中,计算解析梯度并将其与数值梯度进行比较以检查实现的正确性是非常常见的。这叫做梯度检验
  解析法的实现与前向传播的计算方法一样,都是直接通过公式计算的。只要能求出导数形式,就可以直接实现。比如sigmoid函数,其函数形式为:
在这里插入图片描述
  而其对x的导数可以写成:
在这里插入图片描述
下面是一个sigmoid函数解析梯度计算的代码示例:

w = [2,-3,-3] # assume some random weights and data
x = [-1, -2]

# forward pass
dot = w[0]*x[0] + w[1]*x[1] + w[2]
f = 1.0 / (1 + math.exp(-dot)) # sigmoid function

# backward pass through the neuron (backpropagation)
ddot = (1 - f) * f # gradient on dot variable, using the sigmoid gradient derivation
dx = [w[0] * ddot, w[1] * ddot] # backprop into x
dw = [x[0] * ddot, x[1] * ddot, 1.0 * ddot] # backprop into w
# we're done! we have the gradients on the inputs to the circuit




*本博客翻译总结自CS231n课程作业网站,该网站需要翻墙才能访问。

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐