在真实数据集上的随机森林模型参数调优 - 简书

标签: | 发表时间:2017-11-14 17:58 | 作者:
出处:http://www.jianshu.com

搞机器学习的人,都会有自己偏爱的某种算法,有的喜欢支持向量机(SVM),因为它公式表达的优雅和可利用方法实现的高质量;有的人喜欢决策树,因为它的简洁性和解释能力;还有人对神经网络非常痴狂,因为它解决问题的灵活性(一般在超大规模的数据集上,使用神经网络,效果会好于其他所有的机器学习算法)。但是就我本人而言,我最喜欢的算法是随机森林,理由如下:

  • 通用性。随机森林算法可以应用于很多类别的模型任务。它们可以很好的处理回归问题,也能对分类问题应付自如,多分类和二分类都可以,一个能当三个用呢!
  • 随机森林算法很难被打败。针对任何给定的数据集,几乎都表现的很好,当然你说神经网络会表现的更好,那么我应该不会反驳,因为我知道你是一个有耐心的人,可以连续很多天不休息,只是为了调参。
  • 天生的并行性。从根本上说,随机森林就是众多的决策树组合,所以很容易把任务分解,使我们的随机森林算法并行。

当然,随机森林也有比较明显的缺点,对机器内存的要求比较高,为了增加我们预测的精度,我们可能需要建立几千棵甚至上万课决策树,所以买一个大内存的电脑是多么的有必要。

1 数据集

我们的数据集是来自一个著名的数据挖掘竞赛网站,是一个关于泰坦尼克号,游客生存情况的调查。可以从这里下载: 泰坦尼克数据集


各个数据字段的含义


上面的一张图,是我从官网上下载的,总的来说,里面的每一行数据,差不多有11个字段,包括游客的年龄、名字、性别、买的几等仓的票等等信息,最后是他的生存情况,在这场事故中,他是死了还是幸存。
不想解释了,直接读入数据吧

      import numpy as np
import pandas as pd
from sklearn.ensemble import RandomForestClassifier
train = pd.read_csv("E:/train.csv", dtype={"Age": np.float64},)
train.head(10)

前十行数据


稍微分析一下,我们就可以筛选出对一个游客的生存与否有关的变量:Pclass, Sex, Age, SibSp,Parch,Fare, Embarked. 一般来说,游客的名字,买的船票号码对其的生存情况应该影响很小。

      len(train_data)
out:891

我们共有891条数据,将近900条,我们使用600条作为训练数据,剩下的291条作为测试数据,通过对随机森林的参数不断调优,找出在测试结果上,预测最为精确的随机森林模型。
在具体的实验之前,我们看一下使用随机森林模型,需要注意哪几个变量:
在 sklearn中,随机森林的函数模型是:

      RandomForestClassifier(bootstrap=True, class_weight=None, criterion='gini',
            max_depth=None, max_features='auto', max_leaf_nodes=None,
            min_samples_leaf=1, min_samples_split=2,
            min_weight_fraction_leaf=0.0, n_estimators=10, n_jobs=1,
            oob_score=False, random_state=None, verbose=0,
            warm_start=False)

A. max_features

随机森林允许单个决策树使用特征的最大数量。 Python为最大特征数提供了多个可选项。 下面是其中的几个:

Auto/None :简单地选取所有特征,每颗树都可以利用他们。这种情况下,每颗树都没有任何的限制。

sqrt :此选项是每颗子树可以利用总特征数的平方根个。 例如,如果变量(特征)的总数是100,所以每颗子树只能取其中的10个。“log2”是另一种相似类型的选项。

0.2:此选项允许每个随机森林的子树可以利用变量(特征)数的20%。如果想考察的特征x%的作用, 我们可以使用“0.X”的格式。

max_features如何影响性能和速度?

增加max_features一般能提高模型的性能,因为在每个节点上,我们有更多的选择可以考虑。 然而,这未必完全是对的,因为它降低了单个树的多样性,而这正是随机森林独特的优点。 但是,可以肯定,你通过增加max_features会降低算法的速度。 因此,你需要适当的平衡和选择最佳max_features。
B. n_estimators

在利用最大投票数或平均值来预测之前,你想要建立子树的数量。 较多的子树可以让模型有更好的性能,但同时让你的代码变慢。 你应该选择尽可能高的值,只要你的处理器能够承受的住,因为这使你的预测更好更稳定。
C. min_sample_leaf

如果您以前编写过一个决策树,你能体会到最小样本叶片大小的重要性。 叶是决策树的末端节点。 较小的叶子使模型更容易捕捉训练数据中的噪声。 一般来说,我更偏向于将最小叶子节点数目设置为大于50。在你自己的情况中,你应该尽量尝试多种叶子大小种类,以找到最优的那个。

