从串糖葫芦游戏到线性回归

2019-06-25 01:50陈凯
中国信息技术教育 2019年11期
关键词:倾角竹签糖葫芦

陈凯

用梯度下降的方法来实现线性回归,是一种很经典的机器学习算法。然而,在基础教育阶段,由于受学生自身数学水平和信息技术水平的限制,他们对这种算法的基本原理以及实现回归过程的程序代码的学习和理解,难度还是比较大的。笔者曾经浏览过不少线性回归方面的资料,发现学习路径颇为陡峭。本篇文章试着从一个小游戏入手,一边玩一边想,逐层铺垫,缓慢进阶,希望能让学习者避免迷失在诸多概念名词和繁杂程序代码之中,真正体验到线性回归算法的精髓。

● 冰糖葫芦手工串

先来看游戏的玩法。有几个糖葫芦散落在桌面上,要求不改变糖葫芦的位置,用一根竹签将它们串起来,游戏一开始,竹签只是平放在桌面边缘,并没有串起任何一个糖葫芦,如图1所示。

所谓的桌面,实際上是一个坐标轴,X轴和Y轴的范围都是0到10;所谓的糖葫芦,是四个面积比较大的点。实现串糖葫芦游戏的Python代码非常简单,如图2所示。

坐标轴上的这四个点的markersize参数是40,所以看上去就相当大,可以想见,这个参数越大,糖葫芦也越大,游戏也越简单。糖葫芦所在的坐标直接写在了plot函数的参数里,为代码简单清晰起见,这里并没有引入随机数。

所谓的竹签,是通过y=t1+t2*x这个一元一次方程产生的直线,其中t1是方程的常数,t2是一次项系数。如果输入t1为0.9,输入t2为0.6,那么竹签就串到了两个糖葫芦,如上页图3所示。

试过几次就可以发现,t1和t2两个数字的作用大不相同:前者决定了竹签的位置,“靠上还是靠下”与“靠左还是靠右”其实是一回事;后者决定了竹签的倾斜度。如果想让竹签往上摆一些,则t1要增加;如果想让竹签摆得平一些,则t2要减少。不妨再试一下,输入t1为3,输入t2为0.2,竹签成功地串起了三个糖葫芦,如上页图4所示。

多次尝试之后,就能体会到t1和t2两个数字的变化与最终直线形态之间的微妙关系。

● 竹签离得有多远

刚才是用人脑来判断竹签的位置t1和倾角t2,那么,怎么让机器判断位置和倾角呢?方法就是“看了再试,试了再看”。

例如,一开始,竹签是平躺着的,竹签到每个点的纵向的距离(为简单起见,这里暂不考虑横向的距离)是可以计算出来的,如图5所示,其中左图显然离开理想结果还很遥远,右图已经比较接近目标了。

为了能够计算出竹签到糖葫芦的距离,以评估竹签与理想目标之间的差距,可以将代码稍微修改一下。由于糖葫芦可能在竹签上面,也可能在竹签下面,在计算距离时,数值可能是正,也可能是负,所以纵向距离统一进行二次方的运算(其实取绝对值也是一样的)。又因为总共有四个糖葫芦,所以要除以4,得到一个纵向距离的平均数。修改后的程序代码如图6所示。

e = (e1+e2+e3+e4)/4/2这段代码,就是将糖葫芦中心点和竹签的纵向距离的平均值赋值给变量e,其中唯一难理解的是,为什么除以4取得平均值后又要除以2,其实这是为了让后续的求导公式更加便捷,若是学习者学习过隐藏在线性回归算法之后的数学原理,那么就能更清楚地知道这里为何要除以2。实际上,因为变量e的值只是用于在运算过程中指示竹签位置和倾角离开理想值的差距,所以是否除以2,其实是无所谓的。假如说任务是要让竹签尽可能靠近糖葫芦的中心,那么就需要观察e值是否能收敛于某个值,然而,本文任务只要求把糖葫芦串起来即可,因此后续的程序代码中并不需要用到e变量。

上述代码中,t1和t2的初始值都是0,运行后,发现得到的e的值是9.15227,这个数字显然太大了,计算结果和人眼的直观感受是符合的,所以需要改变t1和t2的值使得竹签距离糖葫芦更近一些。

● 竹签需要重新摆

为了让竹签有可能串起更多糖葫芦,就要重新调整竹签的位置和倾角,其实就是更改t1和t2的值。但计算机怎么知道应该如何调整呢?

首先来看竹签的位置,竹签究竟是往上放还是往下放?应该需要调整多少距离?想象一下,如果大部分糖葫芦都在竹签上方,那么就要往上挪,反之就是往下挪,离开越远,挪的距离就越多,程序中涉及的公式如上页图7所示。

这个公式是用微积分的方法推演出来的,然而就算是直观上也是可以理解的,当竹签平躺着的时候,得到的d1的值是4.18,这表示竹签要往上方移动4.18个单位,如果d1的数值是负数,则表示要将竹签往下方移动。

倾角的调整要复杂一些,因为这和每个糖葫芦的横向位置有关,涉及的公式如上页图8所示。

这同样是用微积分求导的方法推演出来的,如果不想深入了解相关数学推导过程,那只需要验证公式的合理性就可以了。当竹签平躺着的时候,得到的值是23.65975。如果是正数,表示要把竹签倾角增大,如果是负数,则表示将倾角变小。不过即便是直观看图9,也是能感受到公式的意义的,因为离开坐标轴原点越远,点的坐标值本身的权重也就越大。

然而,按公式计算后,d1和d2这两个数值都太大了,实际操作时矫枉过正,于是还要对这两个值再乘上步长系数0.05,此数可大可小,要根据实际运行情况来调整。系数太小,则需要很多次调整才能达成目标;系数太大,则会在理想结果周围来回跳跃。

最后,将d1和d2的修正值叠加到原先的t1和t2值上,将循环次数增加到200次,每一次循环中,做的都是同样的事:用当前的t1和t2计算出直线摆放姿态,然后将运行效果比对预期效果后得到调整值d1和d2,再用d1和d2修正t1和t2值,这种方法称为迭代法。图10、图11是完整的代码和运行结果。

这个例子本身形象直观,而代码也比较简单,若去掉绘图相关的代码,核心代码仅有十多行,其中隐藏了超出学生当前水平的知识点,尤其是数学微积分和线性代数有关的知识技能,但同时又留下了继续深入学习的路径指引,为学习者提供了真切的机器学习算法的实践体验。

猜你喜欢
倾角竹签糖葫芦
“糖葫芦”
竹签,算筹
糖葫芦
系列长篇科幻故事,《月球少年》之八:地球轴倾角的改邪归正
糖葫芦真好吃
会“动”的竹签
糖葫芦
挣扎(外一首)
竹签陀螺站起来
汽车行驶性能中车轮的重要影响