第 2 章 学习回归——基于广告费预测点击量

第 2 章 学习回归——基于广告费预测点击量

绫乃请美绪教她机器学习中常用的数学知识。
她首先要学习的是“回归”。
她们准备根据绫乃运营的 Web 服务的广告费数据来学习。
那么,绫乃到底能不能理解回归呢?

2.1 设置问题

 我们就先一起来看一看回归吧。下面我们结合具体的例子来说。

 好呀,具体的例子就像明天的午饭一样重要啊。

 你这个比喻的意义我完全无法理解……不过例子确实很重要。对了,我记得你说过你在运营一个 Web 服务?

 是啊,当时是为了学习编程而建立的。用户可以通过它上传时装照片,然后再分享给大家。除了编程我还能学到时尚的穿搭,真挺不错的。

 好像挺有意思的,我也有意用用了。

 那太好了。不过现在的访问数还很少,我在想要不要发点广告什么的,让更多的人知道这个服务。

 这样啊。那好,我们就以 Web 广告和点击量的关系为例来学习回归吧。

 我对 Web 营销倒是挺感兴趣的,不过这和机器学习有关系吗?

 先听我说完。为了简化问题,我们假设存在这样一个前提:投入的广告费越多,广告的点击量就越高,进而带来访问数的增加。

 嗯,广告基本上就是这样的。

 不过点击量经常变化,投入同样的广告费未必能带来同样的点击量。根据广告费和实际点击量的对应关系数据,可以将两个变量用下面的图展示出来(图 2-1)。图中的值是随便选的。

图 2-1

 原来如此。投入的广告费越多,点击量就越高。

 那你看着这张图来回答一下(图 2-2)。如果花了 200 日元的广告费,广告的点击量会是多少呢?

图 2-2

 这个问题太简单了!500 次左右吧?

 对的,好厉害。

 你不是在讽刺我吧……?(笑)

 没有没有!刚才你不是根据现有的数据,在图上标出了“大概在这里”了吗?

 嗯,是呀。

 这就是机器学习。你所做的事情正是从数据中进行学习,然后给出预测值。接下来我们就要使用机器学习,像你刚才做的那样,尝试进行根据广告费预测点击量的任务。

 原来是这么回事。但是就算不使用机器学习,谁看到这张图都能说出正确答案吧。

 就像我一开始所说的,这是我们把问题设置得非常简单的缘故。

 也就是投入的广告费越多,点击量就越高这个前提?

 对。不过,实际要使用机器学习来解决的问题都会更复杂,很多问题无法像这样画出图来。现在我们为了加深理解才用了这样一个简单的例子,后面的例子会越来越难的。

 这样啊,现在的我对此还没有什么头绪……

2.2 定义模型

 那如何应用机器学习呢?

 把图想象为函数(图 2-3)。只要知道通过图中各点的函数的形式,就能根据广告费得知点击量了。不过刚才我也说过,点击量经常变化,这叫作“点击量中含有噪声”,所以函数并不能完美地通过所有的点。

图 2-3

 莫非这个函数是一次函数?

 没错,就是一次函数。初中的时候老师让你画过函数的图像吧?

 是啊,没少画,还挺怀念的。一次函数的表达式就是 y=ax+b,其中 a斜率b截距,对吧?

 嗯,没错。只要确定了斜率和截距,一次函数的图像形状也就确定了,所以接下来我们要看的就是 ab

 原来是这样,我懂了。

 考虑到后面的学习,我们得像下面这样定义一次函数的表达式,不再使用 ab

y=\theta_0+\theta_1x\quad\quad\quad\quad\quad\quad\quad(2.2.1)

 哇,突然变得很有数学风格了……这个 \theta 是什么?

 它读作“西塔”,就是接下来我们要去求的未知数。也有人管它叫参数

 参数……那用 ab 不也挺好的吗?为什么要特意用 \theta 呢?

 在统计学领域,人们常常使用 \theta 来表示未知数和推测值。采用 \theta 加数字下标的形式,是为了防止当未知数增加时,表达式中大量出现 abcd …这样的符号。这样不但不易理解,还可能会出现符号本身不够用的情况。

 原来是这样,总之我现在把它们当作斜率和截距就没问题了对吧?

 对现在的例子来说没问题。还有,我想你应该知道,x 是广告费、y 是点击量。

 这两个没问题。

 代入具体的值会有助于理解。比如我们设 \theta_0=1\theta_1=2,那么表达式 2.2.1 的 y=\theta_0+\theta_1x 会变成什么样的表达式呢?

 代入就行了?这个简单。

y=1+2x\quad\quad\quad\quad\quad\quad\quad(2.2.2)

 很好。接下来我们就向这个表达式中的 x 代入具体的数值来计算 y

 好,那我就计算一下 x=100y 的值。

\begin{aligned}y&=1+2x\\&=1+2\times100\\&=201\quad\quad\quad\quad\quad\quad\quad(2.2.3)\end{aligned}

 这也就是说,在参数 \theta_0=1\theta_1=2 的情况下,100 日元的广告费带来的点击量为 201 左右。这个明白吗?

 不对呀,看一下刚才的图(图 2-4),如果广告费为 100 日元,那么点击量应该大于 400 呀?

