机器学习面试题41-60

41.是否可以捕获协连续变量和非连续变量之间的的相关性

是的,我们可以用ANCOVA(协方差分析)技术来捕获连续型变量和分类变量之间的相关性。

42.GBM和随机森林的区别

最根本的区别是,随机森林算法使用bagging技术做出预测。 GBM采用boosting技术做预测。在bagging技术中,数据集用随机采样的方法被划分成使n个样本。然后,使用单一的学习算法,在所有样本上建模。接着利用投票或者求平均来组合所得到的预测。 Bagging是平行进行的。而boosting是在第一轮的预测之后,算法将分类出错的预测加高权重,使得它们可以在后续一轮中得到校正。这种给予分类出错的预测高权重的顺序过程持续进行,一直到达到停止标准为止。随机森林通过减少方差(主要方式)提高模型的精度。生成树之间是不相关的,以把方差的减少最大化。在另一方面,GBM提高了精度,同时减少了模型的偏差和方差。

43.什么是凸包

当数据是线性可分的,凸包就表示两个组数据点的外边界。 一旦凸包建立,我们得到的最大间隔超平面(MMH)作为两个凸包之间的垂直平分线。 MMH是能够最大限度地分开两个组的线。

44.如何理解第一类错误和第二类错误

第一类错误是当原假设为真时,我们却拒绝了它,也被称为“假阳性”。

第二类错误是当原假设为是假时,我们接受了它,也被称为“假阴性”。 在混淆矩阵里,我们可以说,当我们把一个值归为阳性(1)但其实它是阴性(0)时,发生第一类错误。而当我们把一个值归为阴性(0)但其实它是阳性(1)时,发生了第二类错误。

45.清洗数据正确步骤

1.将数据导入

2.看数据:重点看元数据,即对字段解释、数据来源等信息;导入数据后,提取部分数据进行查看

3.缺失值清洗 - 根据需要对缺失值进行处理,可以删除数据或填充数据 - 重新取数:如果某些非常重要的字段缺失,需要和负责采集数据的人沟通,是否可以再获得

4.数据格式清洗:统一数据的时间、日期、全半角等显示格式

5.逻辑错误的数据 - 重复的数据 - 不合理的值

6.不一致错误的处理:指对矛盾内容的修正,最常见的如身份证号和出生年月日不对应 不同业务中数据清洗的任务略有不同,比如数据有不同来源的话,数据格式清洗和不一致错误的处理就尤为突出。数据预处理是数据类岗位工作内容中重要的部分。

46.过拟合与欠拟合

欠拟合(underfiting / high bias) 训练误差和验证误差都很大,这种情况称为欠拟合。出现欠拟合的原因是模型尚未学习到数据的真实结构。因此,模拟在训练集和验证集上的性能都很差。

解决办法

1 做特征工程,添加跟多的特征项。如果欠拟合是由于特征项不够,没有足够的信息支持模型做判断。

2 增加模型复杂度。如果模型太简单,不能够应对复杂的任务。可以使用更复杂的模型,减小正则化系数。具体来说可以使用核函数,集成学习方法。

3 集成学习方法boosting(如GBDT)能有效解决high bias

过拟合(overfiting / high variance) 模型在训练集上表现很好,但是在验证集上却不能保持准确,也就是模型泛化能力很差。这种情况很可能是模型过拟合。 造成原因主要有以下几种:

1 训练数据集样本单一,样本不足。如果训练样本只有负样本,然后那生成的模型去预测正样本,这肯定预测不准。所以训练样本要尽可能的全面,覆盖所有的数据类型。

2 训练数据中噪声干扰过大。噪声指训练数据中的干扰数据。过多的干扰会导致记录了很多噪声特征,忽略了真实输入和输出之间的关系。

3 模型过于复杂。模型太复杂,已经能够死记硬背记录下了训练数据的信息,但是遇到没有见过的数据的时候不能够变通,泛化能力太差。

我们希望模型对不同的模型都有稳定的输出。模型太复杂是过拟合的重要因素。 针对过拟合的上述原因,对应的预防和解决办法如下:

1 在训练和建立模型的时候,从相对简单的模型开始,不要一开始就把特征做的非常多,模型参数跳的非常复杂。

2 增加样本,要覆盖全部的数据类型。数据经过清洗之后再进行模型训练,防止噪声数据干扰模型。

3 正则化。在模型算法中添加惩罚函数来防止过拟合。常见的有L1,L2正则化。

4 集成学习方法bagging(如随机森林)能有效防止过拟合

5 减少特征个数(不是太推荐) 注意:降维不能解决过拟合。降维只是减小了特征的维度,并没有减小特征所有的信息。

47.树知识点详解

 

前言
xgboost一直在竞赛江湖里被传为神器,比如时不时某个kaggle/天池比赛中,某人用xgboost于千军万马中斩获冠军。

而我们的机器学习课程里也必讲xgboost,如寒所说:“RF和GBDT是工业界大爱的模型,Xgboost 是大杀器包裹,Kaggle各种Top排行榜曾一度呈现Xgboost一统江湖的局面,另外某次滴滴比赛第一名的改进也少不了Xgboost的功劳”。

此外,公司七月在线从2016年上半年起,就开始组织学员参加各种比赛,以在实际竞赛项目中成长(毕竟,搞AI不可能没实战,而参加比赛历经数据处理、特征选择、模型调优、代码调参,是一个极好的真刀真枪的实战机会,对能力的提升和找/换工作的帮助都非常大)。

AI大潮之下,今年特别多从传统IT转行转岗转型AI的朋友,很多朋友都咨询如何转行AI,我一般都会着重强调学习AI或找/换AI的四大金刚:课程 + 题库 + LeetCode + kaggle/天池。包括集训营的毕业考核更会融合kaggle或天池比赛。

考虑到kaggle/天池比赛对搞数学科学的重要性,特写此文介绍xgboost,助力大家快速入门xgboost以及在比赛中获得优异成绩。

最后,xgboost不是我July发明的,但我会确保本文对它的介绍是最通俗易懂的。另,感谢文末所列的全部参考文献,有何问题,欢迎随时留言评论,thanks。

1 决策树
举个例子,集训营某一期有100多名学员,假定给你一个任务,要你统计男生女生各多少人,当一个一个学员依次上台站到你面前时,你会怎么区分谁是男谁是女呢?

很快,你考虑到男生的头发一般很短,女生的头发一般比较长,所以你通过头发的长短将这个班的所有学员分为两拨,长发的为“女”,短发为“男”。

