机器学习基础知识

机器学习种类

机器学习种类大概可以分为监督式学习(Supervised learning)非监督式学习(Unsupervised learning)

监督式学习(Supervised learning)

监督式学习算法会从给定的数据中学习,数据中包含输入和对应的正确输出。最终,监督式学习算法可以将输入与输出建立对应关系,从而实现给它一个输入,它能根据输入输出一个结果。

监督式学习有很多算法,目前常用的有下面几种。

算法回归(Regression)分类(Classification)
结果类型预测数字预测种类
结果数量可能的结果是无限的可能的结果是有限的
例子根据房子面积,楼层预测房价根据输入的图片预测是猫还是狗

非监督式学习(Unsupervised learning)

非监督式学习训练的数据中不包含对应的输出。所以它用来寻找数据中的有趣的模式或者关联,而不是输出特定的结果。常见的非监督式学习算法有:聚合(Clustering),异常检测(Anormaly detection),降维(Dimensionally reduction)。

线性回归(Linner regression)

公式

$$ f_{w,b}(x^{(i)}) = wx^{(i)} + b \tag{1}\nonumber $$

\( w \), \( b \) 是参数

代价函数

代价函数的作用是评估我们的模型和训练数据的拟合程度,越小代表我们的模型拟合的越好。常用的有平方代价函数,数学公式为:

$$ J(w,b) = \frac{1}{2m} \sum\limits_{i = 0}^{m-1} (f_{w,b}(x^{(i)}) - y^{(i)})^2 $$

目标

$$ \underset{w, b}{\text{minimize}}J(w,b)$$

梯度下降(Gradient descent)

梯度下降是一种常用的模型训练方法,它可以逐步更新参数直至找到代价函数的局部最小值。当代价函数使用平方时,代价函数的形状会是碗形(Convex shape)。这意味着局部最小值也是全局最小值,所以可以用梯度下降来训练模型参数直至参数到达全局最小值。梯度下降的数学公式为:

$$ w = w - \alpha \frac{\partial J(w,b)}{\partial w} $$ $$ b = b - \alpha \frac{\partial J(w,b)}{\partial b} $$

$$ \frac{\partial J(w,b)}{\partial w} = \frac{1}{m} \sum\limits_{i = 0}^{m-1} (f_{w,b}(x^{(i)}) - y^{(i)})x^{(i)} $$

$$ \frac{\partial J(w,b)}{\partial b} = \frac{1}{m} \sum\limits_{i = 0}^{m-1} (f_{w,b}(x^{(i)}) - y^{(i)}) $$

\(w\) 和 \(b\) 需要同步更新。

\(\alpha\) 为学习率,不能太大也不能太小。\(\alpha\) 太小会导致每次训练参数变化值的很小,可能训练很久也没多大变化。\(\alpha\) 太大会导致拟合不了,代价会越来越大,导致离散(diverge)。

学习率在梯度下降的过程中是不变的,\(w\) 和 \(b\) 的偏导数会随着训练变小。所以随着训练次数的增加,代价的减小幅度是在变小的。

运行

这样就集齐了所有的要素,现在可以通过对所有数据重复运行梯度下降来训练模型参数。

向量化(Vectorization)

当数据量很大的时候,使用循环来一个一个计算是很慢的。现代的 CPU 和 GPU 都实现了 Single Instruction, Multiple Data (SIMD) pipelines 功能,这允许并行执行多个指令,在数据量大的时候可以极大的加快我们的计算速度。在 Python 中,可以使用 numpy 库来创建向量。

多元线性回归(Multiple linear regression)

公式

$$ f_{\mathbf{w},b}(\mathbf{x}) = \mathbf{w} \cdot \mathbf{x} + b $$

$$ \mathbf{w} = \begin{pmatrix} w_0 \\ w_1 \\ \cdots\\ w_{n-1} \end{pmatrix}$$

\( b \) 是一个数字

代价函数

$$J(\mathbf{w},b) = \frac{1}{2m} \sum\limits_{i = 0}^{m-1} (f_{\mathbf{w},b}(\mathbf{x}^{(i)}) - y^{(i)})^2 $$

\( \mathbf{w} \) 和 \( \mathbf{x}^{(i)} \) 都是向量

梯度下降

$$\begin{align*} \text{repeat}&\text{ until convergence:} \lbrace \newline; & w_j = w_j - \alpha \frac{\partial J(\mathbf{w},b)}{\partial w_j} & \text{for j = 0..n-1}\ \newline &b\ \ = b - \alpha \frac{\partial J(\mathbf{w},b)}{\partial b} \newline \rbrace \end{align*}$$ $$ \begin{align} \frac{\partial J(\mathbf{w},b)}{\partial w_j} &= \frac{1}{m} \sum\limits_{i = 0}^{m-1} (f_{\mathbf{w},b}(\mathbf{x}^{(i)}) - y^{(i)})x_{j}^{(i)} \\ \frac{\partial J(\mathbf{w},b)}{\partial b} &= \frac{1}{m} \sum\limits_{i = 0}^{m-1} (f_{\mathbf{w},b}(\mathbf{x}^{(i)}) - y^{(i)}) \end{align} $$ m 是训练集的样本数,n 是特征数

