欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

机器学习之python实现梯度下降

程序员文章站 2022-07-14 15:15:07
...

本文使用pytohn3,jupyter notebook
本文禁止转载!

一、一元函数的梯度下降

已知一个一元函数:
f(x)=3x2+2x1f(x)=3x^2+2x-1
求f(x)最低点。
实际上用初中知识我们就可以求出最低点坐标,但是我们今天来使用梯度下降的方法。

1.什么是梯度下降

对于该函数,我们想求出最低点,但是我们不知道最低点在哪里,于是我们瞎蒙一个:x=5
求得f(5)=84。
但是我们不知道它是不是最低点,但是我们会求导:
f(x)=6x+2 f^’(x)=6x+2
f(5)=32 f^’(5) = 32
很显然,x=5处不是最低点,而且此处导数为正,函数单调上升。
那么我们可以尝试把x变小一点,这样就会更接近最低点。
令x=4。
得f(4)=55,比刚刚更接近最低点,这样我们就可以不断接近最低点了。
机器学习之python实现梯度下降
但是为什么让x减小到4?减小到3可以吗?减小到4.5可以吗?
我们把x的变化称之为步长,那么这个步长应该怎么选取?
我们知道如果导数的绝对值越大,离极值点也就越远,那么我们应该把步子迈得大一些。而导数越接近于0,离极值点就越近,那么我们应该小心翼翼的前进。所以步长是与改点的导数成正相关。他们的比例系数我们称之为学习率。

如果学习率选取的不合理就会出现梯度消失梯度爆炸
梯度消失:
机器学习之python实现梯度下降
可以看到,步长如果比较大,就会在极值点附近来回震荡,而误差也减小得很慢。

梯度爆炸:
机器学习之python实现梯度下降
可以看到,步长非常大时,不仅没有靠近极值点,反而越来越远,我们称之为梯度爆炸
下面,我们来实现梯度下降的过程。

2.导入必要的包

import matplotlib.pyplot as plt
%matplotlib inline
import numpy as np

3.画出函数图像

f = lambda x:3*x**2+2*x-1
x = np.linspace(-6,5,1000)
y = np.array(list(map(f, x)))
plt.plot(x,y)

机器学习之python实现梯度下降

4.求导

d = lambda x:6*x+2

5.梯度下降

# 设置学习率
learning_rate = 0.1
# 精确度
precision = 0.0001
# 随机生成一个初始x
min_x = random.random()*11-6
# 计数
count = 0
while True:
    # 求出该点导数
    dx = d(min_x)
    print('count:{},x:{}'.format(count,min_x))
    # 沿导数方向前进
    min_x -= learning_rate * dx
    count += 1
    if abs(learning_rate * dx) < precision or count > 5000:
        break
print('count:{},x:{}'.format(count,min_x))

6.画图

plt.figure(figsize=(12,7))
x = np.linspace(-6,5,1000)
y = np.array(list(map(f, x)))
plt.plot(x,y)
x = np.array(x_list)
y = np.array(list(map(f, x)))
plt.plot(x,y,color='red')

机器学习之python实现梯度下降

二、二元函数梯度下降

有二元函数:
f(x,y)=x2+y2+2xf(x,y)=x^2+y^2+2x
求最低点。

1.导入必要的包

from matplotlib import pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D

2.画出三维图像

fig = plt.figure(figsize=(12,7))
ax = Axes3D(fig)
X = np.linspace(-100, 100, 50)
Y = np.linspace(-100, 100, 50)
X, Y = np.meshgrid(X, Y)
# R = np.sqrt(X**2 + Y**2)
Z = X**2 + Y**2 + 2*X 
ax.plot_surface(X, Y, Z,cmap='rainbow')

机器学习之python实现梯度下降

3.导函数

二元函数存在两个方向上的导数

dx = lambda x,y:2*x+2
dy = lambda x,y:2*y

4.梯度下降

# 设置学习率
learning_rate = 0.2
# 精确度
precision = 0.0001
# 随机生成一个初始x,y
min_x = random.random()*200-100
min_y = random.random()*200-100
# 计数
count = 0
# 记录过程
xy_list = []
while True:
    xy_list.append([min_x,min_y])
    # 求出该点导数
    dx_ = dx(min_x,min_y)
    dy_ = dy(min_x,min_y)
    print('count:{},x:{},y:{}'.format(count,min_x,min_y))
    # 沿导数方向前进
    step_x = learning_rate * dx_
    step_y = learning_rate * dy_
    min_x -= step_x
    min_y -= step_y
    count += 1
    if step_x**2+step_y**2 < precision**2 or count > 5000:
        xy_list.append([min_x,min_y])
        break
print('count:{},x:{},y:{}'.format(count,min_x,min_y))

5.画图

fig = plt.figure(figsize=(12,7))
ax = Axes3D(fig)
X = np.linspace(-100, 100, 50)
Y = np.linspace(-100, 100, 50)
X, Y = np.meshgrid(X, Y)
Z = X**2 + Y**2 + 2*X 
ax.plot_surface(X, Y, Z,cmap='rainbow',alpha=0.3)

xy_np = np.array(xy_list)
X = xy_np[:,0].reshape([-1])
Y = xy_np[:,1].reshape([-1])
Z = X**2 + Y**2 + 2*X
ax.plot(X, Y, Z,color='red')

机器学习之python实现梯度下降
可以看到一条逐渐滑向谷底的线。


下一篇:纯python实现线性回归