相当于你依靠一个指标“头发长短”将整个班的人进行了划分,于是形成了一个简单的决策树,而划分的依据是头发长短。 
这时,有的人可能有不同意见了:为什么要用“头发长短”划分呀,我可不可以用“穿的鞋子是否是高跟鞋”,“有没有喉结”等等这些来划分呢,答案当然是可以的。

但究竟根据哪个指标划分更好呢?很直接的判断是哪个分类效果更好则优先用哪个。所以,这时就需要一个评价标准来量化分类效果了。 

怎么判断“头发长短”或者“是否有喉结”是最好的划分方式,效果怎么量化呢?直观上来说,如果根据某个标准分类人群后,纯度越高效果越好,比如说你分为两群,“女”那一群都是女的,“男”那一群全是男的,那这个效果是最好的。但有时实际的分类情况不是那么理想,所以只能说越接近这种情况,我们则认为效果越好。

量化分类效果的方式有很多,比如信息增益(ID3)、信息增益率(C4.5)、基尼系数(CART)等等。

信息增益的度量标准:熵

ID3算法的核心思想就是以信息增益度量属性选择,选择分裂后信息增益最大的属性进行分裂。

什么是信息增益呢?为了精确地定义信息增益,我们先定义信息论中广泛使用的一个度量标准,称为熵(entropy),它刻画了任意样例集的纯度(purity)。给定包含关于某个目标概念的正反样例的样例集S,那么S相对这个布尔型分类的熵为:

 

上述公式中,p+代表正样例,比如在本文开头第二个例子中p+则意味着去打羽毛球,而p-则代表反样例,不去打球(在有关熵的所有计算中我们定义0log0为0)。

举例来说,假设S是一个关于布尔概念的有14个样例的集合,它包括9个正例和5个反例(我们采用记号[9+,5-]来概括这样的数据样例),那么S相对于这个布尔样例的熵为:

Entropy([9+,5-])=-(9/14)log2(9/14)-(5/14)log2(5/14)=0.940。

So,根据上述这个公式,我们可以得到:

如果S的所有成员属于同一类,则Entropy(S)=0;
如果S的正反样例数量相等,则Entropy(S)=1;
如果S的正反样例数量不等,则熵介于0,1之间

如下图所示:


看到没,通过Entropy的值,你就能评估当前分类树的分类效果好坏了。

更多细节如剪枝、过拟合、优缺点、可以参考此文《决策树学习》。

所以,现在决策树的灵魂已经有了,即依靠某种指标进行树的分裂达到分类/回归的目的,总是希望纯度越高越好。


2.回归树与集成学习
如果用一句话定义xgboost,很简单:Xgboost就是由很多分类和回归树集成。分类树好理解,但,回归树又是什么呢?

数据挖掘或机器学习中使用的决策树有两种主要类型:

分类树分析是指预测结果是数据所属的类(比如某个电影去看还是不看)
回归树分析是指预测结果可以被认为是实数(例如房屋的价格,或患者在医院中的逗留时间)
而术语分类和回归树(CART,Classification And Regression Tree)分析是用于指代上述两种树的总称,由Breiman等人首先提出。

2.1 回归树
事实上,分类与回归是两个很接近的问题,分类的目标是根据已知样本的某些特征,判断一个新的样本属于哪种已知的样本类,它的结果是离散值。而回归的结果是连续的值。当然,本质是一样的,都是特征(feature)到结果/标签(label)之间的映射。

理清了什么是分类和回归之后,理解分类树和回归树就不难了。

分类树的样本输出(即响应值)是类的形式,比如判断这个救命药是真的还是假的,周末去看电影《风语咒》还是不去。而回归树的样本输出是数值的形式,比如给某人发放房屋贷款的数额就是具体的数值,可以是0到300万元之间的任意值。

所以,对于回归树,你没法再用分类树那套信息增益、信息增益率、基尼系数来判定树的节点分裂了,你需要采取新的方式评估效果,包括预测误差(常用的有均方误差、对数误差等)。而且节点不再是类别,是数值(预测值),那么怎么确定呢?有的是节点内样本均值,有的是最优化算出来的比如Xgboost。

CART回归树是假设树为二叉树,通过不断将特征进行分裂。比如当前树结点是基于第j个特征值进行分裂的,设该特征值小于s的样本划分为左子树,大于s的样本划分为右子树。



而CART回归树实质上就是在该特征维度对样本空间进行划分,而这种空间划分的优化是一种NP难问题,因此,在决策树模型中是使用启发式方法解决。典型CART回归树产生的目标函数为:



因此,当我们为了求解最优的切分特征j和最优的切分点s,就转化为求解这么一个目标函数:



所以我们只要遍历所有特征的的所有切分点,就能找到最优的切分特征和切分点。最终得到一棵回归树。


2.2 boosting集成学习

所谓集成学习,是指构建多个分类器(弱分类器)对数据集进行预测,然后用某种策略将多个分类器预测的结果集成起来,作为最终预测结果。通俗比喻就是“三个臭皮匠赛过诸葛亮”,或一个公司董事会上的各董事投票决策,它要求每个弱分类器具备一定的“准确性”,分类器之间具备“差异性”。

集成学习根据各个弱分类器之间有无依赖关系,分为Boosting和Bagging两大流派:

Boosting流派,各分类器之间有依赖关系,必须串行,比如Adaboost、GBDT(Gradient Boosting Decision Tree)、Xgboost
Bagging流派,各分类器之间没有依赖关系,可各自并行,比如随机森林(Random Forest)
而著名的Adaboost作为boosting流派中最具代表性的一种方法,本博客曾详细介绍它。

AdaBoost,是英文"Adaptive Boosting"(自适应增强)的缩写,由Yoav Freund和Robert Schapire在1995年提出。它的自适应在于:前一个基本分类器分错的样本会得到加强,加权后的全体样本再次被用来训练下一个基本分类器。同时,在每一轮中加入一个新的弱分类器,直到达到某个预定的足够小的错误率或达到预先指定的最大迭代次数。

    具体说来,整个Adaboost 迭代算法就3步:

初始化训练数据的权值分布。如果有N个样本,则每一个训练样本最开始时都被赋予相同的权值:1/N。
训练弱分类器。具体训练过程中,如果某个样本点已经被准确地分类,那么在构造下一个训练集中,它的权值就被降低;相反,如果某个样本点没有被准确地分类,那么它的权值就得到提高。然后,权值更新过的样本集被用于训练下一个分类器,整个训练过程如此迭代地进行下去。
将各个训练得到的弱分类器组合成强分类器。各个弱分类器的训练过程结束后,加大分类误差率小的弱分类器的权重,使其在最终的分类函数中起着较大的决定作用,而降低分类误差率大的弱分类器的权重,使其在最终的分类函数中起着较小的决定作用。换言之,误差率低的弱分类器在最终分类器中占的权重较大,否则较小。
而另一种boosting方法GBDT(Gradient Boost Decision Tree),则与AdaBoost不同,GBDT每一次的计算是都为了减少上一次的残差,进而在残差减少(负梯度)的方向上建立一个新的模型。