图 2-4

 是的,这说明我们刚才确定的参数 \theta_0=1\theta_1=2 完全不正确。接下来我们就要使用机器学习来求出正确的 \theta_0\theta_1 的值。

 原来是这么回事呀。

2.3 最小二乘法

 道理我懂了,可是怎么求参数 \theta 呢?

 在讲这个之前,我们还是把前面的表达式 2.2.1 修改成这个样子吧。

f_{\theta}(x)=\theta_0+\theta_1x\quad\quad\quad\quad\quad\quad\quad(2.3.1)

 就是把 y 换成了 f_{\theta}(x) 吗?这是为什么呀?

 这样修改之后,我们就可以一眼看出这是一个含有参数 \theta,并且和变量 x 相关的函数。而且,如果继续使用 y,后面可能会造成混乱。

 好吧,那就按你说的来吧……

 那我们就马上去求 \theta 吧。现在我们手头有的是广告费及其相应点击量的数据。

 就是在刚才的图上画的那些点吧?

 是啊。这些数据称为训练数据。我们将训练数据中的广告费代入 f_{\theta}(x),把得到的点击量与训练数据中的点击量相比较,然后找出使二者的差最小的 \theta

 你等会儿!我不太理解你的意思……

 那我具体举几个训练数据的例子(表 2-1),可能会有助于你理解。

表 2-1

广告费 \boldsymbol{x}

点击量 \boldsymbol{y}

58

374

70

385

81

375

84

40

 也就是这 4 个点吧(图 2-5)?

图 2-5

 是的。刚才我们随便确定了一个参数,得到了形式为 f_{\theta}(x)=1+2x 的表达式 2.2.2,下面我们将广告费的值代入这个 f_{\theta}(x) 中进行计算。

 代入广告费就行是吧……这样吗(表 2-2)?

表 2-2

广告费 \boldsymbol{x}

点击量 \boldsymbol{y}

\boldsymbol{\theta_0=1} \boldsymbol{\theta_1=2} 时的 \boldsymbol{f_{\theta}(x)}

58

374

117

70

385

141

81

375

163

84

401

169

 不错。刚才我们也聊到过,这种用随便确定的参数计算的值与实际的值存在偏差。这个表 2-2 能让我们更确信这一点。

 也就是说表 2-2 中的 yf_{\theta}(x) 的值完全不同,对吧?

 是的。不过,我们希望出现的最理想的情况是 yf_{\theta}(x) 的值一致,这个明白吗?

 嗯,f_{\theta}(x) 就是为了研究 y 的值才建立的函数呀。

 那么我们来思考一下,为了接近理想的情况要怎么做呢?

 理想的情况就是二者一致,也就是 y=f_{\theta}(x)……

 我们对你说的这个表达式稍做调整,让它变形为 \y=f_{\theta}(x)=0。这就是说 yf_{\theta}(x) 之间的误差为 0。没有误差是最理想的情况。

 我懂啦!我们的目标是让误差最小。可是,让所有点的误差都等于 0 是不可能的吧?

 是的,不可能让所有点的误差都等于 0。所以我们要做的是让所有点的误差之和尽可能地小。

 嗯,你说过点击量的数据中包含噪声,所以函数不能丝毫不差地通过所有的点。

 看一下这张图(图 2-6),这样表示是不是很容易理解了?图中的虚线箭头表示训练数据的点和 f_{\theta}(x) 图像的误差。

图 2-6

 清晰易懂。我们只要想办法缩小误差虚线的高度,就能预测正确的点击量了。

 我们来把刚才说的内容用表达式展现出来。假设有 n 个训练数据,那么它们的误差之和可以用这样的表达式表示。这个表达式称为目标函数E(\theta)E 是误差的英语单词 Error 的首字母。

E(\theta)={1\over2}\sum^n_{i=1}\bigl(y^{(i)}-f_{\theta}(x^{(i)})\bigr)^2\quad\quad\quad\quad\quad\quad\quad(2.3.2)

 关于 \Sigma(读作“西格玛”)的更多内容,请参考附录 A.1。

 哇,一下子变得这么难……我还没有做好心理准备呀。

 我会一个一个说明的,放心好了。首先,为了避免引起误解我先说明一下:x^{(i)}y^{(i)} 中的 i 不是 i 次幂的意思,而是指第 i 个训练数据。

 让我看一下表 2-2,x^{(1)} 为 58 的时候 y^{(1)} 等于 374,x^{(2)} 为 70 的时候 y^{(2)} 等于 385,对吧?

 对的。\sum\nolimits^n_{i=1} 是求和符号,我们对每个训练数据的误差取平方之后,全部相加,然后乘以 {1\over2} 。这么做是为了找到使 E(\theta) 的值最小的 \theta。这样的问题称为最优化问题

 为什么要计算误差的平方呢?

 如果只是简单地计算差值,我们就得考虑误差为负值的情况。比如 f_{\theta}(x) 的图像是这样的(图 2-7),你想一想这种情况下计算误差之和会得到什么结果。