特征缩放(Feature scaling)

当有多个 x 且 x 的数量级差距较大时(一两个数量级以上),由于学习率 \( \alpha \) 对于每个特征都是固定的,这会导致数量级大的特征拟合的很快,然后拖慢其他所有的特征的拟合速度,使得整体的拟合速度很慢。所以,需要将所有特征缩放到差不多的数量级再进行训练,常用的方法有:

  • 当特征中的每个值都为正时,将每个特征都除以它的最大值,可以保证缩放后的特征都在 0 ~ 1 之间。
  • Mean normalization: \( x_i := \dfrac{x_i - \mu_i}{max - min} \)。将每个特征都减去平均值然后除以最大值和最小值的差值。可以适用于任何场景。缩放后的值在 -1 ~ 1 中。
  • Z-score normalization: \(x^{(i)}_j = \dfrac{x^{(i)}_j - \mu_j}{\sigma_j} \) 将每个特征都将去平均值然后除以标准差。可以适用于任何场景。缩放后的值均值为 0 ,标准差为 1。

学习率(Learning rate)

学习率需要经过尝试来选择一个最好的值。可以通过迭代固定的较小的次数,观察代价随着迭代次数的变化曲线。如果代价随着迭代升高,证明学习率过大或代码中有 Bug 。如果下降很缓慢,可能是学习率过小,可以适当调高学习率(每次大3倍)直至下降的很快或着代价开始随着迭代上升。

特征工程(Feature engineering)

特征工程是指通过观察和直觉选择合适的特征参与训练。比如一个房子的长和宽是两个特征,可以将它们两个相乘来得到一个新特征:面积。这个特征会比长和宽更好。

在一些比较复杂的模型中,比如多项式回归(Polynomial regression),选择合适的特征是很重要的。可以在一开始多加几个特征,进行一定次数的迭代。假如一开始的特征为 \( y=w_0x_0 + w_1x_1^2 +b\) 。可以将其扩展为: \( y=w_0x_0 + w_1x_1^2 + w_2x_2^3+b \)。迭代几千次 。重要的特征参数会在迭代中变大,不重要的特征会随着迭代趋近于 0。可以根据迭代后的特征对应的参数大小来判断合适的特征。

逻辑回归(Logistic regression)

分类任务需要输出特定的值,比如 1, 0。而线性回归的结果是无穷多的。所以我们需要一个新的模型来处理这种情况,也就是逻辑回归。

sigmod 函数

sigmod 函数是逻辑回归中的重要函数,他们可以将结果限制在 0 ~1 的区间内,方便我们将结果归到 1 或 0 。具体公式为:

$$ g(x) = \frac{1}{1+e^{x}} $$

决策边界(Decision boundry)

有了 sigmod 函数后,我们把结果限制在了 0~1 的区间内。但我们想要的是 0 或 1,所以,我们需要一个边界,高于这个边界的我们认为结果是 1。低于这个边界的我们认为结果是 0。这个边界就是决策边界。边界可以根据不同需求来调整,一般 0.5 可以认为是一个合理的决策边界。

公式

将线性回归公式的 \( f_{\mathbf{w},b}(\mathbf{x}) \) 作为 \( x \) 带入 sigmod 函数中即可得到逻辑回归的公式: $$ \begin{align} f_{\mathbf{w},b}(\mathbf{x^{(i)}}) = g(z^{(i)}) \\ g(z^{(i)}) = \frac{1}{1+e^{-z^{(i)}}} \\ z^{(i)} = \mathbf{w} \cdot \mathbf{x}^{(i)}+ b \\ \end{align} $$

代价函数

逻辑回归不能用和线性回归一样的平方代价函数。因为它的代价函数的形状不是平滑的,存在很多个局部最小值,这会导致使用平台代价函数梯度下降时卡在某个局部最小值而不是下降到全局最小值。所以,我们需要一个新的代价函数:

$$ J(\mathbf{w},b) = \frac{1}{m} \sum_{i=0}^{m-1} \left[ loss(f_{\mathbf{w},b}(\mathbf{x}^{(i)}), y^{(i)}) \right] $$

\( loss(f_{\mathbf{w},b}(\mathbf{x}^{(i)}), y^{(i)}) \) 指的是每个样本的损失函数:

$$loss(f_{\mathbf{w},b}(\mathbf{x}^{(i)}), y^{(i)}) = -y^{(i)} \log\left(f_{\mathbf{w},b}\left( \mathbf{x}^{(i)} \right) \right) - \left( 1 - y^{(i)}\right) \log \left( 1 - f_{\mathbf{w},b}\left( \mathbf{x}^{(i)} \right) \right) $$