boosting集成学习由多个相关联的决策树联合决策,什么叫相关联?举个例子

1、有一个样本[数据->标签]是:[(2,4,5)-> 4]
2、第一棵决策树用这个样本训练的预测为3.3
3、那么第二棵决策树训练时的输入,这个样本就变成了:[(2,4,5)-> 0.7]
4、也就是说,下一棵决策树输入样本会与前面决策树的训练和预测相关

很快你会意识到,Xgboost为何也是一个boosting的集成学习了。

而一个回归树形成的关键点在于:

• 分裂点依据什么来划分(如前面说的均方误差最小,loss);
• 分类后的节点预测值是多少(如前面说,有一种是将叶子节点下各样本实际值得均值作为叶子节点预测误差,或者计算所得)

至于另一类集成学习方法,比如Random Forest(随机森林)算法,各个决策树是独立的、每个决策树在样本堆里随机选一批样本,随机选一批特征进行独立训练,各个决策树之间没有啥关系。本文暂不展开介绍。


3.GBDT
说到Xgboost,不得不先从GBDT(Gradient Boosting Decision Tree)说起。因为xgboost本质上还是一个GBDT,但是力争把速度和效率发挥到极致,所以叫X (Extreme) GBoosted。

包括前面说过,两者都是boosting方法(如图所示:Y = Y1 + Y2 + Y3)



咱们来看个年龄预测的例子。

简单起见,假定训练集只有4个人:A,B,C,D,他们的年龄分别是14,16,24,26。其中A、B分别是高一和高三学生;C,D分别是应届毕业生和工作两年的员工。

如果是用一棵传统的回归决策树来训练,会得到如下图所示结果:


现在我们使用GBDT来做这件事,由于数据太少,我们限定叶子节点做多有两个,即每棵树都只有一个分枝,并且限定只学两棵树。

我们会得到如下图所示结果:


在第一棵树分枝和图1一样,由于A,B年龄较为相近,C,D年龄较为相近,他们被分为左右两拨,每拨用平均年龄作为预测值。

 • 此时计算残差(残差的意思就是:A的实际值 - A的预测值 = A的残差),所以A的残差就是实际值14 - 预测值15 = 残差值-1。
 • 注意,A的预测值是指前面所有树累加的和,这里前面只有一棵树所以直接是15,如果还有树则需要都累加起来作为A的预测值。

残差在数理统计中是指实际观察值与估计值(拟合值)之间的差。“残差”蕴含了有关模型基本假设的重要信息。如果回归模型正确的话, 我们可以将残差看作误差的观测值。

进而得到A,B,C,D的残差分别为-1,1,-1,1。

然后拿它们的残差-1、1、-1、1代替A B C D的原值,到第二棵树去学习,第二棵树只有两个值1和-1,直接分成两个节点,即A和C分在左边,B和D分在右边,经过计算(比如A,实际值-1 - 预测值-1 = 残差0,比如C,实际值-1 - 预测值-1 = 0),此时所有人的残差都是0。

残差值都为0,相当于第二棵树的预测值和它们的实际值相等,则只需把第二棵树的结论累加到第一棵树上就能得到真实年龄了,即每个人都得到了真实的预测值。

换句话说,现在A,B,C,D的预测值都和真实年龄一致了。Perfect!
A: 14岁高一学生,购物较少,经常问学长问题,预测年龄A = 15 – 1 = 14
B: 16岁高三学生,购物较少,经常被学弟问问题,预测年龄B = 15 + 1 = 16

C: 24岁应届毕业生,购物较多,经常问师兄问题,预测年龄C = 25 – 1 = 24
D: 26岁工作两年员工,购物较多,经常被师弟问问题,预测年龄D = 25 + 1 = 26

4.Xgboost
4.1 xgboost树的定义

本节的示意图基本引用自xgboost原作者陈天奇的讲义PPT中。

举个例子,我们要预测一家人谁是谁,则可以先通过年龄区分开小孩和大人,然后再通过性别区分开是男是女,如下图所示。


就这样,训练出了2棵树tree1和tree2,类似之前gbdt的原理,两棵树的结论累加起来便是最终的结论,所以小孩的预测分数就是两棵树中小孩所落到的结点的分数相加:2 + 0.9 = 2.9。爷爷的预测分数同理:-1 + (-0.9)= -1.9。具体如下图所示


恩,你可能要拍案而起了,惊呼,这不是跟上文介绍的gbdt乃异曲同工么?

事实上,如果不考虑工程实现、解决问题上的一些差异,xgboost与gbdt比较大的不同就是目标函数的定义。xgboost的目标函数如下图所示:


其中

 • 红色箭头所指向的L 即为损失函数(比如平方损失函数:l (yi,y^i) = (yi−y^i)2,或logistic损失函数:

)
 • 红色方框所框起来的是正则项(包括L1正则、L2正则)
 • 红色圆圈所圈起来的为常数项
 • 对于f(x),xgboost利用泰勒展开三项,做一个近似

我们可以很清晰地看到,最终的目标函数只依赖于每个数据点的在误差函数上的一阶导数和二阶导数。

额,峰回路转,突然丢这么大一个公式,不少人可能瞬间就懵了。没事,下面,咱们来拆接下这个目标函数。

4.2 xgboost目标函数

xgboost的核心算法思想不难,基本就是

1、不断地添加树,不断地进行特征分裂来生长一棵树,每次添加一个树,其实是学习一个新函数,去拟合上次预测的残差。


注:w_q(x)为叶子节点q的分数,F 对应了所有K棵回归树(regression tree)的集合,而f(x)为其中一棵回归树。

2、当我们训练完成得到k棵树,我们要预测一个样本的分数,其实就是根据这个样本的特征,在每棵树中会落到对应的一个叶子节点,每个叶子节点就对应一个分数
3、最后只需要将每棵树对应的分数加起来就是该样本的预测值。

显然,我们的目标是要使得树群的预测值 尽量接近真实值 yi,而且有尽量大的泛化能力。

所以,从数学角度看这是一个泛函最优化问题,故把目标函数简化如下:


