Excel和Python实现梯度下降法

一、梯度下降法是什么

梯度下降法(Gradient Descent,GD)是一种常用的求解无约束最优化问题的方法,在最优化、统计学以及机器学习等领域有着广泛的应用。

梯度下降法的基本思想:梯度下降法(Gradient Descent) – 现代机器学习的血液

二、概念理解

1. 微分理解

我们所要优化的函数必须是一个连续可微的函数,可微,既可微分,意思是在函数的任意定义域上导数存在。如果导数存在且是连续函数,则原函数是连续可微的。

  • 函数图像中,某点的切线的斜率
  • 函数的变化率

例子:
d ( x 2 ) d x = 2 x d ( 5 − x ) d x = − 2 ( 5 − x ) \frac{d(x^2)}{dx} = 2x \\ \frac{d(5-x)}{dx} = -2(5-x) dxd(x2)=2xdxd(5x)=2(5x)
多元连续可微函数求微分的例子:
∂ ∂ x ( x 2 y 2 ) = 2 x y 2 ∂ ∂ y ( − 2 y 5 + z 2 ) = − 10 y 4 ∂ ∂ x 2 [ 0.55 − ( 5 x 1 + 2 x 2 − 12 x 3 ) ] = − 2 \frac{\partial}{\partial x}(x^2y^2) = 2xy^2 \\ \frac{\partial}{\partial y}(-2y^5 + z^2) = -10y^4 \\ \frac{\partial }{\partial x_2}[0.55 - (5x_1 + 2x_2 - 12x_3)] = -2 x(x2y2)=2xy2y(2y5+z2)=10y4x2[0.55(5x1+2x212x3)]=2

2. 梯度理解

以二元函数 z = f ( x , y ) z=f(x,y) z=f(x,y) 为例,假设其对每个变量都具有连续的一阶偏导数 ∂ z ∂ x \frac{\partial z}{\partial x} xz ∂ z ∂ y \frac{\partial z}{\partial y} yz,则这两个偏导数构成的向量 [ ∂ z ∂ x , ∂ z ∂ y ] [\frac{\partial z}{\partial x}, \frac{\partial z}{\partial y}] [xz,yz] ,即为该二元函数的梯度向量,一般记作 ∇ f ( x , y ) \nabla f(x,y) f(x,y),其中 ∇ \nabla 读作“Nabla”。

例子:
J ( Θ ) = 0.55 − ( 5 θ 1 + 2 θ 2 − 12 θ 3 ) ∇ J ( Θ ) = [ ∂ J ∂ θ 1 , ∂ J ∂ θ 2 , ∂ J ∂ θ 3 ] = [ − 5 , − 2 , 12 ] J(\Theta) = 0.55 - (5\theta_1 + 2\theta_2 - 12\theta_3) \\ \nabla J(\Theta) = [\frac{\partial J}{\partial \theta_1},\frac{\partial J}{\partial \theta_2},\frac{\partial J}{\partial \theta_3}]=[-5,-2,12] J(Θ)=0.55(5θ1+2θ212θ3)J(Θ)=[θ1J,θ2J,θ3J]=[5,2,12]
梯度的意义:

  • 在单变量的函数中,梯度其实就是函数的微分,代表着函数在某个给定点的切线的斜率
  • 在多变量函数中,梯度是一个向量,向量有方向,梯度的方向就指出了函数在给定点的上升最快的方向

从几何意义来讲,梯度的方向表示的是函数增加最快的方向,这正是我们下山要找的“最陡峭的方向”的反方向!因此后面要讲到的迭代公式中,梯度前面的符号为“-”,代表梯度方向的反方向。

3. 梯度下降法的数学解释

更多请参考:深入浅出–梯度下降法及其实现

三、梯度下降法手工求解

问题描述:

求函数 f ( X ) = f ( x 1 , x 2 ) = 1 3 x 1 2 + 1 2 x 2 2 f(X) = f(x_1, x_2) = \frac{1}{3}x_1^2 + \frac{1}{2}x_2^2 f(X)=f(x1,x2)=31x12+21x22 的极小值点。

解:设初始点为 X 1 = ( 3 , 2 ) X_1 = (3,2) X1=(3,2),学习率为 α \alpha α

