当前位置:   article > 正文

【深度学习】梯度下降(通俗易懂)_深度学习梯度下降

深度学习梯度下降

文章目录

1、前言

2、理论与代码

1、求极值问题

2、梯度下降

3、实例演示


1、前言

最近有朋友问到我,损失函数与激活函数的问题,由于工作等原因有段时间没接触深度学习没有回答的很好。我最近也是浅浅复习了下深度学习,正好分享下自己对深度学习的理解。

2、理论与代码

1、求极值问题

大家可以思考下, y =(x-3)**2+1 ,y的最小值怎么求的。这里常规做法应该是:

1、因为(x-3)**2>=0 所以y>=1 所以最小值1

2、对x求导,令 dy/dx = 2(x-3)  等于0 ,求导x=3 极值点,根据导数判断当x<3,dy/dx <0,递减,x>3,dy/dx>0递增。带入原方程算得极小值为1,简单判断下,这个极小值就是最小值。

3、来看看我们利用梯度下降的思想如何做(导数与梯度是不同的,一个标量一个矢量。为了便于说明,我们后面直接说梯度)

先观察下函数图像。

给个任意初始值x,如 x = -1,我们想要找到x = 3,如何做呢。根据导数dy/dx,我们可以对x迭代。x = x - dy/dx ,由于我们 dy/dx 计算的值比较大,就相当于我们每次迭代 x 一步跨的很长。所以我们设定一个参数 lr (learning rate)也就是我们所说的"学习率"或者"步长"。

  x = x-lr*dy/dx 

我们写段代码看下。

  1. import matplotlib.pyplot as plt
  2. import numpy as np
  3. # 先画下 y = (x-3)**2 + 1 曲线图
  4. m = np.linspace(-1,7,1000)
  5. n = m**2 - 6*m + 10
  6. plt.plot(m,n)
  7. x = -1 # 给个x的初始值
  8. lr = 0.01 # 学习率
  9. list_x,list_y= [],[]
  10. for epoch in range(200):
  11. y_d = 2*x - 6 # y对x的导数 y_d
  12. list_x.append(x)
  13. list_y.append(x**2 - 6*x + 10) # 把每次的数据存下,后面可视化
  14. x = x - y_d*lr
  15. # 每次迭代散点图
  16. plt.scatter(list_x,list_y,color="red")
  17. plt.show()

1、可以发现,我们在迭代过程中,逐渐接近我们想要的值。迭代的这个过程x = x-lr*dy/dx 是极其关键。我们可以理解为  往下走楼梯,一步一步逐渐接近于我们的目标。

2、当我们要求极大值时,比如求 - (x-3)**2+1 的极大值,我们只需要上述式子 负号变为正号就可以了 x = x + lr*dy/dx ,这个过程 我们称为 梯度上升。我们平常讲的都是梯度下降,因为我们要的就是求最小值。我们要建立的模型是 y = F(x),要求模型输出的值越接近实际值,也就是误差(损失)最小。后面会举个实例说明。

3、大家可以自行调整上述代码的两个参数 lr 、 迭代次数。

比如 我现在设置  lr = 1.0 ,会发现什么?无论迭代次数是多少,总会在两个点来回震荡。

关于参数这个就不过多说明了,大家可以自己实践下。

2、梯度下降

梯度这个概念相信大家都知道,不记得的可以百度看下。

举个例子:求 z = x**2 + y**2 + 1 最小值  ,把导数换成各个参数的偏导,其他类似。直接上代码 

  1. import matplotlib.pyplot as plt
  2. import numpy as np
  3. from mpl_toolkits.mplot3d import Axes3D
  4. # 计算z = x**2+ y**2 + 1 的最小值
  5. '''
  6. 可视化3D图
  7. '''
  8. fig = plt.figure()
  9. ax1 = plt.axes(projection="3d")
  10. x = np.linspace(-1.5,1.5,1000)
  11. y = np.linspace(-1.5,1.5,1000)
  12. x,y = np.meshgrid(x,y)
  13. z = x**2 + y**2 + 1
  14. ax1.plot_surface(x,y,z,cmap="rainbow")
  15. plt.show()
  16. x,y = -2,-2 # 随机给个初始值
  17. lr = 0.02 # 学习率
  18. for i in range(100):
  19. z_x = 2*x # z对x偏导
  20. z_y = 2*y # z对y偏导
  21. x = x-z_x*lr
  22. y = y-z_y*lr
  23. print(x,y) # 打印看下发现(x,y)越来越接近(0,0)