如你所见,这个目标函数分为两部分:误差函数和正则化项。且误差/损失函数揭示训练误差(即预测分数和真实分数的差距),正则化定义复杂度。

对于上式而言,是整个累加模型的输出,正则化项∑kΩ(^{f_{k}})是则表示树的复杂度的函数,值越小复杂度越低,泛化能力越强,其表达式为


T表示叶子节点的个数,w表示叶子节点的分数。直观上看,目标要求预测误差尽量小,且叶子节点T尽量少(γ控制叶子结点的个数),节点数值w尽量不极端(λ控制叶子节点的分数不会过大),防止过拟合。

插一句,一般的目标函数都包含下面两项

其中,误差函数鼓励我们的模型尽量去拟合训练数据,使得最后的模型会有比较少的 bias。而正则化项则鼓励更加简单的模型。因为当模型简单之后,有限数据拟合出来结果的随机性比较小,不容易过拟合,使得最后模型的预测更加稳定。

4.2.1 模型学习与训练误差

具体来说,目标函数第一部分中的i表示第个样本, l(y^i−yi) 表示第i个样本的预测误差,我们的目标当然是误差越小越好。

类似之前GBDT的套路,xgboost也是需要将多棵树的得分累加得到最终的预测得分。


那接下来,我们如何选择每一轮加入什么 f 呢?答案是非常直接的,选取一个 f 来使得我们的目标函数尽量最大地降低。



再强调一下,第t轮的模型预测等于前t-1轮的模型预测y(t-1)加上ft,因此误差函数项记为l(yi,y(t-1)+ft),后面一项为正则化项。在当前步,yi 以及y(t-1)都是已知值,模型学习的是f。

上面这个公式可能有些过于抽象,我们可以考虑当 是平方误差的情况,这个时候我们的目标可以被写成下面这样的二次函数



更加一般的,损失函数不是二次函数咋办?泰勒展开,不是二次的想办法近似为二次(如你所见,定义了一阶导g和二阶导h)。


由于前t-1棵树的预测分数与y_{i}的残差对目标函数的优化不影响,可以直接去掉,且常数项也可以移除,从而得到如下一个比较统一的目标函数。


这时,目标函数只依赖于每个数据点的在误差函数上的一阶导数g和二阶导数h(相信你已看出xgboost的不同了,目标函数保留了泰勒展开的二次项)。

到目前为止我们讨论了目标函数中的第一个部分:训练误差。接下来我们讨论目标函数的第二个部分:如何定义树的复杂度。

4.2.2 树的复杂度

首先,梳理下几个规则

 • 用叶子节点集合以及叶子节点得分表示 
 • 每个样本都落在一个叶子节点上 
 • q(x)表示样本x在某个叶子节点上,wq(x)是该节点的打分,即该样本的模型预测值

所以当我们把树成结构部分q和叶子权重部分w后,结构函数q把输入映射到叶子的索引号上面去,而w给定了每个索引号对应的叶子分数是什么。


另外,如下图所示,xgboost对树的复杂度包含了两个部分:

1、一个是树里面叶子节点的个数T
2、一个是树上叶子节点的得分w的L2模平方(对w进行L2正则化,相当于针对每个叶结点的得分增加L2平滑,目的是为了避免过拟合)



还记得4.2节开头对目标函数的说明吧(损失函数揭示训练误差 + 正则化定义复杂度)?

从数学角度看这是一个泛函最优化问题,故把目标函数简化如下:



如你所见,这个目标函数分为两部分:误差函数和正则化项。且误差/损失函数揭示训练误差(即预测分数和真实分数的差距),正则化定义复杂度。

对于上式而言,是整个累加模型的输出,正则化项∑kΩ(fk)是则表示树的复杂度的函数,值越小复杂度越低,泛化能力越强,其表达式为



T表示叶子节点的个数,w表示叶子节点的分数。直观上看,目标要求预测误差尽量小,且叶子节点T尽量少(γ控制叶子结点的个数),节点数值w尽量不极端(λ控制叶子节点的分数不会过大),防止过拟合。

在这种新的定义下,我们可以把目标函数进行如下改写


其中Ij被定义为每个叶节点 j 上面样本集合 ,g是一阶导数,h是二阶导数。这一步是由于xgboost目标函数第二部分加了两个正则项,一个是叶子节点个数(T),一个是叶子节点的分数(w)。

从而,加了正则项的目标函数里就出现了两种累加

 • 一种是 i - > n(样本数)
 • 一种是 j -> T(叶子节点数)
这一个目标包含了T个相互独立的单变量二次函数。我们可以定义


最终公式可以化简为


通过对wj求导等于0,可以得到


然后把wj最优解代入得到:


4.3 打分函数计算

Obj代表了当我们指定一个树的结构的时候,我们在目标上面最多减少多少。我们可以把它叫做结构分数(structure score)


4.3.1 分裂节点

xgboost的原始论文中给出了两种分裂节点的方法

(1)枚举所有不同树结构的贪心法

不断地枚举不同树的结构,利用这个打分函数来寻找出一个最优结构的树,加入到我们的模型中,再重复这样的操作。不过枚举所有树结构这个操作不太可行,所以常用的方法是贪心法,每一次尝试去对已有的叶子加入一个分割。对于一个具体的分割方案,我们可以获得的增益可以由如下公式计算。


对于每次扩展,我们还是要枚举所有可能的分割方案,如何高效地枚举所有的分割呢?我假设我们要枚举所有x < a 这样的条件,对于某个特定的分割a,我们要计算a左边和右边的导数和。


我们可以发现对于所有的a,我们只要做一遍从左到右的扫描就可以枚举出所有分割的梯度和GL和GR。然后用上面的公式计算每个分割方案的分数就可以了。

观察这个目标函数,大家会发现第二个值得注意的事情就是引入分割不一定会使得情况变好,因为我们有一个引入新叶子的惩罚项。优化这个目标对应了树的剪枝, 当引入的分割带来的增益小于一个阀值的时候,我们可以剪掉这个分割。

大家可以发现,当我们正式地推导目标的时候,像计算分数和剪枝这样的策略都会自然地出现,而不再是一种因为heuristic(启发式)而进行的操作了。

下面是论文中的算法


(2)近似算法

主要针对数据太大,不能直接进行计算


4.4 小结:Boosted Tree Algorithm 

总结一下,如图所示


咱们来再次回顾整个过程。

如果某个样本label数值为4,那么第一个回归树预测3,第二个预测为1; 另外一组回归树,一个预测2,一个预测2,那么倾向后一种,为什么呢?前一种情况,第一棵树学的太多,太接近4,也就意味着有较大的过拟合的风险。