初始点处的梯度为 ∇ f ( X 1 ) = ( 2 3 × 3 , 2 2 × 2 ) = ( 2 , 2 ) \nabla f(X_1) = (\frac{2}{3} \times 3, \frac{2}{2} \times 2) = (2,2) f(X1)=(32×3,22×2)=(2,2)

因此更新迭代公式带入原函数中,得:

f ( X 2 ) = f ( X 1 − α ∇ f ( X 1 ) ) = 10 3 α 2 − 8 α + 5 f(X_2) = f(X_1 - \alpha\nabla f(X_1)) = \frac{10}{3}\alpha^2 - 8\alpha + 5 f(X2)=f(X1αf(X1))=310α28α+5

此时, α 1 ∗ = 6 5 \alpha_1^* = \frac{6}{5} α1=56时,为函数极小点。

因此, X 2 = X 1 − a 1 ∗ = ( 3 5 , − 2 5 ) X_2 = X_1 - a_1^*=(\frac{3}{5},-\frac{2}{5}) X2=X1a1=(53,52),一次迭代结束。

然后,再将 X 2 X_2 X2作为初始点,重复上面的迭代步骤,

得到: X 3 = ( 3 5 2 , 2 5 2 ) X_3 = (\frac{3}{5^2}, \frac{2}{5^2}) X3=(523,522)

根据规律显然可知: X k = ( 3 5 k − 1 , ( − 1 ) k − 1 2 5 k − 1 ) X_k = (\frac{3}{5^{k-1}},(-1)^{k-1}\frac{2}{5^{k-1}}) Xk=(5k13,(1)k15k12)

例中目标函数 f ( X ) f(X) f(X)是三维空间中的椭圆抛物面,其投影至二维空间上的等高线是一簇椭圆(如下图所示)。 f ( X ) f(X) f(X)的极小点就是这簇椭圆的中心 X ∗ = ( 0 , 0 ) X^*=(0,0) X=(0,0)。我们求得的迭代公式 { X k } \{X_k\} {Xk}是逐渐趋近于 X ∗ X^* X

在这里插入图片描述

四、Excel演示梯度下降法的数据变化

求解函数:
z = 2 ( x − 1 ) 2 + y 2 z = 2(x-1)^2 + y^2 z=2(x1)2+y2
可求出其梯度为:
( ∂ z ∂ x , ∂ z ∂ y ) = ( 4 x − 4 , 2 y ) (\frac{\partial z}{\partial x},\frac{\partial z}{\partial y}) = (4x-4,2y) (xz,yz)=(4x4,2y)
1. 初始设定

给出初始位置 ( x i , y i ) , i = 0 (x_i,y_i),i=0 (xi,yi),i=0 与 学习率 α = 0.1 \alpha=0.1 α=0.1

在这里插入图片描述

2. 计算位移量
( Δ x i , Δ y i ) = − α ( ∂ z ∂ x , ∂ z ∂ y ) = − α ( 4 x i − 4 , 2 y i ) (\Delta x_i,\Delta y_i)= -\alpha(\frac{\partial z}{\partial x},\frac{\partial z}{\partial y}) = -\alpha(4x_i-4,2y_i) (Δxi,Δyi)=α(xz,yz)=α(4xi4,2yi)
这个位移量可以看作是通过小步长来找出局部最小值

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DM26LKX4-1617434635145)(E:%5Cdasan2%5C%E5%AE%9E%E9%AA%8C%E4%BD%9C%E4%B8%9A%5C%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0%5C%E6%A2%AF%E5%BA%A6%E4%B8%8B%E9%99%8D%E6%B3%95%5C1617427983658.png)]

3. 更新位置

当 i = 0时,将当前位置 ( x 0 , y 0 ) = ( 3 , 2 ) (x_0,y_0)=(3,2) (x0,y0)=(3,2) 与当前计算得到的位移偏移量 ( − 0.8 , − 0.4 ) (-0.8,-0.4) (0.8,0.4) 相加得到 ( 2.2 , 1.6 ) (2.2,1.6) (2.2,1.6)

即, ( x i + 1 , y i + 1 ) = ( x i , y i ) + ( Δ x i , Δ y i ) (x_{i+1},y_{i+1}) = (x_i,y_i)+(\Delta x_i,\Delta y_i) (xi+1,yi+1)=(xi,yi)+(Δxi,Δyi)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-t6kUhOXC-1617434635148)(E:%5Cdasan2%5C%E5%AE%9E%E9%AA%8C%E4%BD%9C%E4%B8%9A%5C%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0%5C%E6%A2%AF%E5%BA%A6%E4%B8%8B%E9%99%8D%E6%B3%95%5C1617428518861.png)]