图 2-7

 中间以左的误差是负数,以右的误差是正数,二者相加正负相抵,我感觉结果会是接近 0 的数。

 对吧?误差之和虽然为 0 了,但是很明显这个水平方向的 f_{\theta}(x) 是不对的。

 原来如此。正数和负数的混合运算比较麻烦,所以为了让误差都为正数,才计算它们的平方啊。那用绝对值计算是不是也行?就像 |y-f_{\theta}(x)| 这样。

 虽然这样也没错,但是我们一般不用绝对值,而用平方。因为之后要对目标函数进行微分,比起绝对值,平方的微分更加简单。

 微分……虽然在高中学过,但基本上全忘了……绝对值的微分很难吗?

 如果是绝对值,有的点不能计算,而且还必须分情况讨论,很麻烦。关于微分,我们后面遇到的时候再讲吧。

 那为什么整个表达式还要乘以 {1\over2} 呢?

 这也和之后的微分有关系,是为了让作为结果的表达式变得简单而随便加的常数。这个也到时候再讲吧。

 嗯,不过可以随便乘以一个常数吗?

 嗯,对于最优化问题,这么做是没有问题的。比如,在 f(x)=x^2 的函数图像中(图 2-8),使函数最小的 x 是什么呢?

图 2-8

 当 x=0 的时候最小。

 那么在刚才的图像上乘以 {1\over2} (图 2-9),使函数 f(x)={1\over2}x^2 最小的 x 是什么呢?

图 2-9

 同样还是当 x=0 的时候最小!

 只要乘以正的常数,函数的形状就会被横向压扁或者纵向拉长,但函数本身取最小值的点是不变的。

 我终于明白这个表达式的意思了。

 我们实际来计算一下表达式 2.3.2 中 E(\theta) 的值吧。设 \theta_0=1\theta_1=2,然后将刚才列举的 4 个训练数据代入表达式。求出来的误差有点大……

\begin{aligned}E(\theta)&={1\over2}\sum^4_{i=1}\Bigl(y^{(i)}-f_{\theta}(x^{(i)})\Bigr)^2\\&={1\over2}\times\bigl((374-117)^2+(385-141)^2+(375-163)^2+(401-169)^2\bigr)\\&={1\over2}\times(66~049+59~536+44~944+53~824)\\&=112~176.5\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad(2.3.3)\end{aligned}

 112 176.5?

 112 176.5 这个值本身没有什么意义,我们要修改参数 \theta,使这个值变得越来越小。

 让这个值变小,也就是让误差变小,对吧?

 就是这样。这种做法称为最小二乘法

2.3.1 最速下降法

 要让 E(\theta) 越来越小我是明白的,不过一边随意修改 \theta 的值,一边计算 E(\theta) 并与之前的值相比较的做法实在是太麻烦了。

 那样做的确很麻烦。所以我们要使用前面简单提到过的微分来求它。

 关于微分的更多内容,请参考附录 A.2。

 微分啊,基本不记得了。

 微分是计算变化的快慢程度时使用的方法。你在学微分的时候,有没有用增减表

 增减表……这么说起来好像是用过。好令人怀念的话题啊。

 我们用简单的例子来试一下吧。比如有一个表达式为 g(x)=(x-1)^2 的二次函数(图 2-10),它的最小值是 g(x)=0,出现在 x=1 时。你知道这个二次函数的增减表是什么样的吗?

图 2-10

 首先要进行微分对吧?将 g(x) 展开,有 (x-1)^2=x^2-2x+1,所以是这样微分吗?

{{\rm d}\over{\rm d}x}g(x)=2x-2\quad\quad\quad\quad\quad\quad\quad(2.3.4)

 嗯,微分结果就是这个。为了写出增减表,我们看一下导数的符号。

 所谓导数,就是微分后的函数吧?只要看 2x-2 的符号就行了,所以增减表是这样的(表 2-3)。

表 2-3

\boldsymbol{x} 的范围

\boldsymbol{{{\rm d}\over{\rm d}x}g(x))} 的符号

\boldsymbol{g(x)} 的增减

x<1

-

x=1

0

 

x>1

+

 很好。根据这张增减表我们可以知道,在 x<1 时,g(x) 的图形向右下方延伸,反之当 x>1 时,g(x) 的图形向右上方延伸,换句话说就是从左下方开始延伸的。

 嗯,不管是看增减表,还是看 g(x) 的图像,的确都是如此。

 比如在 x=3 这一点,为了使 g(x) 的值变小,我们需要向左移动 x,也就是必须减小 x (图 2-11)。

图 2-11

 如果是在另一侧的 x=-1 这一点,为了使 g(x) 的值变小,我们需要向右移动 x,也就是必须增加 x (图 2-12)。

图 2-12

 是不是要根据导数的符号来决定移动 x 的方向?

 没错。只要向与导数的符号相反的方向移动 xg(x) 就会自然而然地沿着最小值的方向前进了。

 我明白了。参数会自动更新,这太方便了。

 我们把刚才说的内容用表达式展示出来,就是这样的。这也被称为最速下降法梯度下降法