OK,听起来很美好,可是怎么实现呢,上面这个目标函数跟实际的参数怎么联系起来,记得我们说过,回归树的参数:

1、选取哪个feature分裂节点呢
2、节点的预测值(总不能靠取平均值这么粗暴不讲道理的方式吧,好歹高级一点)

最终的策略就是:贪心 + 最优化(对的,二次最优化) 。

通俗解释贪心策略:就是决策时刻按照当前目标最优化决定,说白了就是眼前利益最大化决定,“目光短浅”策略。

这里是怎么用贪心策略的呢,刚开始你有一群样本,放在第一个节点,这时候T=1,w多少呢,不知道,是求出来的,这时候所有样本的预测值都是w,带入样本的label数值,此时loss function变为


 • 如果这里的l(w−yi)误差表示用的是平方误差,那么上述函数就是一个关于w的二次函数求最小值,取最小值的点就是这个节点的预测值,最小的函数值为最小损失函数。
 • 本质上来讲,这就是一个二次函数最优化问题!但要是损失函数不是二次函数咋办?泰勒展开,不是二次的想办法近似为二次。

接着来,接下来要选个feature分裂成两个节点,变成一棵弱小的树苗,那么需要:

1、确定分裂用的feature,how?最简单的是粗暴的枚举/穷举(嗯,够粗暴),然后选择loss function效果最好的那个;
2、如何确立节点的w以及最小的loss function,大声告诉我怎么做?对,二次函数的求最值(计算二次的最值一般都有固定套路,即导数等于0的点) 。所以,选择一个feature分裂,计算loss function最小值,然后再选一个feature分裂,又得到一个loss function最小值,你枚举完,找一个效果最好的,把树给分裂,就得到了小树苗。

在分裂的时候,你可以注意到,每次节点分裂,loss function被影响的只有这个节点的样本,因而每次分裂,计算分裂的增益(loss function的降低量)只需要关注打算分裂的那个节点的样本。

总而言之,XGBoost使用了和CART回归树一样的想法,利用贪婪算法,遍历所有特征的所有特征划分点,不同的是使用的目标函数不一样。具体做法就是分裂后的目标函数值比单子叶子节点的目标函数的增益,同时为了限制树生长过深,还加了个阈值,只有当增益大于该阈值才进行分裂。

以下便为设定的阈值


从而继续分裂,形成一棵树,再形成一棵树,每次在上一次的预测基础上取最优进一步分裂/建树,是不是贪心策略?

凡是这种循环迭代的方式必定有停止条件,什么时候停止呢?简言之,设置树的最大深度、当样本权重和小于设定阈值时停止生长以防止过拟合。具体而言,则

1、当引入的分裂带来的增益小于设定阀值的时候,我们可以剪掉这个分裂,所以并不是每一次分裂loss function整体都会增加的,有点预剪枝的意思,阈值参数为γ(即正则项里叶子节点数T的系数);

2、当树达到最大深度时则停止建立决策树,设置一个超参数max_depth,避免树太深导致学习局部样本,从而过拟合;
 
3、当样本权重和小于设定阈值时则停止建树。什么意思呢,即涉及到一个超参数-最小的样本权重和min_child_weight,和GBM的 min_child_leaf 参数类似,但不完全一样。大意就是一个叶子节点样本太少了,也终止同样是防止过拟合; 

4、貌似看到过有树的最大数量的…

48.GBDT原理

GBDT主要由三个概念组成:Regression Decistion Tree(即DT),Gradient Boosting(即GB),Shrinkage (算法的一个重要演进分枝,目前大部分源码都按该版本实现)。搞定这三个概念后就能明白GBDT是如何工作的,要继续理解它如何用于搜索排序则需要额外理解RankNet概念,之后便功德圆满。下文将逐个碎片介绍,最终把整张图拼出来。

一、 DT:回归树 Regression Decision Tree
提起决策树(DT, Decision Tree) 绝大部分人首先想到的就是C4.5分类决策树。但如果一开始就把GBDT中的树想成分类树,那就是一条歪路走到黑,一路各种坑,最终摔得都要咯血了还是一头雾水。但,这说的就是LZ自己啊有木有。咳嗯,所以说千万不要以为GBDT是很多棵分类树。

决策树分为两大类,回归树和分类树。前者用于预测实数值,如明天的温度、用户的年龄、网页的相关程度;后者用于分类标签值,如晴天/阴天/雾/雨、用户性别、网页是否是垃圾页面。这里要强调的是,前者的结果加减是有意义的,如10岁+5岁-3岁=12岁,后者则无意义,如男+男+女=到底是男是女? 

GBDT的核心在于累加所有树的结果作为最终结果,就像前面对年龄的累加(-3是加负3),而分类树的结果显然是没办法累加的,所以GBDT中的树都是回归树,不是分类树,这点对理解GBDT相当重要(尽管GBDT调整后也可用于分类但不代表GBDT的树是分类树)。那么回归树是如何工作的呢?

下面我们以对人的性别判别/年龄预测为例来说明,每个instance都是一个我们已知性别/年龄的人,而feature则包括这个人上网的时长、上网的时段、网购所花的金额等。

作为对比,先说分类树,我们知道C4.5分类树在每次分枝时,是穷举每一个feature的每一个阈值,找到使得按照feature<=阈值,和feature>阈值分成的两个分枝的熵最大的feature和阈值(熵最大的概念可理解成尽可能每个分枝的男女比例都远离1:1),按照该标准分枝得到两个新节点,用同样方法继续分枝直到所有人都被分入性别唯一的叶子节点,或达到预设的终止条件,若最终叶子节点中的性别不唯一,则以多数人的性别作为该叶子节点的性别。

回归树总体流程也是类似,不过在每个节点(不一定是叶子节点)都会得一个预测值,以年龄为例,该预测值等于属于这个节点的所有人年龄的平均值。分枝时穷举每一个feature的每个阈值找最好的分割点,但衡量最好的标准不再是最大熵,而是最小化均方差--即(每个人的年龄-预测年龄)^2 的总和 / N,或者说是每个人的预测误差平方和 除以 N。

这很好理解,被预测出错的人数越多,错的越离谱,均方差就越大,通过最小化均方差能够找到最靠谱的分枝依据。

分枝直到每个叶子节点上人的年龄都唯一(这太难了)或者达到预设的终止条件(如叶子个数上限),若最终叶子节点上人的年龄不唯一,则以该节点上所有人的平均年龄做为该叶子节点的预测年龄。

