梯度下降Gradient descent

来源:http://cs231n.github.io/optimization-1/

 

对于一个分类问题,可以概括为以下三部分: score function + lossfunction + optimization. 以图像分类为例,我们选择线性分类器,那么scorefunction可以写成如下形式:

 同时Multiclass SupportVector Machine loss可以写成如下形式:


Loss function是W的函数,因此问题转化为最小化loss function的optimization问题。式中N是训练集中所有的样本数。也就是说,在计算loss function时候把所有的训练样本都用了个遍,后面可以看到,计算梯度的时候也用到了所有样本。

 

Strategy #1: A first very bad idea solution: Randomsearch

假设不知道W有什么规律,也不知道该怎么找,最笨的办法就是每次都随机一组数,如果loss function比之前小了就更新下weightvector W,代码如下:

# assume X_train is the data where each column is an example (e.g. 3073 x 50,000)
# assume Y_train are the labels (e.g. 1D array of 50,000)
# assume the function L evaluates the loss function
bestloss = float("inf") # Python assigns the highest possible float value
for num in xrange(1000):
  W = np.random.randn(10, 3073) * 0.0001 # generate random parameters
  loss = L(X_train, Y_train, W) # get the loss over the entire training set
  if loss < bestloss: # keep track of the best solution
    bestloss = loss
    bestW = W
  print 'in attempt %d the loss was %f, best %f' % (num, loss, bestloss)

# prints:
# in attempt 0 the loss was 9.401632, best 9.401632
# in attempt 1 the loss was 8.959668, best 8.959668
# in attempt 2 the loss was 9.044034, best 8.959668
# in attempt 3 the loss was 9.278948, best 8.959668
# in attempt 4 the loss was 8.857370, best 8.857370
# in attempt 5 the loss was 8.943151, best 8.857370
# in attempt 6 the loss was 8.605604, best 8.605604
# ... (trunctated: continues for 1000 lines)

显然这种办法是傻办法,而且很难找到最优解,是不可行的。   

Strategy #2: Random Local Search

       第二种策略是首先初始化个W, 然后让他一步一步往前走,定义步伐为 , 那么下一步他的位置就是 而且只有在loss function变小的时候才往下走,否则不走:

W = np.random.randn(10, 3073) * 0.001 # generate random starting W
bestloss = float("inf")
for i in xrange(1000):
  step_size = 0.0001
  Wtry = W + np.random.randn(10, 3073) * step_size
  loss = L(Xtr_cols, Ytr, Wtry)
  if loss < bestloss:
    W = Wtry
    bestloss = loss
  print 'iter %d loss is %f' % (i, bestloss)

这种方法虽然比上一种好一点,但是计算成本太大,没有一个明确的方向,所以也不好。

 

Strategy #3: Following the Gradient

       终于引出了梯度下降法,梯度的定义如下:

如果是一维情况就是求个微分,如果是高维情况就是求个偏微分。这里说的梯度就是高维向量中每一维的一个偏微分。

接下来介绍两种求梯度的方法。

 

numerical gradient:比较慢,是近似值,并且比较容易

analytic gradient:比较快,是精确值,但是容易犯错,需要微积分的知识。

 

Case1 Computing the gradient numerically with finitedifferences

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
# to use the generic code above we want a function that takes a single argument
# (the weights in our case) so we close over X_train and Y_train
def CIFAR10_loss_fun(W):
  return L(X_train, Y_train, W)

W = np.random.rand(10, 3073) * 0.001 # random weight vector
df = eval_numerical_gradient(CIFAR10_loss_fun, W) # get the gradient
loss_original = CIFAR10_loss_fun(W) # the original loss
print 'original loss: %f' % (loss_original, )

# lets see the effect of multiple step sizes
for step_size_log in [-10, -9, -8, -7, -6, -5,-4,-3,-2,-1]:
  step_size = 10 ** step_size_log
  W_new = W - step_size * df # new position in the weight space
  loss_new = CIFAR10_loss_fun(W_new)
  print 'for step size %f new loss: %f' % (step_size, loss_new)

# prints:
# original loss: 2.200718
# for step size 1.000000e-10 new loss: 2.200652
# for step size 1.000000e-09 new loss: 2.200057
# for step size 1.000000e-08 new loss: 2.194116
# for step size 1.000000e-07 new loss: 2.135493
# for step size 1.000000e-06 new loss: 1.647802
# for step size 1.000000e-05 new loss: 2.844355
# for step size 1.000000e-04 new loss: 25.558142

上述代码使用 公式进行计算,实际情况使用centered difference formula会更好 ,原因[wiki ]

       上述算法虽然可行但是效率太低,当特征维数太高时不能使用。


Case2 Computing the gradient analytically withCalculus

第一中方法虽然简单但是不是精确值,是近似值,实际可以通过直接推导的方式计算,但是也更容易出错,因此经常使用第二中方法计算然后再去用第一种方法验证下对不对,这种方法叫:gradient check。

 

———————————————————————————————————————

 

上述分析就是梯度下降法的思考过程,梯度下降法是目前最常用且成熟的方法,在优化神经网络loss function问题上。

但是当数据量较大时不适合用这种方法,因为将全部训练样本都用上只为了训练一个参数是非常耗时的,比如有1.2million个数据,使用上述方法是非常耗时的。

 

Mini-batch gradientdescent(MGD or BGD)是比较常用的方法,即只使用一部分训练样本做训练。假设一个极端的例子,如果1.2million样本中只有1000个样本是不一样的,剩下的全是这1000个样本的简单复制,那么即使使用全部样本训练最终也会和1000个样本的效果一样,因此下面的方法将会更快。当然实际情况可能不是完全复制,结果也只是真是结果的一个近似值,但是在牺牲一点精度的情况下可以大大提高效率。

MGD更极端一点的例子是只有一个图像,剩下的全是复制品,那么每次训练只用一个样本计算lossfunction,这种情况叫Stochastic Gradient Descent (SGD,有时候也叫on-line gradient descent,比较形象)。SGD这种情况实际使用并不多见,因为一次计算100个样本比计算1个样本100次要更有效率。有时人们说的SGD也是指的MGD。

MGD实际操作过程中一般选择样本个数时都选2的整次幂,因为在向量化的计算过程中速度可以更快。




注:上述文章从写完的word文档中直接copy,公式编辑器写的东西复制不过来,文章格式也有很多错乱,为了不浪费第二遍时间都不做整理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

此人姓于名叫罩百灵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值