宝可梦实例
寻找一个function,将宝可梦的一些相关信息作为输入(input),如cp值(Xcp)、宝可梦的物种(Xs)、宝可梦的生命值(Xhp)、宝可梦的重量(Xw)、宝可梦的高度(Xh)等。该function的输出值为宝可梦进化后的cp值
具体步骤
-
找一个模型(function set)
如:线性模型 ,其中Xi为需要输入的宝可梦信息,称为feature,Wi称为weight ,b称为bias。则function set 为线性模型的集合(在该实例中,假设function set 为y=b+WXcp) -
从function set 中找到一个表现好的function
用上标来表示一个完整的个体,则在。训练数据集中:
其中,x表示某个宝可梦个体的输入信息,y表示该宝可梦升级后真实的cp值。
定义一个Loss Function来评估function set中的各种函数中参数(b与w)的好坏,称为估测误差。
Loss Function 的一般形式:
在该Loss Function 中,b+w*Xcp表示某个function预测出来的宝可梦进化后的cp值。
Loss Function 的值越大,则Function的表现越差
- 画出Loss Function关于参数b与w的图像
在该图像中,每一个点都代表一个Loss Function,颜色越偏红色,Loss Function越大,Function的表现越差;颜色越偏蓝色,Loss Function越小,Function表现越好。
- 找到最好的Function
法一:穷举所有的w与b,带入f *,找到使得f *最小的(b,w)组合
法二:Gradient Descent
当只有一个未知参数w时:
首先,画出w取值在(-∞,+∞)范围内时Loss Function变化的图像。
其次,找出Loss Function取最小值时,参数w所对应的取值:
生成一个随机点w0,计算w0处参数w对Loss Function的微分(w0所对应的函数上点的切线斜率),微分小于0(切线斜率小于0,左边高右边低),增加w0的值;微分大于0(切线斜率大于0,左边低右边高),减小w0的值
然后,决定步长的大小:
在该式中,dL/dw表切线斜率,数值越大,表明在w0附近曲线越陡峭,步长越大;反之,数值越小,表明在w0附近曲线越平缓,步长越小。η表 learning rate,是一个事先定好的数值,该数值越大,说明参数更新的幅度大,学习速度快;反之,更新幅度小,学习速度慢。
重复步骤3,直到算出微分为0。
当存在两个未知参数w与b时:
首先,随机选取两个参数的初始值w0与b0
其次,分别计算w=w0时,Loss Function对w的偏微分,b=b0时,Loss Function对b的偏微分。
分别更新参数w与b
再对新的参数取值分别计算偏微分(重复步骤2)
更新参数w与b(重复步骤3)
直到找到使得Loss Function最小的b与w
(箭头为等高线的法线方向)
Gradient Descent的缺点:
当图形较为复杂时,如:
有可能找到的最优值不是全局最优值,而是局部最优值(这与随机点的选取有关)
在linear regression中不必担心这个问题,因为linear regression中没有其他的局部最优值
模型y=b+w*Xcp使得Loss Function最小的参数组合为b=-188.4,w=2.7。
评估该Function在training data 上的表现;
平均误差为:
评估该function在testing data上的表现
平均误差为:
优化模型:
运用Gradient Descent找出最优参数:
该function在training data上的误差为:
该function在testing data上的误差为:
继续优化模型:
在模型优化过程中,training data 中的平均误差不断下降,但testing data中的平均误差先减小,后增大。当模型在training data中表现好,但在testing data上表现很差时,这种现象称为过拟合(overfitting)
当收集的宝可梦数量增加时:
可以发现:宝可梦进化后的cp值可能不仅只与进化前的cp值有关,还可能与宝可梦的物种、高度等因素有关。
当考虑宝可梦进化前的cp值与物种时:
将不同物种的宝可梦用不同颜色的点表示:
此时,function可以表示为:
training data的平均误差为3.8,testing data的平均误差为14.3
当考虑宝可梦进化前的cp值、物种、高度时,function可以写成:
此时,training data的平均误差为1.9,testing data的平均误差为102.3,出现了过拟合的现象,需要重新设计Loss Function:
由于原来的Loss Function 只考虑到了预测值与真实值之间的误差,现在要加上一个额外的值,我们希望Wi越小越好,λ越大越好,function才能表现得比较平滑,不容易被噪声(noise)影响。
当λ增大时,training data与testing data中的平均误差表现如下:
发现当λ增大时,training data的平均误差会增大,这是由于当λ很大时,若要使Loss Function取最小值,则需要着重考虑Wi本身的值,从而放松了对预测值与真实值之间的误差的考虑。
Gradient Descent代码:
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
import numpy as np
import matplotlib.pyplot as plt
x=np.arange(-200,-100,1) #bias
y=np.arange(-5,5,0.1) # weight
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]=z[j][i]+(y_data[n] - b - w * x_data[n])**2
z[j][i]=z[j][i]/len(x_data)
b=-120 # bias的初始值
w=-4 #weight的初始值
lr=1 #学习率
iteration =100000 #循环次数
b_history=[b] #储存b的初始值
w_history=[w] #储存w的初始值
#分别定义b与w的学习率
lr_b=0
lr_w=0
for i in range(iteration):
b_grad=0.0 #参数b梯度的初始值
w_grad=0.0 #参数w梯度的初始值
# 计算每一个点的梯度方向
for n in range(len(x_data)):
b_grad=b_grad-2.0*(y_data[n]-b-w*x_data[n])*1.0
w_grad=w_grad-2.0*(y_data[n]-b-w*x_data[n])*x_data[n]
lr_b=lr_b+b_grad**2
lr_w=lr_w+w_grad**2
# 更新参数b与w
b=b-lr/np.sqrt(lr_b)*b_grad
w=w-lr/np.sqrt(lr_w)*w_grad
# 储存每一个更新的b与w
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=10)
plt.ylabel(r'$w$',fontsize=10)
plt.show()
得到下列图像: