目录
numpy.zeros(shape, dtype=float, order=‘C’)
matplotlib.pyplot.contourf([X, Y,] Z,[levels], **kwargs)
matplotlib.pyplot.plot((x, y, format_string, **kwargs)
求回归中的参数有很多种方法,这里重点介绍梯度下降法。
1. 源代码
import numpy as np
import matplotlib.pyplot as plt
x_data = [338.,333.,328.,207.,226.,25.,179.,60.,208.,606.]
y_data = [640.,633.,619.,393.,428.,27.,193.,66.,226.,1591.]
#ydata = b +w * xdata 使用梯度下降法找出b和w
x = np.arange(-200,-100,1) #偏置,即b
y = np.arange(-5,5,0.1) #权重,即w
Z = np.zeros((len(x),len(y)))
X,Y = np.meshgrid(x,y) #生成网格点坐标矩阵,用于后续绘制等高线图
for i in range (len(x)):
for j in range (len(y)):
b = x[i]
w = y[j]
Z[j][i] = 0
for n in range (len(x_data)):
#Z[j][i]为 b=x[i] 及 w=y[j] 时,对应的损失函数的大小
Z[j][i] = Z[j][i] + (y_data[n] - b - w*x_data[n])**2 #对应公式1(损失函数)
Z[j][i] = Z[j][i]/len(x_data) #求损失函数的均值
#ydata = b +w * xdata
b = -120 #初始化b的值
w = -4 #初始化w的值
lr = 0.0000001 #初始化学习率
iteration = 10000 #设置迭代次数
#存储绘图的初始值
b_history = [b]
w_history = [w]
#迭代
for i in range(iteration): #进行10000次迭代并查看最后结果
b_grad = 0.0 #对b_grad赋初值为0
w_grad = 0.0 #对w_grad赋初值为0
for n in range (len(x_data)):
#分别对损失函数中的w和b求偏导,计算b和w对损失函数的偏微分,查看w、b在各自的轴上的移动
b_grad = b_grad - 2.0*(y_data[n] - b -w*x_data[n])*1.0 #对应公式3
w_grad = w_grad - 2.0*(y_data[n] - b -w*x_data[n])*x_data[n] #对应公式2
#更新参数
b = b - lr * b_grad
w = w - lr * w_grad
#存储用于画图的参数
b_history.append(b)
w_history.append(w)
#绘制图像
plt.contourf(x,y,Z,50,alpha = 0.5,cmap = plt.get_cmap('jet')) #绘制等高线图
plt.plot([-188.4],[2.67],'x',ms = 12 ,markeredgewidth = 3,color = 'orange')
plt.plot(b_history,w_history,'o-',ms = 3,lw = 1.5,color = 'black')
plt.xlim(-200,-100)
plt.ylim(-5,5)
plt.xlabel(r'$b$',fontsize = 16)
plt.ylabel(r'$w$',fontsize = 16)
plt.show()
2. 代码函数解析
numpy.arange()
返回一个有起点和终点的固定步长的排列。例如np.arange(0,3,1)的返回值为[0,1,2]。返回值是左闭右开的。
x = np.arange(-200,-100,1)
#函数返回起点是-200,终点是-100,步长为1的排列
当只有一个参数时,默认起点为0,步长为1。
numpy.zeros(shape, dtype=float, order=‘C’)
返回来一个给定形状和类型的用0填充的数组;
参数解析:shape-数组形状 dtype-(可选)数据类型,默认为float64 order-(可选)C代表行优先,F代表列优先
Z = np.zeros((len(x),len(y)))
#返回一个len(x)*len(y)大小的零数组
numpy.meshgrid()
生成网格点坐标矩阵。
matplotlib.pyplot.contourf([X, Y,] Z,[levels], **kwargs)
绘制等高线。
参数解析:levels-(可选)确定轮廓线的数量和位置 alpha-(可选)透明度 cmap-(可选)str或colormap,Colormap用于将数据值(浮点数)从间隔转换为相应Colormap表示的RGBA颜色。用于将数据缩放到间隔中看
matplotlib.pyplot.get_cmap()
绘图颜色渐变。
matplotlib.pyplot.plot((x, y, format_string, **kwargs)
用于画图。
参数解析:format_string-(可选)控制曲线的格式
color颜色:'b'
蓝色 'm'
洋红色 magenta 'g'
绿色 'y'
黄色 'r'
红色 '
k'
黑色 'w'
白色 'c'
青绿色 cyan '#008000'
RGB某颜色 '0.8'
灰度值字符串
linestyle风格:'‐'
实线 '‐‐'
破折线 '‐.'
点划线 ':'
虚线 '' ' '
无线条
marker标记风格:'.'
点标记 ','
像素标记(极小点) 'o'
实心圈标记 'v'
倒三角标记 '^'
上三角标记 '>'
右三角标记 '<'
左三角标记
3. 实验结果及改进
最终代码运行结果如下:
图上的颜色代表不同参数下的损失值,纵轴是w的变化,横轴是b的变化。“×”处是损失值最低的点。
从b = -120,w = -4处开始更新参数,但是经过十万次迭代后,参数更新值仍距离“×”处很远,所以考虑增大学习率。
当学习率=0.000001时,结果如下图,此时离最佳点近了一些。但是发生了剧烈的震荡现象。
当学习率=0.00001时,结果如下图,效果并不如之前。
为解决这一问题,需要给b和w设置不同的学习率。
#ydata = b +w * xdata
b = -120 #初始化b的值
w = -4 #初始化w的值
lr = 1 #初始化学习率
iteration = 10000 #设置迭代次数
#存储绘图的初始值
b_history = [b]
w_history = [w]
#分别给b和w设定学习率
lr_b = 0
lr_w = 0
#迭代
for i in range(iteration): #进行10000次迭代并查看最后结果
b_grad = 0.0 #对b_grad赋初值为0
w_grad = 0.0 #对w_grad赋初值为0
for n in range (len(x_data)):
#分别对损失函数中的w和b求导,查看w、b在各自的轴上的移动
b_grad = b_grad - 2.0*(y_data[n] - b -w*x_data[n])*1.0 #对应公式3
w_grad = w_grad - 2.0*(y_data[n] - b -w*x_data[n])*x_data[n] #对应公式2
lr_b = lr_b + b_grad ** 2
lr_w = lr_w + w_grad **2
#更新参数
b = b - lr/np.sqrt(lr_b) * b_grad
w = w - lr/np.sqrt(lr_w) * w_grad
#存储用于画图的参数
b_history.append(b)
w_history.append(w)
#绘制图像
plt.contourf(x,y,Z,50,alpha = 0.5,cmap = plt.get_cmap('jet')) #绘制等高线图
plt.plot([-188.4],[2.67],'x',ms = 12 ,markeredgewidth = 3,color = 'orange')
plt.plot(b_history,w_history,'o-',ms = 3,lw = 1.5,color = 'black')
plt.xlim(-200,-100)
plt.ylim(-5,5)
plt.xlabel(r'$b$',fontsize = 16)
plt.ylabel(r'$w$',fontsize = 16)
plt.show()
最终的得到的结果如下图所示。此时效果已经远远优于之前的效果。