x:=x-\eta{{\rm d}\over{\rm d}x}g(x)\quad\quad\quad\quad\quad\quad\quad(2.3.6)

 你可能还不熟悉 A := B 这种写法,它的意思是通过 B 来定义 A。

 拿表达式 2.3.5 来说就是用上一个 x 来定义新的 x,是这样的吧?

 没错。

 \eta 是什么?

 它是称为学习率的正的常数,读作“伊塔”。根据学习率的大小,到达最小值的更新次数也会发生变化。换种说法就是收敛速度会不同。有时候甚至会出现完全无法收敛,一直发散的情况。

 稍等!这里我又不明白了……

 我们再代入具体的值看一看。比如 \eta=1,从 x=3 开始,那么 x 会如何变化呢?

 我算算看。g(x) 的微分是 2x-2,那么更新表达式就是 x:=x-\eta(2x-2) 对吧?我就用这个表达式计算了(图 2-13)。

\begin{matrix}x:=&3-1(2\times3-2)&=&~~3-4&=&-1&\\x:=&-1-1(2\times-1-2)&=&-1+4&=&~~3&\quad(2.3.6)&\\x:=&3-1(2\times3-2)&=&~~3-4&=&-1&\end{matrix}

图 2-13

 欸?怎么一直在 3 和 -1 上跳来跳去啊,这不就陷入了死循环吗?

 那设 \eta=0.1,同样从 x=3 开始,会怎么样呢?

 小数的计算有点麻烦,四舍五入并保留两位小数后再计算也没问题吧?我试试(图 2-14)。

\begin{matrix}x:=&3-0.1\times(2\times3-2)&=&3~~-0.4&=&2.6\\x:=&2.6-0.1\times(2\times2.6-2)&=&2.6-0.3&=&2.3\\x:=&2.3-0.1\times(2\times2.3-2)&=&2.3-0.2&=&2.1\\x:=&2.1-0.1\times(2\times2.1-2)&=&2.1-0.2&=&1.9&(2.3.7)\end{matrix}

图 2-14

 这次渐渐接近 x=1 了,只是速度好慢啊……真让人着急。

 就是这样。如果 \eta 较大,那么 x:=x-\eta(2x-2) 会在两个值上跳来跳去,甚至有可能远离最小值。这就是发散状态。而当 \eta 较小时,移动量也变小,更新次数就会增加,但是值确实是会朝着收敛的方向而去。

 原来是这么回事啊,我现在非常明白了。

 那我们回过头来看一下目标函数 E(\theta)。还记得目标函数的表达式吗?

 你是说表达式 2.3.2 吗?

E(\theta)={1\over2}\sum^n_{i=1}\bigl(y^{(i)}-f_{\theta}(x^{(i)})\bigr)^2\quad\quad\quad\quad\quad\quad\quad(2.3.8)

 是的。这个目标函数和刚才例子中的 g(x) 同样是开口向上的形状,所以刚才讨论的内容也同样适用于它。不过这个目标函数中包含 f_{\theta}(x),从表达式 2.3.1 又可以看出,f_{\theta}(x) 拥有 \theta_0\theta_1 两个参数。也就是说这个目标函数是拥有 \theta_0\theta_1 的双变量函数,所以不能用普通的微分,而要用偏微分。如此一来,更新表达式就是这样的。

\begin{aligned}&\theta_0:=\theta_0-\eta{{\partial E}\over{\partial\theta_0}}\\&\theta_1:=\theta_1-\eta{{\partial E}\over{\partial\theta_1}}\quad\quad\quad\quad\quad(2.3.9)\end{aligned}

 我感觉开始变难了……表达式 2.3.5 的 g(x) 变成了 E,然后要用偏微分对吧?

 关于偏微分的更多内容,请参考附录 A.3。

 是的。下面我们实际地计算一下偏微分。首先从表达式 2.3.9 的 \theta_0 的偏微分表达式开始。绫乃,这个你会吗?

 这个……欸,E 中怎么没有 \theta_0 啊?啊,对了,\theta_0f_{\theta}(x) 里面呢。还得去展开平方,好像很难呀……

 正面去突破它是很麻烦的,我们可以使用复合函数的微分。就像你刚才说的,E(\theta) 中有 f_{\theta}(x),而 f_{\theta}(x) 中又有 \theta_0,所以我们可以这样分别去考虑它们。

\begin{aligned}&u=E(\theta)\\&v=f_{\theta}(x)\quad\quad\quad\quad\quad(2.3.10)\end{aligned}

 关于复合函数的更多内容,请参考附录 A.4。

 然后再像这样阶梯性地进行微分。

{{\partial u}\over{\partial\theta_0}}={{\partial u}\over{\partial v}}\cdot{{\partial v}\over{\partial\theta_0}}\quad\quad\quad\quad\quad\quad\quad(2.3.11)

 原来这就是复合函数的微分。那我先从 uv 微分的地方开始计算。把函数展开后再分别求微分就行了吧?

\begin{aligned}{{\partial u}\over{\partial v}}&={{\partial}\over{\partial v}}\Biggl({1\over2}\sum^n_{i=1}\biggl(y^{(i)}-v\biggr)^2\Biggr)\\&={1\over2}\sum^n_{i=1}\Biggl({{\partial}\over{\partial v}}\biggl(y^{(i)}-v\biggr)^2\Biggr)\\&={1\over2}\sum^n_{i=1}\Biggl({{\partial}\over{\partial v}}\biggl(y^{(i)^2}-2y^{(i)}v+v^2\biggr)\Biggr)\\&={1\over2}\sum^n_{i=1}\biggl(-2y^{(i)}v+2v\biggr)\\&=\sum^n_{i=1}\biggl(v-y^{(i)}\biggr)\quad\quad\quad\quad\quad\quad\quad\quad\quad(2.3.12)\end{aligned}

 在最后一行,常数与 \frac{1}{2} 相抵消了,微分后的表达式变简单了吧?这就是一开始乘以 \frac{1}{2} 的理由。

 原来是这么回事啊。表达式确实变整洁了。下面就是 v\theta_0 进行微分的部分了。

