python 底层原理_梯度下降的原理及Python实现

1. 原理篇

我们用人话而不是大段的数学公式来讲讲梯度下降归是怎么一回事。

1.1 什么是梯度?

多元函数的各个变量的偏导数以向量的形式写出来,就是梯度。比如函数

equation?tex=f%28x%2C+y%29+%3D+x+%5E+2+%2B+siny ,那么它的梯度

equation?tex=grad%5C+f%28x%2C+y%29 或者

equation?tex=%5CDelta+f%28x%2C+y%29 就是

equation?tex=%282x%2C+cosy%29

1.2 下降了什么?

在机器学习里,我们用梯度下降是用来求解一个损失函数

equation?tex=L%28%5CTheta%29 的最小值,所谓下降实际上是这个损失函数的值在下降。

1.3 什么是梯度下降?

沿着函数梯度的负方向不断地更新损失函数的变量

equation?tex=%5CTheta ,来不断地“逼近”最小值。

1.4 如何理解方向?

因为函数的梯度是向量,而向量是有方向的,如函数

equation?tex=z+%3D+x+%5E+2+%2B+y+%5E+2

equation?tex=%28x%2C+y%29 是多维向量,可以沿着无数个方向进行更新。

1.5 为什么是梯度的负方向?

根据泰勒公式,

equation?tex=f%28X+%2B+X_0%29+%5Capprox+f%28X%29+%2B+X_0f%27%28X%29 ,其中

equation?tex=f%28X%29 是当前的函数值,

equation?tex=f%27%28X%29 是梯度,

equation?tex=X_0

equation?tex=X 的增量。让

equation?tex=f%28X+%2B+X_0%29 最小,也就是让

equation?tex=X_0f%27%28X%29 最小。两个向量做点乘的时候,如果向量模长一定,那么当向量夹角是π的时候结果最小,即向量

equation?tex=X_0 与梯度

equation?tex=f%27%28X%29 相反的时候

equation?tex=f%28X+%2B+X_0%29 最小。

1.6 什么是凸函数?

简单说,就是函数图像向下凹的函数。注意,这跟很多数学教材的定义是相反的。严格的定义是函数在区间I上有定义,当且仅当

equation?tex=%5Cforall+x_1%2C+x_2+%5Cin+I ,有

equation?tex=%5Bf%28x_1%29+%2B+f%28x_2%29%5D+%2F+2+%5Cgeq+f%5B%28x_1+%2B+x_2%29%2F2%5D 时,

equation?tex=f%28x%29 是凸函数。证明一个凸函数的方法是它的二阶导数非负,对于多元函数来说就是海瑟矩阵半正定(不了解可以略过)。从导数定义上可以知道,二阶导数非负,说明一阶导数是单调增函数,那么函数的切线斜率越来越大,所以函数的形状向下凸的。

1.7 梯度下降与凸函数

在机器学习领域,我们用梯度下降优化损失函数的时候往往希望损失函数是个凸函数,是因为凸函数处处可导,能用梯度下降求解。且有唯一的最小值,确保最后会收敛在全局最优解。

2. 实现篇

本人用全宇宙最简单的编程语言——Python实现了梯度下降,没有依赖任何第三方库,便于学习和使用。简单说明一下实现过程,更详细的注释请参考本人github上的代码。

随机生成

equation?tex=%5CTheta 的初始值

计算当前的梯度

更新

equation?tex=%5CTheta

如果函数收敛或者超过最大迭代次数则返回

from random import random

def gradient_decent(fn, partial_derivatives, n_variables, lr=0.1,

max_iter=10000, tolerance=1e-5):

theta = [random() for _ in range(n_variables)]

y_cur = fn(*theta)

for i in range(max_iter):

# Calculate gradient of current theta.

gradient = [f(*theta) for f in partial_derivatives]

# Update the theta by the gradient.

for j in range(n_variables):

theta[j] -= gradient[j] * lr

# Check if converged or not.

y_cur, y_pre = fn(*theta), y_cur

if abs(y_pre - y_cur) < tolerance:

break

return theta, y_cur

3. 效果评估

3.1 定义二元函数及其导数

定义二元函数f(x, y),显然x = 1, y = 2时,函数可以取最小值2

对x和y分别求偏导

def f(x, y):

return (x + y - 3) ** 2 + (x + 2 * y - 5) ** 2 + 2

def df_dx(x, y):

return 2 * (x + y - 3) + 2 * (x + 2 * y - 5)

def df_dy(x, y):

return 2 * (x + y - 3) + 4 * (x + 2 * y - 5)

3.2 求解函数最小值

def main():

print("Solve the minimum value of quadratic function:")

n_variables = 2

theta, f_theta = gradient_decent(f, [df_dx, df_dy], n_variables)

theta = [round(x, 3) for x in theta]

print("The solution is: theta%s, f(theta)%.2f.\n" % (theta, f_theta))

3.3 效果展示

梯度下降的求解结果如下,效果还不错。如果希望结果更加精确,可以把tolerance调小一些。

v2-73066f1e924f9f71dd9bfadedf3c67d4_720w.jpg

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值