下面我们对上面提到的三个参数,进行调优,首先参数A,由于在我们的这个数据中,数据段总共只有七八个,所以我们就简单的选取所有的特征,所以我们只需要对剩下的两个变量进行调优。
在sklearn自带的随机森林算法中,输入的值必须是整数或者浮点数,所以我们需要对数据进行预处理,将字符串转化成整数或者浮点数

      def harmonize_data(titanic):
    # 填充空数据 和 把string数据转成integer表示
    # 对于年龄字段发生缺失,我们用所有年龄的均值替代
    titanic["Age"] = titanic["Age"].fillna(titanic["Age"].median())
    # 性别男: 用0替代
    titanic.loc[titanic["Sex"] == "male", "Sex"] = 0
    # 性别女: 用1替代
    titanic.loc[titanic["Sex"] == "female", "Sex"] = 1

    titanic["Embarked"] = titanic["Embarked"].fillna("S")

    titanic.loc[titanic["Embarked"] == "S", "Embarked"] = 0
    titanic.loc[titanic["Embarked"] == "C", "Embarked"] = 1
    titanic.loc[titanic["Embarked"] == "Q", "Embarked"] = 2

    titanic["Fare"] = titanic["Fare"].fillna(titanic["Fare"].median())

    return titanic

train_data = harmonize_data(train)

上面的代码是对原始数据进行清洗,填补缺失数据, 把string类型数据转化成int数据
下面的工作,我们开始划分训练数据和测试数据,总的数据有891个,我们用600个训练数据集,剩下的291个作为测试数据集。

      # 列出对生存结果有影响的字段
predictors = ["Pclass", "Sex", "Age", "SibSp", "Parch", "Fare", "Embarked"]
# 存放不同参数取值,以及对应的精度,每一个元素都是一个三元组(a, b, c)
results = []
# 最小叶子结点的参数取值
sample_leaf_options = list(range(1, 500, 3))
# 决策树个数参数取值
n_estimators_options = list(range(1, 1000, 5))
groud_truth = train_data['Survived'][601:]

for leaf_size in sample_leaf_options:
    for n_estimators_size in n_estimators_options:
        alg = RandomForestClassifier(min_samples_leaf=leaf_size, n_estimators=n_estimators_size, random_state=50)
        alg.fit(train_data[predictors][:600], train_data['Survived'][:600])
        predict = alg.predict(train_data[predictors][601:])
        # 用一个三元组,分别记录当前的 min_samples_leaf,n_estimators, 和在测试数据集上的精度
        results.append((leaf_size, n_estimators_size, (groud_truth == predict).mean()))
        # 真实结果和预测结果进行比较,计算准确率
        print((groud_truth == predict).mean())

# 打印精度最大的那一个三元组
print(max(results, key=lambda x: x[2]))

总的来说,调参对随机森林来说,不会发生很大的波动,相比神经网络来说,随机森林即使使用默认的参数,也可以达到良好的结果。在我们的例子中,通过粗略的调参,可以在测试集上达到84%的预测准确率,我觉得效果应该出乎我的意料吧。
附上全部代码:

      __author__ = 'Administrator'
import numpy as np
import pandas as pd
from sklearn.ensemble import RandomForestClassifier

train = pd.read_csv("E:/train.csv", dtype={"Age": np.float64},)


def harmonize_data(titanic):
    # 填充空数据 和 把string数据转成integer表示

    titanic["Age"] = titanic["Age"].fillna(titanic["Age"].median())

    titanic.loc[titanic["Sex"] == "male", "Sex"] = 0
    titanic.loc[titanic["Sex"] == "female", "Sex"] = 1

    titanic["Embarked"] = titanic["Embarked"].fillna("S")

    titanic.loc[titanic["Embarked"] == "S", "Embarked"] = 0
    titanic.loc[titanic["Embarked"] == "C", "Embarked"] = 1
    titanic.loc[titanic["Embarked"] == "Q", "Embarked"] = 2

    titanic["Fare"] = titanic["Fare"].fillna(titanic["Fare"].median())

    return titanic

train_data = harmonize_data(train)

predictors = ["Pclass", "Sex", "Age", "SibSp", "Parch", "Fare", "Embarked"]
results = []
sample_leaf_options = list(range(1, 500, 3))
n_estimators_options = list(range(1, 1000, 5))
groud_truth = train_data['Survived'][601:]

for leaf_size in sample_leaf_options:
    for n_estimators_size in n_estimators_options:
        alg = RandomForestClassifier(min_samples_leaf=leaf_size, n_estimators=n_estimators_size, random_state=50)
        alg.fit(train_data[predictors][:600], train_data['Survived'][:600])
        predict = alg.predict(train_data[predictors][601:])
        # 用一个三元组,分别记录当前的 min_samples_leaf,n_estimators, 和在测试数据集上的精度
        results.append((leaf_size, n_estimators_size, (groud_truth == predict).mean()))
        # 真实结果和预测结果进行比较,计算准确率
        print((groud_truth == predict).mean())

# 打印精度最大的那一个三元组
print(max(results, key=lambda x: x[2]))

有问题可以一起交流:
EMAIL:[email protected]

相关 [真实 数据 随机森林] 推荐:

在真实数据集上的随机森林模型参数调优 - 简书