\begin{aligned}{{\partial v}\over{\partial\theta_0}}&={{\partial}\over{\partial\theta_0}}(\theta_0+\theta_1x)\\&=1\quad\quad\quad\quad\quad\quad\quad\quad\quad(2.3.13)\end{aligned}

 做得不错。接下来只要依照复合函数的微分表达式 2.3.11 将各部分的结果相乘,就可以得到对 \theta_0 进行微分的结果了。对了,不要忘了把表达式 2.3.12 中的 v 替换回f_{\theta}(x)

 让各部分相乘,是这样吗?

\begin{aligned}{{\partial u}\over{\partial\theta_0}}&={{\partial u}\over{\partial v}}\cdot{{\partial v}\over{\partial\theta_0}}\\&=\sum^n_{i=1}\biggl(v-y^{(i)}\biggr)\cdot1\\&=\sum^n_{i=1}\biggl(f_{\theta}(x^{(i)})-y^{(i)}\biggr)\quad\quad\quad\quad\quad\quad\quad\quad\quad(2.3.14)\end{aligned}

 计算正确!接下来再算一下对 \theta_1 进行微分的结果吧。

 也就是解出这个表达式对吧?我试试看。

{{\partial u}\over{\partial\theta_1}}={{\partial u}\over{\partial v}}\cdot{{\partial v}\over{\partial\theta_1}}\quad\quad\quad\quad\quad\quad\quad(2.3.15)

 uv 微分的部分与表达式 2.3.12 完全相同,所以这次只要计算 v\theta_1 微分的部分就行了。

 嗯,仔细想想确实是这样。v\theta_1 微分……是这样吗?

\begin{aligned}{{\partial v}\over{\partial\theta_1}}&={{\partial}\over{\partial\theta_1}}(\theta_0+\theta_1x)\\&=x\quad\quad\quad\quad\quad\quad\quad\quad\quad(2.3.16)\end{aligned}

 对的。那最终 u\theta_1 微分的结果是什么样的呢?

 是这样的。

\begin{aligned}{{\partial u}\over{\partial\theta_1}}&={{\partial u}\over{\partial v}}\cdot{{\partial v}\over{\partial\theta_1}}\\&=\sum^n_{i=1}\biggl(v-y^{(i)}\biggr)\cdot x^{(i)}\\&=\sum^n_{i=1}\biggl(f_{\theta}(x^{(i)})-y^{(i)}\biggr)x^{(i)}\quad\quad\quad\quad\quad(2.3.17)\end{aligned}

 正确!所以参数 \theta_0\theta_1 的更新表达式就是这样的,这里没问题吧?

\begin{aligned}&\theta_0:=\theta_0-\eta\sum^n_{i=1}\biggl(f_{\theta}(x^{(i)})-y^{(i)}\biggr)\\&\theta_1:=\theta_1-\eta\sum^n_{i=1}\biggl(f_{\theta}(x^{(i)})-y^{(i)}\biggr)x^{(i)}\quad\quad\quad\quad\quad(2.3.18)\end{aligned}

 嗯,这个表达式看起来好复杂啊。只要根据这个表达式来更新 \theta_0\theta_1,就可以找到正确的一次函数 f_{\theta}(x) 了吗?

 是的。用这个方法找到正确的 f_{\theta}(x),然后输入任意的广告费,就可以得到相应的点击量。这样我们就能根据广告费预测点击量了。

 仅仅是为了找到这么简单的一次函数就费了很多事……而且这个过程也不是很有意思。

 一开始我就说过,为了便于说明我简化了问题,也许是因为这个你才没能感受到其中的妙处。我们去看看难一些的问题吧。

 我有点累了,想休息一下。我们一起吃甜甜圈吧!

 好呀。

2.4 多项式回归

 好好吃!

 很好吃吧?我最喜欢甜食了。哎,咱们要接着讲回归对吗?

 是啊。我们将刚才关于回归的话题再稍微扩展一下吧。

 这样难度又会突然加大吧……

 只要刚才讲的内容你都理解了,就不会觉得接下来要讲的很难了。还记得我们定义的用于预测的一次函数吗?

 表达式 2.3.1 吗?记得,它是这样的。

f_{\theta}(x)=\theta_0+\theta_1x\quad\quad\quad\quad\quad\quad\quad(2.4.1)

 没错。因为是一次函数,所以它的图像是直线(图 2-15)。

图 2-15

 嗯,确实是直线。刚才我们用微分求出了这个函数的斜率和截距。

 对。不过,对于一开始我在图中添加的数据点来说,其实曲线比直线拟合得更好(图 2-16)。

图 2-16

 的确是这样!曲线看起来更拟合数据。

 我们把 f_{\theta}(x) 定义为二次函数,就能用它来表示这条曲线了。

