1.3 监督学习
监督学习指的就是我们给学习算法一个数据集。
回归这个词的意思是,我们在试着推测出这一系列连续值属性。
分类指的是,我们试着推测出离散的输出值:0或1良性或恶性,而事实上在分类问题中,输出可能不止两个值。
1.4 无监督学习
无监督学习中,我们已知的数据。看上去有点不一样,不同于监督学习的数据的样子,即无监督学习中没有任何的标签或者是有相同的标签。针对数据集,无监督学习就能判断出数据有两个不同的聚集簇。
2.单变量线性回归(Linear Regression with One Variable)
2.1模型表示
因为只含有一个特征/输入变量,因此这样的问题叫作单变量线性回归问题。
2.2代价函数
目标便是选择出可以使得建模误差的平方和能够最小的模型参数。 即使得代价函数 最小。代价函数也被称作平方误差函数,平方误差代价函数可能是解决回归问题最常用的手段了。
2.5 梯度下降
梯度下降是一个用来求函数最小值的算法,批量梯度下降(batch gradient descent)算法的公式为:
repeat until convergence{
(for j=0 and j=1)
}
其中a 是学习率(learning rate),它决定了我们沿着能让代价函数下降程度最大的方向向下迈出的步子有多大,在批量梯度下降中,我们每一次都同时让所有的参数减去学习速率乘以代价函数的导数。 如果a 太小的话,可能会很慢,因为它会一点点挪动,它会需要很多步才能到达全局最低点。如果a 太大,那么梯度下降法可能会越过最低点,甚至可能无法收敛,下一次迭代又移动了一大步,越过一次,又越过一次,一次次越过最低点。
结合梯度下降法,以及平方代价函数,我们会得出第一个机器学习算法,即线性回归算法。
2.7 梯度下降的线性回归
将梯度下降和代价函数结合,应用于具体的拟合直线的线性回归算法里。
则算法改写成:
Repeat {
}
上述称为 批量梯度下降。
3.线性代数回顾(Linear Algebra Review)
3.1 矩阵和向量
3.2 加法和标量乘法
矩阵的加法:行列数相等的可以加。
例:
矩阵的乘法:每个元素都要乘
组合算法也类似。
3.3 矩阵向量乘法
3.4 矩阵乘法
3.5 矩阵乘法的性质
3.6 逆、转置
4.多变量线性回归(Linear Regression with Multiple Variables)
4.1 多维特征
此时模型中的参数是一个维的向量,任何一个训练实例也都是
维的向量,特征矩阵
的维度是
。 因此公式可以简化为:
4.2 多变量梯度下降
找出使得代价函数最小的一系列参数。 多变量线性回归的批量梯度下降算法:
Repeat {
(simultaneously update for j=0,1...,n )
}
开始随机选择一系列的参数值,计算所有的预测结果后,再给所有的参数一个新的值,如此循环直到收敛。
4.3 梯度下降法实践1-特征缩放
面对多维特征问题的时候,要保证这些特征都具有相近的尺度,这将帮助梯度下降算法更快地收敛。尝试将所有特征的尺度都尽量缩放到-1到1之间。
,其中 是平均值,是标准差
4.5 特征和多项式回归
线性回归并不适用于所有数据,有时我们需要曲线来适应我们的数据,比如一个二次方模型:
或者三次方模型:
通常我们需要先观察数据然后再决定准备尝试怎样的模型。 另外,我们可以令:
从而将模型转化为线性回归模型。采用多项式回归模型,在运行梯度下降算法前,特征缩放非常有必要。
4.6 正规方程
求解方程来找出使得代价函数最小的参数,正规方程解出向量
梯度下降与正规方程的比较:
总结,只要特征变量的数目并不大,标准方程是一个很好的计算参数θ 的替代方法
5.6 向量化
写代码做矩阵乘法,不如用合适的向量化方法来实现
6.逻辑回归(Logistic Regression)
6.1 分类问题
在分类问题中,你要预测的变量 y 是离散的值,我们将学习一种叫做逻辑回归。将因变量(dependent variable)可能属于的两个类分别称为负向类(negative class)和正向类(positive class),则因变量 ,其中 0 表示负向类,1 表示正向类。这个算法的性质是:它的输出值永远在0到 1 之间。这个算法的名字中出现了“回归”使你感到困惑,但逻辑回归算法实际上是一种分类算法,它适用于标签 y 取值离散的情况。
6.2 假说表示
逻辑回归模型的假设是:
其中: 代表特征向量
代表逻辑函数(logistic function),常用的逻辑函数为S形函数(Sigmoid function),公式为:
。
的作用是,对于给定的输入变量,根据选择的参数计算输出变量=1的可能性(estimated probablity)即
例如,如果对于给定的x ,通过已经确定的参数计算得出
,则表示有70%的几率y 为正向类,相应地y 为负向类的几率为1-0.7=0.3。
6.3 判定边界
决策边界(decision boundary),我们可以绘制直线 ,这条线便是我们模型的分界线,将预测为1的区域和预测为 0的区域分隔开。
6.4代价函数
对于线性回归模型,我们定义的代价函数是所有模型误差的平方和 对逻辑回归模型沿用这个定义,得到的代价函数将是一个非凸函数(non-convexfunction),有许多局部最小值,影响梯度下降算法寻找全局最小值。
重新定义逻辑回归的代价函数为:
,其中
构建的
函数的特点是:当实际的 y=1 且 也为 1 时误差为 0,当 y=1 但 不为1时误差随着 变小而变大;当实际的 y=0 且 也为 0 时代价为 0,当 y=0但 不为 0时误差随着 的变大而变大。简化为
虽然得到的梯度下降算法表面上看上去与线性回归的梯度下降算法一样,但是这里的与线性回归中不同,所以实际上是不一样的。另外,在运行梯度下降算法之前,进行特征缩放依旧是非常必要的。
6.5 简化的成本函数和梯度下降
用 梯度下降最小化逻辑回归中代价函数
,简化为
6.7 多类别分类:一对多
使用逻辑回归 (logistic regression)来解决多类别分类问题,具体来说,叫做"一对多" (one-vs-all) 的分类算法。
(上图右,将其分成3个二元分类问题。)创建一个新的"伪"训练集。将多个类中的一个类标记为正向类(y=1 ),然后将其他所有类都标记为负向类,这个模型记作, 拟合出一个合适的分类器。接着,类似地第我们选择另一个类标记为正向类(y=2 ),再将其它类都标记为负向类,将这个模型记作 ,依此类推。 最后我们得到一系列的模型简记为: 其中:i=(1,2,3...k)
最后,在我们需要做预测时,我们将所有的分类机都运行一遍,三个分类器里面输入 x ,然后我们选择一个让最大的i ,即。
7.正则化(Regularization)
7.1 过拟合的问题
第一个模型是一个线性模型,欠拟合,不能很好地适应我们的训练集;第三个模型是一个四次方的模型,过于强调拟合原始数据,而丢失了算法的本质即预测新数据,称为过拟合(over-fitting)。中间的模型似乎最合适。拟合的越好,相应的预测的能力就可能变差,应该如何处理?
1.丢弃一些不能帮助我们正确预测的特征。可以是手工选择保留哪些特征,或者使用一些模型选择的算法来帮忙(例如PCA)
2.正则化。 保留所有的特征,但是减少参数的大小(magnitude)。
7.2代价函数
上面的回归问题中如果我们的模型是: ,那些高次项导致了过拟合的产生,所以如果我们能让这些高次项的系数接近于0的话,就能很好的拟合了,所以在一定程度上减小这些参数的值,这就是正则化的基本方法。减少 和的大小,我们要做的便是修改代价函数,在其中 和设置一点惩罚,在尝试最小化代价时也需要将这个惩罚纳入考虑中,并最终导致选择较小一些的 和 。
修改后的代价函数如下:,通过这样的代价函数选择出的 和 对预测结果的影响就比之前要小许多。假如我们有非常多的特征,我们并不知道其中哪些特征我们要惩罚,我们将对所有的特征进行惩罚,并且让代价函数最优化的软件来选择这些惩罚的程度。这样的结果是得到了一个较为简单的能防止过拟合问题的假设:
,其中λ 又称为正则化参数(Regularization Parameter)。 注:根据惯例,我们不对
进行惩罚。经过正则化处理的模型与原模型的可能对比如下图所示:
如果选择的正则化参数λ过大,则会把所有的参数都最小化了,导致模型变成,也就是上图中红色直线所示的情况,造成欠拟合。要取一个合理的的值。把这些概念应用到到线性回归和逻辑回归中去,那么我们就可以让他们避免过度拟合了。
7.3 正则化线性回归
基于梯度下降:每次都在原有算法更新规则的基础上令θ 值减少了一个额外的值。
Repeat until convergence{
}
对上面的算法中j=1,2,...,n 时的更新式子进行调整可得:
基于正规方程:图中的矩阵尺寸为 (n+1)*(n+1) 。
7.4 正则化的逻辑回归模型
对于逻辑回归,我们也给代价函数增加一个正则化的表达式,得到代价函数:
要最小化该代价函数,通过求导,得出梯度下降算法为:
Repeat until convergence{
for j=1,2,...n
}
注:1、看上去同线性回归一样,但是知道 ,所以与线性回归不同。2、不参与其中的任何一个正则化。
8. 神经网络的表述(Neural Networks: Representation)
8.3模型表示1
在神经网络中,参数又可被称为权重(weight)。神经网络模型是许多逻辑单元按照不同层级组织起来的网络,每一层的输出变量都是下一层的输入变量。下图为一个3层的神经网络,第一层成为输入层(Input Layer),最后一层称为输出层(Output Layer),中间一层成为隐藏层(Hidden Layers)。我们为每一层都增加一个偏差单位(bias unit):
我们把这样从左到右的算法称为前向传播算法( FORWARD PROPAGATION ),把x , θ , a 分别用矩阵表示,我们可以得到θ⋅X=a :
8.4 模型表示2
我们可以把a0,a1,a2,a3 看成更为高级的特征值,也就是x0,x1,x2,x3 的进化体,并且它们是由 x 决定的,因为是梯度下降的,所以a 是变化的,并且变得越来越厉害,所以这些更高级的特征值远比 x 次方厉害,也能更好的预测新数据。这就是神经网络相比于逻辑回归和线性回归的优势。
从本质上讲,神经网络能够通过学习得出其自身的一系列特征。在普通的逻辑回归中,我们被限制为使用数据中的原始特征x1,x2,...,xn ,我们虽然可以使用一些二项式项来组合这些特征,但是我们仍然受到这些原始特征的限制。在神经网络中,原始特征只是输入层,在我们上面三层的神经网络例子中,第三层也就是输出层做出的预测利用的是第二层的特征,而非输入层中的原始特征,我们可以认为第二层中的特征是神经网络通过学习后自己得出的一系列用于预测输出变量的新特征。
8.7多类分类
9.神经网络的学习(Neural Networks: Learning)
9.1代价函数
代价函数会比逻辑回归更加复杂一些,为:
通过代价函数来观察算法预测的结果与真实情况的误差有多大。
9.2反向传播算法
在计算神经网络预测结果的时候我们采用了一种正向传播方法,我们从第一层开始正向一层一层进行计算,直到最后一层的 。现在,为了计算代价函数的偏导数 ,我们需要采用一种反向传播算法,也就是首先计算最后一层的误差,然后再一层一层反向求出各层的误差,直到倒数第二层。首先用正向传播方法计算出每一层的激活单元,利用训练集的结果与神经网络预测的结果求出最后一层的误差,然后利用该误差运用反向传播法计算出直至第二层的所有误差。在求出了 之后,我们便可以计算代价函数的偏导数了
9.5梯度检验
对一个较为复杂的模型(例如神经网络)使用梯度下降算法时,可能会存在一些不容易察觉的错误,虽然代价看上去在不断减小,但最终的结果可能并不是最优解。为了避免这样的问题,我们采取一种叫做梯度的数值检验(Numerical Gradient Checking)方法:在代价函数上沿着切线的方向选择离两个非常近的点然后计算两个点的平均值用以估计梯度。这种方法的思想是通过估计梯度值来检验我们计算的导数值是否真的是我们要求的。
9.6随机初始化
任何优化算法都需要一些初始的参数。通常初始参数为正负之间的随机值。
9.7综合起来
小结一下使用神经网络时的步骤:
1、网络结构:第一件要做的事是选择网络结构,即决定选择多少层以及决定每层分别有多少个单元。第一层的单元数即我们训练集的特征数量。最后一层的单元数是我们训练集的结果的类的数量。如果隐藏层数大于1,确保每个隐藏层的单元个数相同,通常情况下隐藏层单元的个数越多越好。我们真正要决定的是隐藏层的层数和每个中间层的单元数。
2、训练神经网络:
- 参数的随机初始化
- 利用优化算法来最小化代价函数
- 编写计算代价函数 J 的代码
- 利用反向传播方法计算所有偏导数
- 利用数值检验方法检验这些偏导数
- 使用正向传播方法计算所有的h θ (x)
10.应用机器学习的建议(Advice for Applying Machine Learning)
10.2评估一个假设
为了检验算法是否过拟合,我们将数据分成训练集和测试集,通常用70%的数据作为训练集,用剩下30%的数据作为测试集。很重要的一点是训练集和测试集均要含有各种类型的数据,通常我们要对数据进行“洗牌”,然后再分成训练集和测试集。
测试集评估:在通过训练集让我们的模型学习得出其参数后,对测试集运用该模型,我们有两种方式计算误差:
1.对于线性回归模型,我们利用测试集数据计算代价函数J
2.对于逻辑回归模型,我们除了可以利用测试数据集来计算代价函数外,还可以计算误分类的比率,然后对计算结果求平均。
10.3 模型选择和交叉验证集( Model Selection and Train_Validation_Test Sets)
越高次数的多项式模型越能够适应我们的训练数据集,但是适应训练数据集并不代表着能推广至一般情况,我们应该选择一个更能适应一般情况的模型。我们需要使用交叉验证集来帮助选择模型,即:使用60%的数据作为训练集,使用 20%的数据作为交叉验证集,使用20%的数据作为测试集
模型选择的方法为:
-
使用训练集训练出10个模型
-
用10个模型分别对交叉验证集计算得出交叉验证误差(代价函数的值)
-
选取代价函数值最小的模型
-
用步骤3中选出的模型对测试集计算得出推广误差(代价函数的值)
Train/validation/test error
training error:
Cross Validation error:
Test error:
10.4 诊断偏差和方差(Diagnosing bias vs. variance)
运行一个学习算法时,如果算法的表现不理想,那么多半是出现两种情况:要么是偏差比较大,要么是方差比较大。换句话说,出现的情况要么是欠拟合,要么是过拟合问题。
我们通常会通过将训练集和交叉验证集的代价函数误差与多项式的次数绘制在同一张图表上来帮助分析:
对于训练集,当 d 较小时,模型拟合程度更低,误差较大;随着 d 的增长,拟合程度提高,误差减小。
对于交叉验证集,当 d 较小时,模型拟合程度低,误差较大;但是随着 d 的增长,误差呈现先减小后增大的趋势,转折点是我们的模型开始过拟合训练数据集的时候。 训练集误差和交叉验证集误差近似时:偏差/欠拟合。 交叉验证集误差远大于训练集误差时:方差/过拟合。
10.5正则化和偏差/方差(Regularization and Bias_Variance )
训练模型的过程中,一般会使用一些正则化方法来防止过拟合。但是我们可能会正则化的程度太高或太小了,即我们在选择λ的值时也需要思考与刚才选择多项式模型次数类似的问题。
选择一系列的想要测试的 值,通常是 0-10之间的呈现2倍关系的值。同样把数据分为训练集、交叉验证集和测试集。
选择λ 的方法为:
1.使用训练集训练出12个不同程度正则化的模型
2.用12个模型分别对交叉验证集计算的出交叉验证误差
3.选择得出交叉验证误差最小的模型
4.运用步骤3中选出模型对测试集计算得出推广误差,我们也可以同时将训练集和交叉验证集模型的代价函数误差与λ的值绘制在一张图表上:
- 当 λ 较小时,训练集误差较小(过拟合)而交叉验证集误差较大
- 随着 λ 的增加,训练集误差不断增加(欠拟合),而交叉验证集误差则是先减小后增加
10.6 学习曲线
学习曲线是学习算法的一个很好的合理检验(sanity check)。学习曲线是将训练集误差和交叉验证集误差(因变量) 作为训练集实例数量(自变量)(m )的函数绘制的图表。即,如果我们有100行数据,我们从1行数据开始,逐渐学习更多行的数据。思想是:当训练较少行数据的时候,训练的模型将能够非常完美地适应较少的训练数据,但是训练出来的模型却不能很好地适应交叉验证集数据或测试集数据。
利用学习曲线识别高偏差/欠拟合:我们用一条直线来适应下面的数据,可以看出,无论训练集实例数量有多么大,误差都不会有太大改观。即在高偏差/欠拟合的情况下,增加数据到训练集不一定能有帮助。
利用学习曲线识别高方差/过拟合:我们用一个非常高次的多项式模型,并且正则化非常小,可以看出,当交叉验证集误差远大于训练集误差时,往训练集增加更多数据可以提高模型的效果。即在高方差/过拟合的情况下,增加更多数据到训练集可能可以提高算法效果。
10.7 决定下一步做什么
我们来看一看我们在什么情况下应该怎样选择:
-
获得更多的训练实例——解决高方差
-
尝试减少特征的数量——解决高方差
-
尝试获得更多的特征——解决高偏差
-
尝试增加多项式特征——解决高偏差
-
尝试减少正则化程度λ——解决高偏差
-
尝试增加正则化程度λ——解决高方差
神经网络的方差和偏差:
11.机器学习系统的设计(Machine Learning System Design)
11.1 首先要做什么
我将谈到机器学习系统的设计。 在谈及在设计复杂的机器学习系统时,你将遇到的主要问题。同时我们会试着给出一些关于如何巧妙构建一个复杂的机器学习系统的建议。下面的课程的的数学性可能不是那么强,但是我认为我们将要讲到的这些东西是非常有用的,可能在构建大型的机器学习系统时,节省大量的时间。
以一个垃圾邮件分类器算法为例进行讨论。
为了解决这样一个问题,我们首先要做的决定是如何选择并表达特征向量。我们可以选择一个由100个最常出现在垃圾邮件中的词所构成的列表,根据这些词是否有在邮件中出现,来获得我们的特征向量(出现为1,不出现为0),尺寸为100×1。
为了构建这个分类器算法,我们可以做很多事,例如:
- 收集更多的数据,让我们有更多的垃圾邮件和非垃圾邮件的样本
- 基于邮件的路由信息开发一系列复杂的特征
- 基于邮件的正文信息开发一系列复杂的特征,包括考虑截词的处理
- 为探测刻意的拼写错误(把watch 写成w4tch)开发复杂的算法
在上面这些选项中,非常难决定应该在哪一项上花费时间和精力,作出明智的选择,比随着感觉走要更好。当我们使用机器学习时,总是可以“头脑风暴”一下,想出一堆方法来试试。实际上,当你需要通过头脑风暴来想出不同方法来尝试去提高精度的时候,你可能已经超越了很多人了。大部分人并不尝试着列出可能的方法,他们做的只是某天早上醒来,因为某些原因有了一个突发奇想:“让我们来试试用Honey Pot项目收集大量的数据吧。”
我们将在随后的课程中讲误差分析,我会告诉你怎样用一个更加系统性的方法,从一堆不同的方法中,选取合适的那一个。因此,你更有可能选择一个真正的好方法,能让你花上几天几周,甚至是几个月去进行深入的研究。
11.2 误差分析
在本次课程中,我们将会讲到误差分析(Error Analysis)的概念。这会帮助你更系统地做出决定。如果你准备研究机器学习的东西,或者构造机器学习应用程序,最好的实践方法不是建立一个非常复杂的系统,拥有多么复杂的变量;而是构建一个简单的算法,这样你可以很快地实现它。
每当吴恩达老师研究机器学习的问题时,他最多只会花一天的时间,就是字面意义上的24小时,来试图很快的把结果搞出来,即便效果不好。坦白的说,就是根本没有用复杂的系统,但是只是很快的得到的结果。即便运行得不完美,但是也把它运行一遍,最后通过交叉验证来检验数据。一旦做完,你可以画出学习曲线,通过画出学习曲线,以及检验误差,来找出你的算法是否有高偏差和高方差的问题,或者别的问题。在这样分析之后,再来决定用更多的数据训练,或者加入更多的特征变量是否有用。这么做的原因是:这在你刚接触机器学习问题时是一个很好的方法,你并不能提前知道你是否需要复杂的特征变量,或者你是否需要更多的数据,还是别的什么。提前知道你应该做什么,是非常难的,因为你缺少证据,缺少学习曲线。因此,你很难知道你应该把时间花在什么地方来提高算法的表现。但是当你实践一个非常简单即便不完美的方法时,你可以通过画出学习曲线来做出进一步的选择。你可以用这种方式来避免一种电脑编程里的过早优化问题,这种理念是:我们必须用证据来领导我们的决策,怎样分配自己的时间来优化算法,而不是仅仅凭直觉,凭直觉得出的东西一般总是错误的。 除了画出学习曲线之外,一件非常有用的事是误差分析,我的意思是说:当我们在构造垃圾邮件分类器时,我会看一看我的交叉验证数据集,然后亲自看一看哪些邮件被算法错误地分类。因此,通过这些被算法错误分类的垃圾邮件与非垃圾邮件,你可以发现某些系统性的规律:什么类型的邮件总是被错误分类。经常地这样做之后,这个过程能启发你构造新的特征变量,或者告诉你:现在这个系统的短处,然后启发你如何去提高它。 构建一个学习算法的推荐方法为:
-
从一个简单的能快速实现的算法开始,实现该算法并用交叉验证集数据测试这个算法
-
绘制学习曲线,决定是增加更多数据,或者添加更多特征,还是其他选择
-
进行误差分析:人工检查交叉验证集中我们算法中产生预测误差的样本,看看这些样本是否有某种系统化的趋势
以我们的垃圾邮件过滤器为例,误差分析要做的既是检验交叉验证集中我们的算法产生错误预测的所有邮件,看:是否能将这些邮件按照类分组。例如医药品垃圾邮件,仿冒品垃圾邮件或者密码窃取邮件等。然后看分类器对哪一组邮件的预测误差最大,并着手优化。
思考怎样能改进分类器。例如,发现是否缺少某些特征,记下这些特征出现的次数。
例如记录下错误拼写出现了多少次,异常的邮件路由情况出现了多少次等等,然后从出现次数最多的情况开始着手优化。
误差分析并不总能帮助我们判断应该采取怎样的行动。有时我们需要尝试不同的模型,然后进行比较,在模型比较时,用数值来判断哪一个模型更好更有效,通常我们是看交叉验证集的误差。
在我们的垃圾邮件分类器例子中,对于“我们是否应该将discount/discounts/discounted/discounting处理成同一个词?”如果这样做可以改善我们算法,我们会采用一些截词软件。误差分析不能帮助我们做出这类判断,我们只能尝试采用和不采用截词软件这两种不同方案,然后根据数值检验的结果来判断哪一种更好。
因此,当你在构造学习算法的时候,你总是会去尝试很多新的想法,实现出很多版本的学习算法,如果每一次你实践新想法的时候,你都要手动地检测这些例子,去看看是表现差还是表现好,那么这很难让你做出决定。到底是否使用词干提取,是否区分大小写。但是通过一个量化的数值评估,你可以看看这个数字,误差是变大还是变小了。 你可以通过它更快地实践你的新想法,它基本上非常直观地告诉你:你的想法是提高了算法表现,还是让它变得更坏,这会大大提高你实践算法时的速度。所以我强烈推荐在交叉验证集上来实施误差分析,而不是在测试集上。但是,还是有一些人会在测试集上来做误差分析。即使这从数学上讲是不合适的。所以我还是推荐你在交叉验证向量上来做误差分析。
总结一下,当你在研究一个新的机器学习问题时,我总是推荐你实现一个较为简单快速、即便不是那么完美的算法。 我几乎从未见过人们这样做。大家经常干的事情是:花费大量的时间在构造算法上,构造他们以为的简单的方法。因此,不要担心你的算法太简单,或者太不完美,而是尽可能快地实现你的算法。当你有了初始的实现之后,它会变成一个非常有力的工具,来帮助你决定下一步的做法。因为我们可以先看看算法造成的错误,通过误差分析,来看看他犯了什么错,然后来决定优化的方式。另一件事是:假设你有了一个快速而不完美的算法实现,又有一个数值的评估数据,这会帮助你尝试新的想法,快速地发现你尝试的这些想法是否能够提高算法的表现,从而你会更快地做出决定,在算法中放弃什么,吸收什么误差分析可以帮助我们系统化地选择该做什么。
11.3 类偏斜的误差度量
在前面的课程中,我提到了误差分析,以及设定误差度量值的重要性。那就是,设定某个实数来评估你的学习算法,并衡量它的表现,有了算法的评估和误差度量值。
有一件重要的事情要注意,就是使用一个合适的误差度量值,这有时会对于你的学习算法造成非常微妙的影响,这件重要的事情就是偏斜类(skewed classes)的问题。类偏斜情况表现为我们的训练集中有非常多的同一种类的样本,只有很少或没有其他类的样本。 例如我们希望用算法来预测癌症是否是恶性的,在我们的训练集中,只有0.5%的实例是恶性肿瘤。假设我们编写一个非学习而来的算法,在所有情况下都预测肿瘤是良性的,那么误差只有0.5%。然而我们通过训练而得到的神经网络算法却有1%的误差。这时,误差的大小是不能视为评判算法效果的依据的。 查准率(Precision)和查全率(Recall) 我们将算法预测的结果分成四种情况:
- 正确肯定(True Positive,TP):预测为真,实际为真
- 正确否定(True Negative,TN):预测为假,实际为假
- 错误肯定(False Positive,FP):预测为真,实际为假
- 错误否定(False Negative,FN):预测为假,实际为真
则: 查准率=TP/(TP+FP)。例,在所有我们预测有恶性肿瘤的病人中,实际上有恶性肿瘤的病人的百分比,越高越好。 查全率(召回率)=TP/(TP+FN)。例,在所有实际上有恶性肿瘤的病人中,成功预测有恶性肿瘤的病人的百分比,越高越好。 这样,对于我们刚才那个总是预测病人肿瘤为良性的算法,其查全率是0(因为你本身预测的群体就是有恶性肿瘤的)。
11.4 查准率和查全率之间的权衡
在之前的课程中,我们谈到查准率和召回率,作为遇到偏斜类问题的评估度量值。在很多应用中,我们希望能够保证查准率和召回率的相对平衡。
在这节课中,我将告诉你应该怎么做,同时也向你展示一些查准率和召回率作为算法评估度量值的更有效的方式。继续沿用刚才预测肿瘤性质的例子。假使,我们的算法输出的结果在0-1 之间,我们使用阀值0.5 来预测真和假。
查准率 (Precision)=TP/(TP+FP) 例,在所有我们预测有恶性肿瘤的病人中,实际上有恶性肿瘤的病人的百分比,越高越好。 查全率 (Recall)=TP/(TP+FN) 例,在所有实际上有恶性肿瘤的病人中,成功预测有恶性肿瘤的病人的百分比,越高越好。
如果我们希望只在非常确信的情况下预测为真(肿瘤为恶性),即我们希望更高的查准率,我们可以使用比0.5更大的阀值,如0.7,0.9。这样做我们会减少错误预测病人为恶性肿瘤的情况,同时却会增加未能成功预测肿瘤为恶性的情况。
如果我们希望提高查全率,尽可能地让所有有可能是恶性肿瘤的病人都得到进一步地检查、诊断,我们可以使用比0.5更小的阀值,如0.3。 我们可以将不同阀值情况下,查全率与查准率的关系绘制成图表,曲线的形状根据数据的不同而不同:
我们希望有一个帮助我们选择这个阀值的方法。一种方法是计算F1 值(F1 Score),其计算公式为:
我们选择使得F1值最高的阀值。
12.支持向量机(Support Vector Machines)
12.1 优化目标
到目前为止,你已经见过一系列不同的学习算法。在监督学习中,许多学习算法的性能都非常类似,因此,重要的不是你该选择使用学习算法A还是学习算法B,而更重要的是,应用这些算法时,所创建的大量数据在应用这些算法时,表现情况通常依赖于你的水平。 比如:你为学习算法所设计的特征量的选择,以及如何选择正则化参数,诸如此类的事。(也就是你所选用的任何一个因素,都会影响你的算法准确度)
还有一个更加强大的算法广泛的应用于工业界和学术界,它被称为支持向量机(Support Vector Machine)。与逻辑回归和神经网络相比,支持向量机,或者简称SVM,在学习复杂的非线性方程时提供了一种更为清晰,更加强大的方式。因此,在接下来的视频中,我会探讨这一算法。在稍后的课程中,我也会对监督学习算法进行简要的总结。当然,仅仅是作简要描述。但对于支持向量机,鉴于该算法的强大和受欢迎度,在本课中,我会花许多时间来讲解它。它也是我们所介绍的最后一个监督学习算法。
正如我们之前开发的学习算法,我们从优化目标开始。那么,我们开始学习这个算法。为了描述支持向量机,事实上,我将会从逻辑回归开始展示我们如何一点一点修改来得到本质上的支持向量机。
那么,在逻辑回归中我们已经熟悉了这里的假设函数形式,和右边的S型激励函数。然而,为了解释一些数学知识.我将用 z 表示
现在考虑下我们想要逻辑回归做什么:如果有一个 y = 1 的样本,我的意思是不管是在训练集中或是在测试集中,又或者在交叉验证集中,总之是 ,现在我们希望 趋近1。因为我们想要正确地将此样本分类,这就意味着当趋近于 1 时,趋近于1时,应当远大于0,这里的意思是远远大于0。这是因为由于 z表示 ,当 z 远大于0时,即到了该图的右边,你不难发现此时逻辑回归的输出将趋近于1。相反地,如果我们有另一个样本,即。我们希望假设函数的输出值将趋近于0,这对应于 ,或者就是 z 会远小于0,因为对应的假设函数的输出值趋近0。
如果你进一步观察逻辑回归的代价函数,你会发现每个样本(x , y )都会为总代价函数增加这样一项
这是每一个样本(x , y )对总代价的“贡献”,我们先不看总代价,就看每一个样本。
因此,对于总代价函数通常会有对所有的训练样本求和,并且这里还有一个项,但是,在逻辑回归中,这里的这一项就是表示一个训练样本所对应的表达式。现在,如果我将完整定义的假设函数代入这里。那么,我们就会得到每一个训练样本都影响这一项。
现在,先忽略 这一项,但是这一项是影响整个总代价函数中的这一项的。
现在,一起来考虑两种情况:
一种是y = 1 的情况;另一种是y = 0 的情况。
在第一种情况中,假设 y = 1,此时在目标函数中只需有第一项起作用,因为时 y = 1,(1 − y)项将等于0。因此,当在 y = 1 的样本中时,即在 (x , y ) 中,我们得到
这样一项,这里同上一张幻灯片一致。 我用 z 表示 。当然,在代价函数中, y前面有负号。我们只是这样表示,如果 y = 1 代价函数中,这一项也等于1。这样做是为了简化此处的表达式。如果画出关于 z 的函数,你会看到左下角的这条曲线,我们同样可以看到,当 z 增大时,也就是相当于 增大时,z 对应的值会变的非常小。对整个代价函数而言,影响也非常小。这也就解释了,为什么逻辑回归在观察到正样本 y = 1 时,试图将 z 设置得非常大。因为,在代价函数中的这一项会变的非常小。
现在开始建立支持向量机,我们从这里开始: 我们会从这个代价函数开始,也就是
一点一点修改,让我取这里的 z = 1点,我先画出将要用的代价函数。
目前,我们只是讨论了y = 1 的情况,另外一种情况是当y = 0 时,此时如果你仔细观察代价函数只留下了第二项,因为第一项被消除了。如果当y = 0 时,那么这一项也就是0了。所以上述表达式只留下了第二项。因此,这个样本的代价或是代价函数的贡献。将会由这一项表示。并且,如果你将这一项作为z 的函数,那么,这里就会得到横轴z 。现在,你完成了支持向量机中的部分内容,同样地,我们要替代这一条蓝色的线,用相似的方法。
如果我们用一个新的代价函数来代替,即这条从0点开始的水平直线,然后是一条斜线,像上图。那么,现在让我给这两个方程命名,左边的函数,我称之为,同时,右边函数我称它为。这里的下标是指在代价函数中,对应的 y = 1 和 y = 0的情况,拥有了这些定义后,现在,我们就开始构建支持向量机。
这是我们在逻辑回归中使用代价函数 。也许这个方程看起来不是非常熟悉。这是因为之前有个负号在方程外面,但是,这里我所做的是,将负号移到了表达式的里面,这样做使得方程看起来有些不同。对于支持向量机而言,实质上我们要将这替换为,也就是,同样地,我也将这一项替换为,也就是代价。这里的代价函数 ,就是之前所提到的那条线。此外,代价函数,也是上面所介绍过的那条线。因此,对于支持向量机,我们得到了这里的最小化问题,即:
然后,再加上正则化参数。现在,按照支持向量机的惯例,事实上,我们的书写会稍微有些不同,代价函数的参数表示也会稍微有些不同。
首先,我们要除去1 / m 这一项,当然,这仅仅是由于人们使用支持向量机时,对比于逻辑回归而言,不同的习惯所致,但这里我所说的意思是:你知道,我将要做的是仅仅除去这1 / m 一项,但是,这也会得出同样的θ 最优值,好的,因为1 / m 仅是个常量,因此,你知道在这个最小化问题中,无论前面是否有1 / m 这一项,最终我所得到的最优值 θ 都是一样的。这里我的意思是,先给你举一个样本,假定有一最小化问题:即要求当取得最小值时的值 u ,这时最小值为:当u = 5 时取得最小值。
现在,如果我们想要将这个目标函数乘上常数10,这里我的最小化问题就变成了:求使得最小的值,然而,使得这里最小的值仍为5。因此将一些常数乘以你的最小化项,这并不会改变最小化该方程时得到 u 值。因此,这里我所做的是删去常量 m 。也相同的,我将目标函数乘上一个常量 m ,并不会改变取得最小值时的 θ 值。
第二点概念上的变化,我们只是指在使用支持向量机时,一些如下的标准惯例,而不是逻辑回归。因此,对于逻辑回归,在目标函数中,我们有两项:第一个是训练样本的代价,第二个是我们的正则化项,我们不得不去用这一项来平衡。这就相当于我们想要最小化 A 加上正则化参数 λ ,然后乘以其他项对吧?这里 A 的表示这里的第一项,同时我用 B 表示第二项,但不包括 λ ,我们不是优化这里 的。我们所做的是通过设置不同正则参数 λ 达到优化目的。这样,我们就能够权衡对应的项,是使得训练样本拟合的更好。即最小化 A 。还是保证正则参数足够小,也即是对于B项而言,但对于支持向量机,按照惯例,我们将使用一个不同的参数替换这里使用的 λ 来权衡这两项。你知道,就是第一项和第二项我们依照惯例使用一个不同的参数称为 C CC ,同时改为优化目标, 。 因此,在逻辑回归中,如果给定 λ,一个非常大的值,意味着给予 B 更大的权重。而这里,就对应于将 C 设定为非常小的值,那么,相应的将会给 B 比 A 给更大的权重。因此,这只是一种不同的方式来控制这种权衡或者一种不同的方法,即用参数 来决定是更关心第一项的优化,还是更关心第二项的优化。当然你也可以把这里的参数 C 考虑成 1 / λ ,同 1 / λ所扮演的角色相同,并且这两个方程或这两个表达式并不相同,因为C = 1 / λ ,但是也并不全是这样,如果当C = 1 / λ 时,这两个优化目标应当得到相同的值,相同的最优值 θ 。因此,就用它们来代替。那么,我现在删掉这里的λ ,并且用常数来代替C 。因此,这就得到了在支持向量机中我们的整个优化目标函数。然后最小化这个目标函数,得到SVM 学习到的参数C 。
最后有别于逻辑回归输出的概率。在这里,我们的代价函数,当最小化代价函数,获得参数时,支持向量机所做的是它来直接预测的值等于1,还是等于0。因此,这个假设函数会预测1。当大于或者等于0时,或者等于0时,所以学习参数就是支持向量机假设函数的形式。那么,这就是支持向量机数学上的定义。
在接下来的视频中,让我们再回去从直观的角度看看优化目标,实际上是在做什么,以及SVM的假设函数将会学习什么,同时也会谈谈如何做些许修改,学习更加复杂、非线性的函数。
12.2 大边界的直观理解
人们有时将支持向量机看作是大间距分类器。在这一部分,我将介绍其中的含义,这有助于我们直观理解SVM模型的假设是什么样的。
这是我的支持向量机模型的代价函数,在左边这里我画出了 z zz 关于 的代价函数,此函数用于正样本,而在右边这里我画出了 z 关于的代价函数,横轴表示,现在让我们考虑一下,最小化这些代价函数的必要条件是什么。如果你有一个正样本,y = 1,则只有在时 z ≥ 1 ,代价函数才等于0(即完全拟合)。
换句话说,如果你有一个正样本,我们会希望,反之 y = 0 ,如果,我们观察一下, 函数,它只有 z ≤ − 1 在的区间里函数值为0。这是支持向量机的一个有趣性质。事实上,如果你有一个正样本 y = 1 ,则其实我们仅仅要求 大于等于0,就能将该样本恰当分出,这是因为如果的话,我们的模型代价函数值为0,类似地,如果你有一个负样本,则仅需要 就会将负例正确分离,但是,支持向量机的要求更高,不仅仅要能正确分开输入的样本,即不仅仅要求≥0,我们需要的是比0值大很多,比如大于等于1,我也想这个比0小很多,比如我希望它小于等于-1,这就相当于在支持向量机中嵌入了一个额外的安全因子,或者说安全的间距因子。
当然,逻辑回归做了类似的事情。但是让我们看一下,在支持向量机中,这个因子会导致什么结果。具体而言,我接下来会考虑一个特例。我们将这个常数设置成一个非常大的值。比如我们假设的值为100000或者其它非常大的数,然后来观察支持向量机会给出什么结果?
如果 C 非常大,则最小化代价函数的时候,我们将会很希望找到一个使第一项为0的最优解。因此,让我们尝试在代价项的第一项为0的情形下理解该优化问题。比如我们可以把 C设置成了非常大的常数,这将给我们一些关于支持向量机模型的直观感受。
我们已经看到输入一个训练样本标签为 y = 1 ,你想令第一项为0,你需要做的是找到一个θ ,使得,类似地,对于一个训练样本,标签为y = 0 ,为了使函数的值为0,我们需要。因此,现在考虑我们的优化问题。选择参数,使得第一项等于0,就会导致下面的优化问题,因为我们将选择参数使第一项为0,因此这个函数的第一项为0,因此是 C CC 乘以0加上二分之一乘以第二项。这里第一项是乘以0,因此可以将其删去,因为我知道它是0。
这将遵从以下的约束: 如果 是等于1 的,则 如果样本是一个负样本,即是等于0,则 这样当你求解这个优化问题的时候,当你最小化这个关于变量的函数的时候,你会得到一个非常有趣的决策边界。
具体而言,如果你考察这样一个数据集,其中有正样本,也有负样本,可以看到这个数据集是线性可分的。我的意思是,存在一条直线把正负样本分开。当然有多条不同的直线,可以把正样本和负样本完全分开。
比如,这就是一个决策边界可以把正样本和负样本分开。但是多多少少这个看起来并不是非常自然是么?
或者我们可以画一条更差的决策界,这是另一条决策边界,可以将正样本和负样本分开,但仅仅是勉强分开,这些决策边界看起来都不是特别好的选择,支持向量机将会选择这个黑色的决策边界,相较于之前我用粉色或者绿色画的决策界。这条黑色的看起来好得多,黑线看起来是更稳健的决策界。在分离正样本和负样本上它显得的更好。数学上来讲,这是什么意思呢?这条黑线有更大的距离,这个距离叫做间距(margin)。
当画出这两条额外的蓝线,我们看到黑色的决策界和训练样本之间有更大的最短距离。然而粉线和蓝线离训练样本就非常近,在分离样本的时候就会比黑线表现差。因此,这个距离叫做支持向量机的间距,而这是支持向量机具有鲁棒性的原因,因为它努力用一个最大间距来分离样本。因此支持向量机有时被称为大间距分类器,而这其实是求解上一页幻灯片上优化问题的结果。
我知道你也许想知道求解上一页幻灯片中的优化问题为什么会产生这个结果?它是如何产生这个大间距分类器的呢?我知道我还没有解释这一点。
我将会从直观上略述为什么这个优化问题会产生大间距分类器。总之这个图示有助于你理解支持向量机模型的做法,即努力将正样本和负样本用最大的间距分开。
在本节课中关于大间距分类器,我想讲最后一点:我们将这个大间距分类器中的正则化因子常数 C设置的非常大,我记得我将其设置为了100000,因此对这样的一个数据集,也许我们将选择这样的决策界,从而最大间距地分离开正样本和负样本。那么在让代价函数最小化的过程中,我们希望找出在y = 1 和y = 0两种情况下都使得代价函数中左边的这一项尽量为零的参数。如果我们找到了这样的参数,则我们的最小化问题便转变成:
事实上,支持向量机现在要比这个大间距分类器所体现得更成熟,尤其是当你使用大间距分类器的时候,你的学习算法会特别受异常点(outlier) 的影响。比如我们加入一个额外的正样本。
在这里,如果你加了这个样本,为了将样本用最大间距分开,也许我最终会得到一条类似这样的决策界,对么?就是这条粉色的线,仅仅基于一个异常值,仅仅基于一个样本,就将我的决策界从这条黑线变到这条粉线(相当于过拟合),这实在是不明智的。而如果正则化参数,设置的非常大,这事实上正是支持向量机将会做的。它将决策界,从黑线变到了粉线,但是如果 设置的小一点,如果你将C设置的不要太大,则你最终会得到这条黑线, 然数据如果不是线性可分的,如果你在这里有一些正样本或者你在这里有一些负样本,则支持向量机也会将它们恰当分开。因此,大间距分类器的描述,仅仅是从直观上给出了正则化参数非常大的情形,同时,要提醒你的作用类似于,是我们之前使用过的正则化参数。这只是非常大的情形,或者等价地 非常小的情形。你最终会得到类似粉线这样的决策界,但是实际上应用支持向量机的时候,当不是非常非常大的时候,它可以忽略掉一些异常点的影响,得到更好的决策界。 至当你的数据不是线性可分的时候,支持向量机也可以给出好的结果。
回顾 C = 1 / λ ,因此:
C 较大时,相当于 λ 较小,可能会导致过拟合,高方差。
C 较小时,相当于 λ 较大,可能会导致低拟合,高偏差。
我们稍后会介绍支持向量机的偏差和方差,希望在那时候关于如何处理参数的这种平衡会变得更加清晰。我希望,这节课给出了一些关于为什么支持向量机被看做大间距分类器的直观理解。它用最大间距将样本区分开,尽管从技术上讲,这只有当参数C 非常大的时候是真的,但是它对于理解支持向量机是有益的。
本节课中我们略去了一步,那就是我们在幻灯片中给出的优化问题。为什么会是这样的?它是如何得出大间距分类器的?我在本节中没有讲解,在下一节课中,我将略述这些问题背后的数学原理,来解释这个优化问题是如何得到一个大间距分类器的。
12.4 核函数1
回顾我们之前讨论过可以使用高级数的多项式模型来解决无法用直线进行分隔的分类问题:
为了获得上图所示的判定边界,我们的模型可能是
的形式。
我们可以用一系列的新的特征来替换模型中的每一项。例如令: 得到$h_θ(x)=θ_1f_1+θ_2f_2+...+θ_nf_n。然而,除了对原有的特征进行组合以外,有没有更好的方法来构造?我们可以利用核函数来计算出新的特征。
给定一个训练样本,我们利用的各个特征与我们预先选定的地标(landmarks)的近似程度来选取新的特征。
例如:
其中:,为实例中所有特征与地标之间的距离的和。上例中的就是核函数,具体而言,这里是一个高斯核函数(Gaussian Kernel)。 注:这个函数与正态分布没什么实际上的关系,只是看上去像而已。
这些地标的作用是什么?如果一个训练样本x 与地标l 之间的距离近似于0,则新特征 f 近似于,如果训练样本与地标之间距离较远,则近似于一个较大的数。
假设我们的训练样本含有两个特征 ,给定地标与不同的α值,见下图:
图中水平面的坐标为 而垂直坐标轴代表f 。可以看出,只有当x 与 重合时f 才具有最大值。随着x 的改变值改变f 的速率受到的控制。
在下图中,当样本处于洋红色的点位置处,因为其离更近,但是离和较远,因此接近1,而 ,接近0。因此,因此预测。同理可以求出,对于离较近的绿色点,也预测y = 1,但是对于蓝绿色的点,因为其离三个地标都较远,预测y = 0
这样,图中红色的封闭曲线所表示的范围,便是我们依据一个单一的训练样本和我们选取的地标所得出的判定边界,在预测时,我们采用的特征不是训练样本本身的特征,而是通过核函数计算出的新特征。
12.5 核函数2
我们讨论了核函数这个想法,以及怎样利用它去实现支持向量机的一些新特性。在这一节视频中,我将补充一些缺失的细节,并简单的介绍一下怎么在实际中使用应用这些想法。
如何选择地标?
我们通常是根据训练集的数量选择地标的数量,即如果训练集中有个样本,则我们选取个地标,并且令:。这样做的好处在于:现在我们得到的新特征是建立在原有特征与训练集中所有其他特征之间距离的基础之上的,即:
下面我们将核函数运用到支持向量机中,修改我们的支持向量机假设为:
给定x ,计算新特征f ,当 时,预测 y = 1 ,否则反之。
相应地修改代价函数为:
在具体实施过程中,我们还需要对最后的正则化项进行些微调整,在计算时,我们用代替,其中是根据我们选择的核函数而不同的一个矩阵。这样做的原因是为了简化计算(只是为了缩短计算时长)。
理论上讲,我们也可以在逻辑回归中使用核函数,但是上面使用 来简化计算的方法不适用与逻辑回归,因此计算将非常耗费时间。
在此,我们不介绍最小化支持向量机的代价函数的方法,你可以使用现有的软件包(如liblinear,libsvm等)。在使用这些软件包最小化我们的代价函数之前,我们通常需要编写核函数,并且如果我们使用高斯核函数,那么在使用之前进行特征缩放是非常必要的。
另外,支持向量机也可以不使用核函数,不使用核函数又称为线性核函数(linear kernel),当我们不采用非常复杂的函数,或者我们的训练集特征非常多而样本非常少的时候,可以采用这种不带核函数的支持向量机。
下面是支持向量机的两个参数和的影响:
12.6 使用支持向量机
目前为止,我们已经讨论了SVM比较抽象的层面,在这个视频中我将要讨论到为了运行或者运用SVM,你实际上所需要的一些东西、
支持向量机算法,提出了一个特别优化的问题。但是就如在之前的视频中我简单提到的,我真的不建议你自己写软件来求解参数,因此由于今天我们中的很少人,或者其实没有人考虑过自己写代码来转换矩阵,或求一个数的平方根等我们只是知道如何去调用库函数来实现这些功能。
同样的,用以解决SVM最优化问题的软件很复杂,且已经有研究者做了很多年数值优化了。因此你提出好的软件库和好的软件包来做这样一些事儿。然后强烈建议使用高优化软件库中的一个,而不是尝试自己落实一些数据。有许多好的软件库,我正好用得最多的两个是liblinear和libsvm,但是真的有很多软件库可以用来做这件事儿。你可以连接许多你可能会用来编写学习算法的主要编程语言。
在高斯核函数之外我们还有其他一些选择,如:
多项式核函数(Polynomial Kernel)
字符串核函数(String kernel)
卡方核函数( chi-square kernel)
直方图交集核函数(histogram intersection kernel)
等等…
这些核函数的目标也都是根据训练集和地标之间的距离来构建新特征,这些核函数需要满足Mercer’s定理,才能被支持向量机的优化软件正确处理。
即使上面的SVM优化软件你可以不用自己去写,但有几件事,是要我们自己做的
-
选择参数C
-
选择内核参数或相似函数
- 其中有一种函数不需要任何内核参数,只是用了来预测,这种函数叫做线性核函数,相当于一个标准的线性分类器,这常常会用在(特征值很多,但训练量很小,那么就希望有一个比较简单的判定边界,因为如何用一个很复杂的函数来预测的话,很可能会过拟合,所以才用一个没有内核参数的线性核函数)
- 也可以构建一个高斯内核函数,这也是之前几节课介绍的,这个就需要选择一个参数 (也就是用来权衡方差和偏差)
当 过大的时候,就会较大的方差,较小的偏差
当 过小的时候,就会较小的方差,较大的偏差
一般用于特征值较少,但数据量比较大的时候,这时候就需要更加贴切的判定边界。
多类分类问题
假设我们利用之前介绍的一对多方法来解决一个多类分类问题。如果一共有个类,则我们需要个模型,以及个参数向量。我们同样也可以训练个支持向量机来解决多类分类问题。但是大多数支持向量机软件包都有内置的多类分类功能,我们只要直接使用即可。
从逻辑回归模型,我们得到了支持向量机模型,在两者之间,我们应该如何选择呢?
下面是一些普遍使用的准则:
n nn为特征数,m mm为训练样本数。
(1)如果相较于m mm而言,n nn要大许多,即训练集数据量不够支持我们训练一个复杂的非线性模型,我们选用逻辑回归模型或者不带核函数的支持向量机。
(2)如果n nn较小,而且m mm大小中等,例如n nn在 1-1000 之间,而m mm在10-10000之间,使用高斯核函数的支持向量机。
(3)如果n nn较小,而m mm较大,例如n nn在1-1000之间,而m mm大于50000,则使用支持向量机会非常慢,解决方案是创造、增加更多的特征,然后使用逻辑回归或不带核函数的支持向量机。
值得一提的是,神经网络在以上三种情况下都可能会有较好的表现,但是训练神经网络可能非常慢,选择支持向量机的原因主要在于它的代价函数是凸函数,不存在局部最小值。
今天的SVM包会工作得很好,但是它们仍然会有一些慢。当你有非常非常大的训练集,且用高斯核函数是在这种情况下,我经常会做的是尝试手动地创建,拥有更多的特征变量,然后用逻辑回归或者不带核函数的支持向量机。如果你看到这个幻灯片,看到了逻辑回归,或者不带核函数的支持向量机。在这个两个地方,我把它们放在一起是有原因的。原因是:逻辑回归和不带核函数的支持向量机它们都是非常相似的算法,不管是逻辑回归还是不带核函数的SVM,通常都会做相似的事情,并给出相似的结果。但是根据你实现的情况,其中一个可能会比另一个更加有效。但是在其中一个算法应用的地方,逻辑回归或不带核函数的SVM另一个也很有可能很有效。但是随着SVM的复杂度增加,当你使用不同的内核函数来学习复杂的非线性函数时,这个体系,你知道的,当你有多达1万(10,000)的样本时,也可能是5万(50,000),你的特征变量的数量这是相当大的。那是一个非常常见的体系,也许在这个体系里,不带核函数的支持向量机就会表现得相当突出。你可以做比这困难得多需要逻辑回归的事情。
最后,神经网络使用于什么时候呢? 对于所有的这些问题,对于所有的这些不同体系一个设计得很好的神经网络也很有可能会非常有效。有一个缺点是,或者说是有时可能不会使用神经网络的原因是:对于许多这样的问题,神经网络训练起来可能会特别慢,但是如果你有一个非常好的SVM实现包,它可能会运行得比较快比神经网络快很多,尽管我们在此之前没有展示,但是事实证明,SVM具有的优化问题,是一种凸优化问题。因此,好的SVM优化软件包总是会找到全局最小值,或者接近它的值。对于SVM你不需要担心局部最优。在实际应用中,局部最优不是神经网络所需要解决的一个重大问题,所以这是你在使用SVM的时候不需要太去担心的一个问题。根据你的问题,神经网络可能会比SVM慢,尤其是在这样一个体系中,至于这里给出的参考,看上去有些模糊,如果你在考虑一些问题,这些参考会有一些模糊,但是我仍然不能完全确定,我是该用这个算法还是改用那个算法,这个没有太大关系,当我遇到机器学习问题的时候,有时它确实不清楚这是否是最好的算法,但是就如在之前的视频中看到的算法确实很重要。但是通常更加重要的是:你有多少数据,你有多熟练是否擅长做误差分析和排除学习算法,指出如何设定新的特征变量和找出其他能决定你学习算法的变量等方面,通常这些方面会比你使用逻辑回归还是SVM这方面更加重要。但是,已经说过了,SVM仍然被广泛认为是一种最强大的学习算法,这是一个体系,包含了什么时候一个有效的方法去学习复杂的非线性函数。因此,实际上与逻辑回归、神经网络、SVM一起使用这些方法来提高学习算法,我认为你会很好地建立很有技术的状态。(编者注:当时GPU计算比较慢,神经网络还不流行。)
机器学习系统对于一个宽泛的应用领域来说,这是另一个在你军械库里非常强大的工具,你可以把它应用到很多地方,如硅谷、在工业、学术等领域建立许多高性能的机器学习系统。
13.聚类(Clustering)
13.1 无监督学习:简介
无监督学习中,我们的数据没有附带任何标签,我们拿到的数据就是这样的:
我们有一系列点,却没有标签。因此,我们的训练集可以写成只有一直到,没有任何标签 。我们需要将一系列无标签的训练数据,输入到一个算法中,让这个算法为我们找找这个数据的内在结构。图上的数据看起来可以分成两个分开的点集(称为簇),一个能够找到我圈出的这些点集的算法,就被称为聚类算法,这将是我们介绍的第一个非监督学习算法。聚类算法可以用来:
13.2 K-均值算法
K-均值是最普及的聚类算法,算法接受一个未标记的数据集,然后将数据聚类成不同的组。K-均值是一个迭代算法,假设我们想要将数据聚类成n个组,其方法为:
首先选择K 个随机的点,称为聚类中心(cluster centroids);
对于数据集中的每一个数据,按照距离K 个中心点的距离,将其与距离最近的中心点关联起来,与同一个中心点关联的所有点聚成一类。
计算每一个组的平均值,将该组所关联的中心点移动到平均值的位置。
重复步骤直至中心点不再变化。
下面是一个聚类示例:
13.3 优化目标
心的索引。算法分为两个步骤,第一个for循环是赋值步骤,即:对于每一个样例i ,计算其应该属于的类。第二个for循环是聚类中心的移动,即:对于每一个类K ,重新计算该类的质心。K-均值最小化问题,是要最小化所有的数据点与其所关联的聚类中心点之间的距离之和,因此 K-均值的代价函数(又称畸变函数 Distortion function)为:
我们知道,第一个循环是用于减小 引起的代价,而第二个循环则是用于减小引起的代价。迭代的过程一定会是每一次迭代都在减小代价函数,不然便是出现了错误。
13.4 随机初始化
随机初始化所有的聚类中心点:
- 我们应该选择K<m ,即聚类中心点的个数要小于所有训练集实例的数量
- 随机选择K 个训练实例,然后令K 个聚类中心分别与这K 个训练实例相等
K-均值的一个问题在于,它有可能会停留在一个局部最小值处,而这取决于初始化的情况。为了解决这个问题,我们通常需要多次运行算法,每一次都重新进行随机初始化,最后再比较多次运行的结果,选择代价函数最小的结果。这种方法在K 较小的时候(2--10)还是可行的,但是如果K 较大,这么做也可能不会有明显地改善。
13.5 选择聚类数
没有所谓最好的选择聚类数的方法,通常是需要根据不同的问题,人工进行选择的,选择时思考运用算法聚类的动机是什么。选择聚类数目的方法时,有一个可能会谈及的方法叫作 “肘部法则” ,我们所需要做的是改变 K 值,也就是聚类类别数目的总数。
曲线的肘点,畸变值下降得很快,那么使用3个聚类来进行聚类是正确的。
14.降维(Dimensionality Reduction)
14.1 动机一:数据压缩(Motivation I_ Data Compression)
第二种类型的无监督学习问题,称为降维。有几个不同的的原因使你可能想要做降维,一是数据压缩。数据压缩不仅允许我们压缩数据,因而使用较少的计算机内存或磁盘空间,也可以加快我们的学习算法。降维是什么?例子:我们收集的数据集有许多特征,我绘制两个在这里。
假设我们未知两个的特征(长度):x1:用厘米表示;x2:用英寸表示同一物体的长度。这给了我们高度冗余表示,我们想要做的是减少数据到一维,只有一个数据测量这个长度。
14.2 动机二:数据可视化( Motivation II_ Visualization)
在许多及其学习问题中,如果我们能将数据可视化,我们便能寻找到一个更好的解决方案,降维可以帮助我们。
假使我们有有关于许多不同国家的数据,每一个特征向量都有50个特征(如GDP,人均GDP,平均寿命等)。如果要将这个50维的数据可视化是不可能的。使用降维的方法将其降至2维,我们便可以将其可视化了。
这样做的问题在于,降维的算法只负责减少维数,新产生的特征的意义就必须由我们自己去发现了。
14.3 主成分分析问题(Principal Component Analysis Problem Formulation)
主成分分析(PCA) 是最常见的降维算法。在PCA中,我们要做的是找到一个方向向量(Vector direction),当我们把所有的数据都投射到该向量上时,我们希望投射平均均方误差能尽可能地小。方向向量是一个经过原点的向量,而投射误差是从特征向量向该方向向量作垂线的长度。
将 n维数据降至 k维,进行数据压缩,目标是找到向量, ,..., 使得总的投射误差最小,如果100维的向量最后可以用10维来表示,那么压缩率为90%。主成分分析与线性回归是两种不同的算法。主成分分析最小化的是投射误差(Projected Error),而线性回归尝试的是最小化预测误差。线性回归的目的是预测结果,而主成分分析不作任何预测。
上图中,左边的是线性回归的误差(垂直于横轴投影),右边则是主要成分分析的误差(垂直于红线投影)。图像处理领域的KL变换使用PCA做图像压缩。但PCA 要保证降维后,还要保证数据的特性损失最小。
PCA技术的一大好处是对数据进行降维的处理。我们可以对新求出的“主元”向量的重要性进行排序,根据需要取前面最重要的部分,将后面的维数省去,可以达到降维从而简化模型或是对数据进行压缩的效果,同时最大程度的保持了原有数据的信息。
PCA技术的一个很大的优点是,它是完全无参数限制的。在PCA的计算过程中完全不需要人为的设定参数或是根据任何经验模型对计算进行干预,最后的结果只与数据相关,与用户是独立的。但是,这一点同时也可以看作是缺点。如果用户对观测对象有一定的先验知识,掌握了数据的一些特征,却无法通过参数化等方法对处理过程进行干预,可能会得不到预期的效果,效率也不高。
14.4 主成分分析算法
减少n 维到k 维:
(1)均值归一化。我们需要计算出所有特征的均值μj ,然后令 xj=xj-μj 。如果特征是在不同的数量级上,我们还需要将其除以标准差 σ2 。
(2)计算协方差矩阵(covariance matrix):
(3)计算协方差矩阵的特征向量(eigenvectors)。利用奇异值分解(singular value decomposition)来求解[U, S, V]。
对于一个 维度的矩阵,上式中的 U是一个具有与数据之间最小投射误差的方向向量构成的矩阵。如果我们希望将数据从 n维降至 k维,我们只需要从 U中选取前 k个向量,获得一个n×k维度的矩阵,通过 计算获得要求的新特征向量,其中x 是n×1 维的,因此结果为k×1 维度。注,我们不对方差特征进行处理。
14.5 选择主成分的数量
主要成分分析是减少投射的平均均方误差:,训练集的方差为:平均均方误差与训练集方差的比例:,我们希望在平均均方误差与训练集方差的比例尽可能小的情况下选择尽可能小的k 值。如果我们希望这个比例小于1%,就意味着原本数据的偏差有99%都保留下来了,也能显著地降低模型中特征的维度。可以先令k=1 ,然后进行主要成分分析,获得Ureduce 和z ,然后计算比例是否小于1%。如果不是的话再令k=2 ,如此类推,直到找到可以使得比例小于1%的最小k 值(原因是各个特征之间通常情况存在某种相关性)。
14.6 重建压缩表示
压缩表示回到原有的近似高维数据。给定的,可能100维,怎么回到原来的表示x (i) ,可能是1000维的数组?
相反的方程为: 。所以,给定未标记的数据集,应用PCA,低维表示z可以映射到高维特征x。
14.7 主成分分析法的应用建议
假设我们正在针对一张 100×100像素的图片进行某个计算机视觉的机器学习,即总共有10000 个特征。
-
第一步是运用主要成分分析将数据压缩至1000个特征
-
然后对训练集运行学习算法。
-
在预测时,采用之前学习而来的,将输入的特征x 转换成特征向量z ,然后再进行预测
注:如果我们有交叉验证集合测试集,也采用对训练集学习而来的。
错误的主要成分分析情况: (1)将其用于减少过拟合(减少了特征的数量)。这样做非常不好,不如尝试正则化处理。原因在于主要成分分析只是近似地丢弃掉一些特征,它并不考虑任何与结果变量有关的信息,因此可能会丢失非常重要的特征。然而当我们进行正则化处理时,会考虑到结果变量,不会丢掉重要的数据。
(2)默认地将主要成分分析作为学习过程中的一部分。虽然很多时候有效果,最好还是从所有原始特征开始,只在有必要的时候(算法运行太慢或者占用太多内存)才考虑采用主要成分分析。
15.异常检测(Anomaly Detection)
15.1 问题的动机
介绍异常检测(Anomaly detection)问题。这是机器学习算法的一个常见应用。这种算法的一个有趣之处在于:它虽然主要用于非监督学习问题,但从某些角度看,它又类似于一些监督学习问题。
什么是异常检测呢?为了解释这个概念,让我举一个例子吧:
假想你是一个飞机引擎制造商,当你生产的飞机引擎从生产线上流出时,你需要进行QA(质量控制测试),而作为这个测试的一部分,你测量了飞机引擎的一些特征变量,比如引擎运转时产生的热量,或者引擎的振动等等。
这样一来,你就有了一个数据集,从
到
,如果你生产了m 个引擎的话,你将这些数据绘制成图表,看起来就是这个样子:
这里的每个点、每个叉,都是你的无标签数据。这样,异常检测问题可以定义如下:我们假设后来有一天,你有一个新的飞机引擎从生产线上流出,而你的新飞机引擎有特征变量x_{test}。所谓的异常检测问题就是:我们希望知道这个新的飞机引擎是否有某种异常,或者说,我们希望判断这个引擎是否需要进一步测试。因为,如果它看起来像一个正常的引擎,那么我们可以直接将它运送到客户那里,而不需要进一步的测试。
给定数据集,,...,我们假使数据集是正常的,我们希望知道新的数据是不是异常的,即这个测试数据不属于该组数据的几率如何。我们所构建的模型应该能根据该测试数据的位置告诉我们其属于一组数据的可能性p(x) 。
上图中,在蓝色圈内的数据属于该组数据的可能性较高,而越是偏远的数据,其属于该组数据的可能性就越低。
这种方法称为密度估计,表达如下:
欺诈检测:
= 用户的第i个活动特征 模型p(x)为我们其属于一组数据的可能性,通过 检测非正常用户。
异常检测主要用来识别欺骗。例如在线采集而来的有关用户的数据,一个特征向量中可能会包含如:用户多久登录一次,访问过的页面,在论坛发布的帖子数量,甚至是打字速度等。尝试根据这些特征构建一个模型,可以用这个模型来识别那些不符合该模式的用户。
再一个例子是检测一个数据中心,特征可能包含:内存使用情况,被访问的磁盘数量,CPU的负载,网络的通信量等。根据这些特征可以构建一个模型,用来判断某些计算机是不是有可能出错了。
15.2 高斯分布
回顾高斯分布的基本知识。
通常如果我们认为变量x符合高斯分布
则其概率密度函数为:
我们可以利用已有的数据来预测总体中的和的计算方法如下:
高斯分布样例:
注:机器学习中对于方差我们通常只除以m 而非统计学中的m-1。 这里顺便提一下,在实际使用中,到底是选择使用1/m还是1/(m-1)其实区别很小,只要你有一个还算大的训练集,在机器学习领域大部分人更习惯使用 1/m 这个版本的公式。这两个版本的公式在理论特性和数学特性上稍有不同,但是在实际使用中,他们的区别甚小,几乎可以忽略不计。
15.3 算法
我将应用高斯分布开发异常检测算法。
异常检测算法:
对于给定的数据集,我们要针对每一个特征计算μ和的估计值。
一旦我们获得了平均值和方差的估计值,给定新的一个训练实例,根据模型计算 :
当时,为异常。
下图是一个由两个特征的训练集,以及特征的分布情况:
下面的三维图表表示的是密度估计函数,轴为根据两个特征的值所估计值:
我们选择一个ϵ ,将p(x) = ϵ 作为我们的判定边界,当 p(x) > ϵ 时预测数据为正常数据,否则为异常。
在这段视频中,我们介绍了如何拟合p(x),也就是 x的概率值,以开发出一种异常检测算法。同时,在这节课中,我们也给出了通过给出的数据集拟合参数,进行参数估计,得到参数 ϵ 和μ ,然后检测新的样本,确定新样本是否是异常。
在接下来的课程中,我们将深入研究这一算法,同时更深入地介绍,怎样让算法工作地更加有效。
15.4 开发和评价一个异常检测系统
异常检测算法是一个非监督学习算法,意味着我们无法根据结果变量 y yy 的值来告诉我们数据是否真的是异常的。我们需要另一种方法来帮助检验算法是否有效。当我们开发一个异常检测系统时,我们从带标记(异常或正常)的数据着手,我们从其中选择一部分正常数据用于构建训练集,然后用剩下的正常数据和异常数据混合的数据构成交叉检验集和测试集。
例如:我们有10000台正常引擎的数据,有20台异常引擎的数据。 我们这样分配数据:
6000台正常引擎的数据作为训练集
2000台正常引擎和10台异常引擎的数据作为交叉检验集
2000台正常引擎和10台异常引擎的数据作为测试集
具体的评价方法如下:
- 根据测试集数据,我们估计特征的平均值和方差并构建p(x)函数
- 对交叉检验集,我们尝试使用不同的ϵ 值作为阀值,并预测数据是否异常,根据F1值或者查准率与查全率的比例来选择ϵ
- 选出 ϵ 后,针对测试集进行预测,计算异常检验系统的F1值,或者查准率与查全率之比
15.5 异常检测与监督学习对比
之前我们构建的异常检测系统也使用了带标记的数据,与监督学习有些相似,下面的对比有助于选择采用监督学习还是异常检测:
两者比较:
-
异常检测:
- 非常少量的异常数据,大量的正常数据
- 有多种异常类型,甚至有些没见过
-
监督学习:
- 大量异常数据和正常数据(同等量级)
- 大部分类型都遇到过
这节课能让你明白一个学习问题的什么样的特征,能让你把这个问题当做是一个异常检测,或者是一个监督学习的问题。另外,对于很多技术公司可能会遇到的一些问题,通常来说,正样本的数量很少,甚至有时候是0,也就是说,出现了太多没见过的不同的异常类型,那么对于这些问题,通常应该使用的算法就是异常检测算法。
15.6 选择特征
对于异常检测算法,我们使用的特征是至关重要的,下面谈谈如何选择特征:
异常检测假设特征符合高斯分布,如果数据的分布不是高斯分布,异常检测算法也能够工作,但是最好还是将数据转换成高斯分布,例如使用对数函数:x=log(x+c),其中 c 为非负常数;或者,c为0-1之间的一个分数,等方法。(注:在python中,通常用np.log1p()函数,log1p就是log(x+1) ,可以避免出现负数结果,反向函数就是np.expm1()
误差分析:
一个常见的问题是一些异常的数据可能也会有较高的值,因而被算法认为是正常的。这种情况下误差分析能够帮助我们,我们可以分析那些被算法错误预测为正常的数据,观察能否找出一些问题。我们可能能从问题中发现我们需要增加一些新的特征,增加这些新特征后获得的新算法能够帮助我们更好地进行异常检测。
异常检测误差分析:
如左图,若只有一个特征时,可能出现异常数据混迹在大量的正常数据中,而且对应的概率p(x)也很大,容易错误判定为正常数据。那么当我们找到这个异常数据的时候,我们就要对他进行观察对比,看是否能够找出其他特征(如右图的),再根据这个新的特征,进行新一轮异常检测(如右图),很明显刚刚那个异常会被特别容易的检测出来。
我们通常可以通过将一些相关的特征进行组合,来获得一些新的更好的特征(异常数据的该特征值异常地大或小),一般会选用一些不是特别大也不是特别小的特征。例如,在检测数据中心的计算机状况的例子中,我们可以用CPU负载与网络通信量的比例作为一个新的特征,如果该值异常地大,便有可能意味着该服务器是陷入了一些问题中。
在此,我们介绍了如何选择特征,以及对特征进行一些小小的转换,让数据更像正态分布,然后再把数据输入异常检测算法。同时也介绍了建立特征时,进行的误差分析方法,来捕捉各种异常的可能。希望你通过这些方法,能够了解如何选择好的特征变量,从而帮助你的异常检测算法,捕捉到各种不同的异常情况。
15.7 多元高斯分布
假使我们有两个相关的特征,而且这两个特征的值域范围比较宽,这种情况下,一般的高斯分布模型可能不能很好地识别异常数据。其原因在于,一般的高斯分布模型尝试的是去同时抓住两个特征的偏差,因此创造出一个比较大的判定边界。
下图中是两个相关特征,洋红色的线(根据ε的不同其范围可大可小)是一般的高斯分布模型获得的判定边界,很明显绿色的X所代表的数据点很可能是异常值,但是其值却仍然在正常范围内。多元高斯分布将创建像图中蓝色曲线所示的判定边界。
在一般的高斯分布模型中,我们计算 的方法是: 通过分别计算每个特征对应的几率然后将其累乘起来,在多元高斯分布模型中,我们将构建特征的协方差矩阵,用所有的特征一起来计算 。
我们首先计算所有特征的平均值,然后再计算协方差矩阵:
注:其中 μ 是一个向量,其每一个单元都是原特征矩阵中一行数据的均值。
最后我们计算多元高斯分布的:
其中:
上图是5个不同的模型,从左往右依次分析:
- 是一个一般的高斯分布模型
- 通过协方差矩阵,令特征1拥有较小的偏差,同时保持特征2的偏差
- 通过协方差矩阵,令特征2拥有较大的偏差,同时保持特征1的偏差
- 通过协方差矩阵,在不改变两个特征的原有偏差的基础上,增加两者之间的正相关性
- 通过协方差矩阵,在不改变两个特征的原有偏差的基础上,增加两者之间的负相关性
多元高斯分布模型与原高斯分布模型的关系:
可以证明的是,原本的高斯分布模型是多元高斯分布模型的一个子集,即像上图中的第1、2、3,3个例子所示,如果协方差矩阵只在对角线的单位上有非零的值时,即为原本的高斯分布模型了。
原高斯分布模型和多元高斯分布模型的比较:
原高斯分布模型被广泛使用着,如果特征之间在某种程度上存在相互关联的情况,我们可以通过构造新新特征的方法来捕捉这些相关性。
如果训练集不是太大,并且没有太多的特征,我们可以使用多元高斯分布模型。
15.8 使用多元高斯分布进行异常检测
关于多元高斯分布,看到的一些建立的各种分布模型,当你改变参数μ 和Σ用它们制定一个不同的异常检测算法。
要回顾一下多元高斯分布和多元正态分布:
分布有两个参数 Σ 和 μ 。其中 μ 这一个 n 维向量和 Σ的协方差矩阵,是一种 n×n 的矩阵。而这里的公式x 的概率 p(x),你可以通过改变参数 μ和 Σ得到一个范围的不同的分布。
因此,让我们谈谈参数拟合或参数估计问题:
假如我有一组样本是一个n维向量,我想我的样本来自一个多元高斯分布。我如何尝试估计我的参数 μ 和 Σ 以及标准公式?
对于估计参数,有一个标准公式,先设置μ μμ是你的训练样本的平均值。 并设置sigma:
这其实只是当我们使用PCA算法时候,写的Σ 是一样的,只需要把他拿出来代入到公式里就能得到估计参数μ 和参数Σ
那么,我们如何把所有这一切结合起来,共同开发一个异常检测算法?以下就是具体操作。
1.首先,用我们的数据集,来拟合模型,即通过设定μ 和Σ 来拟合p(x)
2.接下来当你有了一个新样本x,即一个测试样本(例如图中绿色的×),我们将这个样本x用下面p(x)这个多元高斯分布公式求出对应的p(x),然后判断p(x)<ϵ ?
如图,该分布在中央最多,越到外面的圈的范围越小。并在该点是出路这里的概率非常低。
原始模型与多元高斯模型的关系如图:
其中:协方差矩阵为:
原始模型和多元高斯分布比较如图:
- 原始模型可能需要通过已知的特征创建一个新的特征,例如之前举的例子:CPU负荷和内存使用情况都是正常的情况下,仍然可能发生异常,那么就需要创建 这个新特征,而多元高斯分布则会自动获取这种新特征(各个特征内部的关系)
- 原始模型最大的有点就是计算成本低,也就是能够适应巨大规模的n,例如n=10000,而多元高斯分布则需要求Σ,而Σ 是一个n×n维矩阵,那么计算成本就非常高。
- 原始模型即使m<n也可以运行,而多元高斯分布必须满足m>n(一般合理的使用原则:m≥10n)
注意:如果你在使用多元高斯分布的时候,发现Σ ΣΣ是一个奇异矩阵,即不可逆矩阵,那么有两种可能:
- 有可能你没有满足,m>n
- 有可能你存在冗余特征,例如两个相同的特征 ,或者不包含任何额外信息的特征
16.推荐系统(Recommender Systems)
16.1 问题规划
涉及推荐系统有两个原因:
第一、仅仅因为它是机器学习中的一个重要的应用。在过去几年,硅谷不同的技术公司,吴恩达老师常和工作在这儿致力于机器学习应用的人们聊天,问他们觉得最重要的机器学习的应用是什么,或者他们最想改进的机器学习应用有哪些。我最常听到的答案是推荐系统。现在,在硅谷有很多团体试图建立很好的推荐系统。因此,如果你考虑网站像亚马逊,或网飞公司或易趣,或iTunes Genius,有很多的网站或系统试图推荐新产品给用户。如亚马逊推荐新书给你,网飞公司试图推荐新电影给你,等等。这些推荐系统,根据浏览你过去买过什么书,或过去评价过什么电影来判断。这些系统会带来很大一部分收入,比如为亚马逊和像网飞这样的公司。因此,对推荐系统性能的改善,将对这些企业的有实质性和直接的影响。
推荐系统是个有趣的问题,在学术机器学习中因此,我们可以去参加一个学术机器学习会议,推荐系统问题实际上受到很少的关注,或者,至少在学术界它占了很小的份额。但是,如果你看正在发生的事情,许多有能力构建这些系统的科技企业,他们似乎在很多企业中占据很高的优先级。这是我为什么在这节课讨论它的原因之一。
我想讨论推荐系统地第二个原因是:这个班视频的最后几集我想讨论和分享机器学习中的一些大思想。这节课我们也看到了,对机器学习来说,特征是很重要的,你所选择的特征,将对你学习算法的性能有很大的影响。因此,在机器学习中有一种大思想,对于一些问题,算法可以为你自动学习一套好的特征。因此,不要试图手动设计,而手写代码这是目前为止我们常干的。有一些环境,能让你开发某个算法用来学习使用哪个特征,推荐系统就是这个环境的一个例子。还有很多其它的,但是通过推荐系统,我们将领略一小部分特征学习的思想,但至少,你将能够了解到这方面的一个例子,我认为,机器学习中的大思想也是这样。
接下来,我们举一个预测电影评分的例子,假使我们是一个电影供应商,我们有 5 部电影和 4 个用户,我们要求用户为电影打分。
前三部电影是爱情片,后两部则是动作片,我们可以看出Alice和Bob似乎更倾向与爱情片, 而 Carol 和 Dave 似乎更倾向与动作片。并且没有一个用户给所有的电影都打过分。我们希望构建一个算法来预测他们每个人可能会给他们没看过的电影打多少分,并以此作为推荐的依据。
下面引入一些标记:
- 代表用户的数量
- 代表电影的数量
- 如果用户 j 给电影 i 评过分则
- 代表用户 j给电影 i 的评分
- 代表用户 j 评过分的电影的总数
16.2 基于内容的推荐系统
上节课举了个例子:通过一些用户对一些电影的评价,借助算法预测他们对其他电影的评价。这节课我们将会介绍一种算法:基于内容的推荐算法。 在我们的例子中,我们可以假设每部电影都有两个特征,如代表电影的浪漫程度, 代表电影的动作程度。
则每部电影都有一个特征向量,如是第一部电影的特征向量为[0.9 0]。
下面我们要基于这些特征来构建一个推荐系统算法。 假设我们采用线性回归模型,我们可以针对每一个用户都训练一个线性回归模型,如是第一个用户的模型的参数。 于是,我们有:
用户 j 的参数向量
电影 i的特征向量
对于用户 j 和电影 i ,我们预测评分为:
代价函数
针对用户(对电影评分了的) ,该线性回归模型的代价为预测误差的平方和,加上正则化项:
其中 i:r(i,j) 表示我们只计算那些用户 j 评过分的电影。在一般的线性回归模型中,误差项和正则项应该都是乘以1/2m ,在这里我们将去掉m 。并且我们不对方差项进行正则化处理。
上面的代价函数只是针对一个用户的,为了学习所有用户,我们将所有用户的代价函数求和:
如果我们要用梯度下降法来求解最优解,我们计算代价函数的偏导数后得到梯度下降的更新公式为:
如果我们要用梯度下降法来求解最优解,我们计算代价函数的偏导数后得到梯度下降的更新公式为:
16.3 协同过滤
这节课我们要讲一种方法来构建推荐系统,叫协同过滤。这种算法有一个特性,叫做特征学习,这种算法可以自行的学习他所要使用的特征。
在之前的基于内容的推荐系统中,对于每一部电影,我们都掌握了可用的特征(通过用户的评价,得到每个电影的爱情和动作占比),但实际生活中,很难也很不现实的得到每个电影的这两个特征,何况每个电影也不只有两个特征,所以我们要如何通过其他方法获取这两个特征。
我们暂时把这个问题放一放。换一个问题,假设我们已经有每个用户对爱情片和动作片的评价,但却没有电影对于这两个特征的参数(用问号表示),如图
理论上,我们可以用上节课的内容,预测评分的公式: ,得到两个参数的值
然后我们可以继续举例,找出电影还有什么合适的特征(自动寻找特征) 让我们将这个例子,标准化到任意特征。 假设我们用户告诉了我们一系列爱好 ,我们想学习电影i ii的特征
所以我们需要把所用用户j 对电影i 的评价求和,来求出电影i的特征,也就是向量 ,其中还是老生常谈,要使的我们选择的特征能够使预测的评价和实际的评价误差最小,后面就是正则化。 总结: 尝试找出特征 ,这个参数能够是的所有用户j 对电影i 的预测评价与实际评价的误差最小。
而上述只是从一个电影学习到特征的方法,我们要学习所有电影所有的特征,所以加上求和。
总结一下: 1.在上节课,我们讲的的是,如果你有所有电影的评分合集,即 和 ,根据不同的特征 我们可以学习到参数 ,即从电影的特征推出用户的评价
- 而这节课讲的就是,我们拥有用户的评价,可以推出各种电影的特征值。
但是如果我们既没有用户的参数,也没有电影的特征,这两种方法都不可行了。协同过滤算法可以同时学习这两者。
通过以上两种方式,我们可以用θ 推出x ,再由x 推出θ ,依次迭代下去,知道我们可以拥有一组合理电影的特征值,以及一组对不同用户的参数的估计,这就是基本的协同过滤算法。
但我们不止局限于基本的协同过滤算法,我们还要对齐进行改进。
16.4 协同过滤算法
上节课我们讲到,如果给了你电影的特征值,可以学习用户的参数,如果给饿了你用户的参数,也可以用它们来学习电影的特征 。本节视频中,我们会把这些概念结合起来,得到协同过滤算法
协同过滤优化目标: 将上节课的两个方式结合在一起。求出x 和θ ,同时最小化,不需要来回折腾。
最后一件事:我们一般设定 ,再协同过滤算法中,我们不再需要
对代价函数求偏导数的结果如下:
注:在协同过滤从算法中,我们通常不使用方差项,如果需要的话,算法会自动学得。 协同过滤算法使用步骤如下:
- 初始 为一些随机小值
- 使用梯度下降算法最小化代价函数
- 在训练完算法后,我们预测 为用户 j 给电影 i 的评分
通过这个学习过程获得的特征矩阵包含了有关电影的重要数据,这些数据不总是人能读懂的,但是我们可以用这些数据作为给用户推荐电影的依据。
16.5 向量化:低秩矩阵分解
在上几节课程中,我们谈到了协同过滤算法,本节视频中我将会讲到有关该算法的向量化实现,以及说说有关该算法你可以做的其他事情。
举例子:
当给出一件产品时,你能否找到与之相关的其它产品。 一位用户最近看上一件产品,有没有其它相关的产品,你可以推荐给他。 我将要做的是:找到一种方法,写出协同过滤算法的预测情况。
我们有关于五部电影的数据集,我将要做的是,将这些用户的电影评分,分组并存到一个矩阵中。
我们有五部电影,以及四位用户,那么 这个矩阵 Y 就是一个5行4列的矩阵,它将这些电影的用户评分数据都存在矩阵里:
分组写入矩阵:
推出评分:
针对这个预测评分矩阵,我们有一个比较简单的或者向量化的方法来写出它们,比如说我定义矩阵X,如果我们再找到一个矩阵,用大写的Θ表示,每行都是一个用户的参数向量。即如图:
所以原预测评分矩阵,就可以由这两个矩阵表示 ,这就是一种向量化的表示,这种协同算法有另一个名字:低秩矩阵分解,这是一个线性代数里面的一个定义:矩阵 为低秩矩阵
找到相关影片:
现在既然你已经对特征参数向量进行了学习,那么我们就会有一个很方便的方法来度量两部电影之间的相似性。例如说:电影 i 有一个特征向量 ,你是否能找到一部不同的电影 j ,保证两部电影的特征向量之间的距离 和 很小,那就能很有力地表明电影 i 和电影 j 在某种程度上有相似,至少在某种意义上,某些人喜欢电影 i ,或许更有可能也对电影 j 感兴趣。总结一下,当用户在看某部电影 i 的时候,如果你想找5部与电影非常相似的电影,为了能给用户推荐5部新电影,你需要做的是找出电影 j,在这些不同的电影中与我们要找的电影 i 的距离最小,这样你就能给你的用户推荐几部不同的电影了。
例如,如果一位用户正在观看电影 ,我们可以寻找另一部电影 ,依据两部电影的特征向量之间的距离的大小。 通过这个方法,希望你能知道,如何进行一个向量化的计算来对所有的用户和所有的电影进行评分计算。同时希望你也能掌握,通过学习特征参数,来找到相关电影和产品的方法。
16.6 推行工作上的细节:均值归一化
让我们来看下面的用户评分数据:
如果我们新增一个用户 Eve,并且 Eve 没有为任何电影评分,那么我们以什么为依据为Eve推荐电影呢?
由上节课的内容,我们可以看出Eve没有对任何电影评价,那么公式前半部分就没有满足 r(i,j)=1 ,所以就不包括前半部分,那么后半部分实际上我们要看到就是 ,这部分的最小值,也就是令 ,那么评分公式 那么也就表明Eve对所有电影都打0分,这显然是不合理的。所以我们要借助均值归一化。
我们首先需要对结果 Y 矩阵进行均值归一化处理,将每一个用户对某一部电影的评分减去所有用户对该电影评分的平均值:
然后我们利用这个新的 Y 矩阵来训练算法。 如果我们要用新训练出的算法来预测评分,则需要将平均值重新加回去,预测 ,对于Eve,我们的新模型会认为她给每部电影的评分都是该电影的平均分。
所以在这个例子中,即使 ,但由于使用了均值归一化处理,那么我们就需要将平均值重新加回去。
17.大规模机器学习(Large Scale Machine Learning)
17.1 大型数据集的学习
接下来的课程,我们会学习大规模机器学习,也就是处理大型数据集的算法,对比之前的算法,我们拥有大量的数据集,使得我们的准确度更高,现在我们要学习如何处理大型数据集。
为什么我们要学会处理大型数据集呢? 我们之前学习过一种高性能的机器学习算法,是采用低偏差的学习算法,并用大数据进行训练,以下是一个我们之前介绍过的例子
我们可以发现,数据量越大,算法准确度越高,也就有一个结论:在机器学习中,通常情况下,决定因素往往不是最好的算法,而是大量的数据集。
不过大量数据集有其特有的问题——计算问题
如果我们有一个低方差的模型,增加数据集的规模可以帮助你获得更好的结果。我们应该怎样应对一个有100万条记录的训练集?
以线性回归模型为例,每一次梯度下降迭代,我们都需要计算训练集的误差的平方和,如果我们的学习算法需要有20次迭代,这便已经是非常大的计算代价。
首先应该做的事是去检查一个这么大规模的训练集是否真的必要,也许我们只用1000个训练集也能获得较好的效果,我们可以绘制学习曲线来帮助判断。
左图中,可以看到,如果增大规模,对准确度的提升是很大的。
右图中,可以看到,如果增大规模,对准确度的提升并不大,那么就没有必要花费大量的代价去获取不显著的提升。
17.2 随机梯度下降法
一般我们会用梯度下降算法来减少我们代价函数的误差,但如果我们有一个大规模的训练集,使用常规的梯度下降算法(批量梯度下降算法),那么计算量会非常大,我们可以尝试使用随机梯度下降法来代替批量梯度下降法。
回顾之前的批量梯度下降算法
我们要对m个数据求和,当m非常大,如3亿时,那么就计算代价就很大。而之后学习的随机梯度下降算法就不需要对m个数据进行计算,而只需要一个实例。
在随机梯度下降法中,我们定义代价函数为一个单一训练实例的代价:
随机梯度下降算法为:首先对训练集随机“洗牌”,然后:
随机梯度下降算法在每一次计算之后便更新参数 ,而不需要将所有的训练集求和,在梯度下降算法还没有完成一次迭代时,随机梯度下降算法便已经走出了很远。但是这样的算法存在的问题是,不是每一步都是朝着”正确”的方向迈出的。因此算法虽然会逐渐走向全局最小值的位置,但是可能无法站到那个最小值的那一点,而是在最小值点附近徘徊。
17.3 小批量梯度下降
小批量梯度下降算法是介于批量梯度下降算法和随机梯度下降算法之间的算法,每计算常数b 次训练实例,便更新一次参数 θ 。
通常我们会令 b bb 在 2-100 之间。这样做的好处在于,我们可以用向量化的方式来循环 b bb 个训练实例,如果我们用的线性代数函数库比较好,能够支持平行处理,那么算法的总体表现将不受影响(与随机梯度下降相同)。
17.4 随机梯度下降收敛
现在我们介绍随机梯度下降算法的调试,保证正确的收敛,以及学习率 α 的选取。
在批量梯度下降中,我们可以令代价函数 J 为迭代次数的函数,绘制图表,根据图表来判断梯度下降是否收敛。但是,在大规模的训练集的情况下,这是不现实的,因为计算代价太大了。
在随机梯度下降中,我们在每一次更新 θ 之前都计算一次代价,然后每次x 迭代后,求出这x 次对训练实例计算代价的平均值,然后绘制这些平均值与x 次迭代的次数之间的函数图表。
当我们绘制这样的图表时,可能会得到一个颠簸不平但是不会明显减少的函数图像(如上面左下图中蓝线所示)。我们可以增加来使得函数更加平缓,也许便能看出下降的趋势了(如上面左下图中红线所示);或者可能函数图表仍然是颠簸不平且不下降的(如洋红色线所示),那么我们的模型本身可能存在一些错误。
如果我们得到的曲线如上面右下方所示,不断地上升,那么我们可能会需要选择一个较小的学习率α 。
我们也可以令学习率随着迭代次数的增加而减小,例如令:
随着我们不断地靠近全局最小值,通过减小学习率(迭代次数越大,分母越小,学习率越小),我们迫使算法收敛而非在最小值附近徘徊。 但是通常我们不需要这样做便能有非常好的效果了,对α 进行调整所耗费的计算通常不值得
总结下,这段视频中,我们介绍了一种方法,近似地监测出随机梯度下降算法在最优化代价函数中的表现,这种方法不需要定时地扫描整个训练集,来算出整个样本集的代价函数,而是只需要每次对最后1000个,或者多少个样本,求一下平均值。应用这种方法,你既可以保证随机梯度下降法正在正常运转和收敛,也可以用它来调整学习速率α 的大小。
17.5 在线学习
在这个视频中,讨论一种新的大规模的机器学习机制,叫做在线学习机制(是随机梯度下降算法的一种变种)。在线学习机制让我们可以模型化问题。
今天,许多大型网站或者许多大型网络公司,使用不同版本的在线学习机制算法,从大批的涌入又离开网站的用户身上进行学习。特别要提及的是,如果你有一个由连续的用户流引发的连续的数据流,进入你的网站,你能做的是使用一个在线学习机制,从数据流中学习用户的偏好,然后使用这些信息来优化一些关于网站的决策。
假定你有一个提供运输服务的公司,用户们来向你询问把包裹从A地运到B地的服务,同时假定你有一个网站,让用户们可多次登陆,然后他们告诉你,他们想从哪里寄出包裹,以及包裹要寄到哪里去,也就是出发地与目的地,然后你的网站开出运输包裹的的服务价格。比如,我会收取20之类的,然后根据你开给用户的这个价格,用户有时会接受这个运输服务,那么这就是个正样本,有时他们会走掉,然后他们拒绝购买你的运输服务,所以,让我们假定我们想要一个学习算法来帮助我们,优化我们想给用户开出的价格。
一个算法来从中学习的时候,来模型化问题。在线学习算法指的是对连续数据流而非离线的静态数据集的学习。许多在线网站都有持续不断的用户流,对于每一个用户,网站希望能在不将数据存储到数据库中便顺利地进行算法学习。
假使我们正在经营一家物流公司,每当一个用户询问从地点A至地点B的快递费用时,我们给用户一个报价,该用户可能选择接受(y = 1)或不接受(y = 0 )。
现在,我们希望构建一个模型,来预测用户接受报价使用我们的物流服务的可能性。因此报价 是我们的一个特征,其他特征为距离,起始地点,目标地点以及特定的用户数据。模型的输出是:p(y = 1 )。
在线学习的算法与随机梯度下降算法有些类似,我们对单一的实例进行学习,而非对一个提前定义的训练集进行循环。
一旦对一个数据的学习完成了,我们便可以丢弃该数据,不需要再存储它了。这种方式的好处在于,我们的算法可以很好的适应用户的倾向性,算法可以针对用户的当前行为不断地更新模型以适应该用户。
每次交互事件并不只产生一个数据集,例如,我们一次给用户提供3个物流选项,用户选择2项,我们实际上可以获得3个新的训练实例,因而我们的算法可以一次从3个实例中学习并更新模型。
这些问题中的任何一个都可以被归类到标准的,拥有一个固定的样本集的机器学习问题中。或许,你可以运行一个你自己的网站,尝试运行几天,然后保存一个数据集,一个固定的数据集,然后对其运行一个学习算法。但是这些是实际的问题,在这些问题里,你会看到大公司会获取如此多的数据,真的没有必要来保存一个固定的数据集,取而代之的是你可以使用一个在线学习算法来连续的学习,从这些用户不断产生的数据中来学习。这就是在线学习机制,然后就像我们所看到的,我们所使用的这个算法与随机梯度下降算法非常类似,唯一的区别的是,我们不会使用一个固定的数据集,我们会做的是获取一个用户样本,从那个样本中学习,然后丢弃那个样本并继续下去,而且如果你对某一种应用有一个连续的数据流,这样的算法可能会非常值得考虑。当然,在线学习的一个优点就是,如果你有一个变化的用户群,又或者你在尝试预测的事情,在缓慢变化,就像你的用户的品味在缓慢变化,这个在线学习算法,可以慢慢地调试你所学习到的假设,将其调节更新到最新的用户行为。
17.6 映射化简和数据并行
映射化简和数据并行对于大规模机器学习问题而言是非常重要的概念。之前提到,如果我们用批量梯度下降算法来求解大规模数据集的最优解,我们需要对整个训练集进行循环,计算偏导数和代价,再求和,计算代价非常大。如果我们能够将我们的数据集分配给不多台计算机,让每一台计算机处理数据集的一个子集,然后我们将计所的结果汇总在求和。这样的方法叫做映射简化,通常运用于梯段下降算法都不能解决的更大规模的问题。
具体而言,如果任何学习算法能够表达为,对训练集的函数的求和,那么便能将这个任务分配给多台计算机(或者同一台计算机的不同CPU 核心),以达到加速处理的目的。
例如,我们有400个训练实例,我们可以将批量梯度下降的求和任务分配给4台计算机进行处理:
很多高级的线性代数函数库已经能够利用多核CPU的多个核心来并行地处理矩阵运算,这也是算法的向量化实现如此重要的缘故(比调用循环快)。
18.应用实例:图片文字识别(Application Example: Photo OCR)
18.1 问题描述和流程图
图像文字识别应用所作的事是,从一张给定的图片中识别文字。这比从一份扫描文档中识别文字要复杂的多。
为了完成这样的工作,需要采取如下步骤:
文字侦测(Text detection)——将图片上的文字与其他环境对象分离开来
字符切分(Character segmentation)——将文字分割成一个个单一的字符
字符分类(Character classification)——确定每一个字符是什么
可以用任务流程图来表达这个问题,每一项任务可以由一个单独的小队来负责解决:
18.2 滑动窗口
滑动窗口是一项用来从图像中抽取对象的技术。假使我们需要在一张图片中识别行人,首先要做的是用许多固定尺寸的图片来训练一个能够准确识别行人的模型。然后我们用之前训练识别行人的模型时所采用的图片尺寸在我们要进行行人识别的图片上进行剪裁,然后将剪裁得到的切片交给模型,让模型判断是否为行人,然后在图片上滑动剪裁区域重新进行剪裁,将新剪裁的切片也交给模型进行判断,如此循环直至将图片全部检测完。
一旦完成后,我们按比例放大剪裁的区域,再以新的尺寸对图片进行剪裁,将新剪裁的切片按比例缩小至模型所采纳的尺寸,交给模型进行判断,如此循环。
滑动窗口技术也被用于文字识别,首先训练模型能够区分字符与非字符,然后,运用滑动窗口技术识别字符,一旦完成了字符的识别,我们将识别得出的区域进行一些扩展,然后将重叠的区域进行合并。接着我们以宽高比作为过滤条件,过滤掉高度比宽度更大的区域(认为单词的长度通常比高度要大)。下图中绿色的区域是经过这些步骤后被认为是文字的区域,而红色的区域是被忽略的。
以上便是文字侦测阶段。 下一步是训练一个模型来完成将文字分割成一个个字符的任务,需要的训练集由单个字符的图片和两个相连字符之间的图片来训练模型。
模型训练完后,我们仍然是使用滑动窗口技术来进行字符识别。
以上便是字符切分阶段。 最后一个阶段是字符分类阶段,利用神经网络、支持向量机或者逻辑回归算法训练一个分类器即可。
18.3 获取大量数据和人工数据
如果我们的模型是低方差的,那么获得更多的数据用于训练模型,是能够有更好的效果的。问题在于,我们怎样获得数据,数据不总是可以直接获得的,我们有可能需要人工地创造一些数据。
以我们的文字识别应用为例,我们可以字体网站下载各种字体,然后利用这些不同的字体配上各种不同的随机背景图片创造出一些用于训练的实例,这让我们能够获得一个无限大的训练集。这是从零开始创造实例。
另一种方法是,利用已有的数据,然后对其进行修改,例如将已有的字符图片进行一些扭曲、旋转、模糊处理。只要我们认为实际数据有可能和经过这样处理后的数据类似,我们便可以用这样的方法来创造大量的数据。
有关获得更多数据的几种方法:
- 人工数据合成
- 手动收集、标记数据
- 众包
18.4 上限分析:哪部分管道的接下去做
在机器学习的应用中,我们通常需要通过几个步骤才能进行最终的预测,我们如何能够知道哪一部分最值得我们花时间和精力去改善呢?这个问题可以通过上限分析来回答。
回到我们的文字识别应用中,我们的流程图如下:
流程图中每一部分的输出都是下一部分的输入,上限分析中,我们选取一部分,手工提供100%正确的输出结果,然后看应用的整体效果提升了多少。假使我们的例子中总体效果为72%的正确率。
如果我们令文字侦测部分输出的结果100%正确,发现系统的总体效果从72%提高到了89%。这意味着我们很可能会希望投入时间精力来提高我们的文字侦测部分。
接着我们手动选择数据,让字符切分输出的结果100%正确,发现系统的总体效果只提升了1%,这意味着,我们的字符切分部分可能已经足够好了。
最后我们手工选择数据,让字符分类输出的结果100%正确,系统的总体效果又提升了10%,这意味着我们可能也会应该投入更多的时间和精力来提高应用的总体表现。