- -
搞机器学习的人,都会有自己偏爱的某种算法,有的喜欢支持向量机(SVM),因为它公式表达的优雅和可利用方法实现的高质量;有的人喜欢决策树,因为它的简洁性和解释能力;还有人对神经网络非常痴狂,因为它解决问题的灵活性(一般在超大规模的数据集上,使用神经网络,效果会好于其他所有的机器学习算法). 但是就我本人而言,我最喜欢的算法是随机森林,理由如下:.

使用python训练随机森林模型辨别可疑流量

- -
通过数据分析辨别可疑和虚假流量的方法我们在之前的文章中曾经介绍过. 本篇文章我们对这个方法进行自动化,介绍如何通过随机森林分类预测模型对流量进行分类,从中发现可疑流量的影子. 需要特殊说明的是本篇文章中的数据并非真实数据,我们只使用三个简单用户行为特征指标对方法和过程进行说明. 随机森林是一个包含多颗决策树的分类预测算法.

一个3000万日活跃用户App的真实数据

- - 鲁塔弗的博客
前天和朋友聊了一会,他担任某App的技术负责人,得到一些数据如下. 日活跃用户3000万(DAU是按单天计算),其中Android用户和ios用户的比例是9:1,这个比例有点惊人. 说明业内软文水分太大,很多宣称ios有上千万用户的都是吹牛b. ios获取用户成本太高,简单折算用户获取成本是android用户成本的9倍,特别是免费应用,地主家都也没有余粮,大家都不敢怎么砸钱.

数据仓库

- Ran - Linux@SOHU
翻译:马少兵、曾怀东、朱翊然、林业. 尽管服务器存储、处理能力得到有效的提高,以及服务器价格的降低,让人们能够负担起大量的服务器,但是商业软件应用和监控工具快速的增加,还是使得人们被大量的数据所困扰. 在数据仓库领域中的许多系统管理员、应用开发者,以及初级数据库管理员发现,他们正在处理“海量数据”-不管你准备与否-都会有好多不熟悉的术语,概念或工具.

数据抽取

- - 数据库 - ITeye博客
转自: http://wiki.mbalib.com/wiki/%E6%95%B0%E6%8D%AE%E6%8A%BD%E5%8F%96#.   数据抽取是指从源数据源系统抽取目的数据源系统需要的. 实际应用中,数据源较多采用的是. 数据迁移或数据复制,它将数据源中的表或视图的数据原封不动的从数 据库中抽取出来,并转换成自己的ETL 工具可以识别的格式.

数据库sharding

- - 数据库 - ITeye博客
当团队决定自行实现sharding的时候,DAO层可能是嵌入sharding逻辑的首选位置,因为在这个层面上,每一个DAO的方法都明确地知道需要访问的数据表以及查询参数,借助这些信息可以直接定位到目标shard上,而不必像框架那样需要对SQL进行解析然后再依据配置的规则进行路由. 另一个优势是不会受ORM框架的制约.

数据脱敏

- - IT瘾-bigdata
作者|李呈祥,其中部分内容由十一城补充. 数据脱敏(Data Masking),又称数据漂白、数据去隐私化或数据变形. 百度百科对数据脱敏的定义为:指对某些敏感信息通过脱敏规则进行数据的变形,实现敏感隐私数据 的可靠保护. 这样,就可以在开发、测试和其它非生产环境以及外包环境中安全地使用脱敏后的真实数据集.

所谓舆论真实版

- yu - 天朝娱乐 | 每天开心一下!
感谢 天朝临时工 投递给天朝娱乐. 拿破仑进军巴黎时,一家报纸在几天内所用的标题:第一天:“科西嘉的怪物在儒安港登陆”;第二天:“吃人的魔鬼向格腊斯前进”;第三天:“篡位者进入格勒诺布尔”;第四天:“波拿巴占领里昂”;第五天:“拿破仑接近枫丹白露”;第六天:“陛下将于今日抵达自己的忠实的巴黎”. 王琳:无舆论压力即无司法公正更可怕.

战略:真实性检验

- 貝殼 - 互联网的那点事
在我过去十几年的代理商生涯中,我有幸和很多非常棒的战略师们共同工作过. 与来自不同背景的人工作是非常有价值的经历. 然而,有时当人们告诉我他们在制定战略的时候,我感到有些困惑. 我见过很多精彩的、充满漂亮的图表和很大的文字的“战略”演讲. 听过这些“战略”的每个人都非常激动,但是之后却没什么实际行动发生.

数据分析之如何用数据?

- - 互联网分析沙龙
光知道怎么看数据,还是不成,你得熟悉这些数据拿到手上之后怎么去用它,怎么让数据显示出来它本身的威力来. 第一个部分,是看历史数据,发现规律. 以社区中的活动和电商中的促销为例,这些都是常见的活动,活动做得好的话有意想不到的效果. 在做这样的活动,最好是拿到前一个月或者两个月的历史数据. 对电商来说,从这里面要去分析各个品类的销售情况,那个品类销量最大,那个品类销量最小,每月或者每周的平均增长率和符合增长率是多少.