随机森林和GBDT的学习

合集下载

GBDT(梯度提升树) 原理小结

GBDT(梯度提升树) 原理小结
输入:是训练集样本T={(x1,y1),(x2,y2)...(xm,ym)}, 最大迭代次数T, 损失函数L。 输出是强学习器f(x)
1) 初始化弱学习器: 2) 对迭代轮数t=1,2,...T有: a)对样本i=1,2,...m,计算负梯度
b)利用(xi,r ti)(i=1,2...m), 拟合一颗CART回归树,得到第t颗回归树,其对应的叶子节点区域为 Rtj,j=1.2...J 。其中J为回归树t的叶子节点的个数。
b)绝对损失,这个损失函数也很常见
对应负梯度误差为:
c)Huber损失,它是均方差和绝对损失的折衷产物,对于远离中心的异常点,采用绝对损 失,而中心附近的点采用均方差。这个界限一般用分位数点度量。损失函数如下:
对应的负梯度误差为:
d) 分位数损,需要我们在回归前指定。对应的负梯度误差为:
这里我们再对常用的GBDT损失函数做一个总结。 对于分类算法,其损失函数一般有对数损失函数和指数损失函数两种: a) 如果是指数损失函数,则损失函数表达式为
其负梯度计算和叶子节点的最佳残差拟合参见Adaboost原理篇。 b) 如果是对数损失函数,分为二元分类和多元分类两种,参见4.1节和4.2节。 对于回归算法,常用损失函数有如下4种: a)均方差,这个是最常见的回归损失函数了
如果我们加上了正则化项,则有:
v 的取值范围为0<v<1.对于同样的训练集学习效果,较小的v意味着我们需要更多的弱学习 器的迭代次数。通常我们用步长和迭代最大次数一起来决定算法的拟合效果。
第二种正则化的方式是通过子采样比例(subsample)。取值为(0,1]。注意这里的子采样和 随机森林不一样,随机森林使用的是放回抽样,而这里是不放回抽样。如果取值为1,则全部样本 都使用,等于没有使用子采样。如果取值小于1,则只有一部分样本会去做GBDT的决策树拟合。 选择小于1的比例可以减少方差,即防止过拟合,但是会增加样本拟合的偏差,因此取值不能太 低。推荐在[0.5, 0.8]之间。

随机森林

随机森林

随机森林基础内容:这里只是准备简单谈谈基础的内容,主要参考一下别人的文章,对于随机森林与GBDT,有两个地方比较重要,首先是information gain,其次是决策树。

这里特别推荐Andrew Moore大牛的Decision Trees Tutorial,与Information Gain Tutorial。

Moore的Data Mining Tutorial系列非常赞,看懂了上面说的两个内容之后的文章才能继续读下去。

决策树实际上是将空间用超平面进行划分的一种方法,每次分割的时候,都将当前的空间一分为二,比如说下面的决策树:就是将空间划分成下面的样子:这样使得每一个叶子节点都是在空间中的一个不相交的区域,在进行决策的时候,会根据输入样本每一维feature的值,一步一步往下,最后使得样本落入N个区域中的一个(假设有N个叶子节点)随机森林(Random Forest):随机森林是一个最近比较火的算法,它有很多的优点:∙在数据集上表现良好∙在当前的很多数据集上,相对其他算法有着很大的优势∙它能够处理很高维度(feature很多)的数据,并且不用做特征选择∙在训练完后,它能够给出哪些feature比较重要∙在创建随机森林的时候,对generlization error使用的是无偏估计∙训练速度快∙在训练过程中,能够检测到feature间的互相影响∙容易做成并行化方法∙实现比较简单随机森林顾名思义,是用随机的方式建立一个森林,森林里面有很多的决策树组成,随机森林的每一棵决策树之间是没有关联的。

在得到森林之后,当有一个新的输入样本进入的时候,就让森林中的每一棵决策树分别进行一下判断,看看这个样本应该属于哪一类(对于分类算法),然后看看哪一类被选择最多,就预测这个样本为那一类。

在建立每一棵决策树的过程中,有两点需要注意- 采样与完全分裂。

首先是两个随机采样的过程,random forest对输入的数据要进行行、列的采样。

GBDT算法原理深入解析

GBDT算法原理深入解析

GBDT算法原理深入解析标签:机器学习集成学习GBM GBDT XGBoost梯度提升(Gradient boosting)是一种用于回归、分类和排序任务的机器学习技术,属于Boosting算法族的一部分。

Boosting是一族可将弱学习器提升为强学习器的算法,属于集成学习(ensemble learning)的范畴。

Boosting方法基于这样一种思想:对于一个复杂任务来说,将多个专家的判断进行适当的综合所得出的判断,要比其中任何一个专家单独的判断要好。

通俗地说,就是“三个臭皮匠顶个诸葛亮”的道理。

梯度提升同其他boosting方法一样,通过集成(ensemble)多个弱学习器,通常是决策树,来构建最终的预测模型。

Boosting、bagging和stacking是集成学习的三种主要方法。

不同于bagging方法,boosting方法通过分步迭代(stage-wise)的方式来构建模型,在迭代的每一步构建的弱学习器都是为了弥补已有模型的不足。

Boosting族算法的著名代表是AdaBoost,AdaBoost算法通过给已有模型预测错误的样本更高的权重,使得先前的学习器做错的训练样本在后续受到更多的关注的方式来弥补已有模型的不足。

与AdaBoost算法不同,梯度提升方法在迭代的每一步构建一个能够沿着梯度最陡的方向降低损失(steepest-descent)的学习器来弥补已有模型的不足。

经典的AdaBoost算法只能处理采用指数损失函数的二分类学习任务,而梯度提升方法通过设置不同的可微损失函数可以处理各类学习任务(多分类、回归、Ranking等),应用范围大大扩展。

另一方面,AdaBoost算法对异常点(outlier)比较敏感,而梯度提升算法通过引入bagging思想、加入正则项等方法能够有效地抵御训练数据中的噪音,具有更好的健壮性。

这也是为什么梯度提升算法(尤其是采用决策树作为弱学习器的GBDT算法)如此流行的原因,有种观点认为GBDT是性能最好的机器学习算法,这当然有点过于激进又固步自封的味道,但通常各类机器学习算法比赛的赢家们都非常青睐GBDT算法,由此可见该算法的实力不可小觑。

机器学习期末常考简答题

机器学习期末常考简答题

1.什么是偏差与方差?泛化误差可以分解成偏差的平方加上方差加上噪声。

偏差度量了学习算法的期望预测和真实结果的偏离程度,刻画了学习算法本身的拟合能力,方差度量了同样大小的训练集的变动所导致的学习性能的变化,刻画了数据扰动所造成的影响,噪声表达了当前任务上任何学习算法所能达到的期望泛化误差下界,刻画了问题本身的难度。

偏差和方差一般称为bias和variance,一般训练程度越强,偏差越小,方差越大,泛化误差一般在中间有一个最小值,如果偏差较大,方差较小,此时一般称为欠拟合,而偏差较小,方差较大称为过拟合。

2.采用EM 算法求解的模型有哪些,为什么不用牛顿法或梯度下降法?用EM算法求解的模型一般有GMM或者协同过滤,k-means其实也属于EM。

EM算法一定会收敛,但是可能收敛到局部最优。

由于求和的项数将随着隐变量的数目指数上升,会给梯度计算带来麻烦。

3.SVM、LR、决策树的对比?模型复杂度:SVM支持核函数,可处理线性非线性问题;LR模型简单,训练速度快,适合处理线性问题;决策树容易过拟合,需要进行剪枝损失函数:SVM hinge loss; LR L2正则化; adaboost 指数损失数据敏感度:SVM添加容忍度对outlier不敏感,只关心支持向量,且需要先做归一化;LR 对远点敏感数据量:数据量大就用LR,数据量小且特征少就用SVM非线性核.4.GBDT 和随机森林的区别随机森林采用的是bagging的思想,bagging又称为bootstrap aggreagation,通过在训练样本集中进行有放回的采样得到多个采样集,基于每个采样集训练出一个基学习器,再将基学习器结合。

随机森林在对决策树进行bagging的基础上,在决策树的训练过程中引入了随机属性选择。

传统决策树在选择划分属性的时候是在当前节点属性集合中选择最优属性,而随机森林则是对结点先随机选择包含k个属性的子集,再选择最有属性,k作为一个参数控制了随机性的引入程度。

Adaboost、GBDT与XGBoost的区别

Adaboost、GBDT与XGBoost的区别

Boosting 集成算法中Adaboost、GBDT与XGBoost的区别所谓集成学习,是指构建多个分类器(弱分类器)对数据集进行预测,然后用某种策略将多个分类器预测的结果集成起来,作为最终预测结果。

通俗比喻就是“三个臭皮匠赛过诸葛亮”,或一个公司董事会上的各董事投票决策,它要求每个弱分类器具备一定的“准确性”,分类器之间具备“差异性”。

集成学习根据各个弱分类器之间有无依赖关系,分为Boosting和Bagging两大流派:Boosting流派,各分类器之间有依赖关系,必须串行,比如Adaboost、GBDT(Gradient Boosting Decision Tree)、XgboostBagging流派,各分类器之间没有依赖关系,可各自并行,比如随机森林(Random Forest)而著名的Adaboost作为boosting流派中最具代表性的一种方法。