f_{\theta}(x)=\theta_0+\theta_1x+\theta_2x^2\quad\quad\quad\quad\quad\quad\quad(2.4.2)

 对哦。确实学过二次函数是曲线。

 或者用更大次数的表达式也可以。这样就能表示更复杂的曲线了。

f_{\theta}(x)=\theta_0+\theta_1x+\theta_2x^2+\theta_3x^3+\cdots+\theta_nx^n\quad\quad\quad\quad\quad\quad\quad(2.4.3)

 这个好厉害啊。我们可以随便决定 f_{\theta}(x) 是什么样的函数吗?

 嗯,不过对于要解决的问题,在找出最合适的表达式之前,需要不断地去尝试。

 不是函数次数越大,拟合得越好吗?

 虽然次数越大拟合得越好,但难免也会出现过拟合的问题。现在说这个就有些跑题了,我们等一会儿再说它吧。

 果然,世上的事情都不是那么简单的呀……

 回到刚才二次函数的话题。我们增加了 \theta_2 这个参数,你知道 \theta_2 更新表达式的推导方法吗?

 和之前一样,用目标函数对 \theta_2 偏微分就能求出来了吧?

 没错!和之前一样,设 u=E(\theta)v=f_{\theta}(x),然后试着用 u\theta_2 偏微分,求出更新表达式。

 uv 微分的部分应该是一样的,所以我们只要求 v\theta_2 的微分就行了吧?

\begin{aligned}{{\partial v}\over{\partial\theta_2}}&={{\partial}\over{\partial\theta_2}}(\theta_1+\theta_1x+\theta_2x^2)\\&=x^2\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad(2.4.4)\end{aligned}

 嗯,不错。最终的参数更新表达式是这样的。

\begin{aligned}&\theta_0:=\theta_0-\eta\sum^n_{i=1}\biggl(f_{\theta}(x^{(i)})-y^{(i)}\biggr)\\&\theta_1:=\theta_1-\eta\sum^n_{i=1}\biggl(f_{\theta}(x^{(i)})-y^{(i)}\biggr)x^{(i)}\\&\theta_2:=\theta_2-\eta\sum^n_{i=1}\biggl(f_{\theta}(x^{(i)})-y^{(i)}\biggr)x^{(i)^2}\quad\quad\quad\quad\quad\quad(2.4.5)\end{aligned}

 那么即使增加参数,比如有 \theta_3\theta_4 等,我们依然可以用同样的方法求出它们的更新表达式吗?

 是的。像这样增加函数中多项式的次数,然后再使用函数的分析方法被称为多项式回归

 之前我还以为会很难,都有些紧张了……现在放心多了。

2.5 多重回归

 关于回归还有些内容,我们一口气把它说完吧。

 这次难度要上升了吧……

 之前我们是根据广告费来预测点击量的。

 嗯,是以这个为前提的。

 但是,实际中要解决的很多问题是变量超过 2 个的复杂问题。

 你的意思是对于那种问题,要用到刚才讲多项式回归时提到的 x^2x^3 等多次项吗?

 不是哦。多项式回归问题中确实会涉及不同次数的项,但是使用的变量依然只有广告费一项。

 欸,是这样吗?你说的我有点不明白啊。

 我们稍微扩展一下之前设置的问题吧。之前只是根据广告费来预测点击量,现在呢,决定点击量的除了广告费之外,还有广告的展示位置和广告版面的大小等多个要素。

 啊,我懂了。原来你说变量超过 2 个是这个意思。

 不过之前变量只有广告费,所以我们还可以用图来展示,现在变量达到了 3 个以上,就无法可视化了。后面我们也就无法画出图像了。

 欸,想不出接下来要做什么……

 不过只要好好理解了之前讲过的内容,那么即使变量增加了,也不会变得很难哦。

 相信自己的实力!我一定会跟上的……

 为了让问题尽可能地简单,这次我们只考虑广告版面的大小,设广告费为 x_1、广告栏的宽为 x_2 、广告栏的高为 x_3,那么 f_{\theta} 可以表示如下,这里有没有问题?

f_{\theta}(x_1,x_2,x_3)=\theta_0+\theta_1x_1+\theta_2x_2+\theta_3x_3\quad\quad\quad\quad\quad\quad\quad(2.5.1)

 函数接收的变量之前只有 1 个 x,现在增加到 3 个了。只有这一点变化,所以我没有问题。

 那这个时候,该如何去求参数 \theta_0,\cdots,\theta_3 呢?

 分别求目标函数对 \theta_0,\cdots,\theta_3 的偏微分,然后更新参数就行了吧?

 没错!看来你已经熟悉这套做法了。

 哎哟~这次也挺简单的,太好了。那么流程上接下来要做的就是实际去求偏微分了吧?

 这个还得等一下,我们可以先试着简化表达式的写法。

 表达式的写法?什么意思?

 刚才我们说有 x_1x_2x_3 共 3 个变量,下面我们把它推广到有 n 个变量的情况。这时候 f_{\theta} 会变成什么样子呢?

 只要写出 n 个变量就行了吧,这样对吗?

