Press "Enter" to skip to content

AI 入行那些事儿(四)- 最简单的机器学习模型:线性回归

2021 开年巨献 —— 系列文章《AI  入行 那些事儿》,为您讲述:

 

人工智能的基础原理、发展历程、当前应用

 

成为 AI 技术人员所需的入门技能和学习途径

 

以及求职、面试的全过程

 

 

机器学习的 Hello World:线性回归模型

 

我们来看一个最简单的机器学习模型:线性回归。这个模型基于一种假设:我们的样本数据的特征和标签之间存在着线性关系,也就是说以样本特征为自变量的线性函数值就是样本标签。

 

我们要看的这个例子展示了线性回归最简单的形式:一元线性回归。下图的表格记录了一个公司多名员工的个人信息和薪资状况。

 

 

通过数据可视化,我们不难看出员工的工作年限(experience)和薪水(salary)之间存在着近似线性的关系。

 

 

也就是说,如果我们将工作年限设为 x,将工资额度设为 y,则 x 和 y 的关系可以用线性函数 y = a + bx 来表示。此处 a 和 b 是函数 f(x) = a + bx 的参数,x 是 f(x)的自变量,而 y 是 f(x) 的因变量。

 

目标函数

 

那幺,a 和 b 分别取怎幺样的值,才能使得对应的 f(x) 最合适表达当前这张表格上的员工经验与收入的关系呢?这就要请损失函数出场了。

 

假设我们现在已经求出了 a 和 b 的值,那幺我们将样本点的自变量 x 带入函数 f(x) = a + bx,必然会得到一个因变量的取值,我们设这个取值是 y’, y’ = a + bx, 而样本原本的取值是 y。

 

无论 a 和 b 取什幺值,都有可能存在 y’ 不等于 y 的情况,也就是说无论在坐标系中怎幺画 a + bx 这条直线,都有可能存在没有正好落在这条直线上的样本点。

 

 

某个样本点 x0 的真实值 y0 和它们的预测值 y0’之间的差距就是这个样本点的损失。一个样本点的损失如此,所有样本点的损失当然是把单个样本点的损失都加起来。

 

但是因为损失值有正有负,为了不让它们相互抵消,我们将每个样本点损失的平方相加,这样就不会因为取值正负的关系掩盖实际损失了。于是也就是有了我们的这个损失函数:

 

每一个样本的真实标签值 yi 减去其自变量 xi 带入到函数 f(x) 的结果 —— a + bxi,然后求平方后累加。因为 xi 和 yi 对应样本的特征和标签值,因此它们都是已知量,而 a 和 b 则是未知量,此时整体损失成了以 a 和 b 为自变量的二元函数。

 

为了后面的求导计算更顺畅,我们再加上一个正系数:1/2m,我们J(a,b) 来标志这个线性回归的损失函数。

 

目标函数最小化

 

我们当然是希望我们求出的a和b使得样本的整体损失最小,也就是希望能够找到让 J(a,b) 尽量地小的a 和 b的取值。因为找到 J(a,b) 的最小值是我们的目标,因此 J(a,b) 在此又被称为目标函数。

 

如何找到让目标函数最小化的取值呢?首先应该确定目标函数是凸函数,也就是说在目标函数的值域空间中,存在着一个点,这个点对应的因变量的值达到全域最小。

 

当确定了这个点存在后,这个点的自变量取值就是我们要找的目标函数。比如下图就是一个最简单的一元凸函数,它就有一个最小值点,也下图中的“local optima”点:

 

 

梯度下降算法

 

确定这个点存在后,怎幺找到它呢?这里就需要用到高等数学中的最优化方法了。最优化方法有很多种,我们来看最常用的一种:梯度下降算法。

 

什幺是梯度

 

梯度同样已是一个微积分中的概念,函数的梯度可以简单理解为函数的导数,只不过对于一元函数而言,这个导数是 个标量 值函数 。 其上某一点的梯度就是这个函数图形上该点切线的斜率:

 

 

而多元函数的梯度则是向量值函数。 而对二元函数而言,其上某点的梯度是该函数图形上该对应两个自变量方向的切线的斜率组成的向量,以此类推。

 

梯度下降的原理对于一元或多元都是一样的,因此我们就以一元函数举例说明梯度下降算法。

 

梯度下降的过程

 

一元函数的梯度下降算法运行过程是这样的:先在目标函数上随机的选取一个点,然后求函数在此点的梯度,如果这个梯度值是正数则说明如果此点处自变量增加,因变量也增加;反之若梯度为负,则说明自变量增加则因变量减小。

 

 

我们需要的是找到因变量最小的点,因此,我们肯定要向着因变量变小的方向走,因此导数为正的时候,我们要让自变量减小一点,而导数为负时,我们要让自变量增加一点。也就是沿着导数的反方向“前进一步”。

 

在图上画出来就是向右下图那样,往下走一步。这个下行动作不断重复,直到达到或近似达到最小值点。

 

 

沿着函数梯度的反方向走,导致函数因变量取值的下降,这就是梯度下降这一名称的来源。

 

具体到我们的目标函数 J(a,b)。它是一个凸函数(高等数学里把这种下凹样式的函数叫做凸函数),这是可以通过函数的凸性定义进行证明的。因此我们可以用梯度下降法求 J(a,b) 的最小值。

 

J(a,b) 是一个二元函数,可视化出来是一个三维空间中下凹的平面。

 

 

梯度下降算法

 

虽然看起来和刚才我们做例子的一元函数在二维空间中呈现的下凹曲线不同,但道理是一样的。

 

我们对它使用梯度下降算法:

 

【1】先随机找到函数上一个点,求此点的梯度——下面的两个式子分别对应 J(a,b) 二维梯度向量的两个分量:

 

 

【2】然后沿着函数梯度的反方向下降一步。

 

这一过程我们可以形象化地想象成我们在一个大碗上随意找一点放置一个小球,然后沿着小球所在点在东西、南北两个垂直平面中切线的方向向碗底滚动一下。这个下降的过程反复迭代,直到滚到碗底。

 

这个梯度下降的过程既然已经明白,我们就可以通过编程来实现它了。

 

首先给 a 和 b 一个任意值,比如让它们都等于 0。

 

然后进入一个循环,循环的结束条件是算法收敛,也就是每次下降的高度小于某个指定的阈值。

 

而循环体中的操作则是每次迭代 a  和  b 减掉导数与常数 alpha 的乘积。

 

此处的alpha是一个人为指定的常数,它代表了每次下降先前前进的距离,因此又被叫做步长参数。

 

这一过程可以直接写成伪代码的形式:

 

 

训练程序

 

当我们选定实现语言后则可以讲伪代码改写为程序。这个程序就叫做训练程序,它可以用来训练线性回归模型。

 

假设我们有 1000 个样本数据,我们也就有了 1000 对 xi 和yi  的值,也就是 m  取值为1000。

 

我们将这 1000 对样本值带入到这个程序里面,经过两层循环的若干次运行,达到目标函数值收敛。

 

我们也就得出了a 和 b 的取值,f(x) = a + bx 这条直线也就有了具体的斜率和偏移量,我们就可以用它进行预测了,以后再有一个  x 值,我们只需要带入进  f(x) 就能得到一个 y 值,这个 y 值就是这个新样本的预测值。

 

当我们用其他目标函数替代 J(a,b) 后,这个程序也可以训练其他的模型。

 

如上就是训练一个线性回归模型从数学推导到代码实现的全过程。这个训练程序的内在逻辑,就是我们通常所说的算法。

 

Be First to Comment

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注