AdaboostAdaBoost,是英文"Adaptive Boosting"(自适应增强)的缩写,由Yoav Freund和Robert Schapire在1995年提出。

它的自适应在于:前一个基本分类器分错的样本会得到加强,加权后的全体样本再次被用来训练下一个基本分类器。

同时,在每一轮中加入一个新的弱分类器,直到达到某个预定的足够小的错误率或达到预先指定的最大迭代次数。

具体说来,整个Adaboost 迭代算法就3步:1.初始化训练数据的权值分布。

如果有N个样本,则每一个训练样本最开始时都被赋予相同的权值:1/N。

2.训练弱分类器。

具体训练过程中,如果某个样本点已经被准确地分类,那么在构造下一个训练集中,它的权值就被降低;相反,如果某个样本点没有被准确地分类,那么它的权值就得到提高。

然后,权值更新过的样本集被用于训练下一个分类器,整个训练过程如此迭代地进行下去。

3.将各个训练得到的弱分类器组合成强分类器。

各个弱分类器的训练过程结束后,加大分类误差率小的弱分类器的权重,使其在最终的分类函数中起着较大的决定作用,而降低分类误差率大的弱分类器的权重,使其在最终的分类函数中起着较小的决定作用。

机器学习集成学习作业

机器学习集成学习作业

机器学习集成学习作业机器学习作业:1、试分析和总结随机森林(Random Forest)和梯度提升树(GBDT)的区别(⾄少写出三条)。

随机森林可以是分类树也可以是回归树;GBDT只能是回归树;随机森林对异常值不敏感,⽽GBDT对异常值很敏感;随机森林对训练集⼀视同仁,GBDT是基于权值的弱分类器的集成;随机森林采⽤多数投票等,BDT则是将所有结果累加起来,或者加权累加来。

2、解释随机森林预测算法的原理,并分析随机森林能够降低⽅差的原因。

随机森林预测算法的原理:①从原始训练集中使⽤Bootstraping⽅法随机有放回采样选出m个样本,共进⾏n_tree次采样,⽣成n_tree个训练集;②对于n_tree个训练集,分别训练n_tree个决策树模型;③对于单个决策树模型,假设训练样本特征的个数为n,那么每次分裂时根据信息增益或信息增益⽐或基尼指数选择最好的特征进⾏分裂;④每棵树都⼀直这样分裂下去,直到该节点的所有训练样例都属于同⼀类。

在决策树的分裂过程中不需要剪枝;⑤将⽣成的多棵决策树组成随机森林。

对于分类问题,按多棵树分类器投票决定最终分类结果;对于回归问题,由多棵树预测值的均值决定最终预测结果。

原因:随机性的引⼊使得随机森林模型不容易陷⼊过拟合,具有很好的抗噪能⼒。

⽽且随机性保证了各⼦模型间的多样性,⼦模型间差异越⼤,模型融合起来的效果会越好,即降低⽅差的效果更好。

3、举例说明AdaBoost中误差率的变化过程。

4、假设已知训练集T={(1, 5.5), (2, 6.5), (3,7.3), (4,8.5),(5,9.3), (6, 8.9), (7, 9.2), (8, 9.5), (9,7.5), (10, 8.9)},试⽤提升树构建回归树(需满⾜L(y,f m (x))<0.2)。

⼀共进⾏23轮,下⾯就前3轮得到的回归树进⾏说明。

初始化.0)(0=x f第1轮结束,.5.383.85.343.6)(0)(,5.383.85.343.6)(111>≤=+=>≤=x x x T x f x x x T 平⽅损失误差最⼩值为4.321 以2轮结束,.5.863.05.816.0)(2≥-<=x x x T .5.820.85.85.399.85.359.6)()()(212>≤<<=+=x x x x T x f x f 平⽅损失误差最⼩值为3.332。

人工智能自然语言技术练习(习题卷11)

人工智能自然语言技术练习(习题卷11)

人工智能自然语言技术练习(习题卷11)第1部分:单项选择题,共45题,每题只有一个正确答案,多选或少选均不得分。

1.[单选题]以下不是数据清洗的方法有A)A: 缺失值填充B)B: 重复值去除C)C: 寻找离群点(奇点)D)D: 集成不同的数据库答案:D解析:2.[单选题]在同质集成(系统中个体学习器的类型相同)中,个体学习器又被称为A)基学习器B)组建学习C)不能判断D)以上都正确答案:A解析:3.[单选题]tf.cast函数的返回值数据类型是什么A)整数型B)布尔型C)浮点型D)字符串答案:C解析:4.[单选题]什么是KNN算法,如何理解KNNA)KNN可以说是最简单的分类算法之一,同时,它也是最常用的分类算法之一B)通过建立自变量因变量之间一次函数的关系去做回归C)找到间隔最大的超平面,去做分类D)不确定答案:A解析:5.[单选题]tf.reverse的正确说法是哪一项?A)沿着某一维度连结tensorB)沿着某一维度将tensor分离为num_split tensorsC)对tensor进行切片操作D)沿着某维度进行序列反转答案:D解析:6.[单选题]sigmoid的输出值在哪个区间?A)0~1B)0~2C)-1~0答案:A解析:7.[单选题]下列关于GBDT的说法正确的是哪个A)GBDT是机器学习的算法B)GBDT是深度学习的算法C)GBDT属于特征工程部分D)以上都正确答案:A解析:8.[单选题]算法经常出现过拟合,以下四个选项中,哪个不容易陷入过拟合A)未剪枝的决策树B)随机森林C)不加正则的线性回归D)不加正则的逻辑回归答案:B解析:9.[单选题]SVM有着广泛的应用,以下几个应用当中正确的是?A)文本分类B)特征提取C)特征降维D)缺失值处理答案:A解析:10.[单选题]EM最大期望算法的第一步是做什么A)求代价B)最大化C)计算期望D)不确定答案:C解析:11.[单选题]BERT有几个训练任务A)1B)2C)3D)4答案:B解析:12.[单选题]LDA的优缺点说法正确的是哪个选项A)LDA适合对非高斯分布样本进行降维;B)不可以使用类别的先验知识;C)LDA不会过度拟合数据。

人工智能自然语言技术练习(习题卷19)

人工智能自然语言技术练习(习题卷19)

人工智能自然语言技术练习(习题卷19)第1部分:单项选择题,共43题,每题只有一个正确答案,多选或少选均不得分。

1.[单选题]关于k-NN中的k,根据偏差,以下哪一项是正确的A)当你增加k时,偏差会增加B)当你减少k时,偏差会增加C)不能判断D)以上都不对答案:A解析:2.[单选题]GBDT和随机森林都属于集成学习,因此他们有相似的地方,下列描述正确的是A)组成随机森林的树可以并行生成,而GBDT是串行生成B)随机森林的结果是多数表决表决的,而GBDT则是多棵树累加之和C)都是由多棵树组成,最终的结果都是由多棵树一起决定。

D)随机森林对异常值不敏感,而GBDT对异常值比较敏感答案:C解析:3.[单选题]如果数据特征太多,需要对数据特征做降维操作,可以使用以下那种方式A)PCA降维B)K-MeansC)SVMD)岭回归答案:A解析:4.[单选题]汉语自动分词的准确率具体定义是()A)P=(系统输出正确词个数/系统输出词个数)*100%B)R=(系统输出正确词个数/标准答案中词的个数)*100%C)F=((β2+1)*P*R)/(β2*P+R)=(B=1)(2*P*R)/(P+R)D)P(A|B)=P(B|A)*P(A)/P(B)答案:A解析:5.[单选题]XGBoost中用到了和哪个树相同的想法,去寻找最优A)随机森林B)CART回归树C)ID3D)C4.5答案:B解析:6.[单选题]层次softmax使用什么结构编码A)拉格朗日乘子方式B)霍夫曼树的结构C)负例采样D)不确定答案:B解析:7.[单选题]属于一对多输出的序列网络有:A)音乐生成B)情感分类C)机器翻译D)DNA序列分析答案:A解析:8.[单选题]以下四个选项中,哪个激活函数的的输出在0~1的范围之间A)reluB)tanhC)Leaky ReluD)sigmoid答案:D解析:9.[单选题]美国Brown大学于20世纪60~70年代开发的通用语料库是A)LOB语料库B)PropBankC)Brown语料库D)Penn TreeBank答案:C解析:10.[单选题]sigmoid函数的缺点:导数值范围为(0,0.25],反向传播时会导致“梯度消失”。

gbdt模型介绍及构建过程