看着很复杂,但考虑到 \( y^{(i)} \) 只有 1 或 0 两个可能的值,损失函数就可以简化为两种情况,就不复杂了。使用这个新的代价函数,我们可以在逻辑回归的情况下得到一个平滑的,局部最小值就是全局最小值的凸形曲线。这样就可以使用梯度下降来训练参数了。

梯度下降

$$\begin{align*} &\text{repeat until convergence:} \; \lbrace \\ & \; \; \; w_j = w_j - \alpha \frac{\partial J(\mathbf{w},b)}{\partial w_j} \; & \text{for j := 0..n-1} \\ & \; \; \; \; \;b = b - \alpha \frac{\partial J(\mathbf{w},b)}{\partial b} \\ &\rbrace \end{align*}$$

$$\begin{align*} \frac{\partial J(\mathbf{w},b)}{\partial w_j} &= \frac{1}{m} \sum\limits_{i = 0}^{m-1} (f_{\mathbf{w},b}(\mathbf{x}^{(i)}) - y^{(i)})x_{j}^{(i)} \\ \frac{\partial J(\mathbf{w},b)}{\partial b} &= \frac{1}{m} \sum\limits_{i = 0}^{m-1} (f_{\mathbf{w},b}(\mathbf{x}^{(i)}) - y^{(i)}) \end{align*}$$

过拟合(Overfitting)

当模型在训练数据上拟合的太过了,模型会在训练数据上表现的很好,它的输出可能与 y 完全相同。但当遇到未被训练过的数据,即新数据时,模型的表现会很差。这中现象就是过拟合,它的泛化(generalization)程度不够,不能实际使用。这种情况也叫 High Variance。有几种方法可以解决这个问题:

获取更多数据

这是最简单直观的方法,更多的数据会让模型更不容易训练的效果更好,更不容易过拟合。

选择合适的特征

有些特征可能是非必要的,当拥有很多特征时,可以考虑去掉一些,保留关键特征。

正则化(Regularization)

正则化是指在代价函数中增加一个惩罚项,这样可以在训练的过程中减小 \( w \) (也可以选择加上正则化 \( b \) ),鼓励模型学习更简单或平滑的函数,提高模型的泛化能力。

正则化线性回归

$$J(\mathbf{w},b) = \frac{1}{2m} \sum\limits_{i = 0}^{m-1} (f_{\mathbf{w},b}(\mathbf{x}^{(i)}) - y^{(i)})^2 + \frac{\lambda}{2m} \sum\limits_{j=0}^{n-1} w_j^2 $$

$$ f_{\mathbf{w},b}(\mathbf{x}^{(i)}) = \mathbf{w} \cdot \mathbf{x}^{(i)} + b $$

相比于为正则化的代价函数多出的: \( \frac{\lambda}{2m} \sum\limits_{j=0}^{n-1} w_j^2 \) 即是惩罚项。

正则化逻辑回归

$$J(\mathbf{w},b) = \frac{1}{m} \sum\limits_{i=0}^{m-1} \left[ -y^{(i)} \log\left(f_{\mathbf{w},b}\left( \mathbf{x}^{(i)} \right) \right) - \left( 1 - y^{(i)}\right) \log \left( 1 - f_{\mathbf{w},b}\left( \mathbf{x}^{(i)} \right) \right) \right] + \frac{\lambda}{2m} \sum\limits_{j=0}^{n-1} w_j^2 $$

$$ f_{\mathbf{w},b}(\mathbf{x}^{(i)}) = sigmoid(\mathbf{w} \cdot \mathbf{x}^{(i)} + b) $$

相比于为正则化的代价函数多出的: \( \frac{\lambda}{2m} \sum\limits_{j=0}^{n-1} w_j^2 \) 即是惩罚项。

梯度下降

对于线性回归和逻辑回归,正则化后的梯度下降只有 \( f_{\mathbf{w},b}(\mathbf{x}^{(i)}) \) 的定义不同

$$\begin{align*} \frac{\partial J(\mathbf{w},b)}{\partial w_j} &= \frac{1}{m} \sum\limits_{i = 0}^{m-1} (f_{\mathbf{w},b}(\mathbf{x}^{(i)}) - y^{(i)})x_{j}^{(i)} + \frac{\lambda}{m} w_j \\ \frac{\partial J(\mathbf{w},b)}{\partial b} &= \frac{1}{m} \sum\limits_{i = 0}^{m-1} (f_{\mathbf{w},b}(\mathbf{x}^{(i)}) - y^{(i)}) \end{align*}$$

因为每次更新 \(w_j\) 的时候都增加了一个正数的惩罚项,所以每次更新都会导致 \(w_j\) 变小一点,这就是正则化的作用。