sklearn调包侠之决策树算法

决策树原理

之前我们详细讲解过决策树的原理,详细内容可以参考该链接(https://www.jianshu.com/p/0dd283516cbe)。

改进算法

但使用信息增益作为特征选择指标(ID3算法)容易造成过拟合。举一个简单例子,每个类别如果都有一个唯一ID,通过ID这个特征就可以简单分类,但这并不是有效的。为了解决这个问题,有了C4.5和CART算法,其区别如下所示:

  • ID3 是信息增益划分
  • C4.5 是信息增益率划分
  • CART 做分类工作时,采用 GINI 值作为节点分裂的依据

实战——泰坦尼克号生还预测

数据导入与预处理

该数据可在kaggle网站下载,这里我们先通过pandas读入数据。

import numpy as np
import pandas as pd

df = pd.read_csv('data/titanic/train.csv',index_col=0)
df.head()

首先,对于一些不重要的信息进行删除(例如Name);我们都知道,机器学习是没法对字符串进行计算的,这里需要把Sex、Embarked转换为整数类型。

# 删除列
df.drop(['Name', 'Ticket', 'Cabin'], axis=1, inplace=True)
# Sex转换
def f1(x):
    if x == 'male':
        return 1
    else:
        return 0
df['Sex'] = df['Sex'].apply(f1)

然后,Embarked有缺失值,我们通过seaborn进行可视化,发现S值最多,所以通过S值进行缺失值填充。

import seaborn as sns
import matplotlib.pyplot as plt
%matplotlib inline

sns.countplot(x="Embarked",data=df)
df['Embarked'] = df['Embarked'].fillna('S')
labels = df['Embarked'].unique().tolist()
df['Embarked'] = df['Embarked'].apply(lambda n: labels.index(n))

年龄字段也有缺失值,我们通过绘制直方图,发现基本呈正态分布,于是使用平均值来填充缺失值。

sns.set(style="darkgrid", palette="muted", color_codes=True)    
sns.distplot(df[df['Age'].notnull()]['Age'])
df['Age'] = df['Age'].fillna(df['Age'].mean())
df['Age'].isnull().sum()

处理完成后的数据如下:

切分数据集
from sklearn.model_selection import train_test_split
X = df.iloc[:, 1:]
y = df['Survived']

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=22)
模型训练与评估

决策树算法使用sklearn.tree模块中的DecisionTreeClassifier方法。该方法有一系列参数来控制决策树生成过程,从而解决过拟合问题(具体可看sklearn的官方文档)。常用的参数如下:

  • criterion:算法选择。一种是信息熵(entropy),一种是基尼系数(gini),默认为gini。
  • max_depth:指定数的最大深度。
  • min_samples_split:默认为2,指定能创建分支的数据集大小。
  • min_impurity_decrease:指定信息增益的阈值。

首先,我们不对参数进行调整。

from sklearn.tree import DecisionTreeClassifier
clf = DecisionTreeClassifier()
clf.fit(X_train, y_train)
clf.score(X_test, y_test)

# result
# 0.82122905027932958

我们用交叉验证查看模型的准确度,发现模型的精度并不是很高。

from sklearn.model_selection import cross_val_score

result = cross_val_score(clf, X, y, cv=10)
print(result.mean())

# result
# 0.772279536942
模型调优

我们可以设置不同的参数,对模型进行调优,这里以max_depth为例,定义函数,求出最好的参数。

def cv_score(d):
    clf = DecisionTreeClassifier(max_depth=d)
    clf.fit(X_train, y_train)
    tr_score = clf.score(X_train, y_train)
    cv_score = clf.score(X_test, y_test)
    return (tr_score, cv_score)

depths = range(2, 15)
scores = [cv_score(d) for d in depths]
tr_scores = [s[0] for s in scores]
cv_scores = [s[1] for s in scores]

best_score_index = np.argmax(cv_scores)
best_score = cv_scores[best_score_index]
best_param = depths[best_score_index]
print('best param: {0}; best score: {1}'.format(best_param, best_score))

plt.figure(figsize=(10, 6), dpi=144)
plt.grid()
plt.xlabel('max depth of decision tree')
plt.ylabel('score')
plt.plot(depths, cv_scores, '.g-', label='cross-validation score')
plt.plot(depths, tr_scores, '.r--', label='training score')
plt.legend()

# result
# best param: 11; best score: 0.8212290502793296
网格搜索

但这种方法存在这两个问题:

  • 结果不稳定。当划分不同的数据集时,可能结果都一样。
  • 不能选择多参数。当需要多参数进行调优时,代码量会变的很多(多次嵌套循环)。

为了解决这些问题,sklearn提供GridSearchCV方法。

from sklearn.model_selection import GridSearchCV
threshholds = np.linspace(0, 0.5, 50)
param_grid = {'criterion':['gini', 'entropy'],
              'min_impurity_decrease':threshholds,
             'max_depth':range(2, 15)}

clf = GridSearchCV(DecisionTreeClassifier(), param_grid, cv=5)
clf.fit(X, y)

print("best param: {0}\nbest score: {1}".format(clf.best_params_, 
                                                clf.best_score_))

# result
# best param: {'criterion': 'entropy', 'max_depth': 8, 'min_impurity_decrease': 0.0}
best score: 0.8204264870931538
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容

  • 1、模型原理 (一)原理 1、原理:引入信息熵(不确定程度)的概念,通过计算各属性下的信息增益程度(信息增益越大,...
    Python_Franklin阅读 12,303评论 0 17
  • 决策树理论在决策树理论中,有这样一句话,“用较少的东西,照样可以做很好的事情。越是小的决策树,越优于大的决策树”。...
    制杖灶灶阅读 5,826评论 0 25
  • sklearn、XGBoost、LightGBM的文档阅读小记 文章导航 目录 1.sklearn集成方法 1.1...
    nightwish夜愿阅读 12,589评论 1 49
  • 昨天,06月19号,父亲节。 转眼间,父亲离开这个世界已有14个年头,仿佛14个月。 可能是有家族遗传的因素,我姑...
    面条大王红阅读 128评论 0 0
  • 今天我拿昨天洗车的小费去买玩具了。 玩具突然涨价了。把我气死了。我就立即去找妈妈。玩具昨天是10块钱,今天是12块...
    为为的小世界阅读 203评论 0 5