f_{\theta}(x_1,\cdots,x_n)=\theta_0+\theta_1x_1+\cdots+\theta_nx_n\quad\quad\quad\quad(2.5.2)

 嗯,对的。不过每次都像这样写 nx 岂不是很麻烦?所以我们还可以把参数 \theta 和变量 x 看作向量

 关于向量的更多内容,请参考附录 A.5。

 我记得向量有大小和方向,并要用箭头来表示。这里要用到它吗?

 嗯,不过这次跟箭头没有关系。我们想要做的只是把 \thetax 用列向量来定义而已。你知道列向量吗?

 列向量是这样定义的吧?我记得向量的符号要用黑体。

\boldsymbol{\theta}=\begin{bmatrix}\theta_0\\\theta_1\\\theta_2\\\vdots\\\theta_n\end{bmatrix}\quad\boldsymbol{x}=\begin{bmatrix}x_1\\x_2\\\vdots\\x_n\end{bmatrix}\quad\quad\quad\quad\quad\quad\quad(2.5.3)

 对!你还记得要用黑体,真厉害。不过有一点很可惜,你写的 \boldsymbol{\theta}\boldsymbol{x} 的维度不同,处理起来会很麻烦。

 你这么说我也没办法改呀,我已经把该写的符号都写上了……

 向量的元素不一定全都是符号哦,可以这样修改你写的向量。

\boldsymbol{\theta}=\begin{bmatrix}\theta_0\\\theta_1\\\theta_2\\\vdots\\\theta_n\end{bmatrix}\quad\boldsymbol{x}=\begin{bmatrix}1\\x_1\\x_2\\\vdots\\x_n\end{bmatrix}\quad\quad\quad\quad\quad\quad\quad(2.5.4)

 欸,可以随便加上 1 吗?

 等到开始计算时你就明白了,像这样一开始就加上 1 反而更自然。\theta 的下标是从 0 开始的,为了与其相配合,设 x_0=1,让 \boldsymbol{x} 的第一个元素为 x_0 会更加整齐。

\boldsymbol{\theta}=\begin{bmatrix}\theta_0\\\theta_1\\\theta_2\\\vdots\\\theta_n\end{bmatrix}\quad\boldsymbol{x}=\begin{bmatrix}x_0\\x_1\\x_2\\\vdots\\x_n\end{bmatrix}\quad(x_0=1)\quad\quad\quad\quad\quad\quad\quad(2.5.5)

 嗯,维度和下标都相同了,确实整齐了……

 那么,把 \boldsymbol{\theta} 转置之后,计算一下它与 \boldsymbol{x} 相乘的结果吧。

 也就是计算 \boldsymbol{\theta}^{{\rm T}}\boldsymbol{x} 吧?把二者相应的元素相乘,然后全部加起来。

\boldsymbol{\theta}^{{\rm T}}\boldsymbol{x}=\theta_0x_0+\theta_1x_1+\theta_2x_2+\cdots+\theta_nx_n\quad\quad\quad\quad\quad\quad\quad(2.5.6)

 这个表达式应该见过吧?注意一下 x_0=1 的部分。

 这不就是刚才的表达式 2.5.2 吗?!

 是的。也就是说,之前用多项式表示的 f_{\theta} ,可以像这样用向量来表示。虽然我们说的是向量,但实际在编程时只需用普通的一维数组就可以了。

f_{\boldsymbol{\theta}}(\boldsymbol{x})=\boldsymbol{\theta}^{{\rm T}}\boldsymbol{x}\quad\quad\quad\quad\quad\quad\quad(2.5.7)

 哇,表达式变得好简单啊!刚才你说要简化表达式的写法,原来是这么回事啊。

 是的。接下来我们就使用 f_{\boldsymbol{\theta}}(\boldsymbol{x}) 来求参数更新表达式吧,方法与之前一样。

 好的。使用向量……欸?使用向量又该怎么求呢?

 设 u=E(\boldsymbol{\theta})v=f_{\boldsymbol{\theta}}(\boldsymbol{x}) 的部分是一样的。为了一般化,我们可以考虑对第 j 个元素 \theta_j偏微分的表达式。

{{\partial u}\over{\partial\theta_j}}={{\partial u}\over{\partial v}}\cdot{{\partial v}\over{\partial\theta_j}}\quad\quad\quad\quad\quad\quad\quad(2.5.8)

 我懂了。uv 微分的部分是一样的,所以只需要求 v\theta_j的微分就好了。这样做对吗?

\begin{aligned}{{\partial v}\over{\partial\theta_j}}&={{\partial}\over{\partial\theta_j}}(\boldsymbol{\theta}^{{\rm T}}\boldsymbol{x})\\&={{\partial}\over{\partial\theta_j}}(\theta_0x_0+\theta_1x_1+\cdots+\theta_nx_n)\\&=x_j\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad(2.5.9)\end{aligned}

 不错!那么第 j 个参数的更新表达式就是这样的。