gbdt模型介绍及构建过程
XGBoost、LightGBM 和 CatBoost 等。这些算法都在 GBDT 的基础上进行了一 些优化,能够更快地构建模型、更好地处理异常值和噪声数据,并且能够进行 多线程并行计算。因此,它们已经成为许多数据科学家和机器学习工程师的首 选算法之一。
GBDT(Gradient Boosting Decision Tree)是一种集成学习模型,它通过将多 个决策树进行集成来提高模型性能。与随机森林不同,GBDT 模型中的树是顺 序生成的,每个树都试图修正前面树的误差。GBDT 在许多领域中都有很好的 应用,比如搜索排序、广告推荐、金融风控等。
GBDT 模型的构建过程可以分为两个阶段:训练阶段和预测阶段。在训练阶 段,GBDT 通过梯度提升算法(Gradient Boosting)逐步构建一个复杂的模 型,而在预测阶段,GBDT 通过将多个决策树的预测结果加起来得到最终的预 测结果。
在训练阶段,GBDT 首先需要选择一个损失函数,例如平方误差(Mean Squared Error)或对数损失(Log Loss)。然后,GBDT 会拟合一个初始的预 测函数,通常是使用所有训练样本的平均值。在每一轮训练中,GBDT 会计算 每个样本在当前模型下的残差,然后将这些残差作为新的标签来训练下一个决 策树。在多轮迭代后,GBDT 会将所有决策树的预测结果加起来,得到最终的 预测结果。同时,GBDT 还可以通过控制树的数量、深度和叶子节点的数量等 参数来控制模型的复杂度。
GBDT 模型中的每棵决策树都是由许多决策节点和叶子节点组成的。在每一轮 迭代中,GBDT 会在当前模型的基础上训练一颗新的决策树,以尽可能地减少 当前模型的残差。在训练过程中,GBDT 需要选择一个合适的切分点来将数据 集划分成两个子集。通常,GBDT 使用贪心算法来选择最佳的切分点,即从所 有可能的切分点中选择最能减少残差的切分点。

人工智能自然语言技术练习(试卷编号171)

人工智能自然语言技术练习(试卷编号171)

人工智能自然语言技术练习(试卷编号171)1.[单选题]在处理文本是,关于NLP中句法结构分析的说法正确的是A)神经网络可以准确地确定句子的句法结构B)机器学习的KNN算法就可以获取到句子的句法结构C)机器学习的K-Means算法就可以获取到句子的句法结构D)不确定答案:A解析:2.[单选题]专家系统是以( )为基础,以推理为核心的系统。

A)专家B)软件C)知识D)解决问题答案:C解析:3.[单选题]sigmoid激活函数的曲线是什么样的A)直线B)A型曲线C)C型曲线D)S型曲线答案:D解析:4.[单选题]以下四个选项中,关于随机森林和GBDT说法正确的是A)都是由多棵树组成,最终的结果都是由多棵树一起决定。

B)RF和GBDT在使用CART树时,只能做回归不能做分类。

C)RF和GBDT在使用CART树时,只能做分类不能做回归。

D)不确定答案:A解析:5.[单选题]下列不属于一般的有指导的机器学习的步骤是()A)预处理B)人工标注C)训练和预测D)数据导出6.[单选题]并行地训练一系列各自独立的不同类模型,然后通过训练一个元模型(meta-model)来将各个模型输出结果进行结合,是什么思想A)BaggingB)BoostingC)StackingD)以上都正确答案:C解析:7.[单选题]小概率事件怎么理解?( )A)发生可能性不大的事件B)发生可能性大的事件C)发生可能性不去确定的事件D)以上都正确答案:A解析:8.[单选题]( )是指用NLP、文本挖掘和计算机语言学等方法对带有情感色彩的主观性文本进行分析、处理、归纳和推理的过程。

A)关键词提取B)文本向量化C)文本情感分析D)智能问答答案:C解析:9.[单选题]在NLP中CRF的到广泛的应用,那么CRF是什么模型A)是生成式模型B)是判别式模型C)即是生成式模型又是判别式D)不确定答案:B解析:10.[单选题]早期的语料库语言学主要研究不包括A)语料库的建设B)语言习得C)音系研究D)方言学与语料库技术的结合11.[单选题]情感分析是一种特殊的文本分析,它侧重于确定个人的偏见或情绪。

机器学习算法分类

机器学习算法分类

机器学习算法分类是否在⼈类监督下进⾏训练(监督,⽆监督和强化学习)在机器学习中,⽆监督学习就是聚类,事先不知道样本的类别,通过某种办法,把相似的样本放在⼀起归位⼀类;⽽监督型学习就是有训练样本,带有属性标签,也可以理解成样本有输⼊有输出。

所有的回归算法和分类算法都属于监督学习。

回归和分类的算法区别在于输出变量的类型,定量输出称为回归,或者说是连续变量预测;定性输出称为分类,或者说是离散变量预测。

分类KNN向量机SVC朴素贝叶斯决策树DecisionTreeClassifier随机森林RandomForestClassifier逻辑回归--》softmax回归回归线性回归--》岭回归 lasso回归向量机SVR决策树DecisionTreeRegressor随机森林回归RandomForestClassifier⼀. K-近邻算法(k-Nearest Neighbors,KNN)(分类)K-近邻是⼀种分类算法,其思路是:如果⼀个样本在特征空间中的k个最相似(即特征空间中最邻近)的样本中的⼤多数属于某⼀个类别,则该样本也属于这个类别。

⼆.⽀持向量机SVM(可分类,可回归)在 SVM 中,选择⼀个超平⾯,它能最好地将输⼊变量空间划分为不同的类,要么是 0,要么是 1。

在 2 维情况下,可以将它看做⼀根线。

三.朴素贝叶斯(Naive Bayesian)(分类)计算参考:四. 线性回归算法 Linear Regression(回归)线性回归就是根据已知数据集求⼀线性函数,使其尽可能拟合数据,让损失函数最⼩,常⽤的线性回归最优法有最⼩⼆乘法和梯度下降法。

线性回归⼜分为两种类型,即简单线性回归(simple linear regression),只有 1 个⾃变量;多变量回归(multiple regression),⾄少两组以上⾃变量。

岭回归(也称为 Tikhonov 正则化)是线性回归的正则化版:在损失函数上直接加上⼀个正则项。

决策树文献综述

决策树文献综述

决策树文献综述简介决策树是一种常用的机器学习算法,已经被广泛应用于各个领域。

本文通过综述相关的文献,全面、详细、完整地探讨决策树的相关主题。

决策树的原理决策树是一种基于树结构的分类算法,通过构建一棵树来进行分类。

决策树的原理可以总结如下:1.特征选择:选择最佳的划分特征,使得划分后的子集尽可能纯净。

2.决策树的构建:递归地构建决策树,直到满足终止条件。

3.决策树的预测:通过遍历决策树来预测新样本的分类。

决策树的优缺点决策树作为一种常用的分类算法,具有以下优点:•简单直观:决策树的结果易于理解和解释,可以生成易于理解的规则。

•高效:决策树的构建和预测效率高,适用于处理大规模数据。

•鲁棒性:决策树对异常值和缺失值具有较好的处理能力。

然而,决策树也有一些缺点:•容易过拟合:决策树容易过分拟合训练数据,导致在新数据上预测效果不佳。

•不稳定性:数据的微小变化可能导致生成完全不同的决策树。

•不适合处理连续型数据:决策树主要适用于离散型数据。

决策树算法的改进为了克服决策树的一些弱点,研究者们提出了一系列改进算法,主要包括以下几个方面:剪枝技术是一种防止决策树过度拟合的方法。

剪枝技术可以分为预剪枝和后剪枝两种:1.预剪枝:在构建决策树的过程中,根据一定的准则选择是否继续分裂节点。

常用的准则有信息增益、基尼指数等。

2.后剪枝:先构建完整的决策树,再根据一定的准则选择节点进行剪枝。

集成学习方法集成学习方法通过组合多个决策树进行预测,以提高分类的准确性和稳定性。

常用的集成学习方法有随机森林和梯度提升树(GBDT)。

1.随机森林:随机森林是通过构建多个决策树并对其进行投票,选择出现次数最多的类别作为最终的预测结果。

2.GBDT:梯度提升树是通过迭代地构建决策树来减小损失函数的梯度,从而逐步提升预测的准确性。

多变量决策树传统的决策树算法只考虑单一特征进行划分,而忽略了特征之间的关系。

多变量决策树引入了多个特征的组合作为划分依据,更适用于处理特征之间存在依赖关系的数据。

人工智能自然语言技术练习(试卷编号221)

人工智能自然语言技术练习(试卷编号221)

人工智能自然语言技术练习(试卷编号221)1.[单选题]不属于基于规则的分词方法的是( )。

A)正向最大匹配法B)逆向最大匹配法C)反向最大匹配法D)双向最大匹配法答案:C解析:2.[单选题]带有深度限制的按叶子生长 (leaf-wise)算法,主要做了什么事情A)增加了一个最大深度的限制,在保证高效率的同时防止过拟合B)先把连续的浮点特征值离散化成k个整数,同时构造一个宽度为k的直方图C)不确定D)以上都正确答案:A解析:3.[单选题]以下的序列数据中,属于一对多(一个输入,多个输出)的关系是哪个?A)音乐生成B)情感分类C)机器翻译D)DNA序列分析答案:A解析:4.[单选题]面向对象的特质有:A)A: 封装B)B: 继承C)C: 多态D)D: 消息答案:D解析:5.[单选题]以下关于智能问答方法的说法错误的是( )。