4. 反复执行2和3的操作

反复执行2和3的操作30次后,得到坐标 ( x 30 , y 30 ) (x_{30},y_{30}) (x30,y30) 的值

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WIq09hEA-1617434635150)(E:%5Cdasan2%5C%E5%AE%9E%E9%AA%8C%E4%BD%9C%E4%B8%9A%5C%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0%5C%E6%A2%AF%E5%BA%A6%E4%B8%8B%E9%99%8D%E6%B3%95%5C1617429134526.png)]

由此可以得出,函数 z z z 在 (1,0) 处取得最小值 0

五、Python 编程实现

实验环境

Anaconda + python3.6 + jupyter

1. 导入所需库

# 导入所需库
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
import math
from mpl_toolkits.mplot3d import Axes3D
import warnings

2. 函数定义

# 原函数
def Z(x,y):
    return 2*(x-1)**2 + y**2
# x方向上的梯度
def dx(x):
    return 4*x-4
# y方向上的梯度
def dy(y):
    return 2*y

3. 赋初值

# 初始值
X = x_0 = 3
Y = y_0 = 2
# 学习率
alpha = 0.1

4. 定义数据保存列表

# 保存梯度下降所经过的点
globalX = [x_0]
globalY = [y_0]
globalZ = [Z(x_0,y_0)]

5. 重复迭代30次

# 迭代30次
for i in range(30):
    temX = X - alpha * dx(X)
    temY = Y - alpha * dy(Y)
    temZ = Z(temX, temY)
    # X,Y 重新赋值
    X = temX
    Y = temY
    # 将新值存储起来
    globalX.append(temX)
    globalY.append(temY)
    globalZ.append(temZ)

6. 打印结果

# 打印结果
print(u"最终结果为:(x,y,z)=(%.5f, %.5f, %.5f)" % (X, Y, Z(X,Y)))
print(u"迭代过程中取值")
num = len(globalX)
for i in range(num):
    print(u"x%d=%.5f, y%d=%.5f, z%d=%.5f" % (i,globalX[i],i,globalY[i],i,globalZ[i]))

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-T8mWKnyU-1617434635152)(E:%5Cdasan2%5C%E5%AE%9E%E9%AA%8C%E4%BD%9C%E4%B8%9A%5C%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0%5C%E6%A2%AF%E5%BA%A6%E4%B8%8B%E9%99%8D%E6%B3%95%5C1617433717668.png)]

可见,函数 z = 2 ( x − 1 ) 2 + y 2 z = 2(x-1)^2 + y^2 z=2(x1)2+y2 在 (1,0) 处取得最小值 0,结果跟excel分析的结果一致

7. 绘制过程图

%matplotlib inline
axisX = np.arange(-4,4,0.2)
axisY = np.arange(-4,4,0.2)
axisX, axisY = np.meshgrid(axisX, axisY) # 生成xv、yv,将axisX、axisY变成n*m的矩阵,方便后面绘图
valueZ = np.array(list(map(lambda t : Z(t[0],t[1]),zip(axisX.flatten(),axisY.flatten()))))
valueZ.shape = axisX.shape # 1600的Z图还原成原来的(40,40)
%matplotlib inline

#作图
fig = plt.figure(facecolor='w',figsize=(12,8))
ax = Axes3D(fig)
ax.plot_surface(axisX,axisY,valueZ,rstride=1,cstride=1,cmap=plt.cm.jet)
ax.plot(globalX,globalY,globalZ,'ko-')
ax.set_title(u'$ z=2×(x-1)^2 + y^2  $')
ax.set_xlabel(u'x')
ax.set_ylabel(u'y')
ax.set_zlabel('z')
plt.show()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kJK4XkGq-1617434635152)(E:%5Cdasan2%5C%E5%AE%9E%E9%AA%8C%E4%BD%9C%E4%B8%9A%5C%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0%5C%E6%A2%AF%E5%BA%A6%E4%B8%8B%E9%99%8D%E6%B3%95%5C1617434325653.png)]

六、参考🔗

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值