\theta_j:=\theta_j-\eta\sum^n_{i=1}\biggl(f_{\boldsymbol{\theta}}(\boldsymbol{x}^{(i)})-y^{(i)}\biggr)x^{(i)}_j\quad\quad\quad\quad(2.5.10)

 之前还给每个 \theta 都写了更新表达式呢,原来它们可以汇总为一个表达式啊。好厉害!

 像这样包含了多个变量的回归称为多重回归。你觉得难不难?

 我想象中应该是更难的,但现在来看似乎没问题!表达式汇总为一个后就变得简单了,这太好了。

 可以基于一般化的思路来思考问题正是数学的优点。

 对了,所谓的最速下降法就是对所有的训练数据都重复进行计算对吧?你说过现在可以收集大量的数据,但是训练数据越多,循环次数也就越多,那么计算起来不就非常花时间了吗?

 果然是平时在工作中就会编程的人,非常注重效率。

 对呀,仅仅是能跑起来可不行。

 正如你所说,计算量大、计算时间长是最速下降法的一个缺点。

 果然如此,那么没有效率更高一些的算法吗?

 当然有了。

2.6 随机梯度下降法

 我们最后就来看一下随机梯度下降法这个算法吧。

 这是一个效率高的算法吗?

 嗯。不过在介绍它之前,还要说一下,最速下降法除了计算花时间以外,还有一个缺点。

 欸,还有缺点?

 嗯,那就是容易陷入局部最优解。

 这是什么意思呀?

 在讲解回归时,我们使用的是平方误差目标函数。这个函数形式简单,所以用最速下降法也没有问题。现在我们来考虑稍微复杂一点的,比如这种形状的函数(图 2-17)。

图 2-17

 这个函数怎么看起来软绵绵的……

 用最速下降法来找函数的最小值时,必须先要决定从哪个 x 开始找起。之前我用 g(x) 说明的时候是从 x=3 或者 x=-1 开始的,还记得吗?

 你这么一说我想起来了。不过为什么要从 3 或者 -1 开始找呢?

 那是为了讲解,我随便选的。

 这样啊,那实际去解决问题时,也可以随便选个初始值吗?

 选用随机数作为初始值的情况比较多。不过这样每次初始值都会变,进而导致陷入局部最优解的问题。

 我还是不太明白这是什么意思……

 我们假设这张图中标记的位置就是初始值(图 2-18)。

图 2-18

 啊,我好像有点明白了。从这个点开始找,似乎可以求出最小值。

 那你说说,什么情况下反而求不出最小值呢?

 是不是把这里作为初始值的情况(图 2-19)?好像没计算完就会停止。

图 2-19

 没错。这就是陷入局部最优解。

 这个算法虽然简单,但是容易发生各种问题呀。这可是你花费了这么多时间教给我的算法,太遗憾了。

 没事儿,最速下降法也不会白学,随机梯度下降法就是以最速下降法为基础的。

 是这样啊。

 你还记得最速下降法的参数更新表达式吗?

 嗯,就是表达式 2.5.10 吧?

\theta_j:=\theta_j-\eta\sum^n_{i=1}\biggl(f_{\boldsymbol{\theta}}(\boldsymbol{x}^{(i)})-y^{(i)}\biggr)x^{(i)}_j\quad\quad\quad\quad(2.6.1)

 对。这个表达式使用了所有训练数据的误差,而在随机梯度下降法中会随机选择一个训练数据,并使用它来更新参数。这个表达式中的 k 就是被随机选中的数据索引。

\theta_j:=\theta_j-\eta\biggl(f_{\boldsymbol{\theta}}(\boldsymbol{x}^{(k)})-y^{(k)}\biggr)x^{(k)}_j\quad\quad\quad\quad(2.6.2)

 \Sigma 变没啦。

 最速下降法更新 1 次参数的时间,随机梯度下降法可以更新 n 次。此外,随机梯度下降法由于训练数据是随机选择的,更新参数时使用的又是选择数据时的梯度,所以不容易陷入目标函数的局部最优解。

 随机选择训练数据来学习这种做法看起来有些敷衍,真的能找到答案吗?

 虽然有些不可思议,但实际上的确会收敛。

 真是不可思议……

 我们前面提到了随机选择 1 个训练数据的做法,此外还有随机选择 m 个训练数据来更新参数的做法。

 这样啊,那具体选择几个是可以由自己决定的吧?

 嗯,设随机选择 m 个训练数据的索引的集合为 K,那么我们这样来更新参数。

\theta_j:=\theta_j-\eta\sum_{k\in K}\biggl(f_{\boldsymbol{\theta}}(\boldsymbol{x}^{(k)})-y^{(k)}\biggr)x^{(k)}_j\quad\quad\quad\quad(2.6.3)

 关于 \sum_{k\in K} 的更多内容,请参考附录 A.1。

 假设训练数据有 100 个,那么在 m=10 时,创建一个有 10 个随机数的索引的集合,例如 K={61,53,59,16,30,21,85,31,51,10\},然后重复更新参数就行了吗?

 就是这样。这种做法被称为小批量(mini-batch)梯度下降法

 这像是介于最速下降法和随机梯度下降法之间的方法。

 不管是随机梯度下降法还是小批量梯度下降法,我们都必须考虑学习率 \eta。把 \eta 设置为合适的值是很重要的。

 那学习率是如何决定的呢?也是随意决定的吗?

 这是一个很难的问题。可以通过反复尝试来找到合适的值,不过,除此之外还有几个办法,你可以研究一下,我觉得会很有意思。

 好呀。不过今天我学到了好多东西,现在有点累了……等我实现的时候要是碰到了问题再去研究好了。

 也好。还没开始做就什么都往脑子里塞,会把头撑破的。

 是啊,谢谢你!

目录