A)智能问答方法包括基于信息检索的方法,基于语义分析的方法,基于规则的专家系统方法,基于深度学习的方法B)基于信息检索的方法要求答案中必须至少包含问句中的一个字或词,所以不如语义解析方法精确C)基于语义分析的方法常用的方法是利用组合范畴语法(CCG),CCG的核心是词汇解析:6.[单选题]在模型训练的阶段,使用的优化算法中,超参数学习率会怎么变化A)保持不变B)持续较小C)持续增大D)不变答案:B解析:7.[单选题]如何对比矩阵是否相等A)c=tf.greater(a,b)B)a=tf.subtract(a,b)C)b=tf.equal(a,b)D)d=tf.matmul(a,b)答案:C解析:8.[单选题]在神经网络中我们经常会使用到正则化,那么正则化有什么作用A)A防止过拟合B)B边缘检测C)C提取特征D)D简化数据答案:A解析:9.[单选题]tf中的conv2d(a,b,c,d),参数b代表什么?A)被卷积数据B)步长C)卷积核D)填充答案:C解析:10.[单选题]下列哪部分不是专家系统的组成部分A)用户B)综合数据库C)推理机D)知识库答案:A11.[单选题]以下几个选项中,可以通过哪种方式来选择参数或超参A)通过常识选择B)随机选择点来试验超参数效果C)选择输入的参数即可D)取离散参数的平均值答案:B解析:12.[单选题]什么是Boosting思想,如何理解Boosting思想A)将基分类器层层叠加,每一层在训练的时候,对前一层基分类器分错的样本,给予更高的权重B)从总体样本当中随机取一部分样本进行训练,通过多次这样的结果,进行投票获取平均值作为结果输出C)不确定D)以上都正确答案:A解析:13.[单选题]哪种数据类型数据类型可以看作关系型数据库的一张表A)半结构化数据B)非结构化数据C)结构化数据D)不确定答案:C解析:14.[单选题]Pytorch为机器学习和()提供了方便灵活的接口A)机器学习B)算法重构C)NPLD)深度学习答案:D解析:15.[单选题]关于有限状态层叠法,下列说法正确的是A)有限状态层叠法B)基于转换的错误驱动的学习方法C)基于实例的规则学习方法D)以上三项都对答案:D解析:A)作用于输出层B)仅作用于输入层C)无法在隐藏层起作用D)用于输入层,甚至深度隐藏层的归一化过程答案:D解析:17.[单选题]正则表达式的功能主要包括( )A)判断输入是否匹配模式B)在输入中查找和模式匹配字符串C)替换输入和模式匹配字符串D)以上都对答案:D解析:18.[单选题]什么是结构化数据,如何去激烈结构化数据A)数据库中的数据B)HTML文档C)文本D)图片答案:A解析:19.[单选题]GBDT(Gradient Boosting Decision Tree)的全名叫什么A)随机森林B)梯度提升决策树C)聚类D)逻辑回归答案:B解析:20.[单选题]若参数C(cost parameter)被设为无穷,下面哪种说法是正确的?A)只要最佳分类超平面存在,它就能将所有数据全部正确分类B)软间隔SVM分类器将正确分类数据C)二者都不对D)不确定答案:A解析:21.[单选题]以下哪个模型使用了双向的Transformer作为特征提取解析:22.[单选题]虽然随机森林和GBDT都属于集成学习,他们有什么不同之处A)都是由多棵树组成,最终的结果都是由多棵树一起决定。

机器学习中的集成学习方法

机器学习中的集成学习方法

机器学习中的集成学习方法机器学习是一门关于让计算机通过数据学习和优化算法的领域。

在机器学习的过程中,集成学习方法被广泛应用于提升模型性能和泛化能力。

本文将介绍机器学习中的集成学习方法,并探讨其在不同领域的应用。

一、集成学习方法概述集成学习是一种通过结合多个弱分类器或回归器来构建一个更强大的模型的方法。

它通过将若干个基分类器组合在一起,以达到获得更高性能和鲁棒性的目标。

常见的集成学习方法包括:Bagging、Boosting、Stacking等。

1. BaggingBagging方法通过从原始数据集中进行有放回的采样,生成多个子集,每个子集用于训练一个基分类器。

最后,通过将这些基分类器的结果进行投票或求均值的方式来预测新样本的类别或数值。

其中,随机森林(Random Forest)是Bagging方法的典型代表。

2. BoostingBoosting方法通过顺序训练多个基分类器,每个基分类器的训练数据集是上一个基分类器错误分类的样本集。

Boosting方法通过不断调整基分类器的权重,使得后续分类器对先前分类器错误分类的样本给予更高的重视。

常见的Boosting算法有Adaboost、GBDT(Gradient Boosting Decision Tree)等。

3. StackingStacking方法通过将多个基分类器的预测结果作为输入,训练一个元分类器来进行最终的分类。

与Bagging和Boosting方法不同的是,Stacking方法的基分类器不是独立学习的,而是相互协作,通过将多个基分类器的预测结果作为特征输入到元分类器中进行训练和预测。

二、集成学习方法的应用集成学习方法在机器学习领域得到了广泛的应用,以下是一些常见的应用场景。

1. 图像分类在图像分类任务中,集成学习方法可以通过将多个基分类器的预测结果进行投票或求均值的方式来提高模型的性能。

例如,在人脸识别任务中,可以使用多个基分类器对人脸图像进行分类,并将它们的预测结果进行集成,以提高识别准确率。

机器学习中的特征选择方法

机器学习中的特征选择方法

机器学习中的特征选择方法特征选择是机器学习中的一个重要问题,其目的是从原始数据中选择出最有用的特征,以达到降低数据维度、提高模型精度和降低模型复杂度的目的。

在实际应用中,特征选择是非常重要的,它可以帮助我们避免过拟合、提高模型的可解释性和减少计算量。

因此,在本文中,我们将会介绍几种主要的特征选择方法,并探讨它们的优劣和适用场景。

一、过滤式特征选择方法过滤式特征选择方法是在训练模型之前,对原始数据进行特征选择。

它的主要思想是通过一些评价准则,根据特征与目标数据之间的相关性,选出最具有代表性的特征。

常用的评价准则有卡方检验、互信息和相关系数等。

1. 卡方检验卡方检验是最早和最广泛使用的特征选择方法之一。

它的基本思想是,以特征和目标变量之间的独立性为假设,通过计算特征和目标变量之间的卡方值来衡量它们之间的关联程度。

当卡方值越大,意味着特征和目标变量之间的关联程度越高,特征则越重要。

2. 互信息互信息是一个用于衡量两个概率分布之间相似性的指标。

它的基本思想是,通过计算特征和目标变量之间的互信息来衡量它们之间的联系,当它们的互信息越大,则意味着它们之间的联系更紧密,特征则更重要。

3. 相关系数相关系数是用来度量两个随机变量之间相关关系的一个指标。

常用的相关系数有 Pearson 相关系数、Spearman 相关系数和Kendall 相关系数等。

其中,Pearson 相关系数适合用于度量线性关系,而 Spearman 相关系数和 Kendall 相关系数适合用于度量非线性关系。

过滤式特征选择方法的优势在于,它可以快速、简单地选择出高质量的特征,对于维度较高的数据集,特别是离散型特征,选择过滤式特征选择方法是一个不错的选择。

然而,过滤式特征选择方法存在的一个问题是,它无法考虑特征与模型的交互作用,因此可能导致一些相关性较低但重要的特征被误删。

二、包裹式特征选择方法包裹式特征选择方法是在训练模型过程中,将特征看作是一个搜索空间,在不断尝试不同的特征子集的过程中,选出最佳特征子集。

机器学习中的集成学习与梯度提升决策树模型参数调优技巧及实现案例

机器学习中的集成学习与梯度提升决策树模型参数调优技巧及实现案例

机器学习中的集成学习与梯度提升决策树模型参数调优技巧及实现案例机器学习中的集成学习与梯度提升决策树(Gradient Boosting Decision Tree,GBDT)是目前常用的强大学习算法之一。

它的优势在于能够处理高维稀疏数据、缺失数据和非线性关系数据。

在本文中,我们将探讨集成学习与梯度提升决策树的优势以及它们的参数调优技巧,并通过一个实例来展示如何实现。

集成学习是一种使用多个基础模型来建立一个更强大的模型的方法。

它通过将多个模型的预测结果进行组合,来得到更准确的预测。

常见的集成学习方法包括随机森林和梯度提升决策树。

随机森林是通过构建多个决策树并对它们的预测结果进行平均来获得最终结果的。

而梯度提升决策树则是通过迭代地拟合一个损失函数的负梯度来逐步改进模型的预测能力。

在梯度提升决策树模型中,有一些重要的参数可以用来调优模型的表现。

其中最关键的参数是学习率(learning rate)、树的数量(n_estimators)、树的深度(max_depth)等等。

学习率是控制每个模型对最终预测结果的贡献度的参数,较小的学习率可以使得模型更加稳定,但收敛速度较慢。

树的数量决定了集成模型的复杂度和拟合能力,数量越多,模型越复杂,但也容易过拟合。

树的深度决定了每棵决策树的层数,过深的树容易过拟合,而过浅的树可能欠拟合。

除了上述基本参数,还有一些其他参数也可以进行调优,例如正则化参数(subsample)、特征抽样比例(colsample_bytree)等等。

正则化参数可以控制每个模型在训练过程中对样本的采样比例,较小的正则化参数可以使得模型更加稳定,但也容易欠拟合。

特征抽样比例可以控制每棵树在训练过程中对特征的采样比例,较小的特征抽样比例可以减少模型的方差,但也可能增加偏差。

针对参数调优,可以使用交叉验证来帮助选择最佳的参数组合。

交叉验证将数据集分成训练集和验证集,然后利用训练集来训练模型,使用验证集来评估模型的性能。

基于树模型的特征选择法

