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

梯度下降法原理解释和代码演示

程序员文章站 2022-06-04 10:51:14
...

原理

梯度下降法也是一种继最小二乘法后求解最优解的技术之一,在机器学习和深度学习上的应用也十分广泛。

最小二乘法对于模型并不复杂的情况来说,可以一步到位的求出最优解,这是它的优势也是劣势。因为对于模型稍微复杂点,就无法在理论和公式上给出一步到位的解。这时就需要梯度下降法来迭代地求出最优解。当然求出的也有可能是局部最优解。

梯度下降法原理解释和代码演示

代码演示

首先进行一维函数的代码演示:下图是一个关于x的二次函数,找出最优解,使得y最小。

import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签
plt.rcParams['axes.unicode_minus']=False #用来正常显示负号
#构建一维图像
def one_dimension_image(x):
    return 0.5*(x-2)**2
#构建一维图像的导数
def one_derivate(x):
    return 0.5*2*(x-2)

Gtadient_Descent_X = []#存放梯度下降的X坐标
Gtadient_Descent_Y = []#存放梯度下降的Y坐标
x_current = 8 #X初始值
y_current = one_dimension_image(x_current)
Gtadient_Descent_X.append(x_current)
Gtadient_Descent_Y.append(y_current)
learning_rate = 1.5
iter_num = 0 #迭代次数
f_change = x_current #变换值初始化为X的初始值
while f_change >= 1e-10 and iter_num < 100:
    x_now = x_current-learning_rate*one_derivate(x_current)
    y_now = one_dimension_image(x_now)
    f_change = np.abs(y_current-y_now)   
    x_current = x_now
    y_current = y_now
    iter_num += 1
    Gtadient_Descent_X.append(x_current)
    Gtadient_Descent_Y.append(y_current)
#构建数据集
X_data = np.arange(-4,8,0.05)
Y_data = np.array(list(map(lambda t:one_dimension_image(t),X_data)))

plt.figure(facecolor='w')
plt.plot(X_data,Y_data,'r-',linewidth = 2)
plt.plot(Gtadient_Descent_X,Gtadient_Descent_Y,'bo--',linewidth=2)
plt.title('函数$y=0.5*(x-2)^2$\n学习率为%.3f,最终解为:{%.5f,%.5f},迭代次数为%d'%(learning_rate,x_current,y_current,iter_num))
plt.show()

梯度下降法原理解释和代码演示

下面进行二维函数的代码演示,与一维不同的是,这次函数的自变量有两个,一个x1,另一个x2.

import matplotlib as mpl
import numpy as np
from mpl_toolkits.mplot3d import Axes3D

mpl.rcParams['font.sans-serif'] = [u'SimHei']
mpl.rcParams['axes.unicode_minus'] = False
#构建二维图像
def two_dimension_image(x1,x2):
    return 0.6*(x1+x2)**2-x1*x2
#构建二维图像的偏导数x1
def two_derivate_x1(x1,x2):
    return 0.6*2*(x1+x2)-x2
#构建二维图像的偏导数x2
def two_derivate_x2(x1,x2):
    return 0.6*2*(x1+x2)-x1
Gtadient_Descent_X1 = []#存放梯度下降的X1坐标
Gtadient_Descent_X2 = []#存放梯度下降的X2坐标
Gtadient_Descent_F = []#存放梯度下降的F坐标
x1_current = 8 #X1初始值
x2_current = 4  #X2初始值
f_current = two_dimension_image(x1_current,x2_current)  #Y初始值
Gtadient_Descent_X1.append(x1_current)
Gtadient_Descent_X2.append(x2_current)
Gtadient_Descent_F.append(f_current)
learning_rate = 0.5
iter_num = 0 #迭代次数
f_change1 = x1_current #变换值初始化为X1的初始值
f_change2 = x2_current #变换值初始化为X2的初始值
while np.abs(f_change1) >= 1e-10 and np.abs(f_change2) >= 1e-10 and iter_num < 500:
    x1_now = x1_current-learning_rate*two_derivate_x1(x1_current,x2_current)
    x2_now = x2_current-learning_rate*two_derivate_x2(x1_current,x2_current)
    f_now = two_dimension_image(x1_now,x2_now)
    f_change1 =x1_current-x1_now
    f_change2 = x2_current-x2_now
    x1_current = x1_now
    x2_current = x2_now
    f_current = f_now
    iter_num += 1
    Gtadient_Descent_X1.append(x1_current)
    Gtadient_Descent_X2.append(x2_current)
    Gtadient_Descent_F.append(f_current)
x1_data = np.arange(-5,5,0.2)
x2_data = np.arange(-5,5,0.2)
x1_data,x2_data = np.meshgrid(x1_data,x2_data)
Y = np.array(list(map(lambda t:two_dimension_image(t[0],t[1]),zip(x1_data.flatten(),x2_data.flatten()))))
Y.shape = x1_data.shape

fig = plt.figure(facecolor='w')
ax = Axes3D(fig)
ax.plot_surface(x1_data,x2_data,Y,rstride = 1,cstride = 1,cmap = plt.cm.jet)
ax.plot(Gtadient_Descent_X1, Gtadient_Descent_X2, Gtadient_Descent_F,'bo--')
ax.set_title('函数$0.6*(x1+x2)^2-x1*x2$,最优解为{%.5f,%.5f,%.5f}\n迭代次数为%d'%(x1_current,x2_current,f_current,iter_num))
plt.show()

梯度下降法原理解释和代码演示

部分代码解释

  • numpy.meshgrid()——生成网格点坐标矩阵

输入参数x和y是列向量,输出的X和Y是坐标矩阵。
比如输入的x是(3,)的,y是(4,)的,那么输出的X矩阵和Y矩阵就是(3,4)。即总共产生了12*12个点。

x = np.array([0, 1,])
y = np.array([0, 1,2])
X, Y = np.meshgrid(x, y)
print(X)
print(Y)

[[0 1]
[0 1]
[0 1]]
[[0 0]
[1 1]
[2 2]]

  • numpy.ndarray.flatten——返回一个折叠成一维的数组

该函数只能适用于numpy对象,即array或者mat,普通的list列表是不行的。

x = np.array([[1,2],[3,4],[5,6]])
a = np.mat([[1,2,3],[4,5,6]])
print(x.flatten())
print(a.flatten())

[1 2 3 4 5 6]
[[1 2 3 4 5 6]]

  • plt.figure(facecolor=‘w’)——创建自定义图像

figure(num=None, figsize=None, dpi=None, facecolor=None, edgecolor=None, frameon=True)

num:图像编号或名称,数字为编号 ,字符串为名称
figsize:指定figure的宽和高,单位为英寸,如(4,3);
dpi参数指定绘图对象的分辨率,即每英寸多少个像素,缺省值为80 1英寸等于2.5cm,A4纸是 21*30cm的纸张
facecolor:背景颜色
edgecolor:边框颜色
frameon:是否显示边框

  • Axes3D(fig)——用于绘制三维图像,将figure变为3d

ax.plot_surface(X, Y, Z,
rstride=1, # rstride(row)指定行的跨度
cstride=1, # cstride(column)指定列的跨度
cmap=plt.get_cmap(‘rainbow’)) # 设置颜色映射

相关标签: math