1. 机器学习概述
在一次散步时,我们告诉一个从没见过猫狗的小朋友这是猫、那是狗,小朋友在下一次见到猫狗时就能基于上一次的经验准确的分辨出猫和狗了,这是我们人类的学习。所谓机器学习,就是希望机器能够像人类一样从经验中学习知识,当遇到类似的新情况时能够做出有效的决策。在计算机系统中,“经验”通常以“数据”的形式存在。因此,机器学习的主要内容,是关于在计算机上从数据中产生Function的算法,这个Function的作用是将将输入映射成合理的输出。例如给Function输入猫的图片,Function能够正确的输出“猫”的判别。在机器学习中,我们通常把Function也叫做模型(Model)。
因此,简单点来讲,机器学习就是要从数据中找到一个Function,可以将输入映射成合理的输出。用数学来表示就是
y
=
f
(
x
)
y=f(x)
y=f(x)机器学习就是要找到这个
f
f
f,其中
x
x
x是输入,
y
y
y是输出。机器学习找这个
f
f
f的过程包含三个基本的步骤:定义一个包含未知参数的Function、定义一个损失函数、优化Function的参数。
下面通过李宏毅老师的关于访问流量预测例子来说明这三个步骤,即用当天的访问流量预测第二天的访问流量:输入是当天的流量,输出是第二天的流量。
2. 机器学习的三个基本步骤
2.1 定义一个包含未知参数的Function
假设第二天的视频访问流量和前一天的视频访问流量呈线性关系,即,
y
=
b
+
w
x
1
y=b+wx_1
y=b+wx1其中
x
1
x_1
x1是前一天的视频访问量,即函数的输入,
y
y
y是预测的第二天的视频访问量,即函数的输出。
b
,
w
b,w
b,w是函数的未知参数,在机器学习里面我们常把
w
w
w称为权值(Weight),把
b
b
b称为偏置(Bias)。
那么是如何定义出这个函数的呢?是基于对这个求解问题的本质了解确定的,也就是领域知识。所以在确定Function的架构时,我们往往需要具备应用领域的专门知识。当然,即使具有领域的专门知识,函数架构的设计不是一蹴而就的,是一个不断修正的过程。即刚开始初步设计一个架构,可能不太理想,然后对其改进,通过反复的迭代,最后得到一个比较满意的Function架构。
2.2 定义一个损失函数
损失函数是一个有关参数
b
,
w
b,w
b,w的函数,它反映模型输出的好坏。我们期望模型的估测值和真实值之间的差距要越小越好。这个差距用
e
e
e表示,计算
e
e
e的方式有多种。对于数值输出,常见的计算方式有平均绝对误差(MAE)和均方误差(MSE):
MAE:
e
=
∣
y
−
y
^
∣
\text{MAE: }e=\mid y-\hat{y}\mid
MAE: e=∣y−y^∣
MSE:
e
=
(
y
−
y
^
)
2
\text{MSE: }e=(y-\hat{y})^2
MSE: e=(y−y^)2
上面
y
y
y表示真实值,
y
^
\hat{y}
y^表示模型的估测值。在这道例题中,李宏毅老师选择了MAE。如果输出是概率分布,例如分类问题,往往采用交叉熵(Cross Entropy):
e
=
−
∑
m
=
1
M
y
c
log
p
c
e=-\sum_{m=1}^M{y_c\log{p_c}}
e=−m=1∑Myclogpc
其中,
M
M
M表示类别的数目;
y
c
y_c
yc是一个符号函数(0或1),如果样本的真实类别等于
c
c
c取1,否则取0;
p
c
p_c
pc模型输出样本属于类别
c
c
c的预测概率。
假设有
N
N
N个训练数据,那么损失函数
L
L
L可以定义为,
Loss:
L
=
1
N
∑
n
=
1
N
e
n
\text{Loss: }L=\frac{1}{N}\sum_{n=1}^N{e_n}
Loss: L=N1n=1∑Nen
每一对确定的参数
b
,
w
b,w
b,w,就可以计算出一个Loss。Loss越小说明模型估测的结果越接近于真实值,表明参数
b
,
w
b,w
b,w的值越好。
上述只是个简单的例子,在实际应用过程中,损失函数的定义往往会要复杂得多,也是影响机器学习好坏的一个关键因素。
2.3 优化Function的参数
参数优化就是要找到最佳的参数 b , w b,w b,w,使Loss最小,即, w ∗ , b ∗ = a r g min w , b L w^* ,b^*=arg\underset{w,b}{\text{min}}L w∗,b∗=argw,bminL那么如何找呢?最为常用的方法就是梯度下降法(Gradient Descent)。梯度下降法可以理解为:我们从山上的某一点出发,找一个向下最陡的坡走一步(也就是找负梯度方向),到达一个点之后,再找向下最陡的坡,再走一步,直到我们不断的这么走,走到最“低”点。其过程主要包括:
- 初始化参数 b 0 , w 0 b_0,w_0 b0,w0,初始化参数可以是自己定的,也可以是随机的。
- 计算损失函式在
b
0
,
w
0
b_0,w_0
b0,w0处对
b
,
w
b,w
b,w的微分值,然后更新参数值:
w 1 ← w 0 − η ∂ L ∂ w ∣ w = w 0 , b = b 0 w^{1} \leftarrow w^{0}-\left.\eta \frac{\partial L}{\partial w}\right|_{w=w^{0}, b=b^{0}} w1←w0−η∂w∂L∣∣∣∣w=w0,b=b0
b 1 ← b 0 − η ∂ L ∂ b ∣ w = w 0 , b = b 0 b^{1} \leftarrow b^{0}-\left.\eta \frac{\partial L}{\partial b}\right|_{w=w^{0}, b=b^{0}} b1←b0−η∂b∂L∣∣∣∣w=w0,b=b0
其中 η \eta η指学习速率,决定了下坡时每走一步跨多大。 - 重复上一步,反复迭代更新 b , w b,w b,w,直到损失函数不再减小。
梯度下降法很简单,但是基本上能应用到绝大部分的深度学习框架上。梯度下降的微分值也不需要我们自己手动去算,我们借助于计算机即可,Python中的Pytorch都提供了很好的工具帮助我们计算微分对参数进行迭代。
当然,梯度下降法也会存在一些问题,最常见的一个问题就是陷入局部最优。因此梯度下降法有很多变形,例如随机梯度下降(SGD)、自适应梯度下降等。
3 模型的测试与修正
前面提到了一个函数
f
f
f的架构设计,也就是模型架构的设计不是一蹴而就的,往往需要根据多次迭代不断修正才会得到比较好的模型。那么如何评价一个模型的好坏呢?前面说到我们希望模型的估测值要和真实值越接近越好,所以我们可以用平均绝对误差(MAE)和均方误差(MSE)来衡量一个模型的好坏。
但是要注意的是我们让机器学习的目的是对未来的事情进行预测,而不是对已经发生的事情进行预测。也就是说我们不能再用训练数据去测试模型的好坏了,而要用新的、未参与训练的数据进行测试。所以我们在做机器学习的时候,往往会把数据集分成训练数据集和测试数据集。训练数据集用于优化模型参数,测试数据集用于测试模型的好坏。例如上面访问流量预测的例子,将2017年—2020年所有的访问流量数据作为训练数据,2021年1月1日—2021年2月14日作为测试数据。这道理子计算得到,在训练数据集上的MAE是0.48k,在测试数据集上的MAE是0.58k。
如果感觉上面的误差有点大,那么如何优化模型架构使误差更小呢?这需要利用领域知识对问题进行分析。比如上面这个例子,将2021年1月1日—2021年2月14日的数据画在图上如下图所示,发现访问流量使呈周期性变化的,周期是一个星期,周末的访问流量明显要低于周内,因为周末休息就懒得学习《机器学习》了。
既然访问流量是按7天一个周期变化的,那么预测第二天的流量只看前一天不太合理,应该看7天的,所以就建立了一个新的模型,
y
=
b
+
∑
j
=
1
7
w
j
x
j
y=b+\sum_{j=1}^{7} w_{j} x_{j}
y=b+j=1∑7wjxj其中
x
j
x_{j}
xj代表前第
i
i
i天的访问流量。经过改进之后,在训练数据集上的MAE是0.38k,在测试数据集上的MAE是0.49k。可见模型的准确度有所提升了。
如果把时间拉得更长,让机器看前28天的访问流量,得到的结果是在训练数据集上的MAE是0.33k,在测试数据集上的MAE是0.46k,又有所提升。如果看56天的,则MAE分别是0.32k,0.46k,没什么提升了,可见增加天数并不是万能的。
上面的模型一般化之后可以表示为
y
=
b
+
∑
j
=
1
N
w
j
x
j
y=b+\sum_{j=1}^{N} w_{j} x_{j}
y=b+j=1∑Nwjxj这个模型在机器学习中称为线性模型(Linear Model),其中
x
j
x_{j}
xj是输入,也称为特征值,
N
N
N代表特征值的个数,也称为特征值维度,
w
j
w_j
wj是权值(Weight),
b
b
b是偏置(Bias)。