当前位置:   article > 正文

梯度下降算法原理python实现,更易理解_如何用pycharm求多元函数的最小值采用梯度下降法

如何用pycharm求多元函数的最小值采用梯度下降法

梯度下降

要找到某个函数的最小值,就是沿着该函数的梯度的负方向寻找。若寻找某函数最大值,则沿着梯度方向找。

那么梯度下降数学表示:

w=wαwf(w)

αwf(w)w:步长或叫学习率,wf(w):是函数关于w的导数

梯度上升数学表示:

w=w+αwf(w)

上述某函数可以理解成最小二乘问题(线性回归和非线性)的损失函数,均方误差损失表示为:

对于凸函数可以使用最小二乘法求解最优点,过程是求关于w的导数,使导数等于0即可

对于梯度下降法则需要迭代N次,每次将wi带入上式中求得wi值下的导数,然后求得wi+1的值

看图理解

上图是梯度下降求解过程,假设求解一个线性回归问题,目标函数是均方误差最小,数学公式表示为:

Z=argmini=1m(f(xi)yi)2

用矩阵表示为:Z=argmin(yXw)T(yXw),其中X已知,y已知,w是求要的参数,圆心视为最优点也是误差最小点,那么对w求导

则梯度的负方向寻找最小点,p0是开始位置,w0可以使初始值1的矩阵,则将w0带入导数方程求得w0导数,那么根据梯度下降法

w1=w0+αwf(w0),根据此方法一直迭代的圆心点附近,求得的wi使得均方误差最小。

实例

首先生成随机样本:

  1. x = np.arange(0, 100, 1)
  2. y = x * 11.8 - np.random.standard_normal(100) * 100

使用梯度下降法求解结果如下图

第一张图表示样本分布,第二张(右上)表示使用梯度下降法求解拟合直线,第三张(左下)表示随着迭代次数增加模型损失逐渐下降直至平稳,第四张图表示参数的学习效果,随着迭代次数增加参数学习逐渐稳定。

  1. 迭代 1 损失:18659840.76439424,weight参数:[[1.0539232487566108, 4.578364388994817]]
  2. 迭代 2 损失:9004152.836684883,weight参数:[[1.0901282014628215, 6.981505910781841]]
  3. 迭代 3 损失:4649307.430631565,weight参数:[[1.1144339831409158, 8.5953966993742]]
  4. 迭代 4 损失:2685213.4523903765,weight参数:[[1.13074857483731, 9.679246133912951]]
  5. 迭代 5 损失:1799380.5932514765,weight参数:[[1.1416964803735679, 10.407132849392006]]
  6. 迭代 6 损失:1399858.0328088128,weight参数:[[1.1490402518776508, 10.89596376971111]]
  7. 迭代 7 损失:1219667.972099556,weight参数:[[1.1539635759490037, 11.22425070567449]]
  8. 迭代 8 损失:1138399.8251730944,weight参数:[[1.157261387354931, 11.44472025576014]]
  9. 迭代 9 损失:1101746.7947403109,weight参数:[[1.1594675447067935, 11.59278230490871]]
  10. 迭代 10 损失:1085215.783217484,weight参数:[[1.1609405742996355, 11.692217259740454]]

迭代10轮,直线方程可以表达为y =  11.692217259740454* x +1.1609405742996355和样本生成方程即(y = x * 11.8 - np.random.standard_normal(100) * 100)比较接近了

python实现代码如下

  1. # @Time : 2020/6/16 19:42
  2. # @Author : 大太阳小白
  3. # @Software: PyCharm
  4. """
  5. 通过程序理解如何使用梯度下降求解
  6. 1、首先程序定义一个样本集,用来代替真实数据的分布
  7. 2、计算模型误差,使用均方误差
  8. 3、利用均方误差求导,解出关于待定参数w的导数
  9. 4、目标函数是误差最小,则关于w的方程求w下降最快方向使目标函数下降最快
  10. 5、定义w初始位置,带入导数方程,求得关于初始位置w的导数
  11. 6、w根据w位置导数移动lamda倍步长,得到新的w1点,带入导数方程求w1导数,如此迭代
  12. 7、当满足一定迭代限制或是误差限制时停止迭代,求得w值
  13. """
  14. import numpy as np
  15. import matplotlib.pyplot as plt
  16. def create_sample_set():
  17. """
  18. 生成样本数据集
  19. :return:
  20. """
  21. x = np.arange(0, 100, 1)
  22. y = x * 11.8 - np.random.standard_normal(100) * 100
  23. return x, y
  24. def loss(weight, x, y):
  25. """
  26. 损失函数使用均方误差
  27. :param weight:权重
  28. :param x:
  29. :param y:
  30. :return:
  31. """
  32. return (x * weight - y).T * (x * weight - y)
  33. def gradient(weight, x, y):
  34. """
  35. 基于损失函数求关于w的导数
  36. :param weight:
  37. :param x:
  38. :param y:
  39. :return:
  40. """
  41. return x.T * (x * weight - y)
  42. def gradient_descent(x, y, max_iter=10, learning_rate=0.001):
  43. """
  44. 梯度下降求解
  45. :param x:
  46. :param y:
  47. :param max_iter:
  48. :param learning_rate:
  49. :return:
  50. """
  51. m, n = np.shape(x)
  52. weight = np.mat(np.ones((n, 1)))
  53. loss_arr = []
  54. weight_arr = np.zeros((max_iter,n))
  55. for i in range(max_iter):
  56. g = gradient(weight, x, y)
  57. weight = weight - learning_rate * g
  58. error = loss(weight, x, y).T.tolist()[0][0]
  59. loss_arr.append(error)
  60. weight_arr[i, :] = weight.T
  61. print("迭代 {} 损失:{},weight参数:{}".format(i + 1, error, weight.T.tolist()))
  62. return weight,loss_arr,weight_arr
  63. if __name__ == '__main__':
  64. plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
  65. features, labels = create_sample_set()
  66. X = np.ones((2, 100))
  67. X[1] = np.mat(features)
  68. X = X.T
  69. Y = labels.reshape(100, 1)
  70. weights,loss_array,weights_array = gradient_descent(X, Y, learning_rate=0.000001)
  71. # 绘制曲线
  72. fig = plt.figure()
  73. ax1 = fig.add_subplot(2, 2, 1)
  74. ax1.set_title("样本数据分布" )
  75. ax1.scatter(features, labels)
  76. ax2 = fig.add_subplot(2, 2, 2)
  77. ax2.set_title("梯度下降拟合效果" )
  78. ax2.scatter(features, labels)
  79. ax2.plot(features, (X * weights).T.tolist()[0])
  80. ax3 = fig.add_subplot(2, 2, 3)
  81. ax3.set_title("随着迭代次数增加loss走势")
  82. ax3.plot(range(len(loss_array)), loss_array)
  83. ax4 = fig.add_subplot(2, 2, 4)
  84. ax4.set_title("随着迭代数增加学习的参数逐渐稳定")
  85. ax4.plot(np.array(weights_array))
  86. plt.show()

模型使用的学习率很小,可以尝试加大学习率(会出现问题),这个时候可以考虑对样本数据进行标准化。

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

闽ICP备14008679号