二、 GB:梯度迭代 Gradient Boosting
Boosting,迭代,即通过迭代多棵树来共同决策。这怎么实现呢?难道是每棵树独立训练一遍,比如A这个人,第一棵树认为是10岁,第二棵树认为是0岁,第三棵树认为是20岁,我们就取平均值10岁做最终结论?--当然不是!且不说这是投票方法并不是GBDT,只要训练集不变,独立训练三次的三棵树必定完全相同,这样做完全没有意义。

之前说过,GBDT是把所有树的结论累加起来做最终结论的,所以可以想到每棵树的结论并不是年龄本身,而是年龄的一个累加量。

GBDT的核心就在于,每一棵树学的是之前所有树结论和的残差,这个残差就是一个加预测值后能得真实值的累加量。

比如A的真实年龄是18岁,但第一棵树的预测年龄是12岁,差了6岁(即残差为6岁)。

那么在第二棵树里我们把A的年龄设为6岁去学习
如果第二棵树真的能把A分到6岁的叶子节点(残差为12岁),那累加两棵树的结论就是A的真实年龄18岁;
如果第二棵树的结论是5岁,则A仍然存在1岁的残差,第三棵树里A的年龄就变成1岁,继续学。

这就是Gradient Boosting在GBDT中的意义,简单吧。

三、 GBDT工作过程实例。
还是年龄预测,简单起见训练集只有4个人,A,B,C,D,他们的年龄分别是14,16,24,26。其中A、B分别是高一和高三学生;C,D分别是应届毕业生和工作两年的员工。

如果是用一棵传统的回归决策树来训练,会得到如下图1所示结果:


现在我们使用GBDT来做这件事,由于数据太少,我们限定叶子节点做多有两个,即每棵树都只有一个分枝,并且限定只学两棵树。

我们会得到如下图2所示结果:


在第一棵树分枝和图1一样,由于A,B年龄较为相近,C,D年龄较为相近,他们被分为两拨,每拨用平均年龄作为预测值。此时计算残差(残差的意思就是: A的预测值 + A的残差 = A的实际值),所以A的残差就是16-15=1(注意,A的预测值是指前面所有树累加的和,这里前面只有一棵树所以直接是15,如果还有树则需要都累加起来作为A的预测值)。进而得到A,B,C,D的残差分别为-1,1,-1,1。

然后我们拿残差替代A,B,C,D的原值,到第二棵树去学习,如果我们的预测值和它们的残差相等,则只需把第二棵树的结论累加到第一棵树上就能得到真实年龄了。这里的数据显然是我可以做的,第二棵树只有两个值1和-1,直接分成两个节点。此时所有人的残差都是0,即每个人都得到了真实的预测值。

换句话说,现在A,B,C,D的预测值都和真实年龄一致了。Perfect!:
A: 14岁高一学生,购物较少,经常问学长问题;预测年龄A = 15 – 1 = 14
B: 16岁高三学生;购物较少,经常被学弟问问题;预测年龄B = 15 + 1 = 16

C: 24岁应届毕业生;购物较多,经常问师兄问题;预测年龄C = 25 – 1 = 24
D: 26岁工作两年员工;购物较多,经常被师弟问问题;预测年龄D = 25 + 1 = 26 

那么哪里体现了Gradient呢?其实回到第一棵树结束时想一想,无论此时的cost function是什么,是均方差还是均差,只要它以误差作为衡量标准,残差向量(-1, 1, -1, 1)都是它的全局最优方向,这就是Gradient。

讲到这里我们已经把GBDT最核心的概念、运算过程讲完了!没错就是这么简单。

不过讲到这里很容易发现三个问题:
1)既然图1和图2 最终效果相同,为何还需要GBDT呢?

答案是过拟合。过拟合是指为了让训练集精度更高,学到了很多”仅在训练集上成立的规律“,导致换一个数据集当前规律就不适用了。其实只要允许一棵树的叶子节点足够多,训练集总是能训练到100%准确率的(大不了最后一个叶子上只有一个instance)。在训练精度和实际精度(或测试精度)之间,后者才是我们想要真正得到的。

我们发现图1为了达到100%精度使用了3个feature(上网时长、时段、网购金额),其中分枝“上网时长>1.1h” 很显然已经过拟合了,这个数据集上A,B也许恰好A每天上网1.09h, B上网1.05小时,但用上网时间是不是>1.1小时来判断所有人的年龄很显然是有悖常识的;

相对来说图2的boosting虽然用了两棵树 ,但其实只用了2个feature就搞定了,后一个feature是问答比例,显然图2的依据更靠谱(当然,这里是LZ故意做的数据,所以才能靠谱得如此狗血。实际中靠谱不靠谱总是相对的)。

Boosting的最大好处在于,每一步的残差计算其实变相地增大了分错instance的权重,而已经分对的instance则都趋向于0。这样后面的树就能越来越专注那些前面被分错的instance。

就像我们做互联网,总是先解决60%用户的需求凑合着,再解决35%用户的需求,最后才关注那5%人的需求,这样就能逐渐把产品做好,因为不同类型用户需求可能完全不同,需要分别独立分析。如果反过来做,或者刚上来就一定要做到尽善尽美,往往最终会竹篮打水一场空。

2)Gradient呢?不是“G”BDT么?
到目前为止,我们的确没有用到求导的Gradient。在当前版本GBDT描述中,的确没有用到Gradient,该版本用残差作为全局最优的绝对方向,并不需要Gradient求解。

3)这不是boosting吧?Adaboost可不是这么定义的。
这是boosting,但不是Adaboost。GBDT不是Adaboost Decistion Tree。就像提到决策树大家会想起C4.5,提到boost多数人也会想到Adaboost。

Adaboost是另一种boost方法,它按分类对错,分配不同的weight,计算cost function时使用这些weight,从而让“错分的样本权重越来越大,使它们更被重视”。详情参见:https://blog.csdn.net/v_july_v/article/details/40718799

Bootstrap也有类似思想,它在每一步迭代时不改变模型本身,也不计算残差,而是从N个instance训练集中按一定概率重新抽取N个instance出来(单个instance可以被重复sample),对着这N个新的instance再训练一轮。由于数据集变了迭代模型训练结果也不一样,而一个instance被前面分错的越厉害,它的概率就被设的越高,这样就能同样达到逐步关注被分错的instance,逐步完善的效果。

Adaboost的方法被实践证明是一种很好的防止过拟合的方法,但至于为什么则至今没从理论上被证明。GBDT也可以在使用残差的同时引入Bootstrap re-sampling,GBDT多数实现版本中也增加的这个选项,但是否一定使用则有不同看法。

