前面的笔记所谈到的分类模型,都是基于线性的,即我们假设数据是线性可分,或者至少看起来用一条线来做分类是不错的。但现实中我们的数据往往不那么容易得能用一条线区分开来。
可以发现$\mathcal{D}$并不是一个线性可分的数据,但使用一个圆圈,却可以很好得把圈圈和叉叉区分开来。这个”圆圈分类器”可以是下面这种形式:
$$h_{SEP}(x)=sign(-x_1^2-x_2^2+0.6)$$
看样子我们需要重新设计分类模型与算法,做一个圆圈版本的PLA,圆圈版本的Regression。所以接下来几篇笔记应该是$\color{orange}{\text{Circular}}-\text{PLA}$、$\color{orange}{\text{Circular}}-\text{Regression}$。事实上是不需要这么麻烦的,下面我们来分析下那个圈圈分类器的方程:
如果我们只看包含$\color{purple}{z}$的部分,它事实上依然是一个线性方程。即,$\mathcal{X}$空间下的一个圆圈,对应到$\mathcal{Z}$空间下的一条直线。
这个转换的过程成为nonlinear feature transform,用符号$\phi$表示,$\phi$把两个互相独立的空间给联系了起来:
$$(1,x_1^2,x_2^2)=\color{purple}{\phi}(x)=\color{purple}{(z_0,z_1,z_2)}=\color{purple}{z}$$
$\mathcal{X}$空间下的每个点,都对应$\mathcal{Z}$空间下的某个点,同样的,$\mathcal{X}$空间下的二次曲线方程,都对应$\mathcal{Z}$空间下的某个一次直线方程。
$$h(x)=sign(\color{orange}{\tilde{w}_0}+\color{orange}{\tilde{w}_1}\color{purple}{x_1^2}+\color{orange}{\tilde{w}_2}\color{purple}{x_2^2})=sign(\color{orange}{\tilde{w}^T}\color{purple}{\phi}(x))=\color{orange}{\tilde{h}(\color{purple}{z})}$$
这样以来,两个空间,在“冥冥之中”,产生了关联,前面说的$\phi$就是这两个空间的纽带,在这个纽带下,$\mathcal{Z}$空间下的不同直线也就对应$\mathcal{X}$下的不同形态的分类器。
$\tilde{w}$ | X空间下的曲线形态 |
---|---|
(0.6,−1,−1) | circle(圈圈在内部,叉叉在外部) |
(−0.6,+1,+1) | circle(圈圈在外部,叉叉在内部) |
(0.6,−1,−2) | ellipse |
(0.6,−1,+2) | hyperbola |
(0.6,+1,+2) | 所有点都判断为圈圈 |
更加一般化,我们把一次空间$\mathcal{X}$映射到二次空间$\mathcal{Z}$的时候,还会保留其一次项,即下面这个样子的映射才是完整的二次映射:
$$\color{purple}{\phi}(x)=(\color{purple}{1,x_1,x_2,x_1^2,x_1x_2,x_2^2})$$
这样一来,这个完整版的$\mathcal{Z}$空间的直线,就可以代表$\mathcal{X}$空间下的所有二次曲线了。
说了这么多,我们回想一下,我们为何要做这个非线性变换?逻辑是这样的:
实际操作上,分以下三步:
d维向量$x$经过Q次多项式变换:
(以上是Q次完整变换,当然我们不一定会需要完整项,譬如之前那个圆圈,就舍弃了$x_1x_2$项)
若考虑完整变化,原来的$1+d$维向量经过变换,就成了$1+\tilde{d}=1+\binom{Q+d}{Q}$维向量,复杂度由$O(d)$变为$O(Q^d)$。
这点很容易理解,如之前的例子,原始数据$(1,x_1,x_2)$经过变换之后变成$(1,x_1,x_2,x_1^2,x_1x_2,x_2^2)$,需要多一倍的空间来存转换后的数据,同时参数的增加,也增大了计算量。
之前的笔记VC Dimension, Part III,有讲到自由度与VC Dimension的关系,线性模型的$d_{vc}\approx 自由度 \approx \tilde{d}+1$。如果Q非常大的话,则模型的$d_{vc}$也会非常大,我们知道$d_{vc}$越大,越容易实现小的$E_{in}$,同时,也会造成$|E_{out}-E_{in}|$的加大,即模型的泛化能力(generalization)变差。
上图是分别使用原始数据进行训练以及进行4次非线性变换后的数据进行训练的结果对比。从视觉上看,虽然右图(经过4次非线性变换的模型)能够把圈圈叉叉完全分开,但显然这种模型过于复杂了。
很多时候我们会面临模型泛化能力和分类能力的权衡取舍,即:
$\tilde{d}(Q)$ | $E_{out}(g)$能否与$E_{in}(g)$很接近? | $E_{in}(g)$是否足够小? |
---|---|---|
higher | :-( | :-D |
lower | :-D | :-( |
(表中符号若不理解,请把屏幕右转90度。XD)
那么如何选择合适的复杂度呢?像上面一样用眼睛看?暂且不讨论10维的数据有没有办法用眼睛看,就拿前面2维的例子来说,用眼睛看来选择模型是件很危险的事情。
在你没看数据之前,你决定要进行完整的2次非线性变换,即:
不过你没有忍住,偷偷先看了下数据:
发现,用一个圆圈,就可以达到理想的效果,于是你决定放弃$\phi_2$变换中的一些维度,即使用:
或者干脆了,你觉得一个正圆就够了,使用:
最终你采用了$d_{vc}$最小的那个方案,因为根据前面说的,用这个正圆,可以完全分开,而且$d_{vc}=2$,并没有增大,真实两全其美。不过,这个时候,$d_{vc}$真的还是2吗?其实这个时候$d_{vc}$是比较难判断的,因为你是在“看过”数据之后,由你大脑选择的一个模型,这里要考虑到你大脑“选择模型”产生的一个复杂度,因为如果重新选取一部分数据,你有可能就不再挑选正圆模型了,事实上你的大脑不知不觉地参与到了模型参数估计上,偷偷地把2次变换中产生的其他项前面的系数,估计为0了。因此要切记,在$\phi$的选择之前,不可以偷偷去看数据。 倘若你在没看数据之前,就决定使用正圆,则此时,该模型的$d_{vc}=2$。
通常我们说的非线性变换,指的是多项式变换(Polynomial Transform)。用符号$\phi_Q$来表示$Q$次多项式变换:
可以发现$\phi_{i}(x)$中包含了$\phi_{i-1}(x)$,因此他们对应的Hypothesis Set也有如下关系:
假如我们分别对原始数据进行$i$次非线性多项式变换并训练模型,$g_i$表示使用$i$次非线性多项式变换后的数据所训练出的最优模型,$\color{blue}{g_i=argmin_{h\in \mathcal{H}_i}E_{in}(h)}$则有:
通常在进行高次非线性变换的时候,应该特别小心,因为$d_{vc}$上升很快,极容易造成overfitting。比较安全的做法是,先尝试不做非线性变换,即使用$\mathcal{H}_{\phi_1}$,如果效果足够好了,就不需要进行非线性变换,如果效果不够好,再慢慢尝试使用复杂更高的模型。
]]>前面的笔记介绍了三种线性模型,PLA、Linear Regression与Logistic Regression。之所以称他们是线性模型,是因为这三种分类模型的方程中,都含有一个相同的部分,该部分是各个特征的一个线性组合,也可以称这个部分叫做线性评分方程:
$$\color{purple}{s}=w^Tx$$
严谨一点来说,PLA并不是一种“模型”,PLA (Perceptron Learning Algorithm) 是一种“算法”,用来寻找在“线性可分”的情况下,能够把两个类别完全区分开来的一条直线,所以我们简单的把PLA对应的那个模型就叫做Linear Classification。
下面对比下这三种模型:
Linear Regression和Logistic Regression的输出是一个实数,而不是一个Binary的值,他们能用来解分类问题吗?可以,只要定一个阈值,高于阈值的输出+1,低于阈值的输出-1就好。既然Linear Regression和Logistic Regression都可以用来解分类问题,并且在最优化上,他们都比Linear Classification简单许多,我们能否使用这两个模型取代Linear Classification呢?
三个模型的区别在于误差的衡量,误差的衡量可以说是一个模型最重要的部分,这部分内容可以参考Noise and Error。
这里$y$是一个binary的值,要么是-1,要么是+1。注意到三个模型的error function都有一个$\color{blue}{y}\color{purple}{s}$的部分,也叫做分类正确性分数 (classification correctness score)。其中$\color{purple}{s}$是模型对某个样本给出的分数,$\color{blue}{y}$是该样本的真实值。
不难看出,当$\color{blue}{y}=+1$时,我们希望$\color{purple}{s}$越大越好,当$\color{blue}{y}=-1$时,我们希望$\color{purple}{s}$越小越好,所以总的来说,我们希望$\color{blue}{y}\color{purple}{s}$尽可能大。因此这里希望给较小的$\color{blue}{y}\color{purple}{s}$较大的cost,给较大的$\color{blue}{y}\color{purple}{s}$较小的cost即可。因此,不同模型的本质差异,就在于这个cost该怎么给。
既然这三个error function都与$\color{blue}{y}\color{purple}{s}$有关,我们可以以$\color{blue}{y}\color{purple}{s}$为横坐标,$err$为纵坐标,把这三个函数画出来。
sqr (squre error)为Linear Regression的误差函数,ce (cross entropy)为Logistic Regression的误差函数。可以看出,$\color{red}{err_{sqr}}$在$\color{blue}{y}\color{purple}{s}$较小的时候很大,但是,在$\color{blue}{y}\color{purple}{s}$较大的时候$\color{red}{err_{sqr}}$同样很大,这点不是很理想,因为我们希望$\color{blue}{y}\color{purple}{s}$大的时候cost要小,尽管如此,至少在$\color{red}{err_{sqr}}$小的时候,$\color{blue}{err_{0/1}}$也很小,因此可以拿来做error function。$err_{ce}$则是一个单调递减的函数,形态有点点像$\color{blue}{err_{0/1}}$,但来的比较平缓。注意到$err_{ce}$有一部分是小于$\color{blue}{err_{0/1}}$的,我们希望$err_{ce}$能成为$\color{blue}{err_{0/1}}$的一个upper bound(目的一会儿会说到),只要将$err_{ce}$做一个换底的动作,即:
$$\color{orange}{\text{scaled}}\text{ ce : err}_{\color{orange}{s}ce}(\color{purple}{s},\color{purple}{y})=\color{orange}{log_2}(1+exp(-\color{purple}{ys}))$$
事实上这里做scale的动作并不会影响最优化的过程,它只是让之后的推导证明更加容易一些。
现在稍稍回忆一下我们的问题是什么:
能不能拿Linear Regression或Logistic Regression来替代Linear Classification?
为什么会想做这样的替代?Linear Classification,在分类这件事上,它做的很好,但在最优化这件事上,由于是NP-hard问题,不大好做,而Linear Regression与Logistic Regression在最优化上比较容易。因此,如果他们在分类能力上的表现能够接近Linear Classification,用他们来替代Linear Classification来处理分类的问题,就是件皆大欢喜的事。这时候就可以想想刚刚为何要把$err_se$ scale 成$err_{0/1}$的upper bound,目的就是为了让这几个模型的观点在某个方向上是一致的,即:
$\color{red}{err_{sqr}}$/$err_{sce}$低的时候,$\color{blue}{err_{0/1}}$也低
通俗一点讲:
假设某种疾病有两种检测方法A和B。A方法检查结果为阳性时,则患病,为阴性时,则未患病。B方法的效率差一些,对于一部分患病的人,B方法不一定结果为阳性,但只要B的结果为阳性,再用A来检查,A的结果一定也为阳性。这么一来,我们就可以说,如果B方法的结果为阳性的时候,我们就没有必要使用A方法再检查一次了,它的效率是和A相同的。
再通俗一点讲:
如果使用$\color{red}{err_{sqr}}$/$err_{sce}$来衡量一个模型分类分得好不好的时候,如果他们认为分得好,那么如果使用$\color{blue}{err_{0/1}}$,它也会认为分得好。
对比下在处理分类问题时,使用PLA,Linear Regression以及Logistic Regression的优缺点。
PLA:
Linear Regression:
Logistic Regression:
所以我们常常可以使用Linear Regresion跑出的$w$作为(PLA/Pocket/Logistic Regression)的$w_0$,然后再使用$w_0$来跑其他模型,这样可以加快其他模型的最优化速度。同时,由于拿到的数据常常是线性不可分的,我们常常会去使用Logistic Regression而不是PLA+pocket。
我们知道PLA与Logistic Regression都是通过迭代的方式来实现最优化的,即:
For t = 0, 1, …
$$w_{t+1}\leftarrow w_t + \eta v$$
when stop, return last w as g
区别在于,PLA每次迭代只需要针对一个点进行错误修正,而Logistic Regression每一次迭代都需要计算每一个点对于梯度的贡献,再把他们平均起来:
这样一来,数据量大的时候,由于需要计算每一个点,Logistic Regerssion就会很慢了。上一篇有讲到Logistic Regression每次是怎样迭代的:
那么我可以不可以每次只看一个点,即不要公式中先求和再取平均数的那个部分呢?随机取一个点n,它对梯度的贡献为:
$$\color{orange}{\triangledown _w err(w,x_n,y_n)}$$
我们把它称为随机梯度,stochastic gradient。而真实的梯度,可以认为是随机抽出一个点的梯度值的期望(红色部分取平均数的动作):
因此我们可以把随机梯度当成是在真实梯度上增加一个均值为0的noise:
$$\color{orange}{\text{stochastic gradient}} = \color{blue}{\text{true gradient}} + \color{red}{\text{zero-mean ‘noise’ directions}}$$
虽然和true gradient存在一定的误差,但是可以认为在足够多的迭代次数之后,也能达到差不多好的结果。我们把这种方法成为随机梯度下降,Stochastic Gradient Descent (SGD):
和之前说到的Gradient Descent相比,SGD的好处在于时间复杂度大幅减小(每次只随机地看一个点),在数据量很大的时候可以很快得得到结果,当然缺点就是,如果前面说到的那个$\color{red}{\text{noise}}$很大的话,会稍稍有点不稳定。
我们现在已经有办法使用线性分类器解决二元分类问题,但有的时候,我们需要对多个类别进行分类,即模型的输出不再是0和1两种,而会是多个不同的类别。那么如何套用二元分类的方法来解决多类别分类的问题呢?
利用二元分类器来解决多类别分类问题主要有两种策略,OVA(One vs. ALL)和OVO(One vs. One)。
先来看看OVA,假设原问题有四个类别,那么每次我把其中一个类别当成圈圈,其他所有类别当成叉叉,建立二元分类器,循环下去,最终我们会得到4个分类器。
做预测的时候,分别使用这四个分类器进行预测,预测为圈圈的那个模型所代表的类别,即为最终的输出。譬如正方形的那个分类器输出圈圈,菱形、三角形、星型这三个分类器都说是叉叉,则我们认为它是正方形。当然这里可能遇到一个问题,就是所有模型都说不是自己的时候(都输出叉叉),怎么办?
很简单,只要让各个分类器都输出是否为自己类别的概率值,即可,然后选择概率值最高的那个分类器所对应的类别,作为最终的输出。
在类别较多的时候,如果使用OVA方法,则又会遇到数据不平衡(unbalance)的问题,你拿一个类别作为圈圈,其他所有类别作为叉叉,那么圈圈的比例就会非常小,而叉叉的比例非常高。为了解决这个不平衡的问题,我们可以利用另外一个策略,OVO,即每次只拿两个类别的数据出来建建立分类器,如下图。
这个想法类似在打比赛,一笔新数据进来之后,分别使用这六个模型进行预测,得票数最多的那个类别,作为最终的输出。这样做的好处是,有效率,每次只拿两个类别的数据进行训练,每个模型训练数据量要少很多。但是缺点是,由于模型的数量增加了,将消耗更多的存储空间,会减慢预测的速度。
]]>
(上图引用自 INTRODUCTION TO HADOOP )
以MapReduce中最经典的wordcount应用为例,来分析一下MapReduce的全过程。这里我们要统计文件中每个单词出现的次数。
(注:这里Mapping工作交给3台电脑,Reducing工作交给4台电脑的说法其实是不严谨的,具体要用多少资源来完成MapReduce由系统根据任务的状况决定,通常一台电脑需要完成多个Mapping与Reducing的工作。)
为何要如此设计?简单来说,因为MapReduce为的是能实现分布式运算,涉及到多台机器同时运算的步骤有Mapping和Reducing,参与Mapping工作的机器可以完全独立工作而不需要知道其他机器上有什么数据;参与Reducing步骤的机器,由于数据之前已经按照key进行了分组,因此其他机器上有什么数据与他毫无关系。参与计算的机器都是互相独立,完全不依赖其他机器的数据,这样就可以很方便写代码,因为所有参与Mapping工作的机器使用一模一样的代码,所有参与Reducing工作的机器也使用一模一样的代码。
我们要在ODPS上要实现MapReduce,就需要写两类代码,一类称为Mapper,另一类称为Reducer。抛开前面所说的原理,我们只需要记住以下两点:
通过MapReduce计算对每个user每天对不同品牌产生的4种行为(点击、购买、收藏、购物车)的次数进行统计,并且计算在某天某user对某个brand的累计点击次数:
input table
user_id | brand_id | type | visit_datetime |
---|---|---|---|
101 | 20001 | 0 | 06-01 |
101 | 20001 | 0 | 06-01 |
101 | 20001 | 0 | 06-02 |
101 | 20002 | 0 | 06-02 |
101 | 20002 | 1 | 06-02 |
101 | 20003 | 0 | 06-02 |
101 | 20001 | 0 | 06-03 |
101 | 20003 | 2 | 06-03 |
101 | 20003 | 3 | 06-03 |
101 | 20003 | 1 | 06-04 |
output table
user_id | brand_id | visit_datetime | clicks | buy | collect | basket | cum_clicks |
---|---|---|---|---|---|---|---|
101 | 20001 | 06-01 | 2 | 0 | 0 | 0 | 2 |
101 | 20001 | 06-02 | 1 | 0 | 0 | 0 | 3 |
101 | 20001 | 06-03 | 1 | 0 | 0 | 0 | 4 |
101 | 20002 | 06-02 | 1 | 1 | 0 | 0 | 1 |
101 | 20003 | 06-02 | 1 | 0 | 0 | 0 | 1 |
101 | 20003 | 06-03 | 0 | 0 | 1 | 1 | 1 |
101 | 20003 | 06-04 | 0 | 1 | 0 | 0 | 1 |
比如output table里第三行的意思是,user_101在06-03这天一共点了brand_20001 1次,从user_101第一次接触brand_20001以来,已经累计点了4次。
由于我们想要实现累计求和,因此我们可以在Mapping步骤中,使用(user_id,brand_id)
作为key,而(type,visit_datetime)
作为value。
这么一来,在Reducing步骤中,每个Reducer就能接受到某个user对某个brand的所有交互信息,这样就能衍生出我们所需的新的value,即(visit_datetime, clicks, buy, collect, basket cum_clicks)
。
在ODPS中需要达到上述目标,需要动手实现3个类,这里我把他们命名为TestMapper,TestReducer,TestDriver,其中TestDriver用来进行一些任务的配置。下面来具体看看如何实现。
Driver主要用来进行一些格式设定。在此之前你需要在eclipse中新建一个ODPS项目。然后在项目的src上右键->new->other,在Aliyun Open Data Processing Service下选择MapReduce Driver…
接着eclipse会帮我们生成一个Driver的模板。官方写的很清楚了,所有的TODO部分是需要我们进行修改的。先来看第一个TODO:
|
|
这是用来设定Mapper输出的时候,key与value的格式。按照之前说的,以(user_id,brand_id)
为key,(type,visit_datetime)
为value。
第二个TODO:
|
|
设定input table与output table。这里把待会儿命令行调用中,第一个参数(args[0]
)设为input table,第二个参数(args[1]
)设为output table。待会儿会通过下面的命令在odps console中启动MapReduce任务。(暂时不需要搞清楚的地方都用*代替)
|
|
其中args[0]
就指代t_alibaba_bigdata_user_brand_total_1
,args[1]
就指代tb_output
。
第三个TODO:
|
|
告诉系统这次任务要用的Mapper和Reducer是谁,按照上面的设定之后,系统就会通知所有负责Mapping工作的电脑待会儿使用TestMapper
中的代码进行运算,通知所有负责Reducing工作的电脑待会儿使用TestReducer
中的代码进行运算。
TestDriver完整代码如下(省略开头import的部分)
|
|
之前说过,Mapper的任务就是对读入的一行数据,接着输出key和value。key和value都属于Record类,并且key和value都可以由单个或者多个字段构成,在我们这个任务中,key由(user_id,brand_id)
两个字段构成,value由(type,visit_datetime)
构成。
与创建TestDriver的步骤类似,使用官方的模板创建一个名为TestMapper的java代码,同样官方模板把大多数代码都生成好了。
|
|
setup
当中是对key和value进行初始化。其中key使用createMapOutputKeyRecord()
进行初始化,value使用createMapOutputValueRecord()
进行初始化。
在map函数中,record代表读入的一行数据,比如101, 20001, 0, 06-01
,我们可以通过record.get(n)
方法获取该行记录第n列的数据。并且方便的是,这里可以直接对读入的数据进行一个类型转换。例如record.getString()
会把读入的数据转为字串,record.getBigInt()
则会把读入的数据转为Long型整数。
在TestDriver的设定当中,我们已经把Mapper输出的key定为(user_id,brand_id)
,value定为(type,visit_datetime)
,在map函数中,我们可以使用key.set()
与value.set()
来分别赋予这4个值。
最后context.write(key, value)
的意思是输出这条key-value,如果不写这行,Mapper就什么都不输出。一个Mapper可以有0个或多个key-value的输出,每调用一次context.write(key,value)
就会输出一行。
TestMapper完整代码如下(省略import部分)
|
|
通常Driver和Mapper方面都很简单,大多情况下,计算工作都在Reducing步骤完成,因此Reducer的代码会略多一些。同样按照前面的方法生成名为TestReducer的Reducer类。
因为我们要按天来汇总四类行为出现的次数,因此这里我使用一个TreeMap
来存储每天四种行为出现的次数。
|
|
这里又再啰嗦一遍,Mapper每次只处理一行数据,而Reducer通常处理的不止一行,而是会处理属于相同key的所有数据。翻到文章开头的那张图片,图中第二个Reducer,所有key为Car的记录,全部交给该一个Reducer处理。
因此reduce函数当中的values
参数是一个Iterator
,通过调用values.next()
来读取所有属于该key的记录。每读取一行记录,都对计数器typeCounter
进行对应type
的累加操作。
Reducer的output是一个Record类,可以通过output.set(n)
来设定该output第n列的数值,同样使用context.write(output)
输出一行数据。在本文的例子中,对于一个key(user_id,brand_id)而言,有N个不同的visit_datetime
,最终就会输出N行数据。因此可以看到TestReducer的context.write(output)
是写在一个for-loop里的,会被调用多次,每次会输出一行。类似的操作如果使用SQL实现,就非常的费神了,而使用MapReduce,反而简单许多。
TestReducer的完整代码(省略模板中的import部分)
|
|
1. 在Package Explorer中你之前建立的ODPS项目下的src上右键,选择Export,然后选择Java底下的JAR file。接着设定下JAR包存放的位置与文件名。这里假设我们放在C:\TOOLS\test.jar
,然后点Finish。
2. 打开odps console,新建一个resource。
|
|
3. 在实际运行之前,需要先建立一个表,作为结果输出的位置。这里我们就叫它tb_output
好了。
进入sql,建立表格
|
|
4. 在odps console下,执行MapReduce任务
|
|
上一篇比较深入地去理解了线性回归的思想和算法。分类和回归是机器学习中很重要的两大内容。而本篇要讲的Logistic Regression,名字上看是回归,但实际上却又和分类有关。
之前提过的二元分类器如PLA,其目标函数为, $f(x)=sign(w^Tx)\in{-1,+1}$,输出要么是-1要么是+1,是一个“硬”的分类器。而Logistic Regression是一个“软”的分类器,它的输出是$y=+1$的概率,因此Logistic Regression的目标函数是 $\color{purple}{f}(x)=\color{orange}{P(+1|x)}\in [0,1]$。
上面的方程背后有什么逻辑呢?
假设医院知道一个病人的年龄、性别、血压、胆固醇水平,可以为他计算他得某种病的概率。最简单的做法就是对这几个特征进行加权求和:
但这里有个问题,就是 $\color{purple}{s}$ 的取值范围是$[-\infty,+\infty]$,而我们希望输出的是对该病人患病概率的一个估计,就需要把输出空间$[-\infty,+\infty]$转换到$[0,1]$上。如何变换?通过sigmoid函数 $\color{blue}{\theta}$ 。
$$\color{blue}{\theta}(\color{purple}{s})=\frac{e^\color{purple}{s}}{1+e^\color{purple}{s}}=\frac{1}{1+e^\color{purple}{-s}}$$
因此,我们就可以利用经过sigmoid变换后的方程来对患病概率进行一个估计。
有了方程的形式,我们就需要一个误差的衡量方式。上一篇我们讲到Linear Regression所使用的是平方误差,那么Logistic 可以使用平方误差吗?当然可以,error是人定的,你爱怎么定就怎么定,但是使用平方误差好不好,不好。为什么呢?
如果使用平方误差,每个点产生的误差是:
此时cost function,$E_{in}(w)=\sum{err}$就是一个关于$w$的非凸函数(non-convex):
非凸函数由于存在很多个局部最小点,因此很难去做最优化(解全局最小)。所以Logistic Regression没有使用平方误差来定义error,而是使用极大似然法来估计模型的参数。那么我们就要先来了解一下这个似然性(likelihood)。
Logistic Regression的目标函数的输出是,在已知$x$的条件下,$y=+1$的概率,因此在已知$x$的条件下,$y=+1$的概率是$f(x)$,$y=-1$的概率是$1-f(x)$:
考虑我们的训练样本$\mathcal{D}={(x_1,\color{blue}{+1}),(x_2,\color{red}{-1}),…,(x_N,\color{red}{-1})}$,并不是每次抽样都能抽到一模一样的$\mathcal{D}$,抽到这么一份样本是由于各种的机缘巧合。那么我们能抽到这么一份$\mathcal{D}$的概率取决于两部分:1、抽到样本$x_1,…,x_N$的概率;2、这些样本对应的$y_1,…,y_N$等于$\color{red}{+1}$的概率。
对于目标函数 $\color{purple}{f}$,抽到$\mathcal{D}$的概率只取决于第1部分,而我们无法知道 $\color{purple}{f}$,即第2部分也是未知的,因此我们称在 $\color{orange}(h)$的作用下抽出$\mathcal{D}$的概率为“似然性”。如果 $\color{orange}{h}\approx\color{purple}{f}$,则 $likelihood(\color{orange}{h})\approx \text{probability using }\color{purple}{f}$,并且我们认为在 $\color{purple}{f}$的作用下,产生$\mathcal{D}$这样的样本的概率通常是非常的大的。
所以有:
$$\text{if } \color{orange}{h}\approx\color{purple}{f}\text{, then }\; likelihood(\color{orange}{h})\approx(\text{probability using }\color{purple}{f})\approx\color{purple}{\text{large}}$$
则理想的hypothesis就是能使得似然函数最大的那个$h$:
$$g=\underset{\color{orange}{h}}{argmax}\;likelihood(\color{orange}{h})$$
当$\color{orange}{h}$是logistic函数的时候,即$h(x)=\theta(w^Tx)$,由于logistic函数的中心对称性,有:
$$1-h(x)=h(-x)$$
所以有:
因此有这么一个相似性:
$$likelihood(logistic\;\color{orange}{h})\propto \prod_{n=1}^{N}\color{orange}{h}(y_nx_n)$$
我们的目标是想找到一个似然性最大的方程:
$$\underset{\color{orange}{h}}{max}\;\;\color{grey}{likelihood(logistic\;\color{orange}{h}) \propto}\prod_{n=1}^{N}\color{orange}{h}(y_nx_n)$$
转化成与参数$w$有关的形式:
求解上式最大值,等价于求解下式的最小值:
求和符号后面的部分就是在极大似然估计下,logistic方程的误差函数,这种形式的误差函数称为cross entropy error:
$$err(\color{orange}{w},x,y)=ln(1+exp(-y\color{orange}{w}x))\\
\color{blue}{\text{cross-entropy error}}$$
有了误差函数后,我们就可以定出Cost function:
该函数是连续,可微,并且是凸函数(二次微分矩阵是正定的)。
那么如何能够最小化$E_{in}(w)$呢?按照之前Linear Regression的逻辑,由于它是凸函数,如果我们能解出一阶微分(梯度)为0的点,这个问题就解决了。
先来看看$E_{in}(w)$在$w_i$方向上的偏微分:
再把偏微分方程中的$x_{n,i}$换成向量的形式,就得到$E_{in}(w)$的一阶微分:
和之前的Linear Regression不同,它不是一个线性的式子,要求解$\triangledown E_{in}(w)=0$这个式子,是困难的。那么该使用何种方法实现$E_{in}(w)$最小化呢?
这里可以使用类似PLA当中的,通过迭代的方式来求解,这种方法又称为梯度下降法(Gradient Descent)。
For t = 0, 1, …
$$w_{t+1} \leftarrow w_t + \color{red}{\eta}\color{blue}{v}$$
when stop, return $\color{purple}{\text{last w as g}}$
其中$\color{red}{\eta}$为每步更新的大小(step size),$\color{blue}{v}$是单位向量,表示每次更新的方向。
有点类似一个小球,往山谷方向滚,直至山谷。每一步我们只要决定两个东西:1、滚动的方向;2、滚动的步长。
滚动的方向好决定,即在该点一阶微分后的向量所指的方向:
步长 $\color{red}{\eta}$比较难决定,太小了,更新太慢,太大了,容易矫枉过正:
一个比较好的做法是让 $\color{red}{\eta}$ 与 $\color{blue}{||\triangledown E_{in}(w_t)||}$ 成一定的比例,让新的和$\color{blue}{||\triangledown E_{in}(w_t)||}$成比例的$\color{purple}{\text{紫色的 }\eta}$ 来代替原来$\color{red}{\text{红色的 }\eta}$:
我们称这个$\color{purple}{\text{紫色的 }\eta}$ 为 $\color{purple}{\text{fixed learning rate}}$。
再来完整的梳理下梯度下降法(Gradient Descent):
initialize $w_0$
For t = 0, 1, …
1. compute
2. update by
…until $\color{orange}{E_{in}(w_{t+1})=0}$ or enough iterations
return $\color{purple}{\text{last }w_{t+1}\text{ as }g}$
]]> 噢,忘了说了这篇文章是关于R语言抓数据以及画图的,与比赛木有关系。本篇的内容纯粹just for fun,不具任何实际价值。是对我最近在cos.name上混来的一些R语言技巧的复习。
好了继续。当然我也参加了比赛,但是很不幸第二周就被挤了出来,于是乎对着这个top 500看了好久,想了好久,睡了好久……
由于参赛队员都是在校学生,而且又是规模空前,几乎全国稍微有点名气的学校都参加了,那么这些学校的表现如何呢?一所大学的综合排名能否很好的表现在比赛中呢?这次的文章就在尝试能否用数据来帮助理解前面这些问题。
首先我们需要获取这份榜单,地址是:
http://102.alibaba.com/competition/addDiscovery/totalRank.htm。
打开发现每页只能显示20支队伍,一共25页。一开始的想法是利用R的XML包,读取HTML TABLE,但是点击第2页的时候,发现网址居然是不会变化的,因此就没有办法根据网址一页一页下载下来。怀疑应该是在你点击下一页的时候,通过一个API获取下一页的信息,再利用javascript来更新表格。
此时派chrome上场,在页面上点右键-审查元素,打开develop tools:
选择Network,然后在排行榜的页面庄重的点”下一页”。然后developer tools就会抓到刚刚点了“下一页”之后发生的http请求。
http://102.alibaba.com/competition/addDiscovery/queryTotalRank.json 就是网页获取排名数据的API了,使用POST方法,带上pageIndex以及pageSize两个参数,就可以获取排名信息。接下来就要请RCurl上场了。
|
|
|
|
teamName | university | score | dateString | |
---|---|---|---|---|
1 | cucyyyy | 中国传媒大学 | 0.0717 | 2014-03-23 |
2 | 花莲 | 南京大学 | 0.0694 | 2014-03-23 |
3 | CUCkdd | 中国传媒大学 | 0.0692 | 2014-03-23 |
4 | WYZ | 清华大学 | 0.0685 | 2014-03-23 |
5 | 車輪戦 | 哈尔滨工业大学 | 0.0684 | 2014-03-16 |
先来看看各个学校都有多少队参加比赛。
|
|
|
|
看来浙大很具主场优势啊,中科院也是来势汹汹。这里参赛队伍数是报名并且成功提交过结果的队伍数,截止3.23凌晨,共有1383队提交过结果。
那么如何衡量学校的表现呢?先来看看哪些学校的牛人最牛。我这里用的方法是计算每个学校最强的5支队伍的平均分数。
|
|
为了减少极端值的影响,这里把参赛队伍数少于5的学校给过滤掉了。
根据每个学校前5名平均分排序
university | average | num_teams | |
---|---|---|---|
1 | 哈尔滨工业大学 | 0.0662 | 45 |
2 | 浙江大学 | 0.0661 | 97 |
3 | 清华大学 | 0.0651 | 37 |
4 | 南京大学 | 0.0645 | 40 |
5 | 中国科学院大学 | 0.0645 | 76 |
6 | 中国科学技术大学 | 0.0643 | 47 |
7 | 北京邮电大学 | 0.0639 | 87 |
8 | 北京理工大学 | 0.0628 | 25 |
9 | 华中师范大学 | 0.0623 | 10 |
10 | 北京航空航天大学 | 0.0622 | 22 |
11 | 北京大学 | 0.0620 | 39 |
12 | 电子科技大学 | 0.0619 | 56 |
13 | 西南交通大学 | 0.0613 | 11 |
14 | 大连理工大学 | 0.0604 | 19 |
15 | 西安电子科技大学 | 0.0600 | 37 |
16 | 中山大学 | 0.0597 | 35 |
17 | 华南理工大学 | 0.0591 | 28 |
18 | 山东大学 | 0.0590 | 14 |
19 | 武汉大学 | 0.0588 | 19 |
20 | 香港科技大学 | 0.0574 | 15 |
21 | 东南大学 | 0.0571 | 27 |
22 | 中国人民大学 | 0.0570 | 9 |
23 | 厦门大学 | 0.0569 | 15 |
24 | 华东师范大学 | 0.0565 | 14 |
25 | 上海交通大学 | 0.0565 | 20 |
26 | 华中科技大学 | 0.0562 | 35 |
27 | 东北大学 | 0.0559 | 17 |
28 | 同济大学 | 0.0557 | 15 |
29 | 复旦大学 | 0.0530 | 25 |
30 | 南开大学 | 0.0520 | 11 |
31 | 天津大学 | 0.0498 | 12 |
32 | 西安交通大学 | 0.0480 | 12 |
33 | 东华大学 | 0.0467 | 11 |
34 | 广东工业大学 | 0.0460 | 8 |
35 | 北京交通大学 | 0.0459 | 7 |
36 | 北京师范大学 | 0.0459 | 6 |
37 | 湖南大学 | 0.0450 | 6 |
38 | 南京邮电大学 | 0.0440 | 8 |
39 | 西北农林科技大学 | 0.0430 | 5 |
40 | 西北工业大学 | 0.0426 | 8 |
41 | 南京航空航天大学 | 0.0413 | 6 |
42 | 中国科学院软件研究所 | 0.0403 | 5 |
43 | 燕山大学 | 0.0378 | 5 |
44 | 吉林大学 | 0.0366 | 6 |
45 | 北京工业大学 | 0.0358 | 5 |
46 | 哈尔滨工业大学(威海) | 0.0356 | 6 |
47 | 中南大学 | 0.0315 | 6 |
48 | 浙江工商大学 | 0.0283 | 5 |
49 | 四川大学 | 0.0267 | 6 |
50 | 武汉理工大学 | 0.0209 | 6 |
51 | 福建师范大学 | 0.0041 | 5 |
上面的学校排名符合您心目中的预期吗?
那么如何去衡量一个学校所有队伍的综合表现呢?当分数的分布有偏的时候,不太好直接使用全部队伍得分的平均数来对比两个学校的表现,而且各个学校参赛队伍数差异很大。中位数是个不错的衡量指标,但它会忽略这个学校最强和最弱的这两群学生。
一个比较直觉的想法是,如果这个学校所有队伍的排名整体比较靠前,则该学校整体实力较强。如果这个学校所有队伍的排名整体比较靠后,则该学校整体实力较弱。
这里可以拿两所学校做个对比。为何会选这两所学校呢?很简单,博主来自于厦大,另外下面那所学校是随机挑的。
|
|
两个学校的整体实力很容易就能看出来了。清华大学的队大部分集中在前500名,表现较好。
另外还想到的就是可能可以利用ROC曲线来衡量一个学校的整体表现。关于ROC的具体介绍,可以看这里。继续以清华为例子,画出它的ROC曲线。
|
|
|
|
这个ROC曲线下的面积成为AUC (area under curve),该部分面积越大,代表整体排名越前。可以利用ROCR包很容易的计算出AUC:
|
|
|
|
AUC的值超过0.5,说明该校整体表现高于平均水准;小于0.5,说明整体表现低于平均水准。
写一个function来计算所有学校的AUC:
|
|
根据AUC排序的榜单
university | auc | num_teams | |
---|---|---|---|
1 | 西南交通大学 | 0.7116 | 11 |
2 | 华中师范大学 | 0.7084 | 10 |
3 | 中国人民大学 | 0.6417 | 9 |
4 | 清华大学 | 0.6233 | 37 |
5 | 香港科技大学 | 0.6228 | 15 |
6 | 北京航空航天大学 | 0.6092 | 22 |
7 | 东北大学 | 0.6062 | 17 |
8 | 华东师范大学 | 0.5975 | 14 |
9 | 中国科学技术大学 | 0.5848 | 47 |
10 | 北京大学 | 0.5785 | 39 |
11 | 武汉大学 | 0.5680 | 19 |
12 | 北京理工大学 | 0.5594 | 25 |
13 | 北京邮电大学 | 0.5489 | 87 |
14 | 浙江大学 | 0.5391 | 97 |
15 | 西北工业大学 | 0.5118 | 8 |
16 | 哈尔滨工业大学 | 0.5106 | 45 |
17 | 广东工业大学 | 0.5073 | 8 |
18 | 上海交通大学 | 0.5047 | 20 |
19 | 大连理工大学 | 0.5006 | 19 |
20 | 南京大学 | 0.4901 | 40 |
21 | 同济大学 | 0.4881 | 15 |
22 | 厦门大学 | 0.4865 | 15 |
23 | 南开大学 | 0.4817 | 11 |
24 | 电子科技大学 | 0.4809 | 56 |
25 | 东南大学 | 0.4769 | 27 |
26 | 中国科学院大学 | 0.4751 | 76 |
27 | 中山大学 | 0.4747 | 35 |
28 | 南京邮电大学 | 0.4724 | 8 |
29 | 天津大学 | 0.4632 | 12 |
30 | 山东大学 | 0.4617 | 14 |
31 | 东华大学 | 0.4585 | 11 |
32 | 西安交通大学 | 0.4277 | 12 |
33 | 复旦大学 | 0.4062 | 25 |
34 | 西安电子科技大学 | 0.4049 | 37 |
35 | 华南理工大学 | 0.4048 | 28 |
36 | 华中科技大学 | 0.3995 | 35 |
上面的学校排名有更符合您心目中的预期吗?
]]>向所有坚持用$\LaTeX$手打公式而不是直接使用截图的偏执狂致敬!
前面花了很大篇幅在说机器为何能学习,接下来要说的是机器是怎么学习的,进入算法$\mathcal{A}$的部分。上一篇稍微提到了几个error的衡量方式,接下来的几篇笔记要讲的就是各种error measurement的区别以及针对它们如何设计最优化的算法。通过设计出来的算法,使得机器能够从$\mathcal{H}$(Hypothesis Set)当中挑选可以使得cost function最小的$h$作为$g$输出。
本篇以众所周知的线性回归为例,从方程的形式、误差的衡量方式、如何最小化$E_{in}$的角度出发,并简单分析了Hat Matrix的性质与几何意义,希望对线性回归这一简单的模型有个更加深刻的理解。
长得很像perceptron(都是直线嘛),perceptron是$h(x)=sign(w^Tx)$。
$h(x)$是一个以$x$为变量的方程,而$E_{in}(w)$变成了一个以$w$为变量的方程。这样一来,我们就把“在$\mathcal{H}$中寻找能使平均误差最小的方程”这个问题,转换为“求解一个函数的最小值”的问题。使得$E_{in}(w)$最小的$w$,就是我们要寻找的那个最优方程的参数。
用矩阵形式表示:
$\color{red}{X}$与$\color{purple}{y}$来源于$\mathcal{D}$,是固定不变的,因此它是一个以$\color{blue}{w}$为变量的函数。我们需要解使得$E_{in}$最小的$\color{blue}{w}$,即$\underset{\color{blue}{w}}{min}\,E_{in}(\color{blue}{w})=\frac{1}{N}\begin{Vmatrix}\color{red}{X}\color{blue}{w}-\color{purple}{y}\end{Vmatrix}^2$。这个$E_{in}(\color{blue}{w})$是一个连续(continuous)、处处可微(differentiable)的凸函数(convex):
对于这一类函数,只需要解其一阶导数为0时的解即可。
关于多元函数的求导,就是线性代数的范畴了:
所以有:
令$\nabla E_{in}(\color{blue}{w})=0$,可得最佳解:
当$\color{red}{X^TX}$可逆的时候用它作为pseudo-inverse矩阵$\color{red}{X^{\dagger}}$,当$\color{red}{X^TX}$不可逆的时候,再用其他方式定义$\color{red}{X^{\dagger}}$,这里就不详述了。
用以$\color{blue}{w_{LIN}}$为参数的线性方程对原始数据做预测,可以得到拟合值$\hat{y}=\color{red}{X}\color{blue}{w_{LIN}}=\color{red}{XX^{\dagger}}\color{purple}{y}$。这里又称$\color{orange}{H}=\color{red}{XX^{\dagger}}$为Hat Matrix,帽子矩阵,$\color{orange}{H}$为$\color{purple}{y}$带上了帽子,成为$\hat{y}$,很形象吧。
这张图展示的是在N维实数空间$\mathbb{R}^N$中,注意这里是N=数据笔数,$\color{purple}{y}$中包含所有真实值,$\hat{y}$中包含所有预测值,与之前讲的输入空间是d+1维是不一样的噢。$\color{red}{X}$中包含d+1个column:
下面来探究一下$\color{orange}{H}$的性质,这个很重要噢。
$$\text{Hat Matrix }\color{orange}{H} = \color{red}{X(X^TX)}^{-1}\color{red}{X^T}:$$
林老师在课堂上讲到:
$$trace(I-\color{orange}{H}) = N-(d+1)$$
$trace$为矩阵的迹。这条性质很重要,但是为什么呢?证明过程有点多,以后有机会再补充,心急的同学可以看这里General formulas for bias and variance in OLS。一个矩阵的$trace$等于该矩阵的所有特征值(Eigenvalues)之和。
假设$\color{purple}{y}$由$\color{red}{f(X)\in span}+noise$构成的。有$\color{purple}{y}=\color{red}{f(X)}+noise$。之前讲到$\color{orange}{H}$作用于某个向量,会得到该向量在$\color{red}{span}$上的投影,而$I-\color{orange}{H}$作用于某个向量,会得到那条与$\color{red}{span}$垂直的向量,在这里就是图中的$\color{green}{y-\hat{y}}$,即$(I-\color{orange}{H})noise=\color{green}{y-\hat{y}}$。
这个$\color{green}{y-\hat{y}}$是真实值与预测值的差,其长度就是就是所有点的平方误差之和。于是就有:
上面的证明不太好整理进来,依然可以参考General formulas for bias and variance in OLS。
因此,就平均而言,有:
花这么大力气是为了什么,又回到之前learning可行性的话题了。
$\color{red}{\overline{E_{in}}}$和$\color{blue}{\overline{E_{out}}}$都向$\sigma ^2$(noise level)收敛,并且他们之间的差异被$\frac{2(d+1)}{N}$给bound住了。有那么点像VC bound,不过要比VC bound来的更严格一些。
]]>这篇笔记是阐述“为什么机器能够学习”这个话题的最后一篇,林老师用了4周时间在告诉我们什么时候机器可以学习以及机器为什么能够学习,对比Ng的那门课,第4周已经在讲类神经网络了。为什么要花这么大的篇幅来搞清楚这些那么理论的东西呢?原因很简单,Ng那门课教的是剑法招式,而林帮主这门课教的是内功。郭靖当年跟着江南七怪习武10多年,进步缓慢,难有所成,但跟着马钰只学了个呼吸吐纳之术,武功却不自觉突飞猛进,原来难以完成的动作突然可以轻松完成了。想要修得真功夫,欲速则不达,林帮主的良苦用心,不知各位同学能否体会。
让我们来回忆一下机器学习的基础架构:
首先我们认为存在一个未知的真理 $f$,认为 $\mathcal{D}$中的$y$就是 $f$作用于$x$产生的,因此虽然无法直接得到 $f$,但若能找到一个和 $f$表现差不多的函数,也算是能学到东西。但在现实世界中,我们拿到的 $\mathcal{D}$并不是完美的,会有noise的存在,什么是noise呢?我们在用收音机听新闻的时候,往往会听到背景有个“沙沙”的声音,信号不好的时候,这种“沙沙”声会越来越大,这个“沙沙”声就是noise。我们耳朵听到的是 $\mathcal{D}$(收音机放出来的东西),我们希望通过 $\mathcal{D}$理解到 $f$(播音员真实要表达的),这个noise就会干扰这个理解的过程, noise越大,我们就越难分辨播音员到底在说什么。在Learning中,noise主要表现为以下几种形式:
$f$ 是一个“确定性”(deterministic)的模型,但$noise$是一个随机发生的东西,他们两个共同作用的结果,就成了一个“概率性”(probabilistic)的东西:
对于某个样本 $x$,理想状态下,应该有$y=f(x)=+1$,但由于某种noise的存在,该noise会有30%的概率会转换$f(x)$的结果(把+1变成-1或把-1变成+1)。因此在$\mathcal{D}$中,该样本有70%的概率表现出$y=+1$,30%的概率表现出$y=-1$.
再举个例子来对比下不考虑noise与考虑noise的情形有什么不同。假设不存在noise的情况下,某个hypothesis $h$在$\mathcal{D}$中的错误率$E_{in}=\mu$。现在考虑加上一个 ‘flipping’ noise level $=1-\lambda$的noise,即:
考虑到了noise,$h$判断正确的样本当中,实际只有$\lambda$这么多的比例是真的判断正确的,同理$h$判断错误的样本中,实际也只有$\lambda$这么多的比例是真的判断错误。假设$\mathcal{D}$中样本量为N:
因此,如果存在noise,则$h$判断错误的数量实际应该为$\lambda \mu N + (1-\lambda)(1-\mu)N$这么多,$h$真实的$E_{in}=\lambda \mu + (1-\lambda)(1-\mu)$。稍微做个合并,得到:
$$\text{true }E_{in} = (2\lambda - 1)\mu + (1-\lambda)$$
假设通过学习我们得到一个$g$,并且有$E_{in}(g)=0.2$(即$\mu = 0.2$),若学习所用的$\mathcal{D}$中存在 ‘flipping’ level=0.1 的noise(即$
\lambda = 0.9$),则真实的$E_{in}(g)=0.26$。若 ‘flipping’ level 达到0.2,则真实的$E_{in}(g) = 0.32$。可见noise的存在对learning是有一定影响的,在noise较大的情况下,算出的$E_{in}$与真实的$E_{in}$也会有很大的差别。因此想要学得好,$\mathcal{D}$的质量非常重要。
在把learning的工作交给机器的时候,必须让机器明白你学习的目标,譬如你想让什么什么最大化,或者什么什么最小化。通常的做法是把每一个预测值与真实值之间的误差(error)看成一种成本,机器要做的,就是在$\mathcal{H}$中,挑选一个能使总成本最低的函数。
之前提到的二元分类问题,就是对判断错误的点,记误差为1,判断正确的点,记误差为0:
不管是把$y=+1$的猜错成$-1$,或是把$y=-1$的猜错成$+1$,其产生的误差都为1。
在实际应用中,这个误差的定义可以很灵活,例如下面两个指纹验证的例子:
超市利用指纹识别判断某个人是否是他们的会员,若是会员会给相应的折扣。这种情形下,可能做出两种不同的错误判断,把非会员错认为是会员,把会员错认为是非会员。但对于超市来说,这两种错误的成本应该是不同的。把非会员错认为是会员,无非损失些许的折扣;但若是把会员识别为非会员从而不给折扣,就会导致顾客的不满,从而损失掉了未来的生意。针对这种需求,或许下面这个error的衡量办法会更加合理一些。把+1(会员)错判为-1(非会员)的error为10,把-1错判为+1的error为1。
(f代表真实值,g代表预测值)
中情局的门禁系统,利用指纹判断是内部工作人员,才允许进入。这种情形下,若是把好人当坏人,代价并不高,无非就是请工作人员多按一次指纹的功夫,但如果把坏人当好人,损失可就大了。针对这种需求,下面这个error的衡量办法可能更加合理。
之前一直说的$E_{in}(h)$,就是$h$作用于$\mathcal{D}$中每一笔数据,所产生的成本之和:
对于上面中情局的例子,$err(h,x_n,y_n)$的定义如下:
这种误差衡量方式称为”pointwise measure”,即对每个点记录误差,总误差为所有点产生的误差之和。在Ng那门课上,这个$E_{in}(h)$被称为cost function,通过cost function可以计算出当前$h$作用于$\mathcal{D}$所造成的总成本,通过learning找到一个能够使总成本最小的$h$,就完成了学习的过程。
针对不同的问题与不同的使用环境,我们可以设计不同的误差衡量方法,下面是集中常见的误差的定义:
0/1 error ,通常用于分类问题:
$err(\widetilde{y},y)=[\widetilde{y}\neq y]$
squared error,通常用于回归问题:
$err(\widetilde{y},y)=(\widetilde{y}-y)^2$
absolute error:
$err(\widetilde{y},y)=abs(\widetilde{y}-y)$
总结一下,先根据问题的不同选择合适的误差衡量方式,0/1 error还是squared error或者是其他针对某一场景特殊设计的error?把$h$作用于$\mathcal{D}$中所有点的error加总起来就成了一个cost function,也就是$E_{in}(h)$,接着要设计一个最优化算法$\mathcal{A}$,它能够从$\mathcal{H}$中挑选出能够使$E_{in}$最小的方程$g$,learning就完成了。对于不同类型的cost function,通常会使用不同的最优化算法。对于某些cost function,很容易实现$E_{in}$最小,比如之后会说的线性回归。对于某些cost function,寻找最小的$E_{in}$是困难的,回忆之前说的PLA,用0/1 error来衡量误差,要minimize $E_{in}$就是个NP Hard问题。
当然除此之外,cost function中还可以增加一些来自于error之外的成本,以达到限制模型复杂度方面的目的,如ridge regression、lasso等,这些以后有机会都会提到。
]]>上一篇讲到了VC Dimension以及VC Bound。VC Bound所描述的是在给定数据量N以及给定的Hypothesis Set的条件下,遇到坏事情的概率的上界,即$E_{in}$与$E_{out}$差很远的概率,最多是多少。VC Bound用公式表示就是:
其中$m_{\mathcal{H}}(N)$为Hypothesis Set的成长函数,有:
因为寻找所有Hypothesis Set的成长函数是困难的,因此我们再利用$N^{d_{vc}}$来bound住所有VC Dimension为$d_{vc}$的Hypothesis Set的成长函数。所以对于任意一个从$\mathcal{H}$中的$g$来说,有:
因此说想让机器真正学到东西,并且学得好,有三个条件:
为什么要费那么大的力气来讲这个VC Bound和VC Dimension呢?因为对于初学者来说,最常犯的错误就是只考虑到了第3点,而忽略掉了前两点,往往能在training set上得到极好的表现,但是在test set中表现却很烂。关于算法$\mathcal{A}$的部分会在后续的笔记当中整理,目前我们只关心前面两点。
对于以下几个$\mathcal{H}$,由于之前我们已经知道了他们的成长函数(见机器学习笔记-VC Dimension, Part I),因此可以根据$m_{\mathcal{H}}(N)\leq N^{d_{vc}}$,直接得到他们的VC Dimension:
由于convex sets的$d_{vc}=\infty$,不满足上面所说的第1个条件,因此不能用convex sets这个$\mathcal{H}$来学习。
但这里要回归本意,通过成长函数来求得$d_{vc}$没有太大的意义,引入$d_{vc}$很大的一部分原因是,我们想要得到某个Hypothesis Set的成长函数是困难的,希望用$N^{d_{vc}}$来bound住对应的$m_{\mathcal{H}}(N)$。对于陌生的$\mathcal{H}$,如何求解它的$d_{vc}$呢?
Homework当中的某题,求解简化版决策树的VC Dimension:
Consider the simplified decision trees hypothesis set on $\mathbb{R}^d$, which is given by
That is, each hypothesis makes a prediction by first using the $d$ thresholds $t_i$ to locate $x$ to be within one of the $2^d$ hyper-rectangular regions, and looking up $S$ to decide whether the region should be +1 or −1. What is the VC-dimension of the simplified decision trees hypothesis set?
如何去理解题意呢?用一个2维的图来帮助理解:
首先把二维实数空间$\mathbb{R}^2$中的向量$x$,通过各个维度上的阈值$t_i$,转换到${{0,1}}^2$空间下的一个点$v$,规则为$v_i=[x_i\gt t_i]$。譬如对于$t=[5,10]$,$x=[6,8]$可以转换为新的空间下的$[1,0]$。这样一来,原来的$\mathbb{R}^2$空间就可以被划分为4个区块$S_1$~$S_4$(hyper-rectangular regions)。$\mathcal{H}$中每一个方程$h$代表着一种对这4块区域是”圈圈“还是”叉叉“的决策(decision),并且这4块区域的决策是互相独立的,$S_1$的决策是”圈圈“还是”叉叉“和$S_2,S_3,S_4$都没有关系。
由于这4块区域的决策是互相独立的,那么它最多最多能shatter掉多少个点呢?4个,(当这4个点分别属于这4块区域的时候),即这4块hyper-rectangular regions所代表的类别可以是(o,o,o,o)、(o,o,o,x)、(o,o,x,o)、…、(x,x,x,x),共16种可能,因此它能够shatter掉4个点。
由上面2维的例子我们可以看出,simplified decision trees的VC Dimension,等于hyper-rectangular regions的个数。$d$维空间$\mathbb{R}^d$可以用$d$条直线切分出$2^d$个互相独立的hyper-rectangular regions,即最多最多可以shatter掉$2^d$个点,因此simplified decision trees的$d_{vc}=2^d$。
我们再来回顾一下Positive Intervals:
也可以按照上面的方法去理解,Positive Intervals有两个thresholds,把直线切分为3块空间。但这3块空间并不是相互独立,中间的部分永远是+1,左右两边永远是-1,所以还要具体看它能够shatter掉多少个点,这里最多最多只能shatter掉2个点,它的$d_{vc}=2$。
对于$d_{vc}$较小的$\mathcal{H}$,可以从它最多能够shatter的点的数量,得到$d_{vc}$,但对于一些较为复杂的模型,寻找能够shatter掉的点的数量,就不太容易了。此时我们可以通过模型的自由度,来近似的得到模型的$d_{vc}$。
维基百科上有不止一个关于自由度的定义,每种定义站在的角度不同。在这里,我们定义自由度是,模型当中可以自由变动的参数的个数,即我们的机器需要通过学习来决定模型参数的个数。
譬如:
Homework当中某题,求$K$个Hypothesis Set的并集$d_{vc}(\cup_{k=1}^{K}\mathcal{H}_k)$的VC Dimension的上下界。下界比较好判断,是$max\{d_{vc}(\mathcal{H}_k)\}_{k=1}^K$,即所有的$\mathcal{H}$都包含于$d_{vc}$最大的那个$\mathcal{H}$当中的时候。上界则出现在各个$\mathcal{H}$互相都没有交集的时候,我们不妨先来看看$K=2$的情况:
求$d_{vc}(\mathcal{H}_1\cup \mathcal{H}_2)$的上界,已知$d_{vc}(\mathcal{H}_1)=d_1$,$d_{vc}(\mathcal{H}_2)=d_2$。
从成长函数上看,有 $m_{\mathcal{H}_1\cup \mathcal{H}_2}(N) \leq m_{\mathcal{H}_1}(N) + m_ {\mathcal{H}_2}(N)$,把成长函数展开,有
用$\binom{N}{i}=\binom{N}{N-i}$替换RHS,有
我们可以尝试寻找下上面这个成长函数有可能的最大的break point,让$N$不断增大,直到出现$m_{\mathcal{H}_1\cup \mathcal{H}_2}(N)\lt 2^N$的时候,这个$N$就是break point。那么$N$要多大才够呢?
$N=d_1$够大吗?不够,因为:
$N=d_1+d_2+1$够大吗?还是不够,因为:
$N=d_1+d_2+2$够大吗?够大了,因为:
所以$m_{\mathcal{H}_1\cup \mathcal{H}_2}(N)$的break point最大可以是$d_1+d_2+2$,此时$d_{vc}(\mathcal{H}_1\cup \mathcal{H}_2)=d_1+d_2+1$。
因此两个$\mathcal{H}$的并集的VC Dimension的上界为$d_{vc}(\mathcal{H}_1)+d_{vc}(\mathcal{H}_2)+1$。利用此方法,就很容易可以推出$K$个$\mathcal{H}$的并集的情况。
机器学习笔记-VC Dimension, Part I一开始就提到,learning的问题应该关注的两个最重要的问题是:1.能不能使$E_{in}$与$E_{out}$很接近,2.能不能使$E_{in}$足够小。
令之前得到的VC Bound为$\delta$,坏事情$[|E_{in}(g)-E_{out}(g)|\gt \epsilon]$发生的概率小于$\delta$,则好事情$[|E_{in}(g)-E_{out}(g)|\leq \epsilon]$发生的概率就大于$1-\delta$,这个$1-\delta$在统计学中又被称为置信度,或信心水准。
因此$E_{in}$、$E_{out}$又有下面的关系:
令$\Omega (N,\mathcal{H},\delta)=\sqrt{…}$,即上式的根号项为来自模型复杂度的,模型越复杂,$E_{in}$与$E_{out}$离得越远。
随着$d_{vc}$的上升,$E_{in}$不断降低,而$\Omega$项不断上升,他们的上升与下降的速度在每个阶段都是不同的,因此我们能够寻找一个二者兼顾的,比较合适的$d_{vc}^{*}$,用来决定应该使用多复杂的模型。
反过来,如果我们需要使用$d_{vc}=3$这种复杂程度的模型,并且想保证$\epsilon = 0.1$,置信度$1-\delta =90\%$,我们也可以通过VC Bound来求得大致需要的数据量$N$。通过简单的计算可以得到理论上,我们需要$N\approx 10,000d_{vc}$笔数据,但VC Bound事实上是一个极为宽松的bound,因为它对于任何演算法$\mathcal{A}$,任何分布的数据,任何目标函数$f$都成立,所以经验上,常常认为$N\approx 10d_{vc}$就可以有不错的结果。
]]>上一篇用成长函数$m_{\mathcal{H}}(N)$来衡量Hypotheses Set $\mathcal{H}$中有效的方程的数量(Effective Number of Hypotheses),以取代Hoeffding’s Inequality中的大$M$,并用一种间接的方式 —- break point,来寻找$m_{\mathcal{H}}(N)$的上界,从而避免了直接研究$\mathcal{H}$的成长函数的困难。
$$m_{\mathcal{H}}(N)\leq \sum_{i=0}^{k-1}\binom {N}{i}$$
根据之前得到的式子,我们知道如果一个$\mathcal{H}$存在break point,我们就有办法保证学出来的东西能够“举一反三”(good generalization)。一般来说break point越大的$\mathcal{H}$,其复杂度也更高,我们可以使用vc dimension来描述一个$\mathcal{H}$的复杂程度,这个vc dimension来自Vladimir Vapnik与Alexey Chervonenkis所提出的VC Theory。
根据定义,一个$\mathcal{H}$的vc dimension(记为$d_{vc}(\mathcal{H})$),是这个$\mathcal{H}$最多能够shatter掉的点的数量 (the largest value of N for which $m_{\mathcal{H}}(N)=2^N$),如果不管多少个点$\mathcal{H}$都能够shatter他们,则$d_{vc}(H)=\infty$。不难看出$d_{vc}$与break point k的关系,有$k=d_{vc}+1$,因此我们用这个$d_{vc}$来描述成长函数的上界:
$$m_{\mathcal{H}}(N)\leq \sum_{i=0}^{d_{vc}} \binom {N}{i}$$
上式右边(RHS)事实上是最高项为$d_{vc}$的多项式,利用数学归纳法可得:
$$m_{\mathcal{H}}(N)\leq \sum_{i=0}^{d_{vc}} \binom {N}{i} \leq N^{d_{vc}}+1$$
上一篇的末尾我们设想利用有限的$m_{\mathcal{H}}(N)$来替换无限的大$M$,得到$\mathcal{H}$遇到Bad Sample的概率上界:
$$\mathbb{P}_\mathcal{D}[BAD\ D]\leq 2m_{\mathcal{H}}(N)\cdot exp(-2\epsilon ^2N)$$
其中$\mathbb{P}_\mathcal{D}[BAD\ D]$是$\mathcal{H}$中所有有效的方程(Effective Hypotheses)遇到Bad Sample的联合概率,即$\mathcal{H}$中存在一个方程遇上bad sample,则说$\mathcal{H}$遇上bad sample。用更加精准的数学符号来表示上面的不等式:
$$\mathbb{P}[\exists h \in \mathcal{H}\text{ s.t. } |E_{in}(h)-E_{out}(h)|\gt \epsilon]\leq 2m_{\mathcal{H}}(N)\cdot exp(-2\epsilon ^2N)$$
注:$\exists h \in \mathcal{H}\text{ s.t. }$ - $\mathcal{H}$中存在($\exists$)满足($\text{ s.t }$)…的$h$
但事实上上面的不等式是不严谨的,为什么呢?$m_{\mathcal{H}}(N)$描述的是$\mathcal{H}$作用于数据量为$N$的资料$\mathcal{D}$,有效的方程数,因此$\mathcal{H}$当中每一个$h$作用于$\mathcal{D}$都能算出一个$E_{in}$来,一共能有$m_{\mathcal{H}}(N)$个不同的$E_{in}$,是一个有限的数。但在out of sample的世界里(总体),往往存在无限多个点,平面中任意一条直线,随便转一转动一动,就能产生一个不同的$E_out$来。$E_{in}$的可能取值是有限个的,而$E_{out}$的可能取值是无限的,无法直接套用union bound,我们得先把上面那个无限多种可能的$E_{out}$换掉。那么如何把$E_{out}$变成有限个呢?
假设我们能从总体当中再获得一份$N$笔的验证资料(verification set)$\mathcal{D}’$,对于任何一个$h$我们可以算出它作用于$\mathcal{D}’$上的$E_{in}^{‘}$,由于$\mathcal{D}’$也是总体的一个样本,因此如果$E_{in}$和$E_{out}$离很远,有非常大的可能$E_{in}$和$E_{in}^{‘}$也会离得比较远。
事实上当N很大的时候,$E_{in}$和$E_{in}^{‘}$可以看做服从以$E_{out}$为中心的近似正态分布(Gaussian),如上图。$[|E_{in}-E_{out}|\text{ is large}]$这个事件取决于$\mathcal{D}$,如果$[|E_{in}-E_{out}|\text{ is large}]$,则如果我们从总体中再抽一份$\mathcal{D}^{‘}$出来,有50%左右的可能性会发生$[|E_{in}-E_{in}^{‘}|\text{ is large}]$,还有大约50%的可能$[|E_{in}-E_{in}^{‘}|\text{ is not large}]$。
因此,我们可以得到$\mathbb{P}[|E_{in}-E_{out}|\text{ is large}]$的一个大概的上界可以是$2\mathbb{P}[|E_{in}-E_{in}^{‘}|\text{ is large}]$,以此为启发去寻找二者之间的关系。
引理:
$$(1-2e^{-\frac{1}{2}\epsilon^2N})\mathbb{P}[\underset{h\in \mathcal{H}}{sup}\ |E_{in}(h)-E_{out}(h)| \gt \epsilon]\leq \mathbb{P}[\underset{h\in \mathcal{H}}{sup}\ |E_{in}(h)-E_{in}^{‘}(h)| \gt \frac{\epsilon}{2}]$$
上面的不等式是从何而来的呢?我们先从RHS出发:
上式第二行的不等号可以由$\mathbb{P}[\mathcal{B}_1]\geq \mathbb{P}[\mathcal{B}_1 \textbf{ and } \mathcal{B}_2]$得到,第三、四行则是贝叶斯公式,联合概率等于先验概率与条件概率之积。
下面来看看不等式的最后一项$\mathbb{P}[\underset{h\in \mathcal{H}}{sup}\ |E_{in}(h)-E_{in}^{‘}(h)| \gt \frac{\epsilon}{2}\;\;|\;\;\underset{h\in \mathcal{H}}{sup}\ |E_{in}(h)-E_{out}(h)| \gt \epsilon]$。对于一个固定的data set $\mathcal{D}$来说,我们任选一个$h^{*}$使得$|E_{in}(h^{*})-E_{out}(h^{*})|\gt \epsilon$,注意到这个$h^{*}$只依赖于$\mathcal{D}$而不依赖于$\mathcal{D}^{‘}$噢,对于$\mathcal{D}^{‘}$来说可以认为这个$h^{*}$ is forced to pick out。
由于$h^{*}$是对于$\mathcal{D}$来说满足$|E_{in}-E_{out}|\gt \epsilon$的任意一个hypothesis,因此可以把式子中的上确界(sup)先去掉。
这里就要稍微出动一下前人的智慧了:
为了直观一点$h^{*}$就不写了。经过各种去掉绝对值符号又加上绝对值符号的运算,可以发现LHS的两个不等式是RHS那个不等式的充分非必要条件。而LHS第二个不等式是已知的,对于$h^{*}$必成立的。因此我们拿LHS这个充分非必要条件去替换RHS这个不等式,继续前面的不等式:
最后一个不等号动用了Hoeffding Inequality:
之前说过对于$\mathcal{D}^{‘}$来说,$h^{*}$ is forced to pick out,因此$M=1$。接着把$\epsilon$替换为$\frac{\epsilon}{2}$,就成了$\mathbb{P}[|…|\lt \frac{\epsilon}{2}]\geq 2exp(-\frac{1}{2}\epsilon^2N)$。则我们可以得到引理中的不等式。
对于$e^{-\frac{1}{2}e^2N}$,一个比较合理的要求是$e^{-\frac{1}{2}\epsilon^2N}\lt \frac{1}{4}$,譬如我们有400笔资料,想要$E_{in}$和$E_{out}$相差不超过0.1。注意到这只是一个bound,只要要求不太过分,也不能太宽松即可,适当的宽松一点是OK的。当然这里也是想跟之前所说的 “$\mathbb{P}[|E_{in}-E_{out}|\text{ is large}]$的一个大概的上界可以是$2\mathbb{P}[|E_{in}-E_{in}^{‘}|\text{ is large}]$” 当中的2倍有所结合。
所以就有$1-2e^{-\frac{1}{2}e^2N}\gt \frac{1}{2}$。带回引理,可得:
$$\mathbb{P}[\underset{h\in \mathcal{H}}{sup}\ |E_{in}(h)-E_{out}(h)| \gt \epsilon]\leq 2\,\mathbb{P}[\underset{h\in \mathcal{H}}{sup}\ |E_{in}(h)-E_{in}^{‘}(h)| \gt \frac{\epsilon}{2}]$$
这样一来我们就把无限多种的$E_{out}$换成了有限多种的$E_{in}$,因为$\mathcal{D}$与$\mathcal{D}^{‘}$的大小相等,都为$N$,因此我们手中一共有$2N$笔数据,这样$\mathcal{H}$作用于$\mathcal{D}+\mathcal{D}^{‘}$最多能产生$m_{\mathcal{H}}(2N)$种dichotomies。此时我们针对上面的不等式,就又可以使用union bound了。(关于union bound,可以参考上一篇VC Dimension, Part I)
前面的动作相当于先从总体中抽出$2N$笔数据,把这$2N$笔数据当成一个比较小的bin,然后在这个bin中抽取$N$笔作为$\mathcal{D}$,剩下的$N$笔作为$\mathcal{D}^{‘}$,$\mathcal{D}$和$\mathcal{D}^{‘}$之间是没有交集的。在我们想象出来的这个small bin当中,整个bin的错误率为$\frac{E_{in}+E_{out}}{2}$,又因为:
$$|E_{in}-E_{in}^{‘}|\gt \frac{\epsilon}{2} \Leftrightarrow |E_{in} - \frac{E_{in}+E_{in}^{‘}}{2}|\gt \frac{\epsilon}{4}$$
所以用RHS替换LHS之后,前面不等式就又可以使用Hoeffding inequality了:
这上面千辛万苦得出来的这个bound就叫做Vapnik-Chervonenkis (VC) bound:
]]>今年4月份偶然跟高中同班的一位同学用QQ聊了几句(这人现在港科大读PHD,主攻AI方向,真正的大神),他向我推荐了一个好东西—Coursera。Coursera是由stanford大学教授创办的大规模开放在线课堂(MOOC),和苹果较早推出的iTunes U很类似,只不过Coursera提供更加丰富的学习体验。在Coursera上每门课需要完成一定量的作业,如果达到开课老师规定的毕业标准,在课程结束之后可以获得一份电子版的证书 (Statement of Accomplishment),类似下面这个东西:
更加有趣的是,在Coursera的讨论区中,可以直接与一起修课的同学,助教,甚至是老师进行交流。 不需要花钱就能享受世界上最棒的那些学校的优质课程,何乐而不为?于是这大半年,有很大一部分精力都花在了Coursera上面。这大半年我一共学了这些课:
今年有一件比较得意的事情就是,暑假参加了台湾SAS举办的「第二屆SAS校園資料採礦競賽」,拿到了第二名(银牌奖)。因为每一届比赛是用同一个比赛网站,所以这个需要截图纪念一下:
决赛结果:
此次比赛共有86队325名同学参加,题目是利用玉山银行房贷申请的历史数据,建制信用风险模型,预测申请户发生房贷违约的风险。初赛从86支队伍中选出准确度最高的前20队进入复赛(我们在准确度上排名第2),复赛阶段评审由各队所提交的模型建制说明ppt中,选出流程合理、理论完善的10队进入决赛,决赛则展现的是各队的现场报告能力,以及回答评委发问的应变能力。最终我们获得了银牌,拿走了10万台币的奖金,结果还是值得感到欣喜的。参加比赛的时候刚好修完Ng开的Machine Learning课,因此许多灵感都来源于那门课。我希望今年找个时间,把参赛的经验整理成一篇blog。
今年比较头大的事情是提论文计划。毕竟已经到了研二了,要想毕业就得写论文。不过我对写论文这方面的事总提不起太大的兴致。不过再纠结了一段时间,认真读了和我研究相关的一些papers之后,也提出了自己的方法。有了前面比赛的一些经验,我论文研究的方向也是与信用风险评分(credit scoring)有关。祈求今年做实验的时候也能会有好结果出来吧。
尽管这是个无人知晓的博客,连百度和google都嫌弃,但我觉得这仍然是我本年度干的最牛逼的一件事儿。作为一个伪geek,我没有直接把blog写在新浪,网易或者啥啥博客上面,而是选择自己搭一个,谁说小菜鸟不可以?
整个blog是用markdown来写的,所以格式什么的也很简单,字都只有一个颜色,好处在于简洁专注,不需要太去思考排版(习惯word的人换用markdown来写确实有耳目一新的感觉)。还有就是想在文章内插入公式也比较方便,但也辛苦,起初因为不懂markdown和mathjax的冲突问题,需要耗费大量时间才能使公式正常显示出来,曾经光为了几个公式就折腾了我两整天,就是为了公式能够更漂亮的展示出来,你会发现这里面所有公式都不是图片,都是可以放大缩小的噢。不过偶然的一次总算被我发现问题所在,所以基本现在markdown和mathjax也比较顺利能够和谐相处了。过段时间准备写一篇来说说如何让他们和谐相处的故事。
blog是利用hexo生成出静态网页并同步到github上,因此不需要花费额外的费用,除了每年几十块的域名(beader.me)费用。
马年马上就要到了,马年有什么计划吗?马年最大的心愿当然是马上有工作啦。对于找工作还是弱弱地有点担忧,貌似自己水平还远远不够。不管怎么说,加油吧,当然不能忘记继续学习充电。我发现在学习ML方面的课程时,线性代数真的太重要了,尤其是之后学习一些较为复杂的ML方法时,需要非常深厚的线性代数知识。希望我能有时间把国立交通大学周志成教授的线性代数学一遍,并且多逛逛他的blog-线代启示录。另外就是把这些根基打牢之后,能够往当下很火热的deep learning方向探一探足。想要做的事情还有很多,说多了便不容易做了,希望都能一一实现。
最后当然是希望自己的家人朋友同学老师以及看到此处的你,能够平安幸福。
上一篇讲到,learning的时候如果遇上bad sample,如果遇上bad sample我们就无法保证$E_{in}$和$E_{out}$很接近。我们用了一个不等式来衡量遇上bad sample的概率:
$$\mathbb{P}_\mathcal{D}[BAD\ D]\leq 2Mexp(-2\epsilon ^2N)$$
因此如果Hypothesis Set中方程的数量$|\mathcal{H}|=M$是有限个,并且N足够大的时候,我们就有很大的概率保证不会遇上bad sample,即不管$\mathcal{A}$挑选了任意一个$g$,都可以保证$E_{out}(g) \approx E_{in}(g)$。因此learning的问题可以聚焦到以下两个问题:
这里我们便遇到了一个两难的选择:
因此这篇笔记主要围绕公式中这个$M$展开:
$$\mathbb{P}[| E_{in}(g) - E_{out}(g) | \gt \epsilon] \leq 2\cdot M \cdot exp(-2\epsilon ^2N)$$
让我们来回忆下这个M是从哪里来的。记$\mathcal{H}$中第m个方程遇到bad sample为事件$\mathcal{B}_m:|E_{in}(h_m) - E_{out}(h_m)| \gt \epsilon$,则$\mathcal{H}$遇到bad sample的概率为其所有方程遇到bad sample概率的联合概率。如果每个方程遇上bad sample这件事是互相独立的,则$\mathcal{H}$遇上bad sample的概率是各方程遇上bad sample的概率之和,因此他们的联合概率一定小于等于各个事件单独发生的概率之和。
$$\mathbb{P}[\mathcal{B}_1 or \mathcal{B}_2 or … or \mathcal{B}_M] \leq \mathbb{P}[\mathcal{B}_1] + \mathbb{P}[\mathcal{B}_2] + … + \mathbb{P}[\mathcal{B}_M]$$
但事实上bad event并不是完全独立的。想象$\mathcal{H}$两个非常类似的方程$h_1\approx h_2$,他们遇到bad sample分别为事件$\mathcal{B}_1$与$\mathcal{B}_2$,因为这两个方程很接近,则往往$\mathcal{B}_1$发生时,$\mathcal{B}_2$也会发生,可以说$\mathcal{B}_1$与$\mathcal{B}_2$的重合度很高(overlapping)。
那么我们就会想,我们能不能把结果接近的那些方程看成一类,譬如有些方程他们的预测结果总是相同或是很接近的。
假设我们的算法要在平面上挑选一条直线方程作为$g$,$\mathcal{H}={all\ lines\ in\ \mathbb{R}^2}$,$\mathcal{H}$当中有无限多个方程,但我们可以把这些个方程归为两类。一类是把$x_1$判断成圈圈的,另一类是把$x_1$判断为叉叉的。
那如果我们手中有2个数据点$x_1$和$x_2$呢?这样的话$\mathcal{H}$中无数条直线可以分为4类。用这4类线对$x_1$和$x_2$进行预测,一共能产生4种不同的结果。
那如果我们手中有3个数据点$x_1$、$x_2$和$x_3$呢?
$\mathcal{H}$中最多有8类直线,作用于$\mathcal{D}$产生如上8种结果。
那如果我们手中有4个数据点$x_1$~$x_4$,情况又会是怎样。前面的例子中我们基本上把各个数据点的情况用排列组合的方式组合出来即可。但对于4个以上的点而言,就不是那么容易了。
在这16种组合中,就有两种是“直线方程”没有办法产生的结果。因此如果$\mathcal{H}$是2维空间中的所有直线,表面上看是在无数条直线方程中去挑,但由于大部分直线方程所产生的结果是一模一样的,结果不一样的直线的类别对应上面的例子分别为2类、4类、8类和14类(Effective Number of Lines)。属于同一类的直线,他们将同时遇到或不遇到bad sample,由于之前那个union bound是基于独立性的假设下的,因此$\mathcal{H}$遭遇bad sample的概率明显被夸大了。所以,我们应该把不等式改写为:
$$\mathbb{P}[|E_{in}(g)-E_{out}(g)|\gt \epsilon]\leq 2\cdot effective(N)\cdot exp(-2\epsilon^2N)$$
从$\mathcal{H}$中任意选取一个方程$h$,让这个$h$对$\mathcal{D}$进行二元分类,输出一个结果向量,比如对4个点进行预测,输出${\mathrm{o},\mathrm{o},\mathrm{o},\times}$,这样的一个输出向量我们称它为一个dichotomy。不难得出,一个直线方程在$\mathcal{D}$中对应一个dichotomy,但一个dichotomy至少对应一个直线方程,我们把一个dichotomy对应的所有直线方程视为一类,则effective number of lines就等于不同$\mathcal{D}$中不同的dichotomy的数量。显然这个dichotomy的数量小于等于所有数据点的排列组合数的,例如上图中画大叉的那幅图对应的排列组合,就不能成为一个dichotomy,因为它们无法由任何一条直线方程产生。(当然如果考虑的不是直线方程,则那种排列组合是可以成为一种dichotomy的)
因此我们前面要找的
$effective(N)$
=平面中能找出多少条不同类的直线
=$\mathcal{H}$作用于$\mathcal{D}$能产生多少不同的dichotomy。
因为不一定所有排列组合都能成为dichotomy,所以不同的dichotomy的数量一定不会超过排列组合数$2^N$,上例中如果存在三点共线的情况,则dichotomy的数量会更少,因此:
$effective(N)$
=$\mathcal{H}$作用于$\mathcal{D}$“最多”能产生多少不同的dichotomy
那么,$\mathcal{H}$作用于$\mathcal{D}$“最多”能产生多少种不同的dichotomy呢?这个数量与$\mathcal{H}$有关,也与数据量$N$有关。用数学式可以表达为:
$$max|\mathcal{H}(x_1,x_2,…,x_N)|$$
上式又称为成长函数(growth function)。在$\mathcal{H}$确定的情况下,growth function是一个与N相关的函数。以下是几种常见的Hypothesis Set的成长函数。
Positive Rays
输入空间为一维实数空间。大于threshold a的预测+1,否则预测-1。
for example: 当N=4时,Positive Rays作用于$x_1$~$x_4$,共能产生5个不同的dichotomies。如下图:
不难去想,4个点,5个可能的切点,最多产生5种dichotomies。因此Positive Rays的成长函数为:
$$m_{\mathcal{H}(N)}=N+1$$
Positive Intervals
和前面的类似,只不过Positive Intervals有两个threshold,夹在两个threshold之间的预测为+1,其余预测为-1。
for example: 当N=4时,Positive Intervals作用于$x_1$~$x_4$,共能产生11种dichotomies。如下图:
同样不难去想,4个点,5个可能的切点选两个作为threshold,加上两个threshold重合产生的一种,因此Positive Intervals的成长函数为:
$$m_{\mathcal{H}(N)}=\binom{N+1}{2} + 1 = \frac{1}{2}N^2 + \frac{1}{2}N + 1$$
Convex Sets
任选k个点,在这k个点组成的convex多边形包围内的所有点都预测+1,否则预测-1。前面我们说到成长函数描述的是“最多”能产生的dichotomy种数,因此如果我们这N个input摆成一个圈,则这N个点的任意一种排列组合都能成为一个dichotomy。因此Convex Sets的成长函数为:
$$m_{\mathcal{H}(N)}=2^N$$
当$\mathcal{H}$作用于有N个inputs的$\mathcal{D}$时,产生的dichotomies数量等于这N个点的排列组合数$2^N$时,我们就称这N个inputs被$\mathcal{H}$给shatter掉了。或者也可以说$\mathcal{H}$产生的$2^N$个dichotomies把这N个点的$2^N$种排列组合给shatter了。
这个shatter的意思似乎不太好理解,这是林老师在讨论区中的回复:
“大家對 break point 的討論很好,不過注意到 shatter 的原意是「打碎」,在此指「N 個點的所有(碎片般的)可能情形都被$\mathcal{H}$產生了」。所以$m_{\mathcal{H}}(N)=2^N$ 的情形是「shatter」。”
我从打游戏过关的角度去理解,shatter作打碎理解:
“$m_{\mathcal{H}}$是把散弹枪,在每个关卡(level N)中,他可以有$m_{\mathcal{H}}(N)$发小子弹(每发小子弹对应一种dichotomy),而你面临的是$2^N$个敌人。你得一枪打出去shatter掉所有人。对于$m_{\mathcal{H}}(N)=2N$这把散弹枪来说,第一关和第二关都还好,第三关6发小子弹shatter不掉8个人,于是它就break了。”
对于给定的成长函数$m_{\mathcal{H}}(N)$,从$N=1$出发,N慢慢增大,当增大到k时,出现$m_{\mathcal{H}}(k)\lt 2^k$的情形,则我们说k是该成长函数的break point,对于任何$N \gt k$个inputs而言,$\mathcal{H}$都没有办法再shatter他们。
不难根据成长函数得出Positive Rays成长函数的break point为2,Positive Intervals成长函数的break point为3,Convex Sets不管N多大都可以去shatter掉那N个点,因此它的成长函数没有break point。2D Perceptrons的break point为4,因为在N=3时,它都能够shatter,产生$2^3=8$种dichotomies,当N=4时,它不能够shatter,最多只能产生14 ($\lt 2^4 = 16$) 种dichotomies,因此2D Perceptrons成长函数的break point为4。
有些$\mathcal{H}$的成长函数很容易找到,比如前面说到的Positive Rays、Positive Intervals以及Convex Sets;有些$\mathcal{H}$则没有那么容易,比如2D perceptrons,我们无法直接看出它的成长函数是什么,那么我们对于这样的$\mathcal{H}$就没辙了吗?也不完全是,至少我们手上还掌握着它的break point,能不能用这个break point干点事呢?如果没办法得到成长函数,能得到成长函数的upper bound也是不错的。
先用例子来看看,当我们完全不知道$\mathcal{H}$是什么,只知道它的break point k时,$\mathcal{H}$作用于$\mathcal{D}$“最多最多”可以产生多少这dichotomies。注意这里我用了两个“最多”,由于我们无法确切知道成长函数,因此我们用这个break point推算出的这个dichotomies的数量仍然是个高估值,这个高估值实际上是任何break point为k的$\mathcal{H}$作用于$\mathcal{D}$所真实产生的dichotomies数量的上界 (upper bound)。
举例说明,假设我们不知道某个$\mathcal{H}$的成长函数$m_{\mathcal{H}}(N)$,但知道它的break point k=2,那么$\mathcal{H}$作用于N=3的$\mathcal{D}$时,“最多最多”能产生多少种dichotomies?
从k=2我们可以知道,任意2个数据点都不能被shatter。还记得shatter的概念吗?意思就是我产生的dichotomies不能完全包含任何2个数据点所有的排列组合。让我们从1个dichotomy开始。
1 dichotomy
2 dichotomies
3 dichotomies
注意看$x_2$和$x_3$这两列,这3个dichotomies已经包含$x_2$和$x_3$这两个点所有的4种排列组合中的3种了。再多加一种,$x_2$、$x_3$就会被shatter。
4 dichotomies
看右边两列,$x_2$和$x_3$被shatter了。但之前说了k=2,即任意2个点不能被shatter,因此不可能产生这4种dichotomies。那我们换一个dichotomy试试看。
4 dichotomies
换了一个dichotomy之后就行了,右边2列只包含了$x_2$、$x_3$所有排列组合4种中的3种,因此那两个点没有被shatter。继续检查任意的两个点($x_1$、$x_2$),($x_1$、$x_3$),都没有被shatter,看来这4种dichotomies是可以的。
5个dichotomies的情形这里就不再画出来了,很容易看出不管增加怎样的dichotomy进去,都会有两个点被shatter掉。因此这里“最多最多”只能有4种dichotomies。因此$N=3$,$k=2$时的upper bound是4。我们用$B(N,k)$来表示break point为k的任意的$\mathcal{H}$作用于size为N的任意的$\mathcal{D}$所能产生的dichotomies的数量的上限(“最多最多”)。则刚刚得出的结论可以表示为$B(3,2)=4$,因为任意2个数据点不能被shatter,因此当$N=2,K=2$时,$B(2,2)\lt 4$,因此最多最多有$B(2,2)=3$。
美妙的地方马上就要到了,虽然很多时候我们无法直接得到成长函数$m_{\mathcal{H}}(N)$,但如果我们知道它的break point是多少,我们似乎还是有办法算出这个$m_{\mathcal{H}}(N)$的上界$B(N,k)$的。于是乎我们就有了新的目标,不去直接研究$m_{\mathcal{H}}(N)$,转而去研究$B(N,k)$。
前面我们已知了$B(2,2)=3$,$B(3,2)=4$。不难知道:
因此我们可以得到下表:
表格剩余的部分该如何填补?$B(4,3)$是否与$B(3,?)$有关呢?
此时某某实验室帮老师抛硬币的研究生要上场了,他穷举了所有可能的dichotomies,发现$B(4,3)=11$,以下是他的研究成果:
我们把这份结果做个排序:
发现秘密了没有,橙色的部分是成对出现的,只有紫色的部分是单独出现的:
如果拿掉$x_4$,只看$x_1,x_2,x_3$这3个点:
$\alpha + \beta$部分可以成为这3个点的dichotomies,因为$k=3$,所以任3个点不能够被shatter,因此有::
$$\alpha + \beta \leq B(3,3)$$
再来看剩下一个$\alpha$的部分:
注意$\alpha$是之前成对存在的部分,并且$\alpha$部分不可以shatter掉任意2个点,因为如果$\alpha$部分的dichotomies可以shatter掉任意2个点,他每一行都再搭配$x_4$的两种情况,这样产生的dichotomies就能shatter掉3个点了,和break point为3相违背。所以$\alpha$不能shatter掉任2个点。因此有:
$$\alpha \leq B(3,2)$$
综合上面两个不等式,我们可以得到:
$$B(4,3)=2\alpha + \beta \leq B(3,3) + B(3,2)$$
这样就能够把前面那张表给填完整:
用数学归纳法可以证明:
$$B(N,k)\leq \sum_{i=0}^{k-1}\binom {N}{i}$$
当$k=1$时不等式恒成立,因此只要讨论$k\geq 2$的情形。$N=1$时,不等式成立,假设$N\leq N_{o}$时对于所有的$k$不等式都成立,则我们需要证明当$N=N_{o}+1$时,不等式也成立。根据前面得到的结论,有:
因此当$N=N_{o}+1$时,不等式也成立。
成长函数的上界-$B(N,k)$都被bound住了,那我们的成长函数同样也可以被这个bound住,因此对于存在break point k的成长函数而言,有:
$$m_{\mathcal{H}}\leq \sum_{i=0}^{k-1}\binom {N}{i}$$
By the way,右手边(RHS)实际上是一个最高次项为k-1次的多项式。以2D Perceptrons为例,它的break point $k=4$,则它的成长函数会被$B(N,4)$给bound住:
$$m_{\mathcal{H}}\leq \sum_{i=0}^{4-1}\binom {N}{i}=\frac{1}{6}N^3+\frac{5}{6}N+1$$
上一篇说的learning的可行性,讲到,如果遇上bad sample,$E_{in}(h)$与$E_{out}(h)$就会差很多,此时learning不可行。遇到bad sample的概率与$\mathcal{H}$中方程的数量$M$以及$\mathcal{D}$中的数据量$N$有关。然而$\mathcal{H}$中方程的数量往往是无穷的(比如2D Perceptrons的$\mathcal{H}$是平面上所有的直线),本篇则继续阐述,方程的数量看上去是无穷的,但真正有效(effective)的方程的数量却是有限的,我们可以用成长函数$m_{\mathcal{H}}(N)$来描述$\mathcal{H}$作用于$\mathcal{D}$会产生多少种有效的方程。如果用有限的成长函数去代替无限的$M$,就有:
$$\mathbb{P}_\mathcal{D}[BAD\ D]\leq 2m_{\mathcal{H}}(N)\cdot exp(-2\epsilon ^2N)$$
但实际上我们很难确切知道各种$\mathcal{H}$的成长函数$m_{\mathcal{H}}(N)$究竟长什么样子,我们只好通过break point去寻找成长函数的upper bound。不过这当中仍然有些情况没有考虑到,将在下一篇笔记中继续说明。
]]>银行在决定是否要通过贷款申请人的授信请求前,会根据申请人的资料对其进行风险评估,(通常银行会为其计算信用评分),申请人状况符合银行要求时,银行通过其申请,反之则婉拒。那么银行凭借什么来判断申请人将来是否会违约呢?通过银行之前的信用贷款记录,这些记录中,有些客户发生了违约行为,其他则表现良好,银行从这些违约与非违约的记录中learning到了一些规律,然后利用这些规律,来对新申请人的违约风险进行估计。因此信用评估模型就是一个learning的问题,那么我们该如何使用历史数据做好learning呢?
下面这张图描述了learning的基础架构:
$f:\mathcal{X} \to \mathcal{Y}$,其中$\mathcal{X}$表示输入空间,譬如下图中第一列
(age, gender, annual salary, year in residence, year in job, current debt)
为输入空间(6维),而右边一列
(23 years, female, NTD 1,000,000, 1 year, 0.5 year, 200,000)
为该输入空间下的一个向量,每位贷款申请人对应该空间下的一个向量。$\mathcal{Y}$表示输出空间,在二元分类中,输出空间是一个1维的取值为+1或-1的空间 $\{-1,+1\}^1$,可以用-1表示非违约,+1表示违约。
$f$是未知的真理,是事物运转的规律,假如我们可以拥有$f$,我们就可以知道一个人到底会不会发生违约行为。但是这个$f$是不可知的,我们无法窥探其中运行的原理(函数内部构造),我们唯一知道的是$f$在我们已知的历史数据$\mathcal{D}$当中的运行情况(把$x_n$当做$f$输入,把$y_n$当做$f$的输出),learning要作的事情,就是找一个在$\mathcal{D}$中运行情况与$f$类似的函数,这个函数对于相同的输入,会有与$f$相同的输出,并且希望在$\mathcal{D}$之外,也就是我们未知的世界,我们找的这个函数的运行情况还能与$f$接近。
$\mathcal{D}:(x_1,y_1), \dotsb,(x_N,y_N)$为训练集,该训练集有N笔数据,每笔数据由某申请人在$\mathcal{X}$中的向量和与其对应的类别构成。
$\mathcal{H}$,hypothesis set是一个由有限个或无限个方程组成的集合,算法$\mathcal{A}$只能从$\mathcal{H}$的范围内挑选方程。
$\mathcal{A}$,是一个学习算法,它能够帮助我们在$\mathcal{H}$中找到一个与$f$的判断最接近或足够接近的一个方程。当然我们可以说穷举法是一种学习算法,当$\mathcal{H}$当中candidate formula数量不多时,我们可以用穷举法来寻找。但往往candidate formula数量很大甚至是无穷的,我们就需要设计一个比较好的算法,他能够在较短时间找到我们想要的那个方程。
$g$,final hypothesis,即$\mathcal{A}$从$\mathcal{H}$中挑选的和$f$判断最接近的那个方程。
说到底,learning在干的事情,就是从hypothesis set里面挑一个“长”的最像$f$的方程$g$,注意前面我的用词是用”它的判断接近$f$”,并不是说$g$和$f$结构很类似,(记住$f$永远是unknown的),而是说他们的判断很一致,即$f(x)\approx g(x)$。并且这里谈到的接近,是针对训练集$\mathcal{D}$而言的,$\mathcal{D}$之外的数据他们能否表现一致,这才是我们最应该关心的问题,如果$\mathcal{D}$之外他们也能够表现一致,说明我们learning的还不错,我们有从$\mathcal{D}$上面学到东西。这时候换个角度来想,能不能有某个理论,来保证我们的$g$与$f$在$\mathcal{D}$之外也能有差不多的接近程度?
图片前两行为training set,对于第一行的所有样本,有$f(x)=-1$,对于第二行的所有样本,有$f(x)=+1$,那么我们能不能通过这6笔数据来猜测一下$f$是长什么样的呢?同学1和同学2利用各自的学习方法分别给出了自己的$g$
对于training set中所有样本,有$g_1(x)=g_2(x)=f(x)$,即两个$g_1,g_2$与$f$的表现是一致的,似乎可以认为他们都”学”到了东西,但是对于测试样本来说$g_1(x)=+1,g_2(x)=-1$。真实的$f$我们无法知道,如果他们中的某一个人在所有非训练的资料中也和$f(x)$表现一致,我们才能说他们当中某个人真的学到了东西。但在目前这种情况下,我们无法说同学1学到了东西还是同学2学到了东西。
让我们再来考虑一个简单的二元分类问题。$\mathcal{X}=\{0,1\}^3$,$\mathcal{Y}=\{\mathrm{o},\times\}^1$
为何要举这么简单的例子呢?因为前面我们说到真实的$f$是我们无法知道的,但在上面这个简单的例子中,我们有办法把所有可能的$f$全部列举出来。
可能产生这样的$\mathcal{D}$的$f$只可能有8种并且只有其中的1个是正确的,这样一来,虽然我们可以保证我们的$g$在$\mathcal{D}$上的判断和真实的$f$一致,但我们无法保证在$\mathcal{D}$之外也同样如此。那么这里便值得怀疑一下机器学习的可行性,机器学习到底可不可行?
我们知道在前面简单版的learning问题中,由于我们无法推断$\mathcal{D}$之外事情,因此learning不可行。但在其他场景中,我们能否利用$\mathcal{D}$来推断$\mathcal{D}$以外的事情呢?在统计推断中,我们可以利用样本的统计量(statistic)来推断总体的参数(parameter),譬如使用样本均值来估计总体期望。假设你想了解某一批大米(1000包)的平均重量,可以通过随机抽样抽取一定数量的样本(20包),用这20包大米的平均重量估计这1000包大米的平均重量,虽然二者并不一定会完全相等,但也不会相差太大,并且你的样本量越大,你得到的统计量与参数之间的误差会越小。在这个例子中,未知的980包大米的平均重量与我们知道的20包大米的平均重量是有关联的,因此我们似乎可以通过$\mathcal{D}$来推断$\mathcal{D}$之外的东西。下面来一个摸球的例子:
问题来了,这个$\nu$能不能在一定程度上代表了$\mu$。也许不能,因为即使bin中orange占多数,也可能发生这样的事情,你抽了10个小球出来但全是green的。但这种事情发生的可能性大吗?不大,并且如果我们有更多的样本(抽出更多的球),则这种事情发生的可能性会越来越小。在概率论中,可以用Hoeffding’s Inequality来描述上面那件事情的概率:
$$\mathbb{P}[|\nu-\mu|>\epsilon]\leq 2exp(-2\epsilon ^2N)$$
注:$\epsilon$是我们的容忍度,当$\mu$与$\nu$的差别小于容忍度时,我们称$\mu$与$\nu$“差不多”(PAC, probably approximately correct),当$\mu$与$\nu$差别大于容忍度时,我们称$\mu$与$\nu$”差很多”。“差很多”这件事发生的概率越小越好,最大不会超过右边。
上面这个不等式中,控制右边数值大小的只有$\epsilon ^2$和$N$,$\epsilon ^2$减小(要求降低)与$N$(样本增加)增大都能够使坏事情发生的概率的上限减少。当上限足够小的时候,我们可以说,sample中orange的比例和bin中orange的概率差不多,如果sample中的orange比例少,则bin中的orange的比例也会比较少。
我们可以把learning与抓球这件事结合起来。
还记得之前说过的$f$吗?他代表未知的真理,而$h(x)是$是属于hypothesis set $\mathcal{H}$的某一个方程。对于某一个向量$x_n$:
利用之前抓小球的逻辑,我们可以利用sample中orange的比例来推断总体中orange出现的概率,则同样的,我们可以利用sample中$h(x)\neq f(x)$的比例来推断总体中$h(x)\neq f(x)$的概率。这里$h(x)\neq f(x)$表示一个error,则我们可以称 $h(x)$ 在sample中出现error的比例为 $E_{in}$ (in-sample-error),在总体中出现error的概率为 $E_{out}$ (out-of-sample-error)。则对于 $h$ 来说:
$E_{out}(h) = \underset{x\sim P}{\epsilon} [h(x)\neq f(x)]$,$\epsilon$表示数学期望
$E_{in}(h) = \frac{1}{N}\sum_{n=1} ^ {N}[h(x_n)\neq y_n]$
利用Hoeffding’s Inequality,我们可以写成:
$$\mathbb{P}[|E_{in}(h)-E_{out}(h)|\gt \epsilon]\leq 2 exp(-2\epsilon ^2N)$$
简单说来,当右边这个“上界”足够小时,我们可以说$h$在sample中的表现(错误率)与$h$在总体中的表现是差不多的。
注意这里仅仅是说,对于一个固定的$h (fixed h)$而言,$E_{in}(h)$会与$E_{out}(h)$很接近,这种情况能说是一种好的learning吗?当然不能,因为如果$E_{in}(h)$很大,则$E_{out}$也大,这样是没有意义的。因此我们的算法$\mathcal{A}$要能够自由的从$\mathcal{H}$中挑选方程,我们把$\mathcal{A}$挑选出的最好的$h$称为$g$ (final hypothesis)。因此这里就需要添加一个验证流程(Verification Flow),这个流程使用历史数据来判断某个$h$够不够好。
前面说到,$\mathcal{A}$要能够自由的在$\mathcal{H}$中挑选它认为最适合的方程,因此这个最适合的方程就有可能是$\mathcal{H}$中的任何一个,有可能是$h_1$,有可能是$h_2$,$\mathcal{H}$中任意一个$h$都有可能成为$g$。但我们知道,我们的$\mathcal{D}$只是来自于总体的一个样本 (sample),既然是sample,就一定会存在抽样误差。譬如你想知道一枚硬币抛出正面的概率是多少,于是你扔了5次,有一定的可能你连续扔了5个正面出来,这时候说抛出正面的概率是1,这样对吗?这当然是行不通的,因此你扔的这5次硬币,就是一个bad sample。凡是由于抽样误差所造成样本分布与总体分布相差很大的样本,我们都可以称之为bad sample。
learning同样会遇到bad sample的麻烦。比如实际上$h_1$是个很好的方程,本来能够成为$g$的,但是由于抽样误差,碰到了bad sample,造成$E_{in}(h_1)$很大,$\mathcal{A}$最终没有选择它。又比如$h_2$是个不好的方程,碰到了bad sample,碰巧$E_{in}(h_2)$又很小,导致$\mathcal{A}$错误得选择了它作为$g$。因此每个$h$都有可能遇上bad sample的烦恼。对于任意一个$h$来说,bad sample会造成他们的$| E_{in}(h) - E_{out}(h) | > \epsilon$。
因此只要$\mathcal{H}$中任意个$h$遇上bad sample,我们的$\mathcal{A}$在挑选方程时就会遇到麻烦,我们的learning就有可能不太好。那么bad sample发生的概率有多大呢?
由此看出,learning得好不好,还与$\mathcal{H}$里面的方程数量$M$有关。当$M$是有限的时候,数据量越大,发生bad sample的可能性越低。同理如果$M$太大,我们也越容易遇到bad sample。
从概率论的角度出发,可以证明learning的确是可行的。因此,只有当$E_{in}(h)$和$E_{out}(h)$的判断很接近的时候,我们才能说learning是可行的。可行之余,倘若$E_{in}(h)$很大,这样的learning也没有太大意义,因为你的这个$h$在sample中表现不好,则他在out-of-sample中表现也不大可能会好。我们把$\mathcal{H}$中表现最好($E_{in}$最低)的那个方程选出来,记为$g$。当然如何定义“最好”,以及如何去寻找“最好”,则是后面的内容。
]]>showtext
这个包,但实际测试发现好像不使用showtext
也能达到同样的效果。下面的R code我是在Mac下的RStudio下实验的,因此如果windows达不到同样的效果,可以参考上面这两篇文章。
正常情况下,R plot不能显示中文,所有中文会变成一个一个方块
|
|
这是因为R无法找到正确的中文字体来显示。简单设置一下字体之后,发现中文标题可以正常显示了。这里”Kai”是系统自带的楷体字。
|
|
不仅仅是标题,我们往plot上增加的text也是可以设置中文字体的。
|
|
那么我们自己下载的字体可不可以呢?答案是可以的。如果不想安装字体,可以按照文章一开始参考的链接,使用showtext
包来载入字体。或者跟我一样先安装字体,这样使用起来就和系统自带的字体一样了。
接下来我们来画一个不同教育程度下性别比例的横向柱状图。首先下载wmpeople1字体。在这种字体下字母”p”将显示为男人,”u”将显示为女人。
下载并解压,会得到一个叫wmpeople1.TTF的字体文件。在Mac下直接双击该字体文件即可安装。
先来看看原始数据:
edu | educode | gender | population |
---|---|---|---|
未上过学 | 1 | m | 17464 |
未上过学 | 1 | f | 41268 |
小 学 | 2 | m | 139378 |
小 学 | 2 | f | 154854 |
初 中 | 3 | m | 236369 |
初 中 | 3 | f | 205537 |
高 中 | 4 | m | 94528 |
高 中 | 4 | f | 70521 |
大专及以上 | 5 | m | 57013 |
大专及以上 | 5 | f | 50334 |
其中人口的单位为(千人),之后会先除以10000转换为(千万人)。
接下来我们将使用ggplot2画图。
|
|
标题,横纵坐标的label,以及内部的text都可以修改字体。那么坐标轴上的文字当然也是可以的。
我们来把教育程度改成暴走字体。和之前一样下载解压,得到一个Memes.ttf的字体文件,安装它。不过注意安装之后该字体的名称并不是叫Memes,如果像之前一样把字体设置为Memes会报错说找不到字体。
安装的时候我们可以看到该字体真实的名字叫做adasdasdsdsd(看名字就够暴走了。。。)
我们这里试着把纵坐标替换为暴走体,因为暴走字体只支持英文大小写以及数字,因此先把这几个教育程度替换为英文字母。
|
|
R语言中可以使用D()
来求一元函数的导数,用deriv()
来求多元函数的偏导数。这两个function都在package:stats
中,会在R启动时默认加载。
下面以一个多元函数作为demo,希望通过gradient decent的方法求最小值:
$$E(u,v) = e^u + e^{2v} + e^{uv} + u^2 - 2uv + 2v^2 - 3u - 2v$$
|
|
|
|
注意看d_Euv这个function里面的内容,d_Euv返回的.value
是原函数Euv在(u,v)下的值,而不是偏导数。该function的末尾把偏导数作为attribute附加到这个value上。因此我们可以通过下面的方法把这个偏导数再提取出来。
|
|
|
|
利用梯度下降法(gradient decent)解Euv最小值。下面只做示范用,只迭代5次,因此得到的值不一定是真正的最小值。利用fixed learning rate $\eta = 0.01$从$(u_0,v_0) = (0,0)$开始,对(u,v)进行更新:
|
|
|
|
函数Euv在(u,v)上的值可以利用以下两种方式去解
|
|
|
|
|
|
|
|
Perceptron - 感知机,它能够根据每笔资料的特征,把资料判断为不同的类别。令$h(x)$是一个perceptron,你给我一个$x$($x$是一个特征向量),把$x$输入$h(x)$,它就会输出这个$x$的类别,譬如在信用违约风险预测当中,输出就可能是这个人会违约,或者不会违约。本质上讲,perceptron是一种二元线性分类器,它通过对特征向量的加权求和,并把这个”和”与事先设定的门槛值(threshold)做比较,高于门槛值的输出1,低于门槛值的输出-1。
更加紧凑一些,我们可以把它写成
$$
h(x) = sign(\sum _{i=1}^{d}w_ix_i+b)
$$
其中$d$表示维度数,$x$是$d$维空间中的一个点, $x=(x_1,x_2,…,x_d)$; $sign()$输出运算结果的符号,大于0的输出+1,其余输出-1。
细心一点可以看出,其实$\sum _{i=1}^{d}w_ix_i+b =0$在1维空间中代表一个点,在2维空间中代表一条直线,在3维空间中代表一个平面。
以2维空间为例:
对于所有满足$\sum_{i=1}^{d}w_ix_i+b<0$的$x$,将落在直线一边的区域中(下图中的蓝色).
对于所有满足$\sum _{i=1}^{d}w_ix_i+b > 0$的$x$,将落在直线的另一边(下图中的红色)。
图1 在2维空间中perceptron是一条直线
为了方便后面计算,我们常常衍生出一个维度出来,使得$b=w_0x_0,x_0$这个维度恒等于1。则perceptron可以用矩阵的形式表示出来:
$$h(x)=sign(\sum _{i=0}^{d}w_ix_i)=w^Tx$$
注意: 这里要搞清楚下标的含义,上文中的$x_i$、$w_i$指$x$向量、$w$向量的第$i$个维度。因为后文都是用矩阵乘法,因此下标不再表示维度,譬如$x_n$表示某笔资料,它是一个向量,而$w_t$指第$t$次更新之后的$w$,它也是一个向量。
Perceptron Learning Algorithm的目的是要找到一个perceptron,能把正确地把不同类别的点区分开来。
在二维平面上,任何找一条直线都可以用来做perceptron,只不过有些perceptron分类能力比较好(分错的少),有些perceptron分类能力比较差(分错的多)。
图2 2维空间中的两个不同的perceptron
上图中是二维平面上的两个perceptron,图中圈圈代表+1的点,叉叉代表-1的点。左边的perceptron把两个叉叉错分到圈圈当中,而右边的则很完美地把圈圈和叉叉区分开来。在二维平面中存在无数个可能的perceptron,而perceptron learning的目的是找到一个好的perceptron。
假设给我们的数据是“线性可分”的,即至少存在一个perceptron,它很厉害,可以做到百分百的正确率(如图2-b),对于任意的$(y_n,x_n)$,有$h(x_n)=y_n$。我们把这个完美的perceptron记为
$$h(x)=sign(w_f^Tx)$$
则Perceptron Learning要做的是,在“线性可分”的前提下,由一个初始的Perceptron $h(x)$开始,通过不断的learning,不断的调整$h(x)$的参数$w$,使他最终成为一个完美的perceptron。
前面说到Perceptron Learning的目的,那么既然要learning就一定有一个learning的方法(譬如随机猜就是一种方法,但它不一定是个好方法),这个方法能够指导我们该如何去慢慢调整$w$,使$h(x)$越来越接近我们心目中完美的perceptron $sign(w_f^Tx)$。
PLA的方法如下:
For t = 0,1,…
找到产生的一个错误点
(注意这里x的下标不是值维度,而是数据点的编号。指第t次更新后的一个分类错误点)
用下面的方法更正这个错误:
…直到找不到错误点,返回最后一次迭代的$w$
以下用图片展示迭代的过程,图片截至台湾大学林轩田老师Machine Learning Foundation的讲义
图3 PLA 知“错”就“改”的过程
从图中可以看出$w$确实在PLA的指导下,慢慢接近心目中的$w_f$。
我们知道在数据线性可分的前提下,我们心目中有个完美的$w_f$,它能够完美的把圈圈和叉叉区分开来。那么如何证明PLA能够使$w$不断接近$w_f$呢?
这里就要用到夹角余弦的公式,如果更新之后的与之间的夹角余弦变大(夹角变小)了,则我们可以说PLA是有效的。首先我们先来看pla的几个性质:
因为$w_f$是完美的,因此对于任意的$x_n$,$w_f$都能把它归入正确的类别:
看起来是更接近了,但他们内积的增大并不能表示他们夹角的变小,也有可能是因为长度增大了。但是的增加是有限的:
根据上面的性质,我们可以来求夹角余弦。从$w_0=0$(初始的向量)开始,经过T次错误更正,变为$w_T$,那么就有:
再来求$w_T$与$w_f$的夹角余弦:
$$
\begin{equation}
\begin{split}
\frac{w_f^Tw_T}{||w_f||||w_T||} &\geq \frac{T\cdot min\ y_nw_f^Tx_n}{||w_f||||w_T||} \
&\geq \frac{T\cdot min\ y_nw_f^Tx_n}{||w_f||\cdot \sqrt{T}\cdot max\ {||x_n||^2}}
= \frac {\sqrt{T}\rho}{R}
\end{split}
\end{equation}
$$
其中$\rho = min\ y_n\frac {w_f^T}{||w_f||}x_n$与$R^2 = max\ {||x_n||^2}$都是大于0的常数。由于夹角余弦是小于等于1的,因此有:
$$1 \geq \frac{w_f^Tw_T}{||w_f||||w_T||} \geq \frac {\sqrt{T}\rho}{R}$$
上面的不等式告诉我们两点:
PLA能够帮助$w_T$进步,因为$w_T$与$w_f$的夹角余弦随着更新错误点的次数T的增加而增加,$w_T$越来越接近$w_f$。
PLA会停止(halt),因为$T \leq R^2/\rho ^2$,即当数据是线性可分时,经过有限次数的迭代,一定能找到一个能够把数据完美区分开的perceptron。
有时我们拿到的数据数量庞大,或是不是线性可分的,这个时候用PLA将消耗大量的时间,或是根本无法停止,这个时候我们可以使用一种委曲求全的办法,在PLA中加入pocket step。这个pocket是做什么用的呢?这个pocket会使用PLA在每次迭代中产生的$w$,带进原始数据,去计算分类错误率,并记录最好的那个$w$,譬如我们设定让PLA迭代N次就停止,则pocket返回这N次迭代中出现的最好的$w$。当N足够大的时候,pocket总能返回还不错的结果。
]]>二元分类器是指要输出(预测)的结果只有两种类别的模型。例如预测阳性/阴性,有病/没病,在银行信用评分模型中,也用来预测用户是否会违约,等等。
既然是一种预测模型,则实际情况一定是有些结果猜对了,有些结果猜错了。因为二元分类器的预测结果有两种类别(以下以阴/阳为例),对应其真实值,则会有以下四种情形:
1. 预测为阳性,真实值为阴性 (伪阳性)
2. 预测为阴性,真实值为阳性 (伪阴性)
3. 预测为阴性,真实值真的为阴性 (真阴性)
4. 预测为阴性,真实值真的为阴性 (真阴性)
图1.confusion matrix (混乱矩阵)
在信号检测理论中,接收者操作特征曲线(receiver operating characteristic curve,或者叫ROC曲线)是一种座标图式的分析工具。
要了解ROC曲线,先要了解一下ROC空间,ROC空间是一个以伪阳性率(FPR, false positive rate)为X轴,真阳性率(TPR, true positive rate)为Y轴的二维坐标系所代表平面。
我们想象这样一种场景,接触阳性样本可以给我们带来“收益”,接触阴性样本则会给我们造成”成本”。
并且如果我们接触样本中所有的阳性样本,我们的收益是1,接触样本中的所有阴性样本,我们的成本也是1。
如果不接触样本,则既不产生收益也不产生成本。
自然的,如果不使用分类器,接触所有样本,则总的效益为1-1=0。现在让我们利用分类器来决定是否接触样本,分类器预测为阳,我们就去接触样本,分类器预测为阴,我们就不去接触。因为不接触样本不会产生收益或是成本,因此我们只需要看分类器预测为阳的样本。预测为阳的样本中,TP将产生 TPR 的收益, FP将产生FPR的成本。
那么一个分类器的分类效果就对应ROC空间里的一个点:
图2.ROC空间
A,B,C三个点可以分别代表三个不同的分类器对同样的样本做预测的结果。
最好的方法是A,因为他的收益大于成本(TPR > FPR),最差的是C(TPR < FPR)。中等的是B,相当于随机分类器。
这里有趣的一点是若把C以(0.5, 0.5)为中点作一个镜像,得到C’, C’的效果比A要来的好。C’相当于一个做与C预测结果完全相反的分类器。
实际的应用当中,分类器还会给出它预测某个样本为阳的概率,并且有一个事先给定的门槛值(threshold),概率高于threshold的就预测为阳性,低于threshold的就预测为阴性。假设以下是某个分类器对id为1-10的客户的分类结果:
表1.分类器预测结果
其中probability of 1为分类器判断该样本为阳性的概率,true class为该样本的真实情况。
如果我们把threshold定位0.5,即去接触id为1~8的客户。此时
TPR = TP / 所有真实值为阳性的样本个数 = 6 / 6 = 1
FPR = FP / 所有真实值为阴性的样本个数 = 2 / 4 = 0.6
同理,如果我们把threshold定位0.8,即去接触id为1~5的客户。此时
TPR = TP / 所有真实值为阳性的样本个数 = 4 / 6 = 0.67
FPR = FP / 所有真实值为阴性的样本个数 = 1 / 4 = 0.25
这两个threshold分别对应ROC空间中的两个点A、B
图3.不同的threshold对应ROC空间中不同的点
上面的例子当中,共有10笔预测数据,则一共有11种threshold的设定方法,每一个threshold对应ROC空间中的一个点,把这些点连接起来,就成了ROC曲线。
图4.ROC曲线
这里因为数据量太少,所以曲线是一折一折的,数据量大的时候,看上去才像”曲线”。
以下直接搬维基百科:
因为是在1x1的方格里求面积,AUC必在0~1之间。
假设threshold以上是阳性,以下是阴性;
若随机抽取一个阳性样本和一个阴性样本,分类器正确判断阳性样本的值高于阴性样本之机率。(即前文当中把C做一个镜像变为C’)
简单说:AUC值越大的分类器,正确率越高。
从AUC判断分类器(预测模型)优劣的标准:
AUC = 1,是完美分类器,采用这个预测模型时,不管设定什么阈值都能得出完美预测。绝大多数预测的场合,不存在完美分类器。
0.5 < AUC < 1,优于随机猜测。这个分类器(模型)妥善设定阈值的话,能有预测价值。
AUC = 0.5,跟随机猜测一样(例:丢铜板),模型没有预测价值。
AUC < 0.5,比随机猜测还差;但只要总是反预测而行,就优于随机猜测,因此不存在AUC < 0.5的情况。
图5.用AUC来衡量不同分类器的分类能力(更准确的说是排序能力)
一个分类模型的分类结果的好坏取决于以下两个部分:
使用AUC来衡量分类模型的好坏,可以忽略由于threshold的选择所带来的影响,因为实际应用中,这个threshold常常由先验概率或是人为决定的。
在用SAS或者其他一些统计分析软件,用来评测分类器分类效果时,常常会看到一个叫做gini coefficient的东西,那么这个gini coefficient又是什么呢?
gini系数通常被用来判断收入分配公平程度,具体请参阅wikipedia-基尼系数。
图6.洛伦茨曲线与基尼系数
Gini coefficient 是指绝对公平线(line of equality)和洛伦茨曲线(Lorenz Curve)围成的面积与绝对公平线以下面积的比例,即gini coefficient = A面积 / (A面积+B面积) 。
用在评判分类模型的预测效力时,是指ROC曲线曲线和中线围成的面积与中线之上面积的比例。
图7.Gini coefficient与AUC
因此Gini coefficient与AUC可以互相转换:
gini = A / (A + B) = (AUC - C) / (A + B) = (AUC -0.5) / 0.5 = 2*AUC - 1
]]>load()
即可将其载入,比较方便。除此之外,也可到UCI Machine Learning Repository下载原始文件,当中包含dataset的中各个变量以及衍生变量的简介,数据格式为纯文本。
|
|
先确定一下当前的工作路径。
|
|
我把samsungData.rda放在~/Dropbox/Homeworks/Data Analysis/DataAnalysisProject2/data中,.rda文件的好处就是直接load一遍就可以把当时储存在内存中的object全部载入,而不需要再从txt或者csv文件中读取数据了。
|
|
|
|
|
|
|
|
|
|
一共有7352条记录,563个变量。
|
|
|
|
这里subject代表志愿者编号,这里共有21个志愿者参与。
把所有变量的名称读出来,随便挑几个看看。
|
|
|
|
变量名称中有-
,()
,可能会使之后的分析工作出现异常,之后要把变量名处理一下。
|
|
|
|
变量名中不重复的有479个,这里面居然会有重名的变量!!
原来是因为有有一些变量忘了标记它来源于加速度传感器与三轴陀螺仪中的X轴,Y轴还是Z轴了,因此重复的变量名都是三个成对地出现,比如fBodyAcc-bandsEnergy()-1,8
,出现了三次。
|
|
|
|
把-X
,-Y
,-Z
补回去即可。前面提到要把-
,()
给去除掉,这里面用到一个小技巧,直接用把data.frame(samsungData)
,即可把变量名中的怪异字符改成.
。
|
|
这个数据集当中不存在空值,并且看了它的说明,每个变量都已经做过标准化处理,全部是数值型变量,数值范围 [-1,1]。因此之后就不需要对变量做其他处理了。
|
|
|
|
把原始数据集分为training set和test set。课上规定说1、3、5、6号志愿者必须在training set中,27、28、29、30必须在test set中。因此剩下的subject,就平均分配给这两个set。
|
|
|
|
|
|
|
|
|
|
这里直接把所有变量都拿去建模,让决策树自己去选择重要的变量。这里应该先尝试用PCA或者SVD降维一下会比较好, 但不想把过程搞的太复杂,因此降维这事情以后可以尝试一下。
|
|
|
|
C&RT最终挑选了8个变量。其中训练集的表现是错分率8.25%,测试集的表现是错分率14.43%。
|
|
|
|
看看test set的confusion matrix。发现sitting和standing之间搞错的比较多,walk, walkdown, walkup之间错的也不少
|
|
|
|
用10-fold cross-validation来测试一下树的内部节点个数定为多少比较合适,太少准确度低,太多容易overfitting。
|
|
由上图可以看出,随着tree size的增大,错误率是在不断减少的,在内部节点数为8的时候最低,(又根据树的停止规则,它不会继续长超过8),因此内部节点数为8是比较好的选择。下面的code可以把这棵树画出来:
|
|
关于随机森林的介绍,可以参考前一篇《林子大了,什么树都有》
|
|
|
|
random forest中最重要的10个变量。
|
|
下面可以看到random forest在trainning set当中惊人的表现。1.31%的错分率。
|
|
再来看看test set的表现。8.37%的错分率,可见还是存在一点的overfitting,不过还好不算太严重。与之前单棵决策树相比,准确率高了不少。
|
|
|
|
|
|
|
|
这次实验所用的数据是已经经过相关领域专家处理过的,并不是传感器采集到的raw data,这当中需要大量的相关知识,并且数据已经经过一定程度的标准化处理,因此不需要多做处理,分析难度大大降低。除此之外实验的目的是为了比较单一的决策树与随机森林这种ensemble的方法在分类准确度上的差异,因此没有费很大的功夫去想降维的方法。在实际应用中,降维是必须的,因为这种复杂的模型所需的计算量是比较大的,如果想在手机上进行预测,无法采用这么暴力的方法。除此之外,还可以尝试使用其他模型,譬如SVM,我用的是e1071这个r package,发现SVM的效果要比random forest要好一些,这里就不详述了。
]]> 在machine learning中,随机森林(Random Forests)是一个包含多个决策树(decision tree)的分类器,其输出的类别由个别树输出的类别的众数决定[1]。如何从一个比较通俗易懂的角度来理解这座森林呢?
某天你想看某部电影但你不确定自己是否会喜欢,此时你可能会问你的好友小赵,问他认为你会不会喜欢这部电影。这个小赵是个非常认真负责的人,他想先了解了解你喜欢哪种类型的电影。于是你给了小赵一份电影清单,上面写了你喜欢哪些电影,不喜欢哪些电影(a labeled training set)。于是小赵去豆瓣上查这些电影的相关信息,他把每一部电影转换成一个特征向量:(导演,编剧,主演,类型,国家,语言,片长…),接着在小赵心目中,就建立起了一套判断准则,这个判断准则中有一系列的衡量标准,譬如动作片+有xxx出演->喜欢
,或者爱情片+悲剧->不喜欢
等等。此时小赵就变成了一棵decision tree。你问小赵你会不会喜欢某部电影,小赵就会根据之前建立起来的规则,猜测你喜欢或者不喜欢。
但是小赵只是一个人类,他并不总能很好的归纳出你的偏好。为了得到更加准确的建议,你可能不仅仅去问小赵,而是去问更多的朋友小钱、小孙、小李、小周、小吴。此时每个好友都代表一颗decision tree,而每次你想知道你是否会喜欢某部电影X时,你会问每个好友,当多数人认为你会喜欢电影X时,你才去看它。此时你就拥有了一座充满decision tree的森林,专业一点的讲法是一个ensemble classifier。
前面说到,你在建立decision tree时,需要给每个人一份记录你喜欢和不喜欢电影的清单,但是如果你给每个人一模一样电影清单,那每个人变成的decision tree也会是一模一样,这样的话问那么多人就没有意义了。为了让每棵decision都长得不一样,你打算给每个人的电影清单也不大一样。为什么要这么做呢?因为事实上连你自己也无法确保你给的电影清单是完全准确的。譬如说你告诉小赵你非常喜欢《泰坦尼克》,但有可能你喜欢它仅仅是因为看《泰坦尼克》的那天是你生日,你的心情很愉悦,你并不是真的有非常喜欢,因此这条记录是有偏差的,如果不把你喜欢《泰坦尼克》这件事告诉其他的朋友,那么其他的朋友所建立的decision tree就不会受到这个偏差的影响。因此你给每个朋友的电影清单都有略微的不同,譬如你告诉小赵你喜欢《盗梦空间》和《泰坦尼克》,讨厌《阿凡达》,但是告诉小张你喜欢《盗梦空间》,讨厌《阿凡达》但是没有提到《泰坦尼克》。这么一来小赵和小张建立的decision tree就可能会有很大的不同。
利用这种ensemble的方法,每个好友对你的了解都不一样,因此可能给出一些具有特质化的意见,小赵可能认为你喜欢看莱昂纳多主演的电影(因为你告诉他你喜欢《盗梦空间》和《泰坦尼克》),而小张可能认为你喜欢看爱情片(因为你只告诉他你喜欢《泰坦尼克》)。
除此之外,还有一种情况,你同时喜欢某几部电影,并不是因为这几部电影都是由某个电影明星主演,而是因为其他方面的原因,对于这些电影,你并不希望你朋友在建立decision tree的时候考虑到电影主演的信息,即你希望把主演从电影的特征向量中删去。
这样一来,你的这些好友所建立的decision tree就成为了一座森林。当你想知道你是否会喜欢某部电影时,你会去问这座森林里的每一棵树,当大部分树认为你会喜欢时,你就去看这部电影。
之前提到的电影清单以及电影的特征向量,我们把他用表格来描述一下,可以长成这样:
movie | 喜欢 | 导演 | 编剧 | 主演 | 类型 | 国家 | 语言 | … |
---|---|---|---|---|---|---|---|---|
a | 1 | xxx | foo | iii | 爱情 | 法国 | 法语 | … |
b | 0 | yyy | bar | jjj | 动作 | 中国 | 中文 | … |
c | 1 | zzz | baz | kkk | 悬疑 | 美国 | 英文 | … |
… | … | … | … | … | … | … | … | … |
那么我们可以来总结一下:
随机森林中每一棵树建立的依据是随机的,这个随机体现在两个方面:
- 建立模型时使用的data是随机的。(random in row - data level)
- 建立模型时使用的features是随机的。(random in column - model level)
]]>下集预告:
实践是检验真理的唯一标准,下一次我们将实战一下 random forests ,使用智能手机的加速度传感器以及陀螺仪的数据来预测当前用户的活动状态(站立,行走,跑步….)。
以下的例子将从Available CRAN Packages页面上抓取目前CRAN上所有的R包,提取当中的title,及各个R包的简介,用来分析R包所涵盖的热门领域。
|
|
|
|
|
|
|
|
下面要把语料库转换成一个Term-Document Matrix[1]。一个document可能是一句话,可以可能是一篇文章。Term-Document Matrix的row表示某个一个document,column表示该document各个词汇出现的次数。下面是一个Term-Document Matrix的简单例子:
则Term-Document Matrix将是这样:
I | like | hate | databases | |
---|---|---|---|---|
D1 | 1 | 1 | 0 | 1 |
D2 | 1 | 0 | 1 | 1 |
|
|
|
|
|
|
|
|
最终的输出效果如图: