花了两周时间学完了吴恩达的机器学习课程,做完了所有作业。虽然编程作业大多是照着公式写代码,框架都给你搭好,几乎是保姆式的服务,但还是或多或少有所收获。因为有点基础,所以看得比较快,十一周的课程只花了两周的时间。总的来说还是值得一看,涉及到了很多方面,在此做个小结。
线性回归
基本形式
线性回归基本形式:
其中$ \theta $代表参数, $ \theta_0 $就是通常说的偏置bias。$ x_n $代表特征,如果$ n = 1 $,则是一元线性回归;$ n > 1 $时是多元线性回归。线性回归可以很方便地改成多项式回归,只需要把特征$ x_n $变换成对应的多项式特征即可。因此掌握了最基本的一元线性回归,就掌握了多元线性回归、多项式回归。
在实际实现中,常常采取如下的向量化:
其中$ X $代表的是训练数据,并且每个训练数据是一行。假设每条训练数据有n个特征(包含$x_0$),总共有m条训练数据,那么$ X $就是$m \times n$的矩阵。$ \theta $代表的是参数矩阵,因为训练数据有n个特征,所以$ \theta $是$n \times 1$的列向量。
损失函数
线性回归的损失函数是平方损失,定义如下所示:
一个直观的解释是,线性回归的损失函数计算的是预测点到实际点的距离的平方和。至于为什么要除以2,是因为在计算损失函数偏导的时候,会乘以2,所以刚好能够抵消,最后系数只剩下 $\frac{1}{m}$。
损失函数的向量化形式如下:
这里又提到了向量化,向量化的意义在于用向量的形式实现,就可以使用矩阵来进行运算,相比于普通的循环来说更加高效,特别是当数据量很大的时候。
模型训练
模型训练就是拟合模型参数的过程,线性回归有两种求解模型参数的办法,一种是将问题转化为损失函数最小化,通过梯度下降法来不断更新要求的参数,使损失函数达到最优;另一种是用Normal Equation直接求出。
梯度下降法就是对损失函数求每个参数$\theta_j$的偏导,偏导就称为梯度,然后通过将当前的$\theta_j$减去其梯度的这种方式来更新参数,直至算法收敛(算法收敛的条件可以是损失函数的值小于某个值)。公式如下:
其中$\alpha$是学习率,$\frac{1}{m} \sum\limits_{i=1}^{m} (h_\theta(x^{(i)}) - y^{(i)}) \cdot x_j^{(i)}$就是$\theta_j$对应的梯度。所以梯度下降法是一个迭代的算法,每轮迭代同时更新所有参数;另外还需要注意学习率$\alpha$的选择,$\alpha$太大的话,可能导致算法不收敛,$\alpha$太小可能导致迭代次数过多,算法收敛慢。
下面是梯度下降法的向量化形式:
Normal Equation也是求解线性回归参数的一种方法,方程如下:
相比于梯度下降法,不需要迭代,也不需要选择学习率$\alpha$,只需要对矩阵求逆。当特征数量很少时,可以采用Normal Equation的方式,更加直接;当特征数量很大时,矩阵求逆会耗费大量的时间,采用梯度下降法更佳。另外,使用Normal Equation时,可能出现矩阵$X^T X$不可逆的情况,可能的原因是存在多余的特征,特征与特征之间依赖比较严重,例如线性相关;或者特征数太多,远大于样本数量,此时应当删去不必要的特征或者采取正则化(Regularization)。
Normal Equation的推导过程可见这里。
特征归一化
特征归一化(Normalization)主要是为了加速梯度下降算法,能够减少梯度下降法的迭代次数。
其中$x_i$是原始的特征,$\mu_i$是特征$x_i$的均值,$s_i$是$x_i$的范围,实际情况中也用$x_i$的标准差来替代$s_i$。
逻辑回归
基本形式
逻辑回归(Logistic Regression)虽然名字上带了“回归”,但主要用于二分类问题。逻辑回归函数的输出是一个处于0-1之间的值,代表输出是1的概率。
\begin{align}& h_\theta(x) = P(y=1 | x ; \theta) = 1 - P(y=0 | x ; \theta) \newline& P(y = 0 | x;\theta) + P(y = 1 | x ; \theta) = 1\end{align}
基本形式如下:
\begin{align}& h_\theta (x) = g ( \theta^T x ) \newline \newline& z = \theta^T x \newline& g(z) = \dfrac{1}{1 + e^{-z}}\end{align}
可以看到逻辑回归其实就是在线性回归上套了一个$g$函数,也称为Sigmoid函数,形式如下图:
可以看到,当$z$的值大于0的时候,$g(z)$是大于0.5的,当$z$小于0时,$g(z)$是小于0.5的。所以如果假设$h_\theta(x) \geq 0.5$时有$y = 1$(即当输出概率大于等于0.5时,判定为类别1),就等价于$\theta^T x \geq 0 \Rightarrow y = 1$。
损失函数
逻辑回归的损失函数是基于最大似然估计推导得到的,推导可见这里。
这里损失函数的意义是度量分类错误的代价,当分类正确时,损失函数中对应的部分为0。损失函数的向量化形式:
\begin{align}
& h = g(X\theta)\newline
& J(\theta) = \frac{1}{m} \cdot \left(-y^{T}\log(h)-(1-y)^{T}\log(1-h)\right)
\end{align}
模型训练
采用梯度下降法,本质上也是对损失函数求偏导,迭代如下:
向量化形式如下:
多分类
由于逻辑回归是用于二分类问题,当需要应用到多分类问题时,采用的是OneVsAll策略,即对于某一类,训练其与其他类的分类器,所以n类需要训练n个分类器。
正则化
正则化(Regularization)主要用来过拟合问题,通常的做法是在损失函数上增加一项关于参数$\theta$的惩罚项。带正则化的逻辑回归损失函数如下:
其中$ \frac{\lambda}{2m}\sum_{j=1}^n \theta_j^2$就是惩罚项,$\lambda$是正则化系数。当$\lambda$过大时,可能造成模型欠拟合。当损失函数带有正则化时,梯度下降时对损失函数求偏导也会带有惩罚项,但需要注意不对$\theta_0$进行惩罚。
神经网络
基本形式
神经网络由神经元组成,单个的神经元的作用是通过若干个输入来输出一个值,如下图所示。通常会添加一个偏置单元bias作为输入。每条输入边上都有相应的参数$\theta$,神经元上有一个激活函数(课程中采用的是sigmoid函数),因此这里$h_\theta(x) = sigmoid(\theta^TX)$。
神经网络由多层神经元组成,每层神经元的数量不等。基本的神经网络由输入层和输出层组成,输入层神经元的个数与特征数量相同,输出层神经元的个数与求解的具体问题相关,如果求解一个二分类问题,输出层的神经元个数就是2个。处于输入层和输出层之间网络层称之为隐层(Hidden Layer)。
神经网络求最后输出层的值采用的是前向传播算法,从前往后分别计算每一层每一个神经元上的值(用前一层神经元的输出值以及对应的权重和神经元上的激活函数来计算)。
损失函数
神经网络的损失函数与逻辑回归的损失函数类似,不过需要考虑网络每条边上的权重。具体形式如下:
反向传播算法是用来最小化神经网络损失函数的一种算法,其本质上也是对损失函数求每条边上参数$\theta$的偏导,不过其采取从后往前一层一层计算的方式。
训练神经网络的一般步骤:
- 随机初始化所有参数。如果将参数初值都设为0,当反向传播时,那么所有节点的更新值都会变成一样,所以一般采用随机初始化的形式;
- 采用前向算法计算每一层神经元的输出值;
- 实现计算损失和用反向传播计算偏导的函数;
- 检查反向传播算法是否正常工作;
- 用梯度下降或者成熟的优化器来优化损失函数,例如在octave中用fmincg来函数优化损失函数,只需要传入计算损失和梯度的函数。
应用机器学习的一些建议
- 将训练数据分为训练集、交叉验证集、测试集。用训练集来训练模型,交叉验证集来测试模型的性能,测试集来测试模型的泛化能力;
- 解决欠拟合:增加特征数量,增加多项式特征,降低正则化系数$\lambda$;
- 解决过拟合:增加训练数据,尝试更少的特征,增加正则化系数$\lambda$;
- 对于二分类问题,当正负样本数不均衡时,采用精确度accuracy来度量模型的性能是不合理的,此时应该采取准确率precision、召回率recall、F1。
支持向量机
基本形式
支持向量机要求函数输出0或者1,而不像逻辑回归是概率。
损失函数
课程中通过逻辑回归的损失函数引出支持向量机的损失函数。对于逻辑回归,如果$y = 1$,要求$\theta^TX \geq 0$,而支持向量机则要求$\theta^TX \gg 0$。基于此,对逻辑回归的损失函数进行一定改变,就得到了支持向量机的损失函数。
损失函数中的$C$是支持向量机的正则化系数,其作用相当于$\frac{1}{\lambda}$。支持向量机寻找能够区分不同类别样本点的最佳决策边界,最佳决策边界到最近的样本点的距离称为间隔,由于支持向量机的本质是最大化这个间隔,所以又称为最大间隔分类器。最大间隔只有当C很大时才会取得,如果存在某些异常点并且我们不想让这些异常点影响最大间隔的决策边界,可以适当减少C。
核函数
不采用核函数的支持向量机(也称为采用线性核linear kernel的支持向量机)对于线性可分数据具有较好的性能,如果数据线性不可分,可以采用核函数来实现非线性支持向量机。所谓核函数,是指某种相似度函数。Andrew Ng对于于核函数的解释非常直观,在输入空间中选取几个代表性的点,将原始特征转化成与这几个代表性的点的相似度的向量作为新的特征,然后用新的特征来最小化损失函数。这样做的效果最后就是,决策边界在这几个代表性的点附近会弯曲,形成非线性的决策面。
课程中提到的一个核函数是高斯核函数(Gaussian),其有个$\sigma^2$参数需要设置,$\sigma^2$太大会导致新特征变化缓慢,容易造成欠拟合;$\sigma^2$过小会导致新特征变化剧烈,容易造成过拟合。所以$\sigma^2$的作用与$C$相反,与$\lambda$相同。如果使用高斯核,建议对特征进行归一化。
接着上面说,实际使用过程中,对于有代表性的点的选取,常常是选择所有的输入数据。所以新的特征维数n与之前的训练数据量m相同。关于逻辑回归和支持向量机使用:
- 如果n远大于m,例如$n=10000$,$m = 100$,建议采用逻辑回归或者线性核支持向量机;
- 如果n很小,m也不大,例如$n = 100$, $m = 1000$,建议使用带高斯核的支持向量机;
- 如果n很小,m很大,例如$n = 100$, $m = 50000+$,建议增加更多特征,然后采用逻辑回归或者线性核支持向量机。
非监督学习
主要介绍了聚类方法k-means和降维方法PCA。
k-means
k-means主要分为两步:
- 随机选取k个中心点;
- 将所有的数据点归类到与其距离最近的某个中心点,然后更新每一类的中心点。
PCA
PCA是将高维数据映射到低维的方法,其步骤如下:
- 计算协方差矩阵$\Sigma = \dfrac{1}{m}\sum^m_{i=1}(x^{(i)})(x^{(i)})^T$;
- 计算协方差矩阵的特征向量;
- 选取前k个特征向量,组成$n \times k$的矩阵$Ureduce$,对于某个原始特征数据$x^{(i)}$,其降维后的特征$z^{(i)} = Ureduce^T \cdot x^{(i)}$
所以PCA的本质是将高维特征通过某个投影矩阵投影到低维。
原始特征的还原:$x_{approx}^{(i)} = U_{reduce} \cdot z^{(i)}$
如何选取k的值来构建投影矩阵?这里定义平方投影误差为$\dfrac{1}{m}\sum^m_{i=1}||x^{(i)} - x_{approx}^{(i)}||^2$,选择最小的k满足如下条件:
但这种方式计算非常缓慢,对于某个k,需要计算所有的还原后的特征向量。现实实现中常常采取如下方式:
其中$S_{ii}$是矩阵$S$里的值,而矩阵S在octave中可以通过如下代码求出:1
[U,S,V] = svd(Sigma)
PCA主要的用处是对特征数据进行降维处理。或者将高维数据映射到2维或者3维使其易于可视化。不要将PCA用来解决过拟合问题,并且不要一开始就对特征进行降维处理,应该先尝试原始特征的效果。
异常检测
异常检测(Anomaly Detection)是为了检测出数据中的异常点。这里我们定义一个模型$p(x)$来告诉我们一个样本是正常样本的概率,然后用一个阈值$\epsilon$来区分正常样本和异常样本($p(x) < \epsilon$)。
我们假设特征符合高斯分布。课程中提到了两种,一种是对于特征的每一维,都符合一个一维高斯分布;另一种是多维特征符合一个多维高斯分布。多维高斯分布相比于多个一维高斯分布,能够自动地捕捉到特征之间的联系,但计算量较大。然后根据训练数据来估计高斯分布的均值和方差。对于样本点$x$,只需计算其在估计出的模型$p(x)$上的值,并与$\epsilon$比较即可。
推荐系统
关于推荐系统介绍了协同过滤算法。假设我们的推荐系统要用于电影的推荐,那么关于电影其实可以用一个特征向量$x$来表述,例如[动作,爱情,悬疑,恐怖]
等,然后用户对电影的喜爱其实是由一个参数向量$\theta$决定的,这样就可以根据评分数据在已知电影特征向量的情况下,为每个用户拟合一个线性回归模型,估计出每个用户的参数向量$\theta$,这就是基于内容的推荐系统。即最小化如下损失函数:
然而很多时候,电影的特征其实不是很好定义,一部电影的动作值是多少?爱情值是多少?这时候可以采用基于用户的推荐系统, 给出用户的参数向量$\theta$(即用户对动作电影的喜欢程度是多少,对爱情电影的喜欢程度是多少等),来拟合电影的特征数据,即最小化如下损失函数:
而协同过滤算法,就是整合了基于内容的推荐系统和基于用户的推荐系统,同时求解用户参数$\theta$和电影特征$x$,其损失函数如下:
参数向量$\theta$和电影特征向量$x$的初始化可以采取随机值,在参数估计完之后,想要预测某用户$j$对某部没有看过电影$i$的评分,可以用$(\theta^{(j)})^T x^{(i)}$来获得。用于电影推荐的推荐系统,在具体实现时,常常对评分矩阵进行均值归一化(即对于每部电影的评分,减去所有用户对其评分的均值),这样对于某位一部电影都没看过的用户,会将其对其他电影的评分预测为平均分,而不全都预测为0分,预测时采用$(\theta^{(j)})^T x^{(i)} + \mu_i$公式来计算。
大规模机器学习
当训练数据量非常大时,传统的梯度下降法(批量梯度下降)会非常耗时,因为每次求梯度都需要遍历所有的训练数据,课程中介绍了两种替代方案:随机梯度下降和小批量梯度下降。
随机梯度下降
对样本进行随机排序,然后按序遍历样本,每次只用当前样本来计算梯度,进行梯度下降。
对样本进行随机排序;
对于$i = 1 … m$,$\Theta_j := \Theta_j - \alpha (h_{\Theta}(x^{(i)}) - y^{(i)}) \cdot x^{(i)}_j$
小批量梯度下降
每次只用小批量样本来计算梯度,假设小批量为10,算法如下:
$For$ $i=1,11,21,31,…,991$
$\theta_j := \theta_j - \alpha \dfrac{1}{10} \displaystyle \sum_{k=i}^{i+9} (h_\theta(x^{(k)}) - y^{(k)})x_j^{(k)}$
总结
洋洋洒洒写了这么多,也算是对课程的一个回顾吧。总的来说,这门课讲得比较形象,虽然涉及到很多公式,但并没有深入去讲公式如何推导等,而是侧重于阐述直观上的理解,非常适合入门。这篇博文虽然涉及到了很多方面,但很多也只是列个公式,并没有做深入的讲解,只是列了一些课程中提到的注意点,说再多也显得晦涩,感兴趣的读者不如直接去看课程的视频吧。
后面准备开始动手实现一遍机器学习中的各种模型,加深对各个模型的理解,敬请期待!