基于树模型的特征选择法

基于树模型的特征选择法
基于树模型的特征选择法一般是通过使用决策树、随机森林、梯度提升树等树模型来评估特征的重要性,并选择重要性较高的特征。

常用的基于树模型的特征选择方法有以下几种:
1. 决策树重要性:使用决策树算法(如CART算法)构建决策树,利用节点分裂时的特征重要性指标(如信息增益、基尼系数等)来评估特征的重要性。

通常情况下,重要性得分越高的特征被认为是更重要的特征。

2. 随机森林特征重要性:使用随机森林算法构建一个随机森林模型,并利用每棵决策树节点分裂时特征的重要性指标(如平均信息增益、平均基尼系数等)对特征进行评估。

最终可以根据平均重要性得分或者直接使用重要性得分进行特征选择,并排除重要性较低的特征。

3. GBDT特征重要性:使用梯度提升树(Gradient Boosting Decision Trees,GBDT)方法构建一个梯度提升树模型,通过计算特征在每棵决策树中的分裂贡献度来评估特征的重要性。

通常,贡献度越高的特征被认为是更重要的特征。

这些方法的特点是可以考虑特征之间的交互作用,并进行非线性特征选择。

但是使用树模型进行特征选择需要注意选择合适的树模型和参数设置,以及合适的特征重要性指标,否则可能会导致未选择到最优的特征集合。

GBDT算法简述

GBDT算法简述

GBDT算法简述提升决策树GBDT梯度提升决策树算法是近年来被提及较多的⼀个算法,这主要得益于其算法的性能,以及该算法在各类数据挖掘以及机器学习⽐赛中的卓越表现,有很多⼈对GBDT算法进⾏了开源代码的开发,⽐较⽕的是陈天奇的XGBoost和微软的LightGBM⼀、监督学习1、监督学习的主要任务监督学习是机器学习算法中重要的⼀种,对于监督学习,假设有m个训练样本:其中,,如分类问题;也可以为连续值,如回归问题。

在监督学习中利⽤训练样本训练出模型,该模型能够细线从样本特征。

为了能够对映射F进⾏求解,通常对模型设置损失函数,并求的损失函数最⼩的情况下的映射为最好的映射。

对于⼀个具体的问题,如线性回归问题,其映射函数的形式为:梯度下降法算法是求解最优化问题最简单、最直接的⽅法。

梯度下降法是⼀种迭代的优化算法,对于优化问题:其基本步骤为:1)随机选择⼀个初始点2)重复以下过程:决定下降的⽅向:选择步长更新:直到满⾜终⽌条件梯度下降法的具体过程如下图所⽰:2、在函数空间的优化以上是在指定的函数空间中对最优化函数进⾏搜索,那么,能否直接在函数空间中查找到最优的函数呢?根绝上述的梯度下降法的思路,对于模型的损失函数,为了⼆、Boosting1、集成⽅法之BoostingBoosting⽅法是集成学习中重要的⼀种⽅法,在集成学习⽅法中最主要的两种⽅法是Bagging和Boosting,在bagging中,通过对训练样本重新采样的⽅法得到不同的训练样本集,在这些新的训练样本集上分别训练学习器,最终合并每⼀个学习器的结果,作为最终的学习结果,Bagging⽅法的具体过程如下图所⽰:在Bagging⽅法中最重要的算法为随机森林RF算法。

由以上的图中可以看出,在Bagging⽅法中,b个学习器之间彼此是相互独⽴的,这样的特点使得Bagging⽅法更容易并⾏。

与bagging不同的是,在Boosting算法中,学习器之间是存在先后顺序的,同时,每⼀个样本是都有权重的,初始时,每⼀个样本的权重都是相等的,⾸先,第1个学习器对训练样本进⾏学习,当学习完成后,增⼤错误样本的权重,同时减⼩正确样本的权重,再利⽤第2个学习器对其进⾏学习,依次进⾏下去,最终得到b个学习器,最终,合并这b个学习器的结果,同时,与Bagging中不同的是,每个学习器的权重也不⼀样,Boosting⽅法的具体过程如下图所⽰:在Boosting⽅法中,最重要的⽅法包括:Adaboost和GBDT。

GBDT算法梳理

GBDT算法梳理

GBDT算法梳理1.GBDT(Gradient Boosting Decision Tree)思想 Boosting : 给定初始训练数据,由此训练出第⼀个基学习器; 根据基学习器的表现对样本进⾏调整,在之前学习器做错的样本上投⼊更多关注; ⽤调整后的样本,训练下⼀个基学习器; 重复上述过程 T 次,将 T 个学习器加权结合。

Gradient boosting Gradient boosting是 boosting 的其中⼀种⽅法,它主要的思想是,每⼀次建⽴单个学习器时,是在之前建⽴的模型的损失函数的梯度下降⽅向。

我们知道损失函数(loss function)越⼤,说明模型越容易出错,如果我们的模型能够让损失函数持续的下降,则说明我们的模型在不停的改进,⽽最好的⽅式就是让损失函数在其梯度(Gradient)的⽅向上下降。

GBDT GBDT是 GB 和 DT(Decision Tree) 的结合,就是当 GB 中的单个学习器为决策树时的情况.决策树分为两⼤类,回归树和分类树。

前者⽤于预测实数值,如明天的温度、⽤户的年龄、⽹页的相关程度;后者⽤于分类标签值,如晴天/阴天/雾/⾬、⽤户性别、⽹页是否是垃圾页⾯。

这⾥要强调的是,前者的结果加减是有意义的,如10岁+5岁-3岁=12岁,后者则⽆意义,如男+男+⼥=到底是男是⼥?GBDT的核⼼就在于,每⼀棵树学的是之前所有树结论和的残差,这个残差就是⼀个加预测值后能得真实值的累加量。

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

那么在第⼆棵树⾥我们把A的年龄设为6岁去学习,如果第⼆棵树真的能把A分到6岁的叶⼦节 如果第⼆棵树的结论是5岁,则A仍然存在1岁的残差,第三棵树⾥A的年龄就变成1岁,继续学。

⽽分类树的结果显然是没办法累加的,所以GBDT中的树都是回归树,这点对理解GBDT相当重要 我们通过⼀张图⽚,来说明gbdt的训练过程: gbdt通过多轮迭代,每轮迭代产⽣⼀个弱分类器,每个分类器在上⼀轮分类器的残差基础上进⾏训练。

GBDT总结

GBDT总结

GBTs目录1.GBTs与随机森林的比较2.GBTs的介绍2.1 GBTs的简单介绍2.2 GBTs算法2.3 损失函数2.4使用技巧2.5训练误差3.示例3.1 回归3.2 分类4.参数设置1. GBTs与随机森林的比较GBTs和随机森林都是对决策树的集成学习算法。

但是它们的学习过程却不一样:①GBTs一次只能训练一棵树(个体学习器间存在强依赖关系,必须使用串行生成序列化方法),而随机森林个体学习器间不存在强依赖关系,可同时生成并行化,所以GBTs的训练时间要比随机森林长。

另一方面,与随机森林相比,GBTs通常使用更小(深度更浅)的树,这样训练更小的树花费的时间更少。

②随机森林不太容易过度拟合。

在随机森林中训练更多的树可以减少过度拟合的可能性,但是使用GBTs训练更多的树会增加过度拟合的可能性。

(在统计学中,随机森林通过使用更多的树来减少方差,而GBTs通过使用更多的树来减少偏差)。

③随机森林可以更容易调整树的数量,因为它性能随着树的数量单调递增(然而,如果GBTs树的数量变得太大,则其性能开始降低)。

④ 组成随机森林的树可以是分类树,也可以是回归树;而GBTs 只由回归树组成。

(尽管GBTs 调整后也可用于分类,但不代表GBTs 是分类树)⑤ 对于最终的输出结果而言,随机森林采用多数投票等;而GBDT 则是将所有结果累加起来,或者加权累加起来。

2. GBTs 的介绍2.1 GBTs 的简单介绍GBTs 是对决策树的集成学习。

GBTs 迭代地训练决策树以使得损失函数最小化。

类似于决策树,GBTs 可处理特征分类问题,也可扩展到多类问题,不需要特征缩放。

spark.mllib 支持GBTs 用于二分类和回归问题。

spark.mllib 使用现有的决策树实现来实现GBTs 。

注:GBTs 还不支持多分类问题,对于多分类问题可以使用决策树或者随机森林。