3、实例演示

还是来个例子演示一遍

特征1数据 : x_data = [1,2,3,4,5]

特征2数据 : y_data = [6,5,4,3,2]

结果:result = [12,9,6,3,0]

现用梯度下降思想来演示一下。

假设 用方程 z = w1*x + w2*y + b 去拟合

  1. def linear_function(x, y):
  2. return w1 * x + w2 * y + b
  3. """
  4. 定义一个误差函数,比如绝对值损失,均方损失,交叉熵损失。
  5. 实际上我们定义的这个my_loss就是均方误差,也就是我们所说的MSE。
  6. """
  7. def my_loss(x, y, z):
  8. loss = 0
  9. n = len(x) # n代表数据组数
  10. for xi, yi, zi in zip(x, y, z):
  11. z_pred = linear_function(xi, yi)
  12. loss += (z_pred - zi) ** 2 / n # 平方和平均
  13. return loss
  14. # 定义个梯度函数
  15. def my_gradient(x, y, z):
  16. n = len(x) # 多少组数
  17. a, b, c = 0, 0, 0
  18. for xi, yi, zi in zip(x, y, z):
  19. z_pred = linear_function(xi, yi)
  20. """
  21. 现在目标是求损失值最小,我们定义的损失为(z-(w1*x + w2*y + b))**2/n
  22. 问题是我们在求解每组数据都会有一个梯度,如何处理呢。简单介绍三种做法。
  23. 我们这里用的第一种
  24. 1、对每一组梯度进行一个求和,就是我们所说的批量梯度下降,所有组的梯度累加。
  25. 特点:全局最优,但是速度慢。
  26. 2、随机梯度下降,每组数据单独算梯度。每组数据单独计算。
  27. 特点:每个参数迭代速度快,但是容易陷局部最优
  28. 3、小批量梯度下降,选取一部分组梯度下降。比如我们这里截取前几组数据。
  29. """
  30. a += 2 * xi * (z_pred - zi) / n
  31. b += 2 * yi * (z_pred - zi) / n
  32. c += 2 * (z_pred - zi) / n
  33. return a, b, c
  34. if __name__ == "__main__":
  35. w1, w2, b = 0, 0, 0 # 随机给初始值
  36. x_data = [1, 2, 3, 4, 5]
  37. y_data = [6, 5, 4, 3, 2]
  38. result = [12, 9, 6, 3, 0]
  39. ls = 0.01 # 学习率
  40. for epoch in range(500):
  41. loss = my_loss(x_data, y_data, result) # 记录损失值
  42. grad = my_gradient(x_data, y_data, result)
  43. # 批量梯度下降,每次更新每个参数
  44. w1 -= ls * grad[0]
  45. w2 -= ls * grad[1]
  46. b -= ls * grad[2]
  47. print("epoch={},loss={}".format(epoch, loss))
  48. print("result", result)
  49. # 打印看下我们求得的结果值与目标值
  50. for x, y in zip(x_data, y_data):
  51. print(w1 * x + w2 * y + b, end=" ")
  52. """
  53. epoch=496,loss=9.387598846525591e-30
  54. epoch=497,loss=9.387598846525591e-30
  55. epoch=498,loss=9.387598846525591e-30
  56. epoch=499,loss=9.387598846525591e-30
  57. result [12, 9, 6, 3, 0]
  58. 11.999999999999995 8.999999999999998 5.999999999999999 3.0000000000000013 3.58046925441613e-15
  59. """

看的出来,效果挺好的。这里又会有个新的问题。

我们怎么知道它是 z = w1*x + w2*y + b ,或者说我们为什么这样假设呢?如果我假设是多次呢?

这就是交给我们的神经网络了。假设我不是线性的呢,这就跟我们激活函数有关了。这次分享的东西可谓是冰山一角中的一角的。。。突然想到校训"求索"。路漫漫其修远兮,吾将上下而求索。

祝大家假期愉快!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/427973?site
推荐阅读
相关标签
  

闽ICP备14008679号