re-sampling一个缺点是它的随机性,即同样的数据集合训练两遍结果是不一样的,也就是模型不可稳定复现,这对评估是很大挑战,比如很难说一个模型变好是因为你选用了更好的feature,还是由于这次sample的随机因素。

49.Adaboost原理

Adaboost是什么  
  
    AdaBoost,是英文"Adaptive Boosting"(自适应增强)的缩写,由Yoav Freund和Robert Schapire在1995年提出。它的自适应在于:前一个基本分类器分错的样本会得到加强,加权后的全体样本再次被用来训练下一个基本分类器。同时,在每一轮中加入一个新的弱分类器,直到达到某个预定的足够小的错误率或达到预先指定的最大迭代次数。

    具体说来,整个Adaboost 迭代算法就3步:

(1)初始化训练数据的权值分布。如果有N个样本,则每一个训练样本最开始时都被赋予相同的权值:1/N。

(2)训练弱分类器。具体训练过程中,如果某个样本点已经被准确地分类,那么在构造下一个训练集中,它的权值就被降低;相反,如果某个样本点没有被准确地分类,那么它的权值就得到提高。然后,权值更新过的样本集被用于训练下一个分类器,整个训练过程如此迭代地进行下去。

(3)将各个训练得到的弱分类器组合成强分类器。各个弱分类器的训练过程结束后,加大分类误差率小的弱分类器的权重,使其在最终的分类函数中起着较大的决定作用,而降低分类误差率大的弱分类器的权重,使其在最终的分类函数中起着较小的决定作用。换言之,误差率低的弱分类器在最终分类器中占的权重较大,否则较小。

50.协同过滤原理

1 推荐引擎的分类

推荐引擎根据不同依据如下分类:
根据其是不是为不同的用户推荐不同的数据,分为基于大众行为(网站管理员自行推荐,或者基于系统所有用户的反馈统计计算出的当下比较流行的物品)、及个性化推荐引擎(帮你找志同道合,趣味相投的朋友,然后在此基础上实行推荐);

根据其数据源,分为基于人口统计学的(用户年龄或性别相同判定为相似用户)、基于内容的(物品具有相同关键词和Tag,没有考虑人为因素),以及基于协同过滤的推荐(发现物品,内容或用户的相关性推荐,分为三个子类,下文阐述);

根据其建立方式,分为基于物品和用户本身的(用户-物品二维矩阵描述用户喜好,聚类算法)、基于关联规则的(The Apriori algorithm算法是一种最有影响的挖掘布尔关联规则频繁项集的算法)、以及基于模型的推荐(机器学习,所谓机器学习,即让计算机像人脑一样持续学习,是人工智能领域内的一个子领域)。

关于上述第二个分类(2、根据其数据源)中的基于协同过滤的推荐:随着 Web2.0 的发展,Web 站点更加提倡用户参与和用户贡献,因此基于协同过滤的推荐机制因运而生。它的原理很简单,就是根据用户对物品或者信息的偏好,发现物品或者内容本身的相关性,或者是发现用户的相关性,然后再基于这些关联性进行推荐。

而基于协同过滤的推荐,又分三个子类:

基于用户的推荐(通过共同口味与偏好找相似邻居用户,K-邻居算法,你朋友喜欢,你也可能喜欢),
基于项目的推荐(发现物品之间的相似度,推荐类似的物品,你喜欢物品A,C与A相似,可能也喜欢C),
基于模型的推荐(基于样本的用户喜好信息构造一个推荐模型,然后根据实时的用户喜好信息预测推荐)。

我们看到,此协同过滤算法最大限度的利用用户之间,或物品之间的相似相关性,而后基于这些信息的基础上实行推荐。下文还会具体介绍此协同过滤。

不过一般实践中,我们通常还是把推荐引擎分两类:

第一类称为协同过滤,即基于相似用户的协同过滤推荐(用户与系统或互联网交互留下的一切信息、蛛丝马迹,或用户与用户之间千丝万缕的联系),以及基于相似项目的协同过滤推荐(尽最大可能发现物品间的相似度);
第二类便是基于内容分析的推荐(调查问卷,电子邮件,或者推荐引擎对本blog内容的分析)。

2 协同过滤推荐

协同过滤是利用集体智慧的一个典型方法。要理解什么是协同过滤 (Collaborative Filtering, 简称 CF),首先想一个简单的问题,如果你现在想看个电影,但你不知道具体看哪部,你会怎么做?大部分的人会问问周围的朋友或者称之为广义上的邻居(neighborhood),看看最近有什么好看的电影推荐,而我们一般更倾向于从口味比较类似的朋友那里得到推荐。这就是协同过滤的核心思想。如下图,你能从图中看到多少信息?


2.1 协同过滤推荐步骤

做协同过滤推荐,一般要做好以下几个步骤:

1)若要做协同过滤,那么收集用户偏好则成了关键。可以通过用户的行为诸如评分(如不同的用户对不同的作品有不同的评分,而评分接近则意味着喜好口味相近,便可判定为相似用户),投票,转发,保存,书签,标记,评论,点击流,页面停留时间,是否购买等获得。如下面第2点所述:所有这些信息都可以数字化,如一个二维矩阵表示出来。

2)收集了用户行为数据之后,我们接下来便要对数据进行减噪与归一化操作(得到一个用户偏好的二维矩阵,一维是用户列表,另一维是物品列表,值是用户对物品的偏好,一般是 [0,1] 或者 [-1, 1] 的浮点数值)。

下面再简单介绍下减噪和归一化操作。

所谓减噪:用户行为数据是用户在使用应用过程中产生的,它可能存在大量的噪音和用户的误操作,我们可以通过经典的数据挖掘算法过滤掉行为数据中的噪音,这样可以是我们的分析更加精确(类似于网页的去噪处理)。

所谓归一化:将各个行为的数据统一在一个相同的取值范围中,从而使得加权求和得到的总体喜好更加精确。最简单的归一化处理,便是将各类数据除以此类中的最大值,以保证归一化后的数据取值在 [0,1] 范围中。至于所谓的加权,很好理解,因为每个人占的权值不同,类似于一场唱歌比赛中对某几个选手进行投票决定其是否晋级,观众的投票抵1分,专家评委的投票抵5分,最后得分最多的选手直接晋级。

3)找到相似的用户和物品,通过什么途径找到呢?便是计算相似用户或相似物品的相似度。

4)相似度的计算有多种方法,不过都是基于向量Vector的,其实也就是计算两个向量的距离,距离越近相似度越大。在推荐中,用户-物品偏好的二维矩阵下,我们将某个或某几个用户对莫两个物品的偏好作为一个向量来计算两个物品之间的相似度,或者将两个用户对某个或某几个物品的偏好作为一个向量来计算两个用户之间的相似度。