2.2 GBTs 算法 2.2.1提升树算法回归问题提升树使用以下前向分步算法:);(,...,2,1),;()()(0)(110m Mm M m M m m x T f M m x T x f x f x f Θ==Θ+==∑=-在前向分步算法的第m 步,给定当前模型)(1x f m -,需求解()()∑=-ΘΘ+=ΘNi m i i m imx T x fy L m11;)(,min arg ˆ得到mΘˆ,即第m 棵树的参数。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

随机森林和GBDT的学习2015-03-31 0个评论来源:走在前往架构师的路上收藏我要投稿前言提到森林,就不得不联想到树,因为正是一棵棵的树构成了庞大的森林,而在本篇文章中的”树“,指的就是Decision Tree-----决策树。

随机森林就是一棵棵决策树的组合,也就是说随机森林=boosting+决策树,这样就好理解多了吧,再来说说GBDT,GBDT全称是Gradient Boosting Decision Tree,就是梯度提升决策树,与随机森林的思想很像,但是比随机森林稍稍的难一点,当然效果相对于前者而言,也会好许多。

由于本人才疏学浅,本文只会详细讲述Random Forest算法的部分,至于GBDT我会给出一小段篇幅做介绍引导,读者能够如果有兴趣的话,可以自行学习。

随机森林算法决策树要想理解随机森林算法,就不得不提决策树,什么是决策树,如何构造决策树,简单的回答就是数据的分类以树形结构的方式所展现,每个子分支都代表着不同的分类情况,比如下面的这个图所示:当然决策树的每个节点分支不一定是三元的,可以有2个或者更多。

分类的终止条件为,没有可以再拿来分类的属性条件或者说分到的数据的分类已经完全一致的情况。

决策树分类的标准和依据是什么呢,下面介绍主要的2种划分标准。

1、信息增益。

这是ID3算法系列所用的方法,C4.5算法在这上面做了少许的改进,用信息增益率来作为划分的标准,可以稍稍减小数据过于拟合的缺点。

2、基尼指数。

这是CART分类回归树所用的方法。

也是类似于信息增益的一个定义,最终都是根据数据划分后的纯度来做比较,这个纯度,你也可以理解为熵的变化,当然我们所希望的情况就是分类后数据的纯度更纯,也就是说,前后划分分类之后的熵的差越大越好。

不过CART算法比较好的一点是树构造好后,还有剪枝的操作,剪枝操作的种类就比较多了,我之前在实现CART算法时用的是代价复杂度的剪枝方法。

这2种决策算法在我之前的博文中已经有所提及,不理解的可以点击我的ID3系列算法介绍和我的CART分类回归树算法。

Boosting原本不打算将Boosting单独拉出来讲的,后来想想还是有很多内容可谈的。

Boosting本身不是一种算法,他更应该说是一种思想,首先对数据构造n个弱分类器,最后通过组合n个弱分类器对于某个数据的判断结果作为最终的分类结果,就变成了一个强分类器,效果自然要好过单一分类器的分类效果。

他可以理解为是一种提升算法,举一个比较常见的Boosting思想的算法AdaBoost,他在训练每个弱分类器的时候,提高了对于之前分错数据的权重值,最终能够组成一批相互互补的分类器集合。

详细可以查看我的AdaBoost算法学习。

OK,2个重要的概念都已经介绍完毕,终于可以介绍主角Random Forest的出现了,正如前言中所说Random Forest=Decision Trees + Boosting,这里的每个弱分类器就是一个决策树了,不过这里的决策树都是二叉树,就是只有2个孩子分支,自然我立刻想到的做法就是用CART算法来构建,因为人家算法就是二元分支的。

随机算法,随机算法,当然重在随机2个字上面,下面是2个方面体现了随机性。

对于数据样本的采集量,比如我数据由100条,我可以每次随机取出其中的20条,作为我构造决策树的源数据,采取又放回的方式,并不是第一次抽到的数据,第二次不能重复,第二随机性体现在对于数据属性的随机采集,比如一行数据总共有10个特征属性,我每次随机采用其中的4个。

正是由于对于数据的行压缩和列压缩,使得数据的随机性得以保证,就很难出现之前的数据过拟合的问题了,也就不需要在决策树最后进行剪枝操作了,这个是与一般的CART算法所不同的,尤其需要注意。

下面是随机森林算法的构造过程:1、通过给定的原始数据,选出其中部分数据进行决策树的构造,数据选取是”有放回“的过程,我在这里用的是CART分类回归树。

2、随机森林构造完成之后,给定一组测试数据,使得每个分类器对其结果分类进行评估,最后取评估结果的众数最为最终结果。

算法非常的好理解,在Boosting算法和决策树之上做了一个集成,下面给出算法的实现,很多资料上只有大篇幅的理论,我还是希望能带给大家一点实在的东西。

随机算法的实现输入数据(之前决策树算法时用过的)input.txt:?1 2 3 4 5 6 7 8 9101112131415Rid Age Income Student CreditRating BuysComputer1 Youth High No Fair No2 Youth High No Excellent No3 MiddleAged High No Fair Yes4 Senior Medium No Fair Yes5 Senior Low Yes Fair Yes6 Senior Low Yes Excellent No7 MiddleAged Low Yes Excellent Yes8 Youth Medium No Fair No9 Youth Low Yes Fair Yes10 Senior Medium Yes Fair Yes11 Youth Medium Yes Excellent Yes12 MiddleAged Medium No Excellent Yes13 MiddleAged High Yes Fair Yes14 Senior Medium No Excellent No树节点类TreeNode.java:?1 2 3 4 5 6 7 8 910111213141516171819202122232425262728293031323334353637383940414243 package DataMining_RandomForest;import java.util.ArrayList;/*** 回归分类树节点** @author lyq**/public class TreeNode {// 节点属性名字private String attrName;// 节点索引标号private int nodeIndex;//包含的叶子节点数private int leafNum;// 节点误差率private double alpha;// 父亲分类属性值private String parentAttrValue;// 孩子节点private TreeNode[] childAttrNode;// 数据记录索引private ArrayList<String> dataIndex;public String getAttrName() {return attrName;}public void setAttrName(String attrName) {this.attrName = attrName;}public int getNodeIndex() {return nodeIndex;}public void setNodeIndex(int nodeIndex) {this.nodeIndex = nodeIndex;}public double getAlpha() {444546474849505152535455565758596061626364656667686970717273747576777879808182838485return alpha;}public void setAlpha(double alpha) {this.alpha = alpha;}public String getParentAttrValue() {return parentAttrValue;}public void setParentAttrValue(String parentAttrValue) { this.parentAttrValue = parentAttrValue;}public TreeNode[] getChildAttrNode() {return childAttrNode;}public void setChildAttrNode(TreeNode[] childAttrNode) { this.childAttrNode = childAttrNode;}public ArrayList<String> getDataIndex() {return dataIndex;}public void setDataIndex(ArrayList<String> dataIndex) {this.dataIndex = dataIndex;}public int getLeafNum() {return leafNum;}public void setLeafNum(int leafNum) {this.leafNum = leafNum;}}决策树类DecisionTree.java:?1 2 3 4 5 6 7 8 91011121314151617181920212223242526272829303132333435363738394041 package DataMining_RandomForest;import java.util.ArrayList;import java.util.HashMap;import java.util.Map;/*** 决策树** @author lyq**/public class DecisionTree {// 树的根节点TreeNode rootNode;// 数据的属性列名称String[] featureNames;// 这棵树所包含的数据ArrayList<String[]> datas;// 决策树构造的的工具类CARTTool tool;public DecisionTree(ArrayList<String[]> datas) {this.datas = datas;this.featureNames = datas.get(0);tool = new CARTTool(datas);// 通过CART工具类进行决策树的构建,并返回树的根节点rootNode = tool.startBuildingTree();}/*** 根据给定的数据特征描述进行类别的判断** @param features* @return*/public String decideClassType(String features) {String classType = "";// 查询属性组String[] queryFeatures;4243444546474849505152535455565758596061626364656667686970717273747576777879808182838485// 在本决策树中对应的查询的属性值描述ArrayList<String[]> featureStrs;featureStrs = new ArrayList<>();queryFeatures = features.split(",");String[] array;for (String name : featureNames) {for (String featureValue : queryFeatures) {array = featureValue.split("=");// 将对应的属性值加入到列表中if (array[0].equals(name)) {featureStrs.add(array);}}}// 开始从根据节点往下递归搜索classType = recusiveSearchClassType(rootNode, featureStrsreturn classType;}/*** 递归搜索树,查询属性的分类类别** @param node* 当前搜索到的节点* @param remainFeatures* 剩余未判断的属性* @return*/private String recusiveSearchClassType(TreeNode node,ArrayList<String[]> remainFeatures) {String classType = null;// 如果节点包含了数据的id索引,说明已经分类到底了if (node.getDataIndex() != null && node.getDataIndex().si classType = judgeClassType(node.getDataIndex());return classType;}// 取出剩余属性中的一个匹配属性作为当前的判断属性名称8687888990919293949596979899 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129String[] currentFeature = null;for (String[] featureValue : remainFeatures) {if (node.getAttrName().equals(featureValue[0])) {currentFeature = featureValue;break;}}for (TreeNode childNode : node.getChildAttrNode()) {// 寻找子节点中属于此属性值的分支if (childNode.getParentAttrValue().equals(currentremainFeatures.remove(currentFeature);classType = recusiveSearchClassType(child remainFeatures);// 如果找到了分类结果,则直接挑出循环break;}else{//进行第二种情况的判断加上!符号的情况String value = childNode.getParentAttrValif(value.charAt(0) == '!'){//去掉第一个!字符value = value.substring(1, value.if(!value.equals(currentFeature[1remainFeatures.remove(curclassType = recusiveSearchClassType(childNode, remainFeatures);break;}}}}return classType;}/*** 根据得到的数据行分类进行类别的决策** @param dataIndex* 根据分类的数据索引号130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165* @return*/public String judgeClassType(ArrayList<String> dataIndex) {// 结果类型值String resultClassType = "";String classType = "";int count = 0;int temp = 0;Map<String, Integer> type2Num = new HashMap<String, Integfor (String index : dataIndex) {temp = Integer.parseInt(index);// 取最后一列的决策类别数据classType = datas.get(temp)[featureNames.length -if (type2Num.containsKey(classType)) {// 如果类别已经存在,则使其计数加1count = type2Num.get(classType);count++;} else {count = 1;}type2Num.put(classType, count);}// 选出其中类别支持计数最多的一个类别值count = -1;for (Map.Entry entry : type2Num.entrySet()) {if ((int) entry.getValue() > count) {count = (int) entry.getValue();resultClassType = (String) entry.getKey()}}return resultClassType;}}随机森林算法工具类RandomForestTool.java: ?1 2 3 4 5 6 7 8 91011121314151617181920212223242526272829303132333435363738394041424344 package DataMining_RandomForest;import java.io.BufferedReader;import java.io.File;import java.io.FileReader;import java.io.IOException;import java.util.ArrayList;import java.util.HashMap;import java.util.Map;import java.util.Random;/*** 随机森林算法工具类** @author lyq**/public class RandomForestTool {// 测试数据文件地址private String filePath;// 决策树的样本占总数的占比率private double sampleNumRatio;// 样本数据的采集特征数量占总特征的比例private double featureNumRatio;// 决策树的采样样本数private int sampleNum;// 样本数据的采集采样特征数private int featureNum;// 随机森林中的决策树的数目,等于总的数据数/用于构造每棵树的数据的private int treeNum;// 随机数产生器private Random random;// 样本数据列属性名称行private String[] featureNames;// 原始的总的数据private ArrayList<String[]> totalDatas;// 决策树森林private ArrayList<DecisionTree> decisionForest;public RandomForestTool(String filePath, double sampleNumRatio,double featureNumRatio) {this.filePath = filePath;this.sampleNumRatio = sampleNumRatio;this.featureNumRatio = featureNumRatio;4546474849505152535455565758596061626364656667686970717273747576777879808182838485868788readDataFile();}/*** 从文件中读取数据*/private void readDataFile() {File file = new File(filePath);ArrayList<String[]> dataArray = new ArrayList<String[]>()try {BufferedReader in = new BufferedReader(new FileReader(file));String str;String[] tempArray;while ((str = in.readLine()) != null) {tempArray = str.split(" ");dataArray.add(tempArray);}in.close();} catch (IOException e) {e.getStackTrace();}totalDatas = dataArray;featureNames = totalDatas.get(0);sampleNum = (int) ((totalDatas.size() - 1) * sampleNumRat//算属性数量的时候需要去掉id属性和决策属性,用条件属性计featureNum = (int) ((featureNames.length -2) * featureNumR// 算数量的时候需要去掉首行属性名称行treeNum = (totalDatas.size() - 1) / sampleNum;}/*** 产生决策树*/private DecisionTree produceDecisionTree() {int temp = 0;DecisionTree tree;String[] tempData;//采样数据的随机行号组ArrayList<Integer> sampleRandomNum;//采样属性特征的随机列号组8990919293949596979899 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 ArrayList<Integer> featureRandomNum;ArrayList<String[]> datas;sampleRandomNum = new ArrayList<>(); featureRandomNum = new ArrayList<>();datas = new ArrayList<>();for(int i=0; i<sampleNum;){temp = random.nextInt(totalDatas.size());//如果是行首属性名称行,则跳过if(temp == 0){continue;}if(!sampleRandomNum.contains(temp)){sampleRandomNum.add(temp);i++;}}for(int i=0; i<featureNum;){temp = random.nextInt(featureNames.length);//如果是第一列的数据id号或者是决策属性列,则跳过if(temp == 0 || temp == featureNames.length-1){continue;}if(!featureRandomNum.contains(temp)){featureRandomNum.add(temp);i++;}}String[] singleRecord;String[] headCulumn = null;// 获取随机数据行for(int dataIndex: sampleRandomNum){singleRecord = totalDatas.get(dataIndex);//每行的列数=所选的特征数+id号tempData = new String[featureNum+2];headCulumn = new String[featureNum+2];133134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176for(int i=0,k=1; i<featureRandomNum.size(); i++,ktemp = featureRandomNum.get(i);headCulumn[k] = featureNames[temp];tempData[k] = singleRecord[temp];}//加上id列的信息headCulumn[0] = featureNames[0];//加上决策分类列的信息headCulumn[featureNum+1] =featureNames[featureNames.length-1];tempData[featureNum+1] =singleRecord[featureNames.length-1];//加入此行数据datas.add(tempData);}//加入行首列出现名称datas.add(0, headCulumn);//对筛选出的数据重新做id分配temp = 0;for(String[] array: datas){//从第2行开始赋值if(temp > 0){array[0] = temp + "";}temp++;}tree = new DecisionTree(datas);return tree;}/*** 构造随机森林*/public void constructRandomTree() {DecisionTree tree;random = new Random();177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220decisionForest = new ArrayList<>();System.out.println("下面是随机森林中的决策树:");// 构造决策树加入森林中for (int i = 0; i < treeNum; i++) {System.out.println("\n决策树" + (i+1));tree = produceDecisionTree();decisionForest.add(tree);}}/*** 根据给定的属性条件进行类别的决策** @param features* 给定的已知的属性描述* @return*/public String judgeClassType(String features) {// 结果类型值String resultClassType = "";String classType = "";int count = 0;Map<String, Integer> type2Num = new HashMap<String, Integfor (DecisionTree tree : decisionForest) {classType = tree.decideClassType(features);if (type2Num.containsKey(classType)) {// 如果类别已经存在,则使其计数加1count = type2Num.get(classType);count++;} else {count = 1;}type2Num.put(classType, count);}// 选出其中类别支持计数最多的一个类别值count = -1;for (Map.Entry entry : type2Num.entrySet()) {if ((int) entry.getValue() > count) {count = (int) entry.getValue();resultClassType = (String) entry.getKey()221 222 223}}return resultClassType;}}CART算法工具类CARTTool.java:?1 2 3 4 5 6 7 8 91011121314151617181920212223242526272829303132 package DataMining_RandomForest;import java.util.ArrayList;import java.util.HashMap;import java.util.LinkedList;import java.util.Queue;/*** CART分类回归树算法工具类** @author lyq**/public class CARTTool {// 类标号的值类型private final String YES = "Yes";private final String NO = "No";// 所有属性的类型总数,在这里就是data源数据的列数private int attrNum;private String filePath;// 初始源数据,用一个二维字符数组存放模仿表格数据private String[][] data;// 数据的属性行的名字private String[] attrNames;// 每个属性的值所有类型private HashMap<String, ArrayList<String>> attrValue;public CARTTool(ArrayList<String[]> dataArray) {attrValue = new HashMap<>();readData(dataArray);}3334353637383940414243444546474849505152535455565758596061626364656667686970717273747576 /*** 根据随机选取的样本数据进行初始化* @param dataArray* 已经读入的样本数据*/public void readData(ArrayList<String[]> dataArray) {data = new String[dataArray.size()][];dataArray.toArray(data);attrNum = data[0].length;attrNames = data[0];}/*** 首先初始化每种属性的值的所有类型,用于后面的子类熵的计算时用*/public void initAttrValue() {ArrayList<String> tempValues;// 按照列的方式,从左往右找for (int j = 1; j < attrNum; j++) {// 从一列中的上往下开始寻找值tempValues = new ArrayList<>();for (int i = 1; i < data.length; i++) {if (!tempValues.contains(data[i][j])) {// 如果这个属性的值没有添加过,则tempValues.add(data[i][j]);}}// 一列属性的值已经遍历完毕,复制到map属性表中attrValue.put(data[0][j], tempValues);}}/*** 计算机基尼指数** @param remainData* 剩余数据* @param attrName* 属性名称* @param value* 属性值7778798081828384858687888990919293949596979899 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120* @param beLongValue* 分类是否属于此属性值* @return*/public double computeGini(String[][] remainData, String attrName,String value, boolean beLongValue) {// 实例总数int total = 0;// 正实例数int posNum = 0;// 负实例数int negNum = 0;// 基尼指数double gini = 0;// 还是按列从左往右遍历属性for (int j = 1; j < attrNames.length; j++) {// 找到了指定的属性if (attrName.equals(attrNames[j])) {for (int i = 1; i < remainData.length; i+// 统计正负实例按照属于和不属于值if ((beLongValue &&remainData[i][j].equals(value))|| (!beLongValue && !remainData[i][j].equals(value))) {if (remainData[i][attrNam 1].equals(YES)) {// 判断此行数据是posNum++;} else {negNum++;}}}}}total = posNum + negNum;double posProbobly = (double) posNum / total;double negProbobly = (double) negNum / total;gini = 1 - posProbobly * posProbobly - negProbobly * negP// 返回计算基尼指数return gini;121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164}/*** 计算属性划分的最小基尼指数,返回最小的属性值划分和最小的基尼指个数组中** @param remainData* 剩余谁* @param attrName* 属性名称* @return*/public String[] computeAttrGini(String[][] remainData, String att String[] str = new String[2];// 最终该属性的划分类型值String spiltValue = "";// 临时变量int tempNum = 0;// 保存属性的值划分时的最小的基尼指数double minGini = Integer.MAX_VALUE;ArrayList<String> valueTypes = attrValue.get(attrName);// 属于此属性值的实例数HashMap<String, Integer> belongNum = new HashMap<>();for (String string : valueTypes) {// 重新计数的时候,数字归0tempNum = 0;// 按列从左往右遍历属性for (int j = 1; j < attrNames.length; j++) {// 找到了指定的属性if (attrName.equals(attrNames[j])) {for (int i = 1; i < remainData.le// 统计正负实例按照属于和进行划分if (remainData[i][j].equatempNum++;}}}}belongNum.put(string, tempNum);}165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208double tempGini = 0;double posProbably = 1.0;double negProbably = 1.0;for (String string : valueTypes) {tempGini = 0;posProbably = 1.0 * belongNum.get(string) / (remai 1);negProbably = 1 - posProbably;tempGini += posProbably* computeGini(remainData, attrNam true);tempGini += negProbably* computeGini(remainData, attrNam false);if (tempGini < minGini) {minGini = tempGini;spiltValue = string;}}str[0] = spiltValue;str[1] = minGini + "";return str;}public void buildDecisionTree(TreeNode node, String parentAttrValString[][] remainData, ArrayList<String> remainAtboolean beLongParentValue) {// 属性划分值String valueType = "";// 划分属性名称String spiltAttrName = "";double minGini = Integer.MAX_VALUE;double tempGini = 0;// 基尼指数数组,保存了基尼指数和此基尼指数的划分属性值String[] giniArray;if (beLongParentValue) {node.setParentAttrValue(parentAttrValue);} else {209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252node.setParentAttrValue("!" + parentAttrValue);}if (remainAttr.size() == 0) {if (remainData.length > 1) {ArrayList<String> indexArray = new ArrayLfor (int i = 1; i < remainData.length; i+indexArray.add(remainData[i][0]);}node.setDataIndex(indexArray);}// System.out.println("attr remain null");return;}for (String str : remainAttr) {giniArray = computeAttrGini(remainData, str);tempGini = Double.parseDouble(giniArray[1]);if (tempGini < minGini) {spiltAttrName = str;minGini = tempGini;valueType = giniArray[0];}}// 移除划分属性remainAttr.remove(spiltAttrName);node.setAttrName(spiltAttrName);// 孩子节点,分类回归树中,每次二元划分,分出2个孩子节点TreeNode[] childNode = new TreeNode[2];String[][] rData;boolean[] bArray = new boolean[] { true, false };for (int i = 0; i < bArray.length; i++) {// 二元划分属于属性值的划分rData = removeData(remainData, spiltAttrName, val bArray[i]);boolean sameClass = true;ArrayList<String> indexArray = new ArrayList<>();for (int k = 1; k < rData.length; k++) {indexArray.add(rData[k][0]);// 判断是否为同一类的253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296if (!rData[k][attrNames.length - 1].equals(rData[1][attrName 1])) {// 只要有1个不相等,就不是同类型sameClass = false;break;}}childNode[i] = new TreeNode();if (!sameClass) {// 创建新的对象属性,对象的同个引用会出错ArrayList<String> rAttr = new ArrayList<>for (String str : remainAttr) {rAttr.add(str);}buildDecisionTree(childNode[i], valueTypebArray[i]);} else {String pAtr = (bArray[i] ? valueType : "!"childNode[i].setParentAttrValue(pAtr);childNode[i].setDataIndex(indexArray);}}node.setChildAttrNode(childNode);}/*** 属性划分完毕,进行数据的移除** @param srcData* 源数据* @param attrName* 划分的属性名称* @param valueType* 属性的值类型* @parame beLongValue 分类是否属于此值类型*/private String[][] removeData(String[][] srcData, String attrNameString valueType, boolean beLongValue) {String[][] desDataArray;ArrayList<String[]> desData = new ArrayList<>();// 待删除数据297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340ArrayList<String[]> selectData = new ArrayList<>();selectData.add(attrNames);// 数组数据转化到列表中,方便移除for (int i = 0; i < srcData.length; i++) {desData.add(srcData[i]);}// 还是从左往右一列列的查找for (int j = 1; j < attrNames.length; j++) {if (attrNames[j].equals(attrName)) {for (int i = 1; i < desData.size(); i++)if (desData.get(i)[j].equals(valu// 如果匹配这个数据,则移selectData.add(desData.ge}}}}if (beLongValue) {desDataArray = new String[selectData.size()][];selectData.toArray(desDataArray);} else {// 属性名称行不移除selectData.remove(attrNames);// 如果是划分不属于此类型的数据时,进行移除desData.removeAll(selectData);desDataArray = new String[desData.size()][];desData.toArray(desDataArray);}return desDataArray;}/*** 构造分类回归树,并返回根节点* @return*/public TreeNode startBuildingTree() {initAttrValue();ArrayList<String> remainAttr = new ArrayList<>();// 添加属性,除了最后一个类标号属性341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384for (int i = 1; i < attrNames.length - 1; i++) {remainAttr.add(attrNames[i]);}TreeNode rootNode = new TreeNode();buildDecisionTree(rootNode, "", data, remainAttr, false);setIndexAndAlpah(rootNode, 0, false);showDecisionTree(rootNode, 1);return rootNode;}/*** 显示决策树** @param node* 待显示的节点* @param blankNum* 行空格符,用于显示树型结构*/private void showDecisionTree(TreeNode node, int blankNum) {System.out.println();for (int i = 0; i < blankNum; i++) {System.out.print(" ");}System.out.print("--");// 显示分类的属性值if (node.getParentAttrValue() != null&& node.getParentAttrValue().length() > 0System.out.print(node.getParentAttrValue());} else {System.out.print("--");}System.out.print("--");if (node.getDataIndex() != null && node.getDataIndex().siString i = node.getDataIndex().get(0);System.out.print("【" + node.getNodeIndex() + "】+ data[Integer.parseInt(i)][attrN 1]);System.out.print("[");for (String index : node.getDataIndex()) {System.out.print(index + ", ");}385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428System.out.print("]");} else {// 递归显示子节点System.out.print("【" + node.getNodeIndex() + ":"+ node.getAttrName() + "】");if (node.getChildAttrNode() != null) {for (TreeNode childNode : node.getChildAtshowDecisionTree(childNode, 2 * b}} else {System.out.print("【 Child Null】");}}}/*** 为节点设置序列号,并计算每个节点的误差率,用于后面剪枝** @param node* 开始的时候传入的是根节点* @param index* 开始的索引号,从1开始* @param ifCutNode* 是否需要剪枝*/private void setIndexAndAlpah(TreeNode node, int index, boolean i TreeNode tempNode;// 最小误差代价节点,即将被剪枝的节点TreeNode minAlphaNode = null;double minAlpah = Integer.MAX_VALUE;Queue<TreeNode> nodeQueue = new LinkedList<TreeNode>();nodeQueue.add(node);while (nodeQueue.size() > 0) {index++;// 从队列头部获取首个节点tempNode = nodeQueue.poll();tempNode.setNodeIndex(index);if (tempNode.getChildAttrNode() != null) {for (TreeNode childNode : tempNode.getChilnodeQueue.add(childNode);}computeAlpha(tempNode);if (tempNode.getAlpha() < minAlpah) {429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472minAlphaNode = tempNode;minAlpah = tempNode.getAlpha();} else if (tempNode.getAlpha() == minAlpa// 如果误差代价值一样,比较包含的剪枝有多叶子节点数的节点if (tempNode.getLeafNum() > minAlphaNode.getLeafNum()) {minAlphaNode = tempNode;}}}}if (ifCutNode) {// 进行树的剪枝,让其左右孩子节点为nullminAlphaNode.setChildAttrNode(null);}}/*** 为非叶子节点计算误差代价,这里的后剪枝法用的是CCP代价复杂度剪** @param node* 待计算的非叶子节点*/private void computeAlpha(TreeNode node) {double rt = 0;double Rt = 0;double alpha = 0;// 当前节点的数据总数int sumNum = 0;// 最少的偏差数int minNum = 0;ArrayList<String> dataIndex;ArrayList<TreeNode> leafNodes = new ArrayList<>();addLeafNode(node, leafNodes);node.setLeafNum(leafNodes.size());for (TreeNode attrNode : leafNodes) {dataIndex = attrNode.getDataIndex();int num = 0;sumNum += dataIndex.size();473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511for (String s : dataIndex) {// 统计分类数据中的正负实例数if (data[Integer.parseInt(s)][attrNames.l 1].equals(YES)) {num++;}}minNum += num;// 取小数量的值部分if (1.0 * num / dataIndex.size() > 0.5) {num = dataIndex.size() - num;}rt += (1.0 * num / (data.length - 1));}//同样取出少偏差的那部分if (1.0 * minNum / sumNum > 0.5) {minNum = sumNum - minNum;}Rt = 1.0 * minNum / (data.length - 1);alpha = 1.0 * (Rt - rt) / (leafNodes.size() - 1);node.setAlpha(alpha);}/*** 筛选出节点所包含的叶子节点数** @param node* 待筛选节点* @param leafNode* 叶子节点列表容器*/private void addLeafNode(TreeNode node, ArrayList<TreeNode> leafN ArrayList<String> dataIndex;if (node.getChildAttrNode() != null) {for (TreeNode childNode : node.getChildAttrNode()dataIndex = childNode.getDataIndex();if (dataIndex != null && dataIndex.size()// 说明此节点为叶子节点leafNode.add(childNode);。

相关文档
最新文档