何为机器学习:让机器具备找一个函数的能力。比如:图像识别,找到一个复杂函数,输入x:图片,输出y:是什么。
机器学习的类别:
1.回归
输出是一个数值,一个标量(scalar)。
我们现在来看一个案列:假设你是一个视频博主,后台可以看到很多相关的信息,比如:每天点赞的人数、订阅人数、观看次数……你要预测你今后的收入,可以通过机器学习找一个函数,该函数的输入是后台的信息,输出是隔天这个频道会有的总观看的次数。
第一个步骤
是写出一个带有未知参数的函数 f,其能预测未来观看次数。比如将函数写成:
其中y是预测的东西,x是前一天数据,w、b是未知参数(通过数据找出)。
那为什么这个函数一定是这样做呢?其实不是这是一个隐约猜测,可能是这样的。猜测往往来自于对这个问题本质上的了解,即领域知识(domain knowledge)。机器学习就需要一些领域知识。这是一个猜测,也许今天的观看次数,总是会跟昨天的观看次数有点关联,所以把昨天的观看次数,乘上一个数值,但是总是不会一模一样,所以再加上一个 b 做修正。
带有未知的参数(parameter)的函数称为模型(model)。模型在机器学习里面,就是一个带有未知的参数的函数,特征(feature) x1 是这个函数里面已知的,它是来自于后台的信息,是已知的,而 w 跟 b 是未知的参数。w 称为权重(weight),b 称为偏置(bias)。这个是第一个步骤。
第二个步骤
是定义损失(loss),损失也是一个函数L(b,w),输入是模型里的未知参数,输出一个值判断:现在如果把这一组未知的参数,设定某一个数值的时候,这笔数值好还是不好。我们举个例子假设b=500,w=1,函数为:.当我们输入已知数据x就会得到一个
.当x1代入4800,预测隔天实际上的观看次数结果为
=5300,真正的结果假设是4900,真实的值称为标签(label),它高估了这个实际数,可以计算一下估测的值跟真实值y的差距。计算差距其实不只一种方式,比如取绝对值:
我们不是只能用第一天预测第二天,也可以第二天预测第三天,依次类推,我们可以得到接下来把每一天的误差,通通加起来取得平均,得到损失L
其中,N 代表训验数据的个数,即几年来的训练数据,计算出一个 L,L 是每一笔训练数据的误差 e 相加以后的结果。L 越大,代表现在这一组参数越不好,L 越小,代表现在这一组参数越好。估测的值跟实际的值之间的差距,其实有不同的计算方法,上文的方法是计算 y 与 之间绝对值的差距,称为平均绝对误差(Mean Absolute Error,MAE)。
如果算 y 与 之间平方的差距,则称为均方误差(Mean Squared Error,MSE)。
有一些任务中 y 和 yˆ 都是概率分布,这个时候可能会选择交叉熵(cross entropy)
我们将b、w不同的组合计算出一系列的ei可视化:
绘制出等高线图。在这个等高线图上面,越偏红色系,代表计算出来的损失越大,就代表这一组 w 跟 b 越差。如果越偏蓝色系,就代表损失越小,就代表这一组 w 跟 b 越好,拿这一组 w 跟 b,放到函数里面,预测会越精准。假设 w = −0.25, b = −500,这代表这个频道每天看的人越来越少,而且损失这么大,跟真实的情况不太合。如果 w = 0.75, b = 500,估测会比较精准。如果 w 代一个很接近 1 的值,b 带一个小小的值,比如说 100 多,这个时候估测是最精准的,这跟大家的预期可能是比较接近的,就是拿前一天的点击的总次数,去预测隔天的点击的总次数,可能前一天跟隔天的点击的总次数是差不多的,因此 w 设 1,b 设一个小一点的数值,也许估测更精准。
第三个步骤
解一个最优化的问题。就是寻找使Loss值找最小的b、w,这个可以让损失最小的 w 跟 b 称为 w∗ 跟 b∗ 代表它们是最好的一组 w 跟 b,可以让损失的值最小。梯度下降(gradient descent)是经常会使用优化的方法。(高数梯度那学过)。
为了方便理解,先假设只有一个未知的参数 w,b 是已知的。w 代不同的数值的时候,就会得到不同的损失,这一条曲线就是误差表面,只是刚才在前一个例子里面,误差表面是 2 维的,这边只有一个参数,所以这个误差表面是 1 维的。
怎么样找一个 w 让损失的值最小呢?
1,首先要随机选取一个初
2,计算,在 w 等于 w0 的时候,参数 w 对损失的微分。计算在这一个点,在 w0 这个位置的误差表面的切线斜率,也就是这一条蓝色的虚线,它的斜率,如果这一条虚线的斜率是负的,代表说左边比较高,右边比较低,说明还有更小的Loss值在这个位置的左边,w可以取得更大,如图所示:
把 w0 往右移一步,新的位置为 w1,这一步的步伐是 η(学习率) 乘上微分的结果,即:
如果算出来的斜率是正的,就是右边。我们可以想像说有一个人站在这个地方,他左右环视一下,算微分就是左右环视,它会知道左边比较高还是右边比较高,看哪边比较低,它就往比较低的地方跨出一步。这一步的步伐的大小取决于两件事情:
(1)第一件事情是这个地方的斜率,斜率大步伐就跨大一点,斜率小步伐就跨小一点
(2)另外,学习率(learning rate)η 也会影响步伐大小。学习率是自己设定的,如果 η 设大一点,每次参数更新就会量大,学习可能就比较快。如果 η 设小一点,参数更新就很慢,每次只会改变一点点参数的数值。这种在做机器学习,需要自己设定,不是机器自己找出来的,称为超参数(hyperparameter)。
3,接下来反复进行刚才的操作,计算一下 w1 微分的结果,再决定现在要把 w1 移动多少,再移动到 w2,再继续反复做同样的操作,不断地移动 w 的位置,最后会停下来。往往有两种情况会停下来:
第一种情况是一开始会设定说,在调整参数的时候,在计算微分的时候,最多计算几次。上限可能会设为 100 万次,参数更新 100 万次后,就不再更新了,更新次数也是一个超参数。
另外一种理想上的,停下来的可能是,当不断调整参数,调整到一个地方,它的微分的值就是这一项,算出来正好是 0 的时候,如果这一项正好算出来是 0,0 乘上学习率 η 还是 0,所以参数就不会再移动位置。假设是这个理想的情况,把 w0 更新到 w1,再更新到 w2,最后更新到 wT 有点卡,wT 卡住了,也就是算出来这个微分的值是 0 了,参数的位置就不会再更新。
但是第二种情况,我们又会遇到新问题,导数为0求出的是极值点,而非最值。所以常常可能会听到有人讲到梯度下降不是个好方法,这个方法会有局部最小值的问题,无法真的找到全局最小值。事实上局部最小值是一个假问题,在做梯度下降的时候,真正面对的难题不是局部最小值。有两个参数的情况下使用梯度下降,其实跟刚才一个参数没有什么不同。如果一个参数没有问题的话,可以很快的推广到两个参数。
真正的难题通常不是局部最小值,而是:
-
鞍点和梯度消失:在高维空间中,鞍点比局部最小值更常见。模型在鞍点附近收敛速度减慢,甚至可能停滞不前。此外,在某些情况下,梯度可能会非常小(梯度消失问题),导致模型几乎无法更新参数。
-
非凸优化的复杂性:很多实际问题中的损失函数是高度非凸的,包含复杂的地形和许多高低起伏。虽然局部最小值可能不是问题,但找到一个合理的收敛路径可能仍然非常具有挑战性。
-
模型的过拟合:在复杂模型中,过拟合是一个更为实际的问题。优化过程可能导致模型对训练数据过于拟合,进而在测试数据上表现不佳。如何平衡模型的复杂性与泛化能力是一个关键挑战。
假设有两个参数,随机初始值为 w0, b0。要计算 w, b 跟损失的微分,计算在 w = w0 的位置,b = b0 的位置,要计算 w 对 L 的微分,计算 b 对 L 的微分
,
计算完后更新 w 跟 b,把 w0 减掉学习率乘上微分的结果得到 w1,把 b0 减掉学习率乘上微分的结果得到 b1。接下来反复进行刚才的操作,一般都是程序自动帮计算的,期待最后,可以找到一个最好的 w,w∗ 跟最好的 b∗. 如图所示
随便选一个初始的值,先计算一下 w 对 L 的微分,跟计算一下 b 对 L 的微分,接下来更新 w 跟 b,更新的方向就是 ∂L/∂w,乘以 -η ,∂L/∂b,算出这个微分的值,就可以决定更新的方向,可以决定 w 要怎么更新。把 w 跟 b 更新的方向结合起来,就是一个向量,就是红色的箭头,再计算一次微分,再决定要走什么样的方向,把这个微分的值乘上学习率,再乘上负号,我们就知道红色的箭头要指向那里,就知道如何移动 w 跟 b 的位置,一直移动,期待最后可以找出一组不错的 w, b。
实际上真的用梯度下降,进行一番计算以后,这个是真正的数据,算出来的最好的 w∗ = 0.97, b∗ = 100,跟猜测蛮接近的。因为x1 的值可能跟 y 很接近,所以这个 w 就设一个接近 1 的值,b 就设一个比较偏小的值。损失 L(w∗, b∗) 算一下是 480,如果使用这一个函数,b 代100,w 代 0.97,平均的误差是 480,其预测的观看次数误差,大概是 500 人左右。
2.分类
让机器做选择题,选择事先准备好的选项。
3.结构化学习
产生一个有结构的物体,比如让机器画一张图,写一篇文章。
1.2 线性模型
w 跟 b 的值刚才已经找出来的,这组 w 跟 b 可以让损失小到 480。在已经知道答案的数 据上去计算损失,2017 到 2020 年每天的观看次数是已知的。所以假装不知道隔天的观看次数,拿这一个函数来进行预测,发现误差是 480。接下来使用这个函数预测未来的观看次数。 预测从 2021 年开始每一天都拿这个函数去预测次日的观看人次:用 2020 年的 12 月 31 日的 观看人次预测 2021 年 1 月 1 日的观看人次,用 2021 年 1 月 1 日的观看人次预测 1 月 2 日 的观看人次,用 1 月 2 日的观看人次去预测 1 月 3 日的观看人次⋯⋯每天都做这件事,一直做到 2 月 14 日,得到平均的值,在 2021 年没有看过的数据上,误差值用 L ′ 来表示,它是 0.58,所以在有看过的数据上,在训练数据上,误差值是比较小的,在没有看过的数据上,在2021 年的数据上,看起来误差值是比较大的,每一天的平均误差有 580 人左右,600 人左右。 如图 1.6 所示,横轴是代表的是时间,所以 0 这个点代表的是 2021 年 1 月 1 日,最右边点代 表的是 2021 年 2 月 14 日,纵轴就是观看的人次,这边是用千人当作单位。红色线是真实的 观看人次,蓝色线是机器用这一个函数预测出来的观看人次。蓝色的线几乎就是红色的线往 右平移一天而已,这很合理,因为 x1 也就是前一天的观看人次,跟隔天观看人次的,要怎么 拿前一天的观看人次,去预测隔天的观看人次呢,前一天观看人次乘以 0.97,加上 100 加上 100,就是隔天的观看人次。机器几乎就是拿前一天的观看人次来预测隔天的观看人次。这个 真实的数据有一个很神奇的现象,它是有周期性的,它每隔 7 天就会有两天特别低(周五和 周六),两天观看的人特别少,每隔 7 天,就是一个循环。目前的模型不太行,它只能够看前 一天。 每隔 7 天它一个循环,如果一个模型参考前 7 天的数据,把 7 天前的数据,直接复制 到拿来当作预测的结果,也许预测的会更准也说不定,所以我们就要修改一下模型。通常一个 模型的修改,往往来自于对这个问题的理解,即领域知识。
一开始,对问题完全不理解的时候,胡乱写一个
并没有做得特别好。接下来我们观察了真实的数据以后,得到一个结论是,每隔 7 天有一个 循环。所以要把前 7 天的观看人次都列入考虑,写了一个新的模型
其中 xj 代表第 j 天的观看测试,也就是 7 天前的数据,通通乘上不同的权重 wj,加起来,再 加上偏置得到预测的结果。使用该模型预测,其在训练数据上的损失是 380,而只考虑 1 天的 模型在训练数据上的损失是 480。因为其考虑了 7 天,所以在训练数据上会得到比较低的损 失。考虑了比较多的信息,在训练数据上应该要得到更好的、更低的损失。在没有看到的数据 上的损失有比较好是 490。只考虑 1 天的误差是 580,考虑 7 天的误差是 490。用梯度下降, 算出 w 跟 b 的最优值如 表 1.1 所示。
机器的逻辑是前一天跟要预测的隔天的数值的关系很大,所以 w ∗ 1 是 0.79,不过它知道, 如果是前两天前四天前五天,它的值会跟未来要预测的,隔天的值是成反比的,所以 w2, w4, w5 最佳的值(让训练数据上的损失为 380 的值)是负的。但是 w1, w3, w6, w7 是正的,考虑前 7 天的值,其实可以考虑更多天,本来是考虑前 7 天,可以考虑 28 天,即
28 天是一个月,考虑前一个月每一天的观看人次,去预测隔天的观看人次,训练数据上 是 330。在 2021 年的数据上,损失是 460,看起来又更好一点。
如果考虑 56 天,在训练数据上损失是 320,在没看过的数据上损失还是 460。考虑更多天没有办法再更降低损 失了。看来考虑天数这件事,也许已经到了一个极限。这些模型都是把输入的特征 x 乘上一 个权重,再加上一个偏置就得到预测的结果,这样的模型称为线性模型(linear model)。接 下来会看如何把线性模型做得更好。
1.2.1 分段线性曲线
线性模型也许过于简单,x1 跟 y 可能中间有比较复杂的关系,如图 1.7 所示。对于线性 模型,x1 跟 y 的关系就是一条直线,随着 x1 越来越高,y 就应该越来越大。设定不同的 w 可以改变这条线的斜率,设定不同的 b 可以改变这一条蓝色的直线跟 y 轴的交叉点。但是无 论如何改 w 跟 b,它永远都是一条直线,永远都是 x1 越大,y 就越大,前一天观看的次数越 多,隔天的观看次数就越多。但现实中也许在 x1 小于某一个数值的时候,前一天的观看次数 跟隔天的观看次数是成正比;也许当 x1 大于一个数值的时候,x1 太大,前天观看的次数太 高,隔天观看次数就会变少;也许 x1 跟 y 中间,有一个比较复杂的、像红色线一样的关系。 但不管如何设置 w 跟 b,永远制造不出红色线,永远无法用线性模型制造红色线。显然线性 模型有很大的限制,这一种来自于模型的限制称为模型的偏差,无法模拟真实的情况。
所以需要写一个更复杂的、更有灵活性的、有未知参数的函数。红色的曲线可以看作是 一个常数再加上一群 Hard Sigmoid 函数。
Hard Sigmoid 函数的特性:是当输入的值,当 x 轴 的值小于某一个阈值(某个定值)的时候,大于另外一个定值阈值的时候,中间有一个斜坡。 所以它是先水平的,再斜坡,再水平的。
所以红色的线可以看作是一个常数项加一大堆的蓝 色函数(Hard Sigmoid)。常数项设成红色的线跟 x 轴的交点一样大。常数项怎么加上蓝色函 数后,变成红色的这一条线?
*蓝线 1 函数斜坡的起点,设在红色函数的起始的地方,第 2 个 斜坡的终点设在第一个转角处,让第 1 个蓝色函数的斜坡和红色函数的斜坡的斜率是一样的, 这个时候把 0+1 就可以得到红色曲线左侧的线段。
*接下来,再加第 2 个蓝色的函数,所以第 2 个蓝色函数的斜坡就在红色函数的第一个转折点到第 2 个转折点之间,让第 2 个蓝色函数的斜率跟红色函数的斜率一样,这个时候把 0+1+2,就可以得到红色函数左侧和中间的线段。
*接下来第 3 个部分,第 2 个转折点之后的部分,就加第 3 个蓝色的函数,第 3 个蓝色的函数 坡度的起始点设的跟红色函数转折点一样,蓝色函数的斜率设的跟红色函数斜率一样,
接下 来把 0+1+2+3 全部加起来,就得到完整红色的线。
所以红色线,即分段线性曲线(piecewise linear curve)可以看作是一个常数,再加上一 堆蓝色的函数。分段线性曲线可以用常数项加一大堆的蓝色函数组合出来,只是用的蓝色函 数不一定一样。要有很多不同的蓝色函数,加上一个常数以后就可以组出这些分段线性曲线。 如果分段线性曲线越复杂,转折的点越多,所需的蓝色函数就越多。
也许要考虑的 x 跟 y 的关系不是分段线性曲线,而是如图 1.9 所示的曲线。可以在这样 的曲线上面,先取一些点,再把这些点点起来,变成一个分段线性曲线。而这个分段线性曲线 跟原来的曲线,它会非常接近,如果点取的够多或点取的位置适当,分段线性曲线就可以逼近 这一个连续的曲线,就可以逼近有角度的、有弧度的这一条曲线。 所以可以用分段线性曲线 去逼近任何的连续的曲线,而每个分段线性曲线都可以用一大堆蓝色的函数组合起来。也就是说,只要有足够的蓝色函数把它加起来,就可以变成任何连续的曲线。
假设 x 跟 y 的关系非常复杂也没关系,就想办法写一个带有未知数的函数。直接写 Hard Sigmoid 不是很容易,但是可以用一条曲线来理解它,用 Sigmoid 函数来逼近 Hard Sigmoid, 如图 1.10 所示。Sigmoid 函数的表达式为
其横轴输入是 x1,输出是 y,c 为常数。
如果 x1 的值,趋近于无穷大的时候,这一项就会消失,当 x1 非常大的时候, 这一条就会收敛在高度为 c 的地方。如果 x1 负的非常大的时候,分母的地方就会非常大,y 的值就会趋近于 0。 所以可以用这样子的一个函数逼近这一个蓝色的函数,即 Sigmoid 函数,Sigmoid 函数 就是 S 型的函数。因为它长得是有点像是 S 型,所以叫它 Sigmoid 函数。 为了简洁,去掉了指数的部分,蓝色函数的表达式为:
注意:
所以可以用 Sigmoid 函数逼近 Hard Sigmoid 函数:
调整这里的 b、w 和 c 可以制造各种不同形状的 Sigmoid 函数,用各种不同形状的 Sigmoid 函数去逼近 Hard Sigmoid 函数。如图 1.11 所示,如果改 w,就会改变斜率,就会改变斜坡 的坡度。如果改了 b,就可以把这一个 Sigmoid 函数左右移动;如果改 c,就可以改变它的高 度。所以只要有不同的 w 不同的 b 不同的 c,就可以制造出不同的 Sigmoid 函数,把不同的 Sigmoid 函数叠起来以后就可以去逼近各种不同的分段线性函数;分段线性函数可以拿来近 似各种不同的连续的函数。
如图 1.12 所示,红色这条线就是 0 加 1+2+3,而 1、2、3 都是蓝色的函数,其都可写 成 (b + wx1),去做 Sigmoid 再乘上 ci1,只是 1、2、3 的 w、b、c 不同。
所以这边每一个式子都代表了一个不同蓝色的函数,求和就是把不同的蓝色的函数相加, 再加一个常数 b。假设里面的 b 跟 w 跟 c,它是未知的,它是未知的参数,就可以设定不同的 b 跟 w 跟 c,就可以制造不同的蓝色的函数,制造不同的蓝色的函数叠起来以后,就可以制造 出不同的红色的曲线,就可以制造出不同的分段线性曲线,逼近各式各样不同的连续函数。
此外,我们可以不只用一个特征 x1,可以用多个特征代入不同的 c, b, w,组合出各种不 同的函数,从而得到更有灵活性(flexibility)的函数,如图 1.13 所示。用 j 来代表特征的编号。如果要考虑前 28 天,j 就是 1 到 28。
直观来讲,先考虑一下 j 就是 1、2、3 的情况,就是只考虑 3 个特征。举个例子,只考 虑前一天、前两天跟前 3 天的情况,所以 j 等于 1,2,3,所以输入就是 x1 代表前一天的观看次数,x2 两天前观看次数,x3 3 天前的观看次数,每一个 i 就代表了一个蓝色的函数。每一 个蓝色的函数都用一个 Sigmoid 函数来比近似它,1,2,3 代表有个 Sigmoid 函数。
wij 代表在第 i 个 Sigmoid 里面,乘给第 j 个特征的权重,w 的第一个下标代表是现在 在考虑的是第一个 Sigmoid 函数。为了简化起见,括号里面的式子为
我们可以用矩阵跟向量相乘的方法,写一个比较简洁的写法。
将其改成线性代数比较常用的表示方式为
r = b + W x
蓝框里面的括号里面做的如式 r = b + W x所示,r 对应的是 r1, r2, r3。r1, r2, r3 分别通过 Sigmoid 函数得到 a1, a2, a3,即
因此蓝色虚线框里面做的事情,是从 x1, x2, x3 得到了 a1, a2, a3,如图 1.14 所示。
上面这个比较有灵活性的函数,如果用线性代数来表示,即
接下来,如图 1.15 所示,x 是特征,绿色的 b 是一个向量,灰色的 b 是一个数值。W, b, , b 是未知参数。把这些东西通通拉直,“拼”成一个很长的向量,我们把 W 的每一行或者是每一列拿出来。无论是拿行或拿列都可以,把 W 的每一列或每一行“拼”成一个长的向量,把 b,
, b ” 拼” 上来,这个长的向量直接用 θ 来表示。所有的未知的参数,一律统称 θ。
接下来要定义损失。之前是 L(w, b),因为 w 跟 b 是未知的。现在未知的参数很多了,再 把它一个一个列出来太累了,所以直接用 θ 来统设所有的参数,所以损失函数就变成 L(θ)。 损失函数能够判断 θ 的好坏,其计算方法跟刚才只有两个参数的时候是一样的。 先给定 θ 的值,即某一组 W, b,
, b 的值,再把一种特征 x 代进去,得到估测出来的 y, 再计算一下跟真实的标签之间的误差 e。把所有的误差通通加起来,就得到损失。 接下来下一步就是优化
要找到 θ 让损失越小越好,可以让损失最小的一组 θ 称为 θ ∗。一开始要随机选一个初始的数值 θ0。接下来计算每一个未知的参数对 L 的微分,得到向量 g,即可以让损失变低的函 数:
假设有 1000 个参数,这个向量的长度就是 1000,这个向量也称为梯度,∇L 代表梯度。 是指计算梯度的位置,是在 θ 等于
的地方。计算出 g 后,接下来跟新参数,
代表它是一个起始的值,它是一个随机选的起始的值,代表
更新过一次的结果,
减掉微分 乘以,减掉 η 乘上微分的值,得到
,以此类推,就可以把 1000 个参数都更新了。
假设参数有 1000 个,就是 1000 个数值,1000 维的向量,g 是 1000 维的向量,
是 1000 维的向量。 整个操作就是这样,由
算梯度,根据梯度去把
更新成
,再算一 次梯度,再根据梯度把 θ1 再更新成 θ2,再算一次梯度把 θ2 更新成 θ3,以此类推,直到不想做。或者计算出梯度为 0 向量,导致无法再更新参数为止,不过在实现上几乎不太可能梯度 为 0,通常会停下来就是我们不想做了。
但实现上有个细节的问题,实际使用梯度下降的时候,如图 1.17 所示,会把 N 笔数据随 机分成一个一个的批量(batch),一组一组的。每个批量里面有 B 笔数据,所以本来有 N 笔数据,现在 B 笔数据一组,一组叫做批量。本来是把所有的数据拿出来算一个损失,现在 只拿一个批量里面的数据出来算一个损失,记为 L1 跟 L 以示区别。假设 B 够大,也许 L 跟 L1 会很接近。所以实现上每次会先选一个批量,用该批量来算 L1,根据 L1 来算梯度,再用 梯度来更新参数,接下来再选下一个批量算出 L2,根据 L2 算出梯度,再更新参数,再取下 一个批量算出 L3,根据 L3 算出梯度,再用 L3 算出来的梯度来更新参数。
所以并不是拿 L 来算梯度,实际上是拿一个批量算出来的 L1, L2, L3 来计算梯度。把所 有的批量都看过一次,称为一个回合(epoch),每一次更新参数叫做一次更新。更新跟回合是不同的东西。每次更新一次参数叫做一次更新,把所有的批量都看过一遍,叫做一个回合。
更新跟回合的差别,举个例子,假设有 10000 笔数据,即 N 等于 10000,批量的大小是 设 10,也就 B 等于 10。10000 个样本(example)形成了 1000 个批量,所以在一个回合里 面更新了参数 1000 次,所以一个回合并不是更新参数一次,在这个例子里面一个回合,已经更新了参数 1000 次了。
第 2 个例子,假设有 1000 个数据,批量大小(batch size)设 100,批量大小和 Sigmoid 的个数都是超参数。1000 个样本,批量大小设 100,1 个回合总共更新 10 次参数。所以做了 一个回合的训练其实不知道它更新了几次参数,有可能 1000 次,也有可能 10 次,取决于它的批量大小有多大。
1.2.2 模型变形
其实还可以对模型做更多的变形,不一定要把 Hard Sigmoid 换成 Soft Sigmoid。Hard Sigmoid 可以看作是两个修正线性单元(Rectified Linear Unit,ReLU)的加总,ReLU 的 图像有一个水平的线,走到某个地方有一个转折的点,变成一个斜坡,其对应的公式为
max(0, b + wx1) 是指看 0 跟 b + wx1 谁比较大,比较大的会被当做输出;
如果 b + wx1 < 0, 输出是 0;如果 b + wx1 > 0,输出是 b + wx1。
通过 w, b, c 可以挪动其位置和斜率。把两 个 ReLU 叠起来就可以变成 Hard 的 Sigmoid,想要用 ReLU,就把 Sigmoid 的地方,换成
如图 1.19 所示,2 个 ReLU 才能够合成一个 Hard Sigmoid。要合成 i 个 Hard Sigmoid, 需要 i 个 Sigmoid,如果 ReLU 要做到一样的事情,则需要 2i 个 ReLU,因为 2 个 ReLU 合 起来才是一个 Hard Sigmoid。因此表示一个 Hard 的 Sigmoid 不是只有一种做法。在机器学 习里面,Sigmoid 或 ReLU 称为激活函数(activation function)。
当然还有其他常见的激活函数,但 Sigmoid 跟 ReLU 是最常见的激活函数,接下来的实 验都选择用了 ReLU,显然 ReLU 比较好,实验结果如图 1.20 所示。如果是线性模型,考虑 56 天,训练数据上面的损失是 320,没看过的数据 2021 年数据是 460。连续使用 10 个 ReLU 作为模型,跟用线性模型的结果是差不多的, 但连续使用 100 个 ReLU 作为模型,结果就有显著差别了,100 个 ReLU 在训练数据上 的损失就可以从 320 降到 280,有 100 个 ReLU 就可以制造比较复杂的曲线,本来线性就是 一直线,但 100 个 ReLU 就可以产生 100 个折线的函数,在测试数据上也好了一些. 接下来使用 1000 个 ReLU 作为模型,在训练数据上损失更低了一些,但是在没看过的数据上,损失 没有变化。
接下来可以继续改模型,如图 1.21 所示,从 x 变成 a,就是把 x 乘上 w 加 b,再通过 Sigmoid 函数。不一定要通过 Sigmoid 函数,通过 ReLU 也可以得到 a,同样的事情再反复地 多做几次。 所以可以把 x 做这一连串的运算产生 a,接下来把 a 做这一连串的运算产生 a ′。 反复地多做的次数又是另外一个超参数。注意,w, b 和 w ′ , b′ 不是同一个参数,是增加了更多 的未知的参数。
每次都加 100 个 ReLU,输入特征,就是 56 天前的数据。如图 1.22 所示,如果做两次, 损失降低很多,280 降到 180。如果做 3 次,损失从 180 降到 140,通过 3 次 ReLU,从 280 降到 140,在训练数据上,在没看过的数据上,从 430 降到了 380。
通过 3 次 ReLU 的实验结果如图 1.23 所示。横轴就是时间,纵轴是观看次数。红色的线 是真实的数据,蓝色的线是预测出来的数据在这种低点的地方啊,看红色的数据是每隔一段 时间,就会有两天的低点,在低点的地方,机器的预测还算是蛮准确的,机器高估了真实的观看人次,尤其是在红圈标注的这一天,这一天有一个很明显的低谷,但是机器没有预测到这一 天有明显的低谷,它是晚一天才预测出低谷。这天最低点就是除夕。但机器只知道看前 56 天 的值,来预测下一天会发生什么事,所以它不知道那一天是除夕。
如图 1.24 所示,Sigmoid 或 ReLU 称为神经元(neuron),很多的神经元称为神经网络 (neural network)。人脑中就是有很多神经元,很多神经元串起来就是一个神经网络,跟人 脑是一样的。人工智能就是在模拟人脑。神经网络不是新的技术,80、90 年代就已经用过了, 后来为了要重振神经网络的雄风,所以需要新的名字。每一排称为一层,称为隐藏层(hidden layer),很多的隐藏层就“深”,这套技术称为深度学习。
所以人们把神经网络越叠越多越叠越深,2012 年的 AlexNet 有 8 层它的错误率是 16.4%, 两年之后 VGG 有 19 层,错误率在图像识别上进步到 7.3 %。这都是在图像识别上一个基准 的数据库(ImageNet)上面的结果,后来 GoogleNet 有 22 层,错误率降到 6.7%。而残差网 络(Residual Network,ResNet)有 152 层,错误率降到 3.57%。
刚才只做到 3 层,应该要做得更深,现在网络都是叠几百层的,深度学习就要做更深。但 4 层在训练数据上,损失是 100,在没有看过 2021 年的数据上,损失是 440。在训练数据上,3 层比 4 层差,但是在没看过的数据上,4 层比较差,3 层比较好,如图 1.25 所示。在训练数 据和测试数据上的结果是不一致的,这种情况称为过拟合(overfitting)。
但是做到目前为止,还没有真的发挥这个模型的力量,2021 年的数据到 2 月 14 日之前 的数据是已知的。要预测未知的数据,选 3 层的网络还是 4 层的网络呢?假设今天是 2 月 26 日,今天的观看次数是未知的,如果用已经训练出来的神经网络预测今天的观看次数。要选 3 层的,虽然 4 层在训练数据上的结果比较好,但在没有看过的数据的结果更重要。应该选一 个在训练的时候,没有看过的数据上表现会好的模型,所以应该选 3 层的网络。深度学习的 训练会用到反向传播(BackPropagation,BP),其实它就是比较有效率、算梯度的方法。
1.2.3 机器学习框架
我们会有一堆训练的数据以及测试数据如下所示,测试集就是只有 x 没有 y。
训练集就要拿来训练模型,训练的过程是 3 个步骤:
1. 先写出一个有未知数 θ 的函数,θ 代表一个模型里面所有的未知参数。fθ(x) 的意思就 是函数叫 fθ(x),输入的特征为 x,;
2. 定义损失,损失是一个函数,其输入就是一组参数,去判断这一组参数的好坏;
3. 解一个优化的问题,找一个 θ,该 θ 可以让损失的值越小越好。让损失的值最小的 θ 为 θ ∗,即
有了 θ ∗ 以后,就把它拿来用在测试集上,也就是把 θ ∗ 带入这些未知的参数,本来 fθ(x) 里面有一些未知的参数,现在 θ 用 θ ∗ 来取代,输入是测试集,输出的结果存起来,上传到 Kaggle 就结束了。