所以说,很简单,找物品间的相似度,用户不变,找多个用户对物品的评分;找用户间的相似度,物品不变,找用户对某些个物品的评分。

5)而计算出来的这两个相似度则将作为基于用户、项目的两项协同过滤的推荐。

常见的计算相似度的方法有:欧几里德距离,皮尔逊相关系数(如两个用户对多个电影的评分,采取皮尔逊相关系数等相关计算方法,可以抉择出他们的口味和偏好是否一致),Cosine相似度,Tanimoto系数。

下面,简单介绍其中的欧几里得距离与皮尔逊相关系数:
欧几里德距离(Euclidean Distance)是最初用于计算欧几里德空间中两个点的距离,假设 x,y 是 n 维空间的两个点,它们之间的欧几里德距离是:


可以看出,当 n=2 时,欧几里德距离就是平面上两个点的距离。当用欧几里德距离表示相似度,一般采用以下公式进行转换:距离越小,相似度越大(同时,避免除数为0):


余弦相似度Cosine-based Similarity
两个项目 i ,j 视作为两个m维用户空间向量,相似度计算通过计算两个向量的余弦夹角,那么,对于m*n的评分矩阵,i ,j 的相似度sim( i , j ) 计算公式:

(其中 " · "记做两个向量的内积)

皮尔逊相关系数一般用于计算两个定距变量间联系的紧密程度,为了使计算结果精确,需要找出共同评分的用户。记用户集U为既评论了 i 又评论了 j 的用户集,那么对应的皮尔森相关系数计算公式为:

其中Ru,i 为用户u 对项目 i 的评分,对应带横杠的为这个用户集U对项目i的评分评分。

6)相似邻居计算。邻居分为两类:
1、固定数量的邻居K-neighborhoods (或Fix-size neighborhoods),不论邻居的“远近”,只取最近的 K 个,作为其邻居,如下图A部分所示;
2、基于相似度门槛的邻居,落在以当前点为中心,距离为 K 的区域中的所有点都作为当前点的邻居,如下图B部分所示。


再介绍一下K最近邻(k-Nearest Neighbor,KNN)分类算法:这是一个理论上比较成熟的方法,也是最简单的机器学习算法之一。该方法的思路是:如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类别。

7)经过4)计算出来的基于用户的CF(基于用户推荐之用:通过共同口味与偏好找相似邻居用户,K-邻居算法,你朋友喜欢,你也可能喜欢),基于物品的CF(基于项目推荐之用:发现物品之间的相似度,推荐类似的物品,你喜欢物品A,C与A相似,那么你可能也喜欢C)。

2.2 基于基于用户相似度与项目相似度

    上述3.1节中三个相似度公式是基于项目相似度场景下的,而实际上,基于用户相似度与基于项目相似度计算的一个基本的区别是,基于用户相似度是基于评分矩阵中的行向量相似度求解,基于项目相似度计算式基于评分矩阵中列向量相似度求解,然后三个公式分别都可以适用,如下图:


(其中,为0的表示未评分)

基于项目相似度计算式计算如Item3,Item4两列向量相似度;
基于用户相似度计算式计算如User3,User4量行向量相似度。

千言万语不如举个例子。我们来看一个具体的基于用户相似度计算的例子。

假设我们有一组用户,他们表现出了对一组图书的喜好。用户对一本图书的喜好程度越高,就会给其更高的评分。我们来通过一个矩阵来展示它,行代表用户,列代表图书。

如下图所示,所有的评分范围从1到5,5代表喜欢程度最高。第一个用户(行1)对第一本图书(列1)的评分是4,空的单元格表示用户未给图书评分。


使用基于用户的协同过滤方法,我们首先要做的是基于用户给图书做出的评价,计算用户之间的相似度。

让我们从一个单一用户的角度考虑这个问题,看图1中的第一行,要做到这一点,常见的做法是将使用包含了用户喜好项的向量(或数组)代表每一个用户。相较于使用多样化的相似度量这种做法,更直接。

在这个例子中,我们将使用余弦相似性去计算用户间的相似度。

当我们把第一个用户和其他五个用户进行比较时,就能直观的看到他和其他用户的相似程度。

对于大多数相似度量,向量之间相似度越高,代表彼此更相似。本例中,第一个用户第二、第三个用户非常相似,有两本共同书籍,与第四、第五个用户的相似度低一些,只有一本共同书籍,而与最后一名用户完全不相似,因为没有一本共同书籍。


更一般的,我们可以计算出每个用户的相似性,并且在相似矩阵中表示它们。这是一个对称矩阵,单元格的背景颜色表明用户相似度的高低,更深的红色表示它们之间更相似。


所以,我们找到了与第一个用户最相似的第二个用户,删除用户已经评价过的书籍,给最相似用户正在阅读的书籍加权,然后计算出总和。

在这种情况下,我们计算出n=2,表示为了产生推荐,需要找出与目标用户最相似的两个用户,这两个用户分别是第二个和第三个用户,然后第一个用户已经评价了第一和第五本书,故产生的推荐书是第三本(4.5分),和第四本(3分)。


此外,什么时候用item-base,什么时候用user-base呢:http://weibo.com/1580904460/zhZ9AiIkZ?mod=weibotime?

一般说来,如果item数目不多,比如不超过十万,而且不显著增长的话,就用item-based 好了。为何?如@wuzh670所说,如果item数目不多+不显著增长,说明item之间的关系在一段时间内相对稳定(对比user之间关系),对于实时更新item-similarity需求就降低很多,推荐系统效率提高很多,故用item-based会明智些。

反之,当item数目很多,建议用user-base。当然,实践中具体情况具体分析。如下图所示(摘自项亮的《推荐系统实践》一书):


3 参考文献
1 推荐引擎算法学习导论:协同过滤、聚类、分类:https://blog.csdn.net/v_july_v/article/details/7184318
2 协同过滤推荐算法和基于内容的过滤算法:https://time.geekbang.org/article/1947

51.随机森林特征重要度是否偏好数值型变量?

① 类别型本身也是转化成数值型处理的,在cart里,转化成 是否是某个属性取值 的01结果

② 应该没这种偏好。不过数值型的字段,可以多次用来切分。一个极端的例子,给树足够的深度,如果一个数值型的字段,每个样本取值都不一样,可以切到足够细(甚至一个叶子节点一个样本),但是显然这时候过拟合了。性别只可以切分一次,属性取值比较有限。

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(机器学习面试题41-60)