数与图(19)——机器学习.上
机器学习是实现人工智能的一种方法,文本通过一个简单的案例,解释机器学习的基本思路与方法。
“机器学习”一词中的机器指的是计算机,机器学习的重点在于“学习”。要理解学习,就必须搞清楚两个问题:学什么、怎么学。
首先解释学什么。对于人类而言,学习一定是学习那些不懂、不会的东西,就像婴儿学说话,从一无所知到准确表达。但机器学习则不尽然,比如图像识别,这件对人类来说轻而易举的事情,让机器学习来可是费尽周折,需要消耗大量的人类智能编写程序,然后再消耗大量电能运行这些程序,最后也只能识别出它“见”过的那类图像。
其次解释怎么学,两个字:训练!具体说是用已知的数据对模型进行训练,那么什么是模型,如何训练,是接下来要重点阐述的内容。
本文采用的案例涉及到两种温度的换算,即,如何将摄氏温度换算成华氏温度。如前所述,这个问题对人类来说是已知的,确切地说,这种换算关系本身就是人类自己设定的
式⑴中的C为摄氏度,F为华氏度。我们的目的是给出10组真实的数据,如表1所示。
表1 一组数据:摄氏度C与华氏度F的对照表
利用上表中的数据,对模型进行训练,那么什么是模型呢?说的浅显一点,模型就是公式。这个公式是建立在假设基础上,我们假设F与C之间是二次函数的关系。为了便于从数学的角度理解模型,我们用y表示华氏温度,用x表示摄氏温度,那么模型可以表示为
y =a*x2+b*x+c ⑵
这是一个标准的二次函数,训练的目的是找到一组a、b、c的目标值,使得⑵式满足表1中的数值关系,即,将表1中的C(x)值代入⑵式,可以得到表中对应的F(y)值。这一过程的实现需要经过以下五个步骤:
为系数abc设定一组假想值,如abc均为1,则⑵式变为
y=x2+x+1 ⑶
将表1中的摄氏度x依次代入⑶式,求出对应的y值。可以想象这些y值与真正的华氏度之间会有多大的差距,这里称计算所得的华氏度为“假y”,而称表1中的华氏度为“真y”。
求10组数据的方差,即,将10组(假y -真y)的平方相加,再用所得的和除以10(数据组数),用数学的方法表示方差
由于abc的假想值与目标值之间存在偏差,导致了方差E,分别求E对abc的导数,如果导数大于零,说明假想值>目标值,则将系数调小,否则,将系数调大。
将调整后的系数重新代入⑵式,重复1~5步操作。将1~5重复执行若干次,如5000次,然后查看所得的系数。
关于上述步骤的描述,有几个技术要点需要特别加以解释。
为什么假设模型是二次方程?
方差是怎样定义的,为何选择方差?
方差E如何对abc求导?
如何根据第3步的求导结果来调整系数缩小误差?
下面我们逐一加以解释。
1、模型设计的数学依据
高中数学中有一部分重要的内容是数列,包括等差数列和等比数列,这两类数列有各自的通项公式及求和公式,这里想要介绍的是另一种数列——泰勒级数。
泰勒级数由多项式组成,其中包含无穷多个项,例如
式⑸中的分母中带有感叹号,这是一种计算符号,通常写作n!,读作“n的阶乘”,表示从1开始连续n个整数的乘积,如4!=4*3*2*1。这样的数列有什么用呢?好问题!你可知⑸式与什么函数等价吗?与指数函数等价。即
在上式中,随着数列项数的增加,右边多项式的值可以无限趋近于左边的指数函数值。这个结论来自于一个更具有普遍性的定理——泰勒定理:如果一个函数f(x)在x0附近有任意阶导数,那么f(x)就可以展开成多项式的形式,这个多项式被称作泰勒级数,可以表示为
⑹式中0!=1,f(n)(x0)是f(x)在x0处的n阶导数,最后一项Rn(x)称作余项,是一个高阶无穷小。
我们在高中学习过的很多函数都可以任意次求导,如sin(x)、cos(x)、ex等。泰勒级数的应用之一就是求近似解,此外,它给了我们一个重要启示:假如我们手头有一些杂乱无章的数据,假如这些数据背后隐藏着某种未知的函数关系,那么我们不妨假设它们可以表达为某个高阶多项式,然后利用已有的数据来求出多项式的系数。用机器学习的语言来说,就是先假设一个模型,再用数据对模型进行训练。这就是我们选择二次函数作为模型的数学依据。其实我们也可以选择三次甚至更高次的多项式,这里选择二次,最终是想证明二次项的系数会收敛到零。
2、方差的定义
方差是一种误差的统计方法。假设有一组测量数据,其中包含n个值a1、a2…an,它们的平均值为a,那么方差的值为
在数学上这样的加和算式可以表达为更简洁的形式
上式中的符号Σ读作西格玛,是第18个希腊字母,在数学中表示连加法。Σ下方的i=1表示下标i的最小值,Σ上方的n表示i的最大值。
求误差的方式有多种,例如平均误差
标准误差
与平均误差相比,方差的特点是,当误差值>1时放大误差,当误差值<1时缩小误差,总体效果是对误差更加敏感;与标准误差相比,方差免去了开方运算,减小了运算量。
3、方差对系数求导
在本文的例子中,方差的计算公式为
可见,我们并没有针对平均值求误差,而是对真y求误差。在表1给出的10组数据中,每个x值都对应一个真y和一个假y,其中真y通过查表获得,而假y由模型计算所得,即
我们要分别求出误差E对系数a、b、c的导数,而这三个系数都在假y的算式中,为此将上式代入到⑷式中,然后进行求导运算
这里需要扩展一下幂函数的求导公式,设幂函数为y=p(qx+r)n,那么对其求导的操作包括两个步骤:1、先对幂函数(qx+r)n求导,得n(qx+r)n-1;2、再对幂函数的底qx+r求导,得到q,最终结果是pq(qx+r)n-1。此外,对多项式求导,等于对每个单项式的求导结果加和。
下面对⑺进行求导,首先求误差E对a的导数
注意:E对a求导意味着a是变量,x2是a的系数。再求误差E对b的导数
最后求误差E对c的导数
以上得到了误差E对三个系数的导数公式,很快这些公式就会用到程序中,来判断误差的特性及修正误差的方法。
4、调整系数缩小误差
由方差的计算公式⑺可知,方差是系数a、b、c的二次函数,因此方差函数可以绘制成一条开口向上的抛物线,且函数具有最小值,我们的目标是将误差调整到最小值。图1中示意性地画出了一条开口向上的抛物线,并在最小值的左侧绘制了一条红色切线(斜率小于零),在最小值右侧绘制了一条蓝色切线(斜率大于零)。你可以把y坐标想象成误差E,把x坐标想象成系数,根据观察,如果系数值偏小,那么导数将小于零,这时应该让系数增大,相反,如果系数偏大,那么导数将大于零,这时应该将系数减小。这就是误差的调整方法:根据导数的正负来调整系数的大小,这是导数在机器学习中的重要应用,系数的调整幅度也称作系数调整步长。
图1 导数与误差调整
有了以上的结论,我们可以开始编写程序了。受到篇幅的限制,本文先做一些准备工作,更多的任务留给下一篇文章。
将《数与图(18)》中求积分的项目另存为“机器学习”,修改屏幕的标题为“机器学习”,删除不必要的按钮及标签,添加一个文本输入框,命名为“训练次数”(仅限数字),结果如图2所示。
图2 修改用户界面
下面开始编写程序。首先声明一个全局变量,将表1中的数据保存为列表,代码如图3所示。
图3 将训练数据保存为列表
再声明几个全局变量,如图4所示。
图4 项目中的全局变量
图4中的全局变量a、b、c是二次函数模型的系数,其初始值均设为1。需要特别说明的是,系数调整步长的设置对于模型训练的结果至关重要,如果步长过大,误差会在最小值附近反复震荡,无法收敛到最小值;如果步长设置过小,收敛的速度会很慢。这里将全局变量“系数调整步长”的初始值设为0.1,是因为我们事先知道了温度转换公式(见式⑴),如果是一个未知的模型,步长设置会不同。图4中的最后三个列表类型的全局变量用来跟踪训练过程中误差的改变,最终将绘制出误差曲线。
最后创建四个有返回值的过程:真y列表、假y列表及方差,代码如图5至图8所示。
图5 有返回值过程——真y列表
图6 有返回值过程——假y列表
图7 有返回值过程——方差
注意,方差过程的返回值中并没有除以系数10,这是对方差公式的简化,不影响下一步求导结果的正负号。
图8 有返回值过程——误差对系数求导
注意,在图8的过程里,求导运算中忽略了式⑻、⑼、⑽中的系数1/5,这也是对公式的简化,不影响求导结果的正负号。
文本就写到这里,在下一篇文章中,我们将编写训练模型的程序,并绘制误差曲线。