精华内容
下载资源
问答
  • 随机森林算法

    千次阅读 2019-03-11 22:15:29
    在这篇文章中,您将学习随机森林算法如何工作以及其他几个重要的事情。 目录: 这个怎么运作 真实生活类比 特征重要性 决策树与随机森林的区别 重要的超参数(预测能力,速度) 优点和缺点 用例 摘要 这个...

    随机森林是一种灵活,易于使用的机器学习算法,即使没有超参数调整,也能在大多数情况下产生出色的结果。它也是最常用的算法之一,因为它简单,并且可以用于分类和回归任务。在这篇文章中,您将学习随机森林算法如何工作以及其他几个重要的事情。

    目录:

    • 这个怎么运作
    • 真实生活类比
    • 特征重要性
    • 决策树与随机森林的区别
    • 重要的超参数(预测能力,速度)
    • 优点和缺点
    • 用例
    • 摘要

    这个怎么运作:

    随机森林是一种监督学习算法。就像你已经从它的名字中看到的一样,它创造了一个森林,并使它在某种程度上是随机的。它构建的“森林”是决策树的集合,大部分时间都是用“装袋”方法训练的。装袋方法的一般思想是学习模型的组合增加了整体结果。

    用简单的话来说:随机森林构建多个决策树并将它们合并在一起以获得更准确和稳定的预测。

    随机森林的一大优势是,它可以用于分类和回归问题,这些问题构成了当前机器学习系统的大部分。我将在分类中讨论随机森林,因为分类有时被认为是机器学习的基石。您可以在下面看到随机森林如何使用两棵树:

    随机森林具有与决策树或装袋分类器几乎相同的超参数。幸运的是,您不必将决策树与装袋分类器组合在一起,只需轻松使用随机森林的分类器类即可。就像我已经说过的,使用Random Forest,你也可以使用Random Forest回归量来处理回归任务。

    随机森林为模型增加了额外的随机性,同时种植树木。它不是在分割节点时搜索最重要的特征,而是在随机特征子集中搜索最佳特征。这导致了广泛的多样性,通常导致更好的模型。

     

    因此,在随机森林中,用于分割节点的算法仅考虑特征的随机子集。您甚至可以通过为每个特征使用随机阈值而不是搜索最佳可能阈值(如正常决策树那样)来使树更随机。

    真实生活类比:

    想象一下,一个名叫安德鲁的人,想要决定在一年的假期旅行中应该去哪些地方。他问那些认识他的人。首先,他去找一位朋友,朋友问安德鲁之前他去过哪里,他是否喜欢。根据答案,他会给安德鲁一些建议。

    这是典型的决策树算法方法。安德鲁斯的朋友通过使用安德鲁的答案创建了规则,以指导他决定应该向安德鲁推荐什么。

     

    之后,安德鲁开始要求越来越多的朋友给他建议,他们再次问他不同的问题,他们可以从中得到一些建议。然后他选择了对他最推荐的地方,这是典型的随机森林算法方法。

    特征重要性:

    随机森林算法的另一个高质量是,很容易测量每个特征对预测的相对重要性。Sklearn为此提供了一个很好的工具,它可以通过查看使用该功能的树节点减少森林中所有树木的杂质来测量特征的重要性。它会在训练后自动为每个要素计算此分数并对结果进行缩放,以使所有重要性的总和等于1。

    如果你不知道决策树是如何工作的,如果你不知道叶子或节点是什么,这里是维基百科的一个很好的描述:在决策树中,每个内部节点代表一个属性的“测试”(例如硬币正面还是反面朝上),每个分支代表测试的结果,每个叶节点代表一个类标签(在计算所有属性后作出决定)。 没有子节点的节点是叶子。

     

    通过查看特征重要性,您可以决定要删除哪些特征,因为它们对预测过程没有足够的贡献或没有贡献。这很重要,因为机器学习的一般规则是,您拥有的特征越多,您的模型就越容易受到过度拟合的影响,反之亦然。

    下面你可以看到一个表格和一个可视化,它显示了13个特征的重要性,我在监督分类项目中使用了有名的泰坦尼克号数据集。你可以在这里找到整个项目。

    决策树与随机森林之间的差异:

    就像我已经提到的,随机森林是决策树的集合,但是存在一些差异。

    如果您将具有要素和标签的训练数据集输入到决策树中,它将制定一组规则,用于进行预测。

    例如,如果您想预测一个人是否会点击在线广告,您可以收集过去点击过的人的广告以及描述他的决定的一些功能。如果将功能和标签放入决策树中,它将生成一些规则。然后,您可以预测广告是否会被点击。相比之下,随机森林算法随机选择观察和特征来构建几个决策树,然后平均结果。

    另一个区别是“深层”决策树可能会受到过度拟合的影响。随机森林通过创建特征的随机子集并使用这些子集构建较小的树来防止过度拟合。之后,它结合了子树。请注意,这不会每次都起作用,并且它还会使计算速度变慢,具体取决于随机林构建的树数。

    重要的超参数:

    随机森林中的超参数用于增加模型的预测能力或使模型更快。我将在这里谈谈sklearns内置随机森林函数的超参数。

    1.增加预测能力

    首先,有“n_estimators”超参数,它只是算法在进行最大投票或取平均预测之前构建的树数。通常,更多数量的树会提高性能并使预测更稳定,但它也会减慢计算速度。

    另一个重要的超参数是“max_features”,它是Random Forest考虑拆分节点的最大特征数。Sklearn提供了几个选项,在他们的文档中有描述。

     

    我们将在速度方面讨论的最后一个重要的超参数是“min_sample_leaf”。与其名称一样,这确定了拆分内部节点所需的最小叶子数。

    2.提高模型速度

    “n_jobs”超参数告诉引擎是多少处理器允许使用。如果它的值为1,则它只能使用一个处理器。值“-1”表示没有限制。

    “random_state”使模型的输出可复制。当模型具有random_state的确定值并且已经给出相同的超参数和相同的训练数据时,该模型将始终产生相同的结果。

    最后,还有“oob_score”(也称为oob采样),它是一种随机森林交叉验证方法。在此抽样中,大约三分之一的数据不用于训练模型,可用于评估其性能。这些样品称为袋外样品。它与留一法交叉验证方法非常相似,但几乎没有额外的计算负担。

    优点和缺点:

    就像我已经提到的,随机森林的一个优点是它可以用于回归和分类任务,并且很容易查看它分配给输入要素的相对重要性。

    随机森林也被认为是一种非常方便易用的算法,因为它的默认超参数通常会产生良好的预测结果。超参数的数量也不是那么高,而且它们很容易理解。

     

    机器学习中的一个重大问题是过度拟合,但大多数情况下,这对于随机森林分类器来说不容易发生。那是因为如果森林中有足够的树,分类器就不会过度拟合模型。

    随机森林的主要局限在于大量决策树可以使算法减慢并且对实时预测无效。一般来说,这些算法训练速度很快,但一旦训练完成预测就很慢。更准确的预测需要更多的树,这导致更慢的模型。在大多数实际应用中,随机森林算法足够快,但肯定存在运行时性能很重要而其他方法更受欢迎的情况。

    当然,随机森林是一种预测建模工具,而不是一种描述性工具。这意味着,如果您正在寻找数据中关系的描述,则首选其他方法。

    用例:

    随机森林算法用于许多不同的领域,如银行,股票市场,医药和电子商务。例如,在银行业中,它用于检测将比其他人更频繁地使用银行服务的客户,并及时偿还他们的债务。在此域中,它还用于检测想要诈骗银行的欺诈客户。在金融领域,它用于确定未来股票的行为。在医疗保健领域,它用于识别医学中组分的正确组合,并分析患者的病史以识别疾病。最后,在电子商务中,随机森林用于确定客户是否真的喜欢该产品。

    摘要:

    随机森林是一个很好的算法,可以在模型开发过程的早期进行训练,看看它是如何执行的,并且由于其简单性,很难建立一个“坏”的随机森林。如果您需要在短时间内开发模型,此算法也是一个很好的选择。最重要的是,它提供了一个非常好的指标,表明它为您的功能赋予的重要性。

    随机森林在性能方面也很难被击败。当然,您可能总能找到一个能够表现更好的模型,比如神经网络,但这些通常需要花费更多的时间进行开发。最重要的是,它们可以处理许多不同的要素类型,如二进制,分类和数字。

    总体而言,随机森林是一种(大多数)快速,简单和灵活的工具,尽管它有其局限性。

    点击英文原文 https://towardsdatascience.com/the-random-forest-algorithm-d457d499ffcd


    更多文章欢迎访问:   http://www.apexyun.com

    公众号:银河系1号

    联系邮箱:public@space-explore.com

    (未经同意,请勿转载)

    展开全文
  • 随机森林算法及其实现(Random Forest)

    万次阅读 多人点赞 2018-09-04 16:36:06
    阅读目录 1 什么是随机森林? 2 随机森林的特点 3 随机森林的相关基础知识 ... 作为新兴起的、高度灵活的一种机器学习算法随机森林(Random Forest,简称RF)拥有广泛的应用前景,从市场营销...

    阅读目录

    回到顶部

    1 什么是随机森林?

      作为新兴起的、高度灵活的一种机器学习算法,随机森林(Random Forest,简称RF)拥有广泛的应用前景,从市场营销到医疗保健保险,既可以用来做市场营销模拟的建模,统计客户来源,保留和流失,也可用来预测疾病的风险和病患者的易感性。最初,我是在参加校外竞赛时接触到随机森林算法的。最近几年的国内外大赛,包括2013年百度校园电影推荐系统大赛、2014年阿里巴巴天池大数据竞赛以及Kaggle数据科学竞赛,参赛者对随机森林的使用占有相当高的比例。此外,据我的个人了解来看,一大部分成功进入答辩的队伍也都选择了Random Forest 或者 GBDT 算法。所以可以看出,Random Forest在准确率方面还是相当有优势的。

      那说了这么多,那随机森林到底是怎样的一种算法呢?

      如果读者接触过决策树(Decision Tree)的话,那么会很容易理解什么是随机森林。随机森林就是通过集成学习的思想将多棵树集成的一种算法,它的基本单元是决策树,而它的本质属于机器学习的一大分支——集成学习(Ensemble Learning)方法。随机森林的名称中有两个关键词,一个是“随机”,一个就是“森林”。“森林”我们很好理解,一棵叫做树,那么成百上千棵就可以叫做森林了,这样的比喻还是很贴切的,其实这也是随机森林的主要思想--集成思想的体现。“随机”的含义我们会在下边部分讲到。

      其实从直观角度来解释,每棵决策树都是一个分类器(假设现在针对的是分类问题),那么对于一个输入样本,N棵树会有N个分类结果。而随机森林集成了所有的分类投票结果,将投票次数最多的类别指定为最终的输出,这就是一种最简单的 Bagging 思想。

    回到顶部

    2 随机森林的特点

      我们前边提到,随机森林是一种很灵活实用的方法,它有如下几个特点:

    • 在当前所有算法中,具有极好的准确率/It is unexcelled in accuracy among current algorithms;
    • 能够有效地运行在大数据集上/It runs efficiently on large data bases;
    • 能够处理具有高维特征的输入样本,而且不需要降维/It can handle thousands of input variables without variable deletion;
    • 能够评估各个特征在分类问题上的重要性/It gives estimates of what variables are important in the classification;
    • 在生成过程中,能够获取到内部生成误差的一种无偏估计/It generates an internal unbiased estimate of the generalization error as the forest building progresses;
    • 对于缺省值问题也能够获得很好得结果/It has an effective method for estimating missing data and maintains accuracy when a large proportion of the data are missing
    • ... ...

      实际上,随机森林的特点不只有这六点,它就相当于机器学习领域的Leatherman(多面手),你几乎可以把任何东西扔进去,它基本上都是可供使用的。在估计推断映射方面特别好用,以致都不需要像SVM那样做很多参数的调试。具体的随机森林介绍可以参见随机森林主页:Random Forest

    回到顶部

    3 随机森林的相关基础知识

      随机森林看起来是很好理解,但是要完全搞明白它的工作原理,需要很多机器学习方面相关的基础知识。在本文中,我们简单谈一下,而不逐一进行赘述,如果有同学不太了解相关的知识,可以参阅其他博友的一些相关博文或者文献。

      1)信息、熵以及信息增益的概念

      这三个基本概念是决策树的根本,是决策树利用特征来分类时,确定特征选取顺序的依据。理解了它们,决策树你也就了解了大概。

      引用香农的话来说,信息是用来消除随机不确定性的东西。当然这句话虽然经典,但是还是很难去搞明白这种东西到底是个什么样,可能在不同的地方来说,指的东西又不一样。对于机器学习中的决策树而言,如果带分类的事物集合可以划分为多个类别当中,则某个类(xi)的信息可以定义如下:

      I(x)用来表示随机变量的信息,p(xi)指是当xi发生时的概率。

      熵是用来度量不确定性的,当熵越大,X=xi的不确定性越大,反之越小。对于机器学习中的分类问题而言,熵越大即这个类别的不确定性更大,反之越小。

      信息增益在决策树算法中是用来选择特征的指标,信息增益越大,则这个特征的选择性越好。

      这方面的内容不再细述,感兴趣的同学可以看 信息&熵&信息增益 这篇博文。

      2)决策树

      决策树是一种树形结构,其中每个内部节点表示一个属性上的测试,每个分支代表一个测试输出,每个叶节点代表一种类别。常见的决策树算法有C4.5、ID3和CART。

      3)集成学习 

      集成学习通过建立几个模型组合的来解决单一预测问题。它的工作原理是生成多个分类器/模型,各自独立地学习和作出预测。这些预测最后结合成单预测,因此优于任何一个单分类的做出预测。

      随机森林是集成学习的一个子类,它依靠于决策树的投票选择来决定最后的分类结果。你可以在这找到用python实现集成学习的文档:Scikit 学习文档

    回到顶部

    4 随机森林的生成

      前面提到,随机森林中有许多的分类树。我们要将一个输入样本进行分类,我们需要将输入样本输入到每棵树中进行分类。打个形象的比喻:森林中召开会议,讨论某个动物到底是老鼠还是松鼠,每棵树都要独立地发表自己对这个问题的看法,也就是每棵树都要投票。该动物到底是老鼠还是松鼠,要依据投票情况来确定,获得票数最多的类别就是森林的分类结果。森林中的每棵树都是独立的,99.9%不相关的树做出的预测结果涵盖所有的情况,这些预测结果将会彼此抵消。少数优秀的树的预测结果将会超脱于芸芸“噪音”,做出一个好的预测。将若干个弱分类器的分类结果进行投票选择,从而组成一个强分类器,这就是随机森林bagging的思想(关于bagging的一个有必要提及的问题:bagging的代价是不用单棵决策树来做预测,具体哪个变量起到重要作用变得未知,所以bagging改进了预测准确率但损失了解释性。)。下图可以形象地描述这个情况:

     

      有了树我们就可以分类了,但是森林中的每棵树是怎么生成的呢?

      每棵树的按照如下规则生成:

      1)如果训练集大小为N,对于每棵树而言,随机且有放回地从训练集中的抽取N个训练样本(这种采样方式称为bootstrap sample方法),作为该树的训练集;

      从这里我们可以知道:每棵树的训练集都是不同的,而且里面包含重复的训练样本(理解这点很重要)。

      为什么要随机抽样训练集?(add @2016.05.28)

      如果不进行随机抽样,每棵树的训练集都一样,那么最终训练出的树分类结果也是完全一样的,这样的话完全没有bagging的必要;

      为什么要有放回地抽样?(add @2016.05.28)

      我理解的是这样的:如果不是有放回的抽样,那么每棵树的训练样本都是不同的,都是没有交集的,这样每棵树都是"有偏的",都是绝对"片面的"(当然这样说可能不对),也就是说每棵树训练出来都是有很大的差异的;而随机森林最后分类取决于多棵树(弱分类器)的投票表决,这种表决应该是"求同",因此使用完全不同的训练集来训练每棵树这样对最终分类结果是没有帮助的,这样无异于是"盲人摸象"。

      2)如果每个样本的特征维度为M,指定一个常数m<<M,随机地从M个特征中选取m个特征子集,每次树进行分裂时,从这m个特征中选择最优的;

      3)每棵树都尽最大程度的生长,并且没有剪枝过程。

      一开始我们提到的随机森林中的“随机”就是指的这里的两个随机性。两个随机性的引入对随机森林的分类性能至关重要。由于它们的引入,使得随机森林不容易陷入过拟合,并且具有很好得抗噪能力(比如:对缺省值不敏感)。

      随机森林分类效果(错误率)与两个因素有关:

    • 森林中任意两棵树的相关性:相关性越大,错误率越大;
    • 森林中每棵树的分类能力:每棵树的分类能力越强,整个森林的错误率越低。

      减小特征选择个数m,树的相关性和分类能力也会相应的降低;增大m,两者也会随之增大。所以关键问题是如何选择最优的m(或者是范围),这也是随机森林唯一的一个参数。

    回到顶部

    5 袋外错误率(oob error)

      上面我们提到,构建随机森林的关键问题就是如何选择最优的m,要解决这个问题主要依据计算袋外错误率oob error(out-of-bag error)。

      随机森林有一个重要的优点就是,没有必要对它进行交叉验证或者用一个独立的测试集来获得误差的一个无偏估计。它可以在内部进行评估,也就是说在生成的过程中就可以对误差建立一个无偏估计。

      我们知道,在构建每棵树时,我们对训练集使用了不同的bootstrap sample(随机且有放回地抽取)。所以对于每棵树而言(假设对于第k棵树),大约有1/3的训练实例没有参与第k棵树的生成,它们称为第k棵树的oob样本。

      而这样的采样特点就允许我们进行oob估计,它的计算方式如下:

      (note:以样本为单位)

      1)对每个样本,计算它作为oob样本的树对它的分类情况(约1/3的树);

      2)然后以简单多数投票作为该样本的分类结果;

      3)最后用误分个数占样本总数的比率作为随机森林的oob误分率。

      (文献原文:Put each case left out in the construction of the kth tree down the kth tree to get a classification. In this way, a test set classification is obtained for each case in about one-third of the trees. At the end of the run, take j to be the class that got most of the votes every time case n was oob. The proportion of times that j is not equal to the true class of n averaged over all cases is the oob error estimate. This has proven to be unbiased in many tests.)

      oob误分率是随机森林泛化误差的一个无偏估计,它的结果近似于需要大量计算的k折交叉验证。

    回到顶部

    6 随机森林工作原理解释的一个简单例子

      描述:根据已有的训练集已经生成了对应的随机森林,随机森林如何利用某一个人的年龄(Age)、性别(Gender)、教育情况(Highest Educational Qualification)、工作领域(Industry)以及住宅地(Residence)共5个字段来预测他的收入层次。

      收入层次 :

        Band 1 : Below $40,000

        Band 2: $40,000 – 150,000

        Band 3: More than $150,000

      随机森林中每一棵树都可以看做是一棵CART(分类回归树),这里假设森林中有5棵CART树,总特征个数N=5,我们取m=1(这里假设每个CART树对应一个不同的特征)。

      CART 1 : Variable Age

      rf1

      CART 2 : Variable Gender

      rf2

      CART 3 : Variable Education

      rf3

      CART 4 : Variable Residence

      rf4

      CART 5 : Variable Industry

      rf5

      我们要预测的某个人的信息如下:

      1. Age : 35 years ; 2. Gender : Male ; 3. Highest Educational Qualification : Diploma holder; 4. Industry : Manufacturing; 5. Residence : Metro.

      根据这五棵CART树的分类结果,我们可以针对这个人的信息建立收入层次的分布情况:

      DF

      最后,我们得出结论,这个人的收入层次70%是一等,大约24%为二等,6%为三等,所以最终认定该人属于一等收入层次(小于$40,000)。

    回到顶部

    7 随机森林的Python实现

      利用Python的两个模块,分别为pandas和scikit-learn来实现随机森林。

     

    复制代码

    from sklearn.datasets import load_iris
    from sklearn.ensemble import RandomForestClassifier
    import pandas as pd
    import numpy as np
    
    iris = load_iris()
    df = pd.DataFrame(iris.data, columns=iris.feature_names)
    df['is_train'] = np.random.uniform(0, 1, len(df)) <= .75
    df['species'] = pd.Factor(iris.target, iris.target_names)
    df.head()
    
    train, test = df[df['is_train']==True], df[df['is_train']==False]
    
    features = df.columns[:4]
    clf = RandomForestClassifier(n_jobs=2)
    y, _ = pd.factorize(train['species'])
    clf.fit(train[features], y)
    
    preds = iris.target_names[clf.predict(test[features])]
    pd.crosstab(test['species'], preds, rownames=['actual'], colnames=['preds'])

    复制代码

     

      分类结果:

      

      与其他机器学习分类算法进行对比:

    复制代码

    import numpy as np
    import matplotlib.pyplot as plt
    from matplotlib.colors import ListedColormap
    from sklearn.cross_validation import train_test_split
    from sklearn.preprocessing import StandardScaler
    from sklearn.datasets import make_moons, make_circles, make_classification
    from sklearn.neighbors import KNeighborsClassifier
    from sklearn.svm import SVC
    from sklearn.tree import DecisionTreeClassifier
    from sklearn.ensemble import RandomForestClassifier, AdaBoostClassifier
    from sklearn.naive_bayes import GaussianNB
    from sklearn.lda import LDA
    from sklearn.qda import QDA
    
    h = .02  # step size in the mesh
    
    names = ["Nearest Neighbors", "Linear SVM", "RBF SVM", "Decision Tree",
             "Random Forest", "AdaBoost", "Naive Bayes", "LDA", "QDA"]
    classifiers = [
        KNeighborsClassifier(3),
        SVC(kernel="linear", C=0.025),
        SVC(gamma=2, C=1),
        DecisionTreeClassifier(max_depth=5),
        RandomForestClassifier(max_depth=5, n_estimators=10, max_features=1),
        AdaBoostClassifier(),
        GaussianNB(),
        LDA(),
        QDA()]
    
    X, y = make_classification(n_features=2, n_redundant=0, n_informative=2,
                               random_state=1, n_clusters_per_class=1)
    rng = np.random.RandomState(2)
    X += 2 * rng.uniform(size=X.shape)
    linearly_separable = (X, y)
    
    datasets = [make_moons(noise=0.3, random_state=0),
                make_circles(noise=0.2, factor=0.5, random_state=1),
                linearly_separable
                ]
    
    figure = plt.figure(figsize=(27, 9))
    i = 1
    # iterate over datasets
    for ds in datasets:
        # preprocess dataset, split into training and test part
        X, y = ds
        X = StandardScaler().fit_transform(X)
        X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=.4)
    
        x_min, x_max = X[:, 0].min() - .5, X[:, 0].max() + .5
        y_min, y_max = X[:, 1].min() - .5, X[:, 1].max() + .5
        xx, yy = np.meshgrid(np.arange(x_min, x_max, h),
                             np.arange(y_min, y_max, h))
    
        # just plot the dataset first
        cm = plt.cm.RdBu
        cm_bright = ListedColormap(['#FF0000', '#0000FF'])
        ax = plt.subplot(len(datasets), len(classifiers) + 1, i)
        # Plot the training points
        ax.scatter(X_train[:, 0], X_train[:, 1], c=y_train, cmap=cm_bright)
        # and testing points
        ax.scatter(X_test[:, 0], X_test[:, 1], c=y_test, cmap=cm_bright, alpha=0.6)
        ax.set_xlim(xx.min(), xx.max())
        ax.set_ylim(yy.min(), yy.max())
        ax.set_xticks(())
        ax.set_yticks(())
        i += 1
    
        # iterate over classifiers
        for name, clf in zip(names, classifiers):
            ax = plt.subplot(len(datasets), len(classifiers) + 1, i)
            clf.fit(X_train, y_train)
            score = clf.score(X_test, y_test)
    
            # Plot the decision boundary. For that, we will assign a color to each
            # point in the mesh [x_min, m_max]x[y_min, y_max].
            if hasattr(clf, "decision_function"):
                Z = clf.decision_function(np.c_[xx.ravel(), yy.ravel()])
            else:
                Z = clf.predict_proba(np.c_[xx.ravel(), yy.ravel()])[:, 1]
    
            # Put the result into a color plot
            Z = Z.reshape(xx.shape)
            ax.contourf(xx, yy, Z, cmap=cm, alpha=.8)
    
            # Plot also the training points
            ax.scatter(X_train[:, 0], X_train[:, 1], c=y_train, cmap=cm_bright)
            # and testing points
            ax.scatter(X_test[:, 0], X_test[:, 1], c=y_test, cmap=cm_bright,
                       alpha=0.6)
    
            ax.set_xlim(xx.min(), xx.max())
            ax.set_ylim(yy.min(), yy.max())
            ax.set_xticks(())
            ax.set_yticks(())
            ax.set_title(name)
            ax.text(xx.max() - .3, yy.min() + .3, ('%.2f' % score).lstrip('0'),
                    size=15, horizontalalignment='right')
            i += 1
    
    figure.subplots_adjust(left=.02, right=.98)
    plt.show()

    复制代码

      这里随机生成了三个样本集,分割面近似为月形、圆形和线形的。我们可以重点对比一下决策树和随机森林对样本空间的分割:

      1)从准确率上可以看出,随机森林在这三个测试集上都要优于单棵决策树,90%>85%,82%>80%,95%=95%;

      2)从特征空间上直观地可以看出,随机森林比决策树拥有更强的分割能力(非线性拟合能力)。

      更多有关随机森林的代码:

      1)Fortran版本

      2)OpenCV版本

      3)Matlab版本

      4)R版本

    回到顶部

    8 参考内容

      [1] Random Forest's homepage (by Leo Breiman and Adele Cutler)

      [2] Introduction to Random forest - Simplified

      [3] Comparing a Random Forest to a CART model (Part 2)

      [4] Introduction to Random forest (博主:爱67)

      [5] Python实现随机森林

      [6] 随机森林之oob error估计

      [7] 随机森林

      [8] Wikipedia-Random Forest

      [9] Ensemble methods

    展开全文
  • 随机森林算法Matlab实现

    万次阅读 多人点赞 2019-05-25 18:26:32
    随机森林算法Matlab实现随机森林算法Matlab实现计算当前自身gini系数求最优划分点及其gini系数对data中按decision属性值从小到大排列生成结点生成随机采样样本数据生成决策树评价函数随机森林样本决策函数正确率计算...

    瞎BB

    1.实现根据样本数据(用眼距离distance、最长持续用眼时长duration、总用眼时长total_time、户外运动时长outdoor、用眼角度angle、健康环境光照用眼比例proportion)判别是否需要近视预警
    2.这个是大一数模校赛写的Matlab实现随机森林算法的代码。那个时候太菜。
    3.代码还有一点bug,在建立决策树时用的是分支,如果样本太少会出bug。
    4.如果不是一定要用Matlab,可以用python中的sklearn库来实现随机森林算法。
    详情:随机森林算法python实现 https://blog.csdn.net/CYBERLIFERK800/article/details/90552735
    5.需改进:用二叉树递归代替分支结构生成决策树,评估函数应改用recall来评判好坏,并交叉验证。等有时间了就改一改。

    代码

    计算当前自身gini系数

    %计算当前自身gini系数
    function gini_now=gini_self(data)
    sample_select=size(data,1)-1;
    decision_select=size(data,2)-1;
    time=0;
    for i=1:sample_select
        if data(i,decision_select+1)
            time=time+1;
        end
    end
    gini_now=1-(time/sample_select)^2-((sample_select-time)/sample_select)^2;
    

    求最优划分点及其gini系数

    %求最优划分点及其gini系数,输入数据和决策属性,输出最优划分点和最优gini系数
    function [boundary_best,gini_best]=gini(data_new,decision)
    sample_select=size(data_new,1)-1;           %选取样本数
    decision_select=size(data_new,2)-1;         %选取决策属性个数
    %初始化
    range=[min(data_new(1:sample_select,decision)) max(data_new(1:sample_select,decision))];%决策属性值范围
    gini_best=1;                    %最优解
    boundary_best=range(1);         %最优边界
    %计算time_lt sum_lt time_ge sum_ge
    for j=range(1)+1:range(2)
        result_temp=[0 0];
        time_lt=0;                      %小于boundary的样本个数
        sum_lt=0;                       %小于boundary的样本中需要预警的个数
        time_ge=0;                      %大于等于boundary的样本个数
        sum_ge=0;                       %大于等于boundary的样本中需要预警的个数
        boundary=j;
        for i=1:sample_select
            if(data_new(i,decision)<boundary)
                time_lt=time_lt+1;
                sum_lt=sum_lt+data_new(i,decision_select+1);
            else
                time_ge=time_ge+1;
                sum_ge=sum_ge+data_new(i,decision_select+1);
            end
        end
        %计算gini系数
        time=[time_lt time_lt time_ge time_ge];
        sum=[sum_lt time_lt-sum_lt sum_ge time_ge-sum_ge];
        rate=sum./time;
        result_temp(1)=1-rate(1)^2-rate(2)^2;
        result_temp(2)=1-rate(3)^2-rate(4)^2;
        result=time_lt/sample_select*result_temp(1)+time_ge/sample_select*result_temp(2);
        if result<gini_best
            gini_best=result;
            boundary_best=boundary;
        end
    end
    

    对data中按decision属性值从小到大排列

    %对data中按decision属性值从小到大排列,输出新数据和划分位置
    function [data_new,index]=BubbleSort(data,decision,boundary)
    sample_select=size(data,1)-1;
    for i=1:sample_select-1
        for j=1:sample_select-i
            if data(j,decision)>data(j+1,decision)
                temp=data(j,:);
                data(j,:)=data(j+1,:);
                data(j+1,:)=temp;
            end
        end
    end
    for i=1:sample_select
        if data(i,decision)>boundary
            break
        end
    end
    index=i-1;
    data_new=data;
    

    生成结点

    %生成结点,输入数据,输出最佳决策属性,最佳划分边界,以及划分后的两组数据及其gini系数和加权gini系数
    function [decision_global_best,boundary_global_best,data_new1,gini_now1,data_new2,gini_now2,gini_new]=generate_node(data_new)
    decision_select=size(data_new,2)-1;
    gini_global_best=1;
    decision_global_best=1;
    boundary_global_best=0;
    for i=1:decision_select
        decision=i;
        [boundary_best,gini_best]=gini(data_new,decision);
        if gini_best<gini_global_best
            gini_global_best=gini_best;
            decision_global_best=decision;
            boundary_global_best=boundary_best;
        end
    end
    %按decision_global_best属性从小到大排列
    [data_nnew,index]=BubbleSort(data_new,decision_global_best,boundary_global_best);
    %生成子结点
    
    data_new1=data_nnew(1:index,:);
    data_new1(index+1,:)=data_nnew(end,:);
    gini_now1=gini_self(data_new1);
    %去除decision_global_best列
    for i=1:decision_select
        if i>=decision_global_best
            data_new1(:,i)=data_new1(:,i+1);
        end
    end
    data_new1(:,i)=[];
    
    data_new2=data_nnew(index+1:end,:);
    gini_now2=gini_self(data_new2);
    %去除decision_global_best列
    for i=1:decision_select
        if i>=decision_global_best
            data_new2(:,i)=data_new2(:,i+1);
        end
    end
    data_new2(:,i)=[];
    
    size1=size(data_new1,1)-1;
    size2=size(data_new2,1)-1;
    gini_new=gini_now1*size1/(size1+size2)+gini_now2*size2/(size1+size2);
    

    生成随机采样样本数据

    %生成随机采样样本数据,对样本有放回采样m组,对决策属性无放回采样n组
    function data_new=select_sample_decision(data,m,n)
    sample_num=size(data,1)-1;      %样本个数
    decision_num=size(data,2)-1;    %决策属性个数
    %随机有放回选取m个样本建立决策树
    data_new1=ones(m+1,decision_num+1);
    data_new1(m+1,:)=data(sample_num+1,:);
    for i=1:m
        k1=ceil(rand*sample_num);
        data_new1(i,:)=data(k1,:);
    end
    %随机选取n个属性进行决策
    k2=randperm(decision_num);
    data_new=ones(m+1,n+1);
    for i=1:n
        data_new(:,i)=data_new1(:,k2(i));
    end
    data_new(:,n+1)=data_new1(:,decision_num+1);
    

    生成决策树

    %生成决策树,输入原始数据,采样样本数,采样决策属性数,预剪枝样本限制
    function [path,boundary,gini,result]=decision_tree(data,sample_select,decision_select,sample_limit)
    score=100;                          %评价函数得分
    while(score>(sample_select*0.05))   %直到找到好树才停止
        data_new=select_sample_decision(data,sample_select,decision_select);
        %计算初始gini系数
        gini_now=gini_self(data_new);
        %主程序
        layer=1;                            %记录决策树当前层数
        leaf_sample=zeros(1,sample_select); %记录子结点样本个数
        leaf_gini=zeros(1,sample_select);   %叶子节点gini系数
        leaf_num=0;                         %记录叶子数
        path=zeros(decision_select,2^(decision_select-1));       %初始化路径
        gini=ones(decision_select,2^(decision_select-1));        %初始化gini
        boundary=zeros(decision_select,2^(decision_select-1));   %初始化划分边界
        result=ones(decision_select,2^(decision_select-1));      %初始化结果
        path(:)=inf;
        gini(:)=inf;
        boundary(:)=inf;
        result(:)=inf;
        %position=[1 0 0 0;1 2 0 0;1 2 3 4];
        %第一层
        [decision_global_best,boundary_global_best,data_new1,gini_now1,data_new2,gini_now2,~]=generate_node(data_new);
        path(layer,1)=data_new(size(data_new,1),decision_global_best);
        boundary(layer,1)=boundary_global_best;
        gini(layer,1)=gini_now;
        layer=layer+1;
        gini(layer,1)=gini_now1;
        gini(layer,2)=gini_now2;
        %第二层
        if ((size(data_new1,1)-1)>=sample_limit)&&(gini(layer,1)>0)
            [decision_global_best,boundary_global_best,data_new1_1,gini_now1_1,data_new1_2,gini_now1_2,~]=generate_node(data_new1);
            path(layer,1)=data_new1(size(data_new1,1),decision_global_best);
            boundary(layer,1)=boundary_global_best;
            layer=layer+1;
            gini(layer,1)=gini_now1_1;
            gini(layer,2)=gini_now1_2;
            %第三层
            if (size(data_new1_1,1)-1)>=sample_limit&&(gini(layer,1)>0)
                [decision_global_best,boundary_global_best,data_new1_1_1,gini_now1_1_1,data_new1_1_2,gini_now1_1_2,~]=generate_node(data_new1_1);
                path(layer,1)=data_new1_1(size(data_new1_1,1),decision_global_best);
                boundary(layer,1)=boundary_global_best;
                layer=layer+1;
    
                gini(layer,1)=gini_now1_1_1;
                temp1=sum(data_new1_1_1);
                temp2=temp1(1,end)-7;
                temp3=size(data_new1_1_1,1)-1;
                temp=temp2>(temp3/2);
                result(layer,1)=temp;
                leaf_num=leaf_num+1;
                leaf_gini(leaf_num)=gini_now1_1_1;
                leaf_sample(leaf_num)=size(data_new1_1_1,1)-1;
    
                gini(layer,2)=gini_now1_1_2;
                temp1=sum(data_new1_1_2);
                temp2=temp1(1,end)-7;
                temp3=size(data_new1_1_2,1)-1;
                temp=temp2>(temp3/2);
                result(layer,2)=temp;
                leaf_num=leaf_num+1;
                leaf_gini(leaf_num)=gini_now1_1_2;
                leaf_sample(leaf_num)=size(data_new1_1_2,1)-1;
            else
                temp1=sum(data_new1_1);
                temp2=temp1(1,end)-7;
                temp3=size(data_new1_1,1)-1;
                temp=temp2>(temp3/2);
                result(layer,1)=temp;
                leaf_num=leaf_num+1;
                leaf_gini(leaf_num)=gini_now1_1;
                leaf_sample(leaf_num)=size(data_new1_1,1)-1;
    
                path(layer,1)=nan;
                boundary(layer,1)=nan;
                gini(layer+1,1:2)=nan;
            end
            layer=3;
            if (size(data_new1_2,1)-1)>=sample_limit&&(gini(layer,2)>0)
                [decision_global_best,boundary_global_best,data_new1_2_1,gini_now1_2_1,data_new1_2_2,gini_now1_2_2,~]=generate_node(data_new1_2);
                path(layer,2)=data_new1_2(size(data_new1_2,1),decision_global_best);
                boundary(layer,2)=boundary_global_best;
                layer=layer+1;
    
                gini(layer,3)=gini_now1_2_1;
                temp1=sum(data_new1_2_1);
                temp2=temp1(1,end)-7;
                temp3=size(data_new1_2_1,1)-1;
                temp=temp2>(temp3/2);
                result(layer,3)=temp;
                leaf_num=leaf_num+1;
                leaf_gini(leaf_num)=gini_now1_2_1;
                leaf_sample(leaf_num)=size(data_new1_2_1,1)-1;
    
                gini(layer,4)=gini_now1_2_2;
                temp1=sum(data_new1_2_2);
                temp2=temp1(1,end)-7;
                temp3=size(data_new1_2_2,2)-1;
                temp=temp2>(temp3/2);
                result(layer,4)=temp;
                leaf_num=leaf_num+1;
                leaf_gini(leaf_num)=gini_now1_2_2;
                leaf_sample(leaf_num)=size(data_new1_2_2,1)-1;
            else
                temp1=sum(data_new1_2);
                temp2=temp1(1,end)-7;
                temp3=size(data_new1_2,1)-1;
                temp=temp2>(temp3/2);
                result(layer,2)=temp;
                leaf_num=leaf_num+1;
                leaf_gini(leaf_num)=gini_now1_2;
                leaf_sample(leaf_num)=size(data_new1_2,1)-1;
    
                path(layer,2)=nan;
                boundary(layer,2)=nan;
                gini(layer+1,3:4)=nan;
            end
        else
            temp1=sum(data_new1);
            temp2=temp1(1,end)-7;
            temp3=size(data_new1,1)-1;
            temp=temp2>(temp3/2);
            result(layer,1)=temp;
            leaf_num=leaf_num+1;
            leaf_gini(leaf_num)=gini_now1;
            leaf_sample(leaf_num)=size(data_new1,1)-1;
    
            path(layer,1)=nan;
            boundary(layer,1)=nan;
            layer=layer+1;
            gini(layer,1:2)=nan;
            %第三层
            path(layer,1:2)=nan;
            boundary(layer,1:2)=nan;
            %gini第四层叶子
            layer=layer+1;
            gini(layer,1:4)=nan;
        end
        layer=2;
        if (size(data_new2,1)-1)>=sample_limit&&(gini(layer,2)>0)
            [decision_global_best,boundary_global_best,data_new2_1,gini_now2_1,data_new2_2,gini_now2_2,~]=generate_node(data_new2);
            path(layer,2)=data_new2(size(data_new2,1),decision_global_best);
            boundary(layer,2)=boundary_global_best;
            layer=layer+1;
            gini(layer,3)=gini_now2_1;
            gini(layer,4)=gini_now2_2;
            %第三层
            if (size(data_new2_1,1)-1)>=sample_limit&&(gini(layer,3)>0)
                [decision_global_best,boundary_global_best,data_new2_1_1,gini_now2_1_1,data_new2_1_2,gini_now2_1_2,~]=generate_node(data_new2_1);
                path(layer,3)=data_new2_1(size(data_new2_1,1),decision_global_best);
                boundary(layer,3)=boundary_global_best;
                layer=layer+1;
    
                gini(layer,5)=gini_now2_1_1;
                temp1=sum(data_new2_1_1);
                temp2=temp1(1,end)-7;
                temp3=size(data_new2_1_1,1)-1;
                temp=temp2>(temp3/2);
                result(layer,5)=temp;
                leaf_num=leaf_num+1;
                leaf_gini(leaf_num)=gini_now2_1_1;
                leaf_sample(leaf_num)=size(data_new2_1_1,1)-1;
    
                gini(layer,6)=gini_now2_1_2;
                temp1=sum(data_new2_1_2);
                temp2=temp1(1,end)-7;
                temp3=size(data_new2_1_2,1)-1;
                temp=temp2>(temp3/2);
                result(layer,6)=temp;
                leaf_num=leaf_num+1;
                leaf_gini(leaf_num)=gini_now2_1_2;
                leaf_sample(leaf_num)=size(data_new2_1_2,1)-1;
            else
                temp1=sum(data_new2_1);
                temp2=temp1(1,end)-7;
                temp3=size(data_new2_1,1)-1;
                temp=temp2>(temp3/2);
                result(layer,3)=temp;
                leaf_num=leaf_num+1;
                leaf_gini(leaf_num)=gini_now2_1;
                leaf_sample(leaf_num)=size(data_new2_1,1)-1;
    
                path(layer,3)=nan;
                boundary(layer,3)=nan;
                gini(layer+1,5:6)=nan;
            end
            layer=3;
            if (size(data_new2_2,1)-1)>=sample_limit&&(gini(layer,4)>0)
                [decision_global_best,boundary_global_best,data_new2_2_1,gini_now2_2_1,data_new2_2_2,gini_now2_2_2,~]=generate_node(data_new2_2);
                path(layer,4)=data_new2_2(size(data_new2_2,1),decision_global_best);
                boundary(layer,4)=boundary_global_best;
                layer=layer+1;
    
                gini(layer,7)=gini_now2_2_1;
                temp1=sum(data_new2_2_1);
                temp2=temp1(1,end)-7;
                temp3=size(data_new2_2_1,1)-1;
                temp=temp2>(temp3/2);
                result(layer,7)=temp;
                leaf_num=leaf_num+1;
                leaf_gini(leaf_num)=gini_now2_2_1;
                leaf_sample(leaf_num)=size(data_new2_2_1,1)-1;
    
                gini(layer,8)=gini_now2_2_2;
                temp1=sum(data_new2_2_2);
                temp2=temp1(1,end)-7;
                temp3=size(data_new2_2_2,1)-1;
                temp=temp2>(temp3/2);
                result(layer,8)=temp;
                leaf_num=leaf_num+1;
                leaf_gini(leaf_num)=gini_now2_2_2;
                leaf_sample(leaf_num)=size(data_new2_2_2,1)-1;
            else
                temp1=sum(data_new2_2);
                temp2=temp1(1,end)-7;
                temp3=size(data_new2_2,1)-1;
                temp=temp2>(temp3/2);
                result(layer,4)=temp;
                leaf_num=leaf_num+1;
                leaf_gini(leaf_num)=gini_now2_2;
                leaf_sample(leaf_num)=size(data_new2_2,1)-1;
    
                path(layer,4)=nan;
                boundary(layer,4)=nan;
                gini(layer+1,7:8)=nan;
            end
        else
            temp1=sum(data_new2);
            temp2=temp1(1,end)-7;
            temp3=size(data_new2,1)-1;
            temp=temp2>(temp3/2);
            result(layer,1)=temp;
            leaf_num=leaf_num+1;
            leaf_gini(leaf_num)=gini_now2;
            leaf_sample(leaf_num)=size(data_new2,1)-1;
    
    
            path(layer,2)=nan;
            boundary(layer,2)=nan;
            layer=layer+1;
            gini(layer,3:4)=nan;
            %第三层  
            path(layer,3:4)=nan;
            boundary(layer,3:4)=nan;
            %gini第四层叶子
            layer=layer+1;
            gini(layer,5:8)=nan;
        end
        score=evaluation(leaf_num,leaf_sample,leaf_gini);
    end
    
    

    评价函数

    %评价函数
    function result=evaluation(leaf_num,sample_num,leaf_gini)
    result=0;
    for t=1:leaf_num
        result=result+sample_num(t)*leaf_gini(t);
    end
    

    随机森林

    %随机森林,共有trees_num棵树
    function result=random_forest(sample,trees_num,data,sample_select,decision_select,sample_limit)
    warning_times=0;
    nowarning_times=0;
    conclusion=zeros(1,trees_num);
    for i=1:trees_num
        [path,boundary,~,result]=decision_tree(data,sample_select,decision_select,sample_limit);
        conclusion(i)=decide(sample,path,boundary,result);
        if conclusion(i)==1
            warning_times=warning_times+1;
        else
            if conclusion(i)==0
                nowarning_times=nowarning_times+1;
            end
        end
    end
    if 2*warning_times>(warning_times+nowarning_times)
        result=1;
    else
        result=0;
    end
    

    样本决策函数

    %样本决策函数,输入样本与决策树,输出判断结果
    function conclusion=decide(sample,path,boundary,result)
    if sample(path(1,1))<boundary(1,1)
        if ~isnan(result(2,1))
            conclusion=result(2,1);
        else
            if sample(path(2,1))<boundary(2,1)
                if ~isnan(result(3,1))
                    conclusion=result(3,1);
                else
                    if sample(path(3,1))<boundary(3,1)
                        conclusion=result(4,1);
                    else
                        conclusion=result(4,2);
                    end
                end
            else
                if ~isnan(result(3,2))
                    conclusion=result(3,2);
                else
                    if sample(path(3,2))<boundary(3,2)
                        conclusion=result(4,3);
                    else
                        conclusion=result(4,4);
                    end
                end
            end
        end
    else
        if ~isnan(result(2,2))
            conclusion=result(2,1);
        else
            if sample(path(2,2))<boundary(2,2)
                if ~isnan(result(3,3))
                    conclusion=result(3,3);
                else
                    if sample(path(3,3))<boundary(3,3)
                        conclusion=result(4,5);
                    else
                        conclusion=result(4,6);
                    end
                end
            else
                if ~isnan(result(3,4))
                    conclusion=result(3,4);
                else
                    if sample(path(3,4))<boundary(3,4)
                        conclusion=result(4,7);
                    else
                        conclusion=result(4,8);
                    end
                end
            end
        end
    end
    

    正确率计算函数

    %正确率计算函数
    function rate_average=check_accuracy(data,sample_select,decision_select,trees_num,sample_limit)
    sample_num=size(data,1)-1;
    rate=zeros(1,sample_num);       %初始化正确率数组
    for j=1:sample_num
        result=zeros(1,sample_num); %初始化结果数组
        for i=1:sample_num          %遍历样本
            sample=data(i,:);
            result(i)=random_forest(sample,trees_num,data,sample_select,decision_select,sample_limit);
        end
        result=result';
        t=0;
        data1=data(1:end-1,end);
        m=result-data1;             %机器判断与专家判断对比,0为相同
        for i=1:sample_num
            if m(i)==0
                t=t+1;
            end
        end
        rate(j)=t/sample_num;       %计算正确率
    end
    rate_average=mean(rate);        %计算平均正确率
    

    主函数

    %使用时只需要调整参数设置里的参数以及对原始数据的决策属性进行标识
    clc,clear
    %初始化
    data=xlsread('data.xlsx');      %读数据 最后一行为决策属性标识
                                    %1用眼距离 2最长持续用眼时长 3总用眼时长 4户外运动时长
                                    %5用眼角度 6健康环境光照用眼比例
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%参数设置%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    sample_select=20;               %选取样本数
    decision_select=3;              %选取决策属性个数
    trees_num=40;                   %设置森林规模
    %剪枝
        %预剪枝参数设置
    deep=3;                         %决策树深度限制
    sample_limit=2;                 %叶子结点样本数限制
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    % 计算平均正确率
    tic
    rate_average=check_accuracy(data,sample_select,decision_select,trees_num,sample_limit);
    toc
    
    %检验样本判断
    sample1=[37	33 100	151 5 80];
    sample2=[10 130 290 30 37 20];
    conclusion1=random_forest(sample1,trees_num,data,sample_select,decision_select,sample_limit);
    conclusion2=random_forest(sample2,trees_num,data,sample_select,decision_select,sample_limit);
    

    样本数据

    sample distance duration total_time outdoor angle proportion warning(1 yes 0 no)
    1 20 72 344 148 11 81 1
    2 34 68 263 135 7 50 1
    3 25 98 357 32 12 64 1
    4 37 65 291 157 8 89 0
    5 34 151 162 169 18 63 1
    6 30 178 259 146 32 50 1
    7 20 35 134 37 23 68 0
    8 39 111 169 87 4 52 0
    9 22 44 265 136 14 76 1
    10 39 151 219 140 2 55 0
    11 21 179 184 64 18 60 1
    12 25 41 241 71 16 72 1
    13 18 171 286 131 35 89 1
    14 32 33 236 102 29 50 1
    15 20 133 226 124 17 81 1
    16 17 148 236 66 32 75 1
    17 34 111 214 57 5 88 0
    18 24 85 163 155 14 32 1
    19 32 165 276 146 33 52 1
    20 25 124 359 171 33 70 0
    21 31 51 167 47 25 47 0
    22 31 63 352 58 22 44 1
    23 16 58 164 45 13 73 0
    24 29 37 326 104 33 68 1
    25 34 47 197 59 5 66 0
    26 36 123 185 165 26 70 0
    27 25 126 171 45 23 33 1
    28 31 84 98 37 30 51 1
    29 30 92 153 114 14 48 0
    30 29 178 278 146 27 45 1
    展开全文
  • 随机森林算法框架

    千次阅读 2019-01-27 15:51:20
    随机森林框架梳理 目录 1. 基础知识 1.1 何为集成学习 ...1.2 集成学习一般流程 ...5. 随机森林算法sklearn实现 6. 随机森林算法参数调优 7. 参考资料 1. 基础知识 1.1 何为集成学习 面对一个机...

    随机森林框架梳理

    目录

    1. 基础知识

    1.1 何为集成学习

    面对一个机器学习问题, 通常有两种策略。 一种是研发人员尝试各种模型,选择其中表现最好的模型做重点调参优化。 这种策略类似于奥运会比赛, 通过强强竞争来选拔最优的运动员, 并逐步提高成绩。 另一种重要的策略是集各家之长, 如同贤明的君主广泛地听取众多谋臣的建议, 然后综合考虑, 得到最终决策。 后一种策略的核心, 是将多个分类器的结果统一成一个最终的决策。 使用这类策略的机器学习方法统称为集成学习。 其中的每个单独的分类器称为基分类器

    1.2 集成学习一般流程

    集成学习一般可分为以下3个步骤。
    (1) 找到误差互相独立的基分类器。
    (2) 训练基分类器。
    (3) 合并基分类器的结果。
    合并基分类器的方法有voting和stacking两种。 前者是用投票的方式, 将获得最多选票的结果作为最终的结果。 后者是用串行的方式, 把前一个基分类器的结果输出到下一个分类器, 将所有基分类器的输出结果相加(或者用更复杂的算法融合, 比如把各基分类器的输出作为特征, 使用逻辑回归作为融合模型进行最后的结果预测) 作为最终的输出。

    1.3 模型融合方法

    • Boosting

    Boosting方法训练基分类器时采用串行的方式, 各个基分类器之间有依赖。它的基本思路是将基分类器层层叠加, 每一层在训练的时候, 对前一层基分类器分错的样本, 给予更高的权重。 测试时, 根据各层分类器的结果的加权得到最终结果。
    Boosting的过程很类似于人类学习的过程,我们学习新知识的过程往往是迭代式的, 第一遍学习的时候, 我们会记住一部分知识, 但往往也会犯一些错误, 对于这些错误, 我们的印象会很深。 第二遍学习的时候, 就会针对犯过错误的知识加强学习, 以减少类似的错误发生。 不断循环往复, 直到犯错误的次数减少到很低的程度。

    • Bagging

    Bagging与Boosting的串行训练方式不同, Bagging方法在训练过程中, 各基分类器之间无强依赖, 可以进行并行训练。 其中很著名的算法之一是基于决策树基分类器的随机森林(Random Forest) 。 为了让基分类器之间互相独立, 将训练集分为若干子集(当训练样本数量较少时, 子集之间可能有交叠) 。 Bagging方法更像是一个集体决策的过程, 每个个体都进行单独学习, 学习的内容可以相同, 也可以不同, 也可以部分重叠。 但由于个体之间存在差异性, 最终做出的判断不会完全一致。 在最终做决策时, 每个个体单独作出判断, 再通过投票的方式做出最后的集体决策

    • Boosting与Bagging解释

    从消除基分类器的偏差和方差的角度来理解Boosting和Bagging方法的差异。 基分类器, 有时又被称为弱分类器, 因为基分类器的错误率要大于集成分类器。 基分类器的错误, 是偏差和方差两种错误之和。 偏差主要是由于分类器的表达能力有限导致的系统性错误, 表现在训练误差不收敛。 方差是由于分类器对于样本分布过于敏感, 导致在训练样本数较少时, 产生过拟合。
    Boosting方法是通过逐步聚焦于基分类器分错的样本, 减小集成分类器的偏差。
    Bagging方法则是采取分而治之的策略, 通过对训练样本多次采样, 并分别训练出多个不同模型, 然后做综合, 来减小集成分类器的方差。 假设所有基分类器出错的概率是独立的, 在某个测试样本上, 用简单多数投票方法来集成结果, 超过半数基分类器出错的概率会随着基分类器的数量增加而下降。

    • Boosting与Bagging主要区别

    样本选择上:Bagging采用的是Bootstrap随机有放回抽样;而Boosting每一轮的训练集是不变的,改变的只是每一个样本的权重。
    样本权重:Bagging使用的是均匀取样,每个样本权重相等;Boosting根据错误率调整样本权重,错误率越大的样本权重越大。
    预测函数:Bagging所有的预测函数的权重相等;Boosting中误差越小的预测函数其权重越大。
    并行计算:Bagging各个预测函数可以并行生成;Boosting各个预测函数必须按顺序迭代生成。

    下面是将决策树与这些算法框架进行结合所得到的新的算法:
    1)Bagging + 决策树 = 随机森林
    2)AdaBoost + 决策树 = 提升树
    3)Gradient Boosting + 决策树 = GBDT

    1.4 如何选择基分类器

    最常用的基分类器是决策树, 主要有以下3个方面的原因。
    (1) 决策树可以较为方便地将样本的权重整合到训练过程中, 而不需要使用过采样的方法来调整样本权重。
    (2) 决策树的表达能力和泛化能力, 可以通过调节树的层数来做折中。
    (3) 数据样本的扰动对于决策树的影响较大, 因此不同子样本集合生成的决策树基分类器随机性较大, 这样的“不稳定学习器”更适合作为基分类器。 此外,在决策树节点分裂的时候, 随机地选择一个特征子集, 从中找出最优分裂属性,很好地引入了随机性。
    除了决策树外, 神经网络模型也适合作为基分类器, 主要由于神经网络模型也比较“不稳定”, 而且还可以通过调整神经元数量、 连接方式、 网络层数、 初始权值等方式引入随机性。

    2. 随机森林简介

    随机森林是一种重要的基于Bagging的集成学习方法,可以用来做分类、回归等问题。

    随机森林有许多优点:

    • 具有极高的准确率
    • 随机性的引入,使得随机森林不容易过拟合
    • 随机性的引入,使得随机森林有很好的抗噪声能力
    • 能处理很高维度的数据,并且不用做特征选择
    • 既能处理离散型数据,也能处理连续型数据,数据集无需规范化
    • 训练速度快,可以得到变量重要性排序
    • 容易实现并行化

    随机森林的缺点:

    • 当随机森林中的决策树个数很多时,训练时需要的空间和时间会较大
    • 随机森林模型还有许多不好解释的地方,有点算个黑盒模型

    随机森林的构建过程大致如下:

    1. 从原始训练集中使用Bootstraping方法随机有放回采样选出m个样本,共进行n_tree次采样,生成n_tree个训练集
    2. 对于n_tree个训练集,我们分别训练n_tree个决策树模型
    3. 对于单个决策树模型,假设训练样本特征的个数为n,那么每次分裂时根据信息增益/信息增益比/基尼指数选择最好的特征进行分裂
    4. 每棵树都一直这样分裂下去,直到该节点的所有训练样例都属于同一类。在决策树的分裂过程中不需要剪枝
    5. 将生成的多棵决策树组成随机森林。对于分类问题,按多棵树分类器投票决定最终分类结果;对于回归问题,由多棵树预测值的均值决定最终预测结果

    3. 随机森林算法推导

    3.1 信息、熵以及信息增益的概念

    这三个基本概念是决策树的根本,是决策树利用特征来分类时,确定特征选取顺序的依据。理解了它们,决策树你也就了解了大概。

    引用香农的话来说,信息是用来消除随机不确定性的东西。当然这句话虽然经典,但是还是很难去搞明白这种东西到底是个什么样,可能在不同的地方来说,指的东西又不一样。对于机器学习中的决策树而言,如果带分类的事物集合可以划分为多个类别当中,则某个类(xi)的信息可以定义如下:
      I(x)用来表示随机变量的信息,p(xi)指是当xi发生时的概率。
      熵是用来度量不确定性的,当熵越大,X=xi的不确定性越大,反之越小。对于机器学习中的分类问题而言,熵越大即这个类别的不确定性更大,反之越小。

    信息增益在决策树算法中是用来选择特征的指标,信息增益越大,则这个特征的选择性越好。

    3.2 bootstrap 重抽样

    bootstrapping 就是一种用来产生数据随机性的统计工具。对同一份数据集,进行不同的重采样(re-sample)以模拟不同的数据集出来,避免了 cross-validation 中数据量的减少。

    3.3 算法说明

    Alt
    在这里插入图片描述

    4. 随机森林算法分析

    随机森林分类效果(错误率)与两个因素有关:

    森林中任意两棵树的相关性:相关性越大,错误率越大;
    森林中每棵树的分类能力:每棵树的分类能力越强,整个森林的错误率越低。
    减小特征选择个数m,树的相关性和分类能力也会相应的降低;增大m,两者也会随之增大。所以关键问题是如何选择最优的m(或者是范围),这也是随机森林唯一的一个参数。

    在这里插入图片描述

    5. 随机森林算法sklearn实现

    • 1.分类问题
    from sklearn.model_selection import cross_val_score
    from sklearn.datasets import load_iris
    from sklearn.ensemble import RandomForestClassifier
    iris = load_iris()
    clf = RandomForestClassifier(n_estimators=100)
    scores = cross_val_score(clf,iris.data,iris.target)
    scores.mean()
    
    • 2.回归问题
    from sklearn.model_selection import cross_val_score
    from sklearn.datasets import load_boston
    from sklearn.ensemble import RandomForestRegressor
    
    boston = load_boston()
    rgm = RandomForestRegressor(n_estimators=100)
    scores = cross_val_score(rgm,boston.data,boston.target)
    scores.mean()
    

    6. 随机森林算法参数调优

    • 1 框架参数:
    • n_estimators : 指定随机森林中的分类器的个数,默认为10。一般来说n_estimators 太小容易欠拟合,太大计算量大,故需要参数调优选择一个适中的数值;
    • oob_score: 是否采用袋外误差来评估模型,默认为 False;
    • criterion :及CART树划分对特征的评价标准,默认我基尼指数,还可以选择信息增益;
    • 2 决策树参数
    • max_features :建立决策树时选择的最大特征数目(从原始特征中选取多少特征进行建立决策树),默认为auto,意味着考虑sqrt(n_features)个特征;还可以为整数,即直接指定数目;浮点数,即指定百分比;sqrt与auto相同;log2即指定log2(n_features);如果是None,则为最大特征数n_features;
    • max_depth :决策树的最大深度,默认是不进行限制的,如果是模型样本量多,特征也多的情况,推荐限制修改这个,常用的可以取值为10-100之间;
    • min_samples_split :限制子树继续划分的条件,如果某节点的样本数目小于此值,则不会再继续划分,默认为2,样本量非常大的时候,应该增大这个值;
    • min_samples_leaf :叶子节点的最小样本数目,如果某叶子节点数目小于样本数,则会和兄弟节点一起被剪枝,默认为1,数据量大的时候可以增大这个值;
    • min_weight_fraction_leaf :叶子节点最小样本权重,这个值限制了叶子节点所有样本权重和最小值,如果小于最小值,则会和兄弟节点被剪枝。默认为0,就是不考虑权重。通常来说,若样本中存在较多的缺失值,或者分类树样本的分布类别偏差很大,就会引入样本权重,这时就需要考虑这个值了。
    • max_leaf_nodes :最大叶子节点数,通过限制最大叶子节点数目来防止过拟合,默认为None,即 不进行限制,如果特征分成很多可以加以限制;
    • min_impurity_split :节点划分最小不纯度,这个值限制了决策树的增长,如果某节点的不纯度小于这个阈值,则该节点不在生成子节点,即为叶子节点,一般不推荐改动,默认值为1e-7;
    • min_impurity_decrease :若一个节点被分割,如果这个分割导致大于或等于该值。默认为0;
    • bootstrap :构建树时是否使用bootstrap采样,默认为True;
    • n_jobs :设置程序的并行作业数量,默认为1,如果为-1,则作业数目为核心数;
    • random_state :随机数的设置;
    • verbose :控制构建树过程中的详细程度。

    7. 参考资料

    白面机器学习
    http://blog.csdn.net/a819825294 https://blog.csdn.net/a819825294/article/details/51177435

    展开全文
  • 随机森林算法学习(RandomForest)

    万次阅读 多人点赞 2017-10-21 16:24:37
    随机森林算法学习最近在做kaggle的时候,发现随机森林这个算法在分类问题上效果十分的好,大多数情况下效果远要比svm,log回归,knn等算法效果好。因此想琢磨琢磨这个算法的原理。要学随机森林,首先先简单介绍一下...
  • matlab实现的随机森林算法,利用分类器可做回归或预测
  • ML之RF:利用Js语言设计随机森林算法【DT之CART算法(gain index)】&并应用随机森林算法 目录 输出结果 设计思路 代码实现(部分代码) 输出结果 设计思路 代码实现(部分代码) var ...
  • 随机森林算法总结

    万次阅读 2019-03-01 19:52:39
    随机森林算法 个体学习器 个体学习器又称为基学习器(base learner),由单个的学习算法训练数据得到,比如“决策树算法”,“神经网络算法”等等。在不正式的说法下,基学习器,弱学习器,弱分类器,个体学习器说的...
  • 随机森林算法工作原理

    千次阅读 2019-02-27 16:42:55
    在这篇文章中,你将了解到随机森林算法的工作原理以及适用范围。   机器学习算法之随机森林算法工作原理 随机森林是一种有监督学习算法。 就像你所看到的它的名字一样,它创建了一个森林,并使它拥有某种方式...
  • 文章目录1,简述一下随机森林算法的原理2,随机森林的随机性体现在哪里?3,随机森林算法的优缺点?4,随机森林为什么不能用全样本去训练m棵决策树?5,随机森林和GBDT的区别? 1,简述一下随机森林算法的原理 2,...
  • 随机森林算法如何改进以达到更高的准确率?或者说有没有随机森林的改进算法?
  • 随机森林算法python实现

    千次阅读 2019-05-25 22:57:45
    随机森林算法python实现瞎BB代码导入数据切分训练集测试集找到最有用的几个属性根据上面的代码更改属性参数组合遍历找最优随机森林样本数据 瞎BB 实现根据样本数据(用眼距离distance、最长持续用眼时长duration、总...
  • Bagging与随机森林算法

    2019-06-30 11:18:21
    注:本篇博客主要参考了博客Bagging与随机森林算法原理总结。 在集成学习中,有两个流派—— boosting 派系 和 bagging 流派。前者的特点是各个弱学习器之间有依赖关系,而后者的特点是各个弱学习器之间没有依赖关系...
  • 图解随机森林算法

    千次阅读 2020-08-30 23:46:28
    在本文中,我们将了解随机森林算法是如何在内部工作的。为了真正理解它,了解一下决策树分类器可能会有帮助。但这并不完全是必需的。 注意:我们不涉及建模中涉及的预处理或特征工程步骤,只查看当我们使用sklearn的...
  • 随机森林算法&python应用

    千次阅读 2020-03-20 18:53:41
    随机森林算法 决策树算法可以很容易的将模型进行可视化,同时它是将每个样本特征进行单独处理,故而不需要的对数据进行转换。但是决策树会很容易出现过拟合,为了避免过拟合现象,可以使用集合学习的方法,像:随机...
  • 文章主要从以下几个方面进行介绍随机森林算法: 决策树算法。 集成学习思想。 随机森林算法的形成 一、决策树算法 请查看 【ML算法】随机森林算法的总结(一) 二、集成学习思想 请查看 【ML算法】随机森林算法的...
  • 随机森林算法简介

    2020-05-19 14:34:40
    随机森林(Random Forest) 实际上是一种改进的bagging方法,它将CART树用作bagging中的模型。...随机森林算法流程: 输入:样本集D={(x,y1),(x2,y2),…(xm,ym)},弱分类器迭代次数T。 输出:最终的强分类器f(x)
  • 随机森林算法小结

    千次阅读 2017-01-12 10:41:39
    随机森林算法1.随机森林原理介绍Random Forest 是 ensemble learning (集成学习?)算法的一种,它利用多棵树对样本进行训练并预测的一种分类器,同样也可用户回归,其输出的类别是由个别树输出的类别的众数而定。 ...
  • 摘要:随机森林(Random Forest,简称RF)是Bagging技巧的一个扩展变体。RF在以决策树为基学习器构建...前言:本文对随机森林算法进行总结概括,以CART决策树为背景,构建随机森林,并且解析OOB,将随机森林算法...
  • 决策树算法以及随机森林算法 (C++)

    热门讨论 2012-01-13 01:49:38
    用C++实现的C4.5算法,以及在此基础上实现的随机森林算法。带有两个训练与测试集合。
  • 文章目录随机森林算法描述:如何对features进行bootstrap?算法代码实现: 随机森林算法描述: 如何对features进行bootstrap? 我们需要一个feature_bound参数,每次把可以选择的features打乱,从种选出log(d)个,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 40,207
精华内容 16,082
关键字:

随机森林算法