sklearn 决策树_sklearn调包侠之决策树算法

b9503fbb4281e6bedcfc470c68de3359.png

bfcc972b3f697cf4d29cb33a5e64fee7.png

决策树原理

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

改进算法

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

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

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

数据导入与预处理

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

  1. import numpy as np
  2. import pandas as pd
  3. df = pd.read_csv('data/titanic/train.csv',index_col=0)
  4. df.head()

1899c773f674c39f347ba07ee6d4daec.png

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

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

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

  1. import seaborn as sns
  2. import matplotlib.pyplot as plt
  3. %matplotlib inline
  4. sns.countplot(x="Embarked",data=df)

d280e91f0512db0adecdf8867643f2c8.png
  1. df['Embarked'] = df['Embarked'].fillna('S')
  2. labels = df['Embarked'].unique().tolist()
  3. df['Embarked'] = df['Embarked'].apply(lambda n: labels.index(n))

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

  1. sns.set(style="darkgrid", palette="muted", color_codes=True)
  2. sns.distplot(df[df['Age'].notnull()]['Age'])

fed5941b6656c7c11d40debb0e6bb748.png
  1. df['Age'] = df['Age'].fillna(df['Age'].mean())
  2. df['Age'].isnull().sum()

处理完成后的数据如下:

d8f4baff7a68face7d5e07a94930227b.png

切分数据集

  1. from sklearn.model_selection import train_test_split
  2. X = df.iloc[:, 1:]
  3. y = df['Survived']
  4. 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:指定数的最大深度。
  • minsamplessplit:默认为2,指定能创建分支的数据集大小。
  • minimpuritydecrease:指定信息增益的阈值。

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

  1. from sklearn.tree import DecisionTreeClassifier
  2. clf = DecisionTreeClassifier()
  3. clf.fit(X_train, y_train)
  4. clf.score(X_test, y_test)
  5. # result
  6. # 0.82122905027932958

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

  1. from sklearn.model_selection import cross_val_score
  2. result = cross_val_score(clf, X, y, cv=10)
  3. print(result.mean())
  4. # result
  5. # 0.772279536942

模型调优

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

  1. def cv_score(d):
  2. clf = DecisionTreeClassifier(max_depth=d)
  3. clf.fit(X_train, y_train)
  4. tr_score = clf.score(X_train, y_train)
  5. cv_score = clf.score(X_test, y_test)
  6. return (tr_score, cv_score)
  7. depths = range(2, 15)
  8. scores = [cv_score(d) for d in depths]
  9. tr_scores = [s[0] for s in scores]
  10. cv_scores = [s[1] for s in scores]
  11. best_score_index = np.argmax(cv_scores)
  12. best_score = cv_scores[best_score_index]
  13. best_param = depths[best_score_index]
  14. print('best param: {0}; best score: {1}'.format(best_param, best_score))
  15. plt.figure(figsize=(10, 6), dpi=144)
  16. plt.grid()
  17. plt.xlabel('max depth of decision tree')
  18. plt.ylabel('score')
  19. plt.plot(depths, cv_scores, '.g-', label='cross-validation score')
  20. plt.plot(depths, tr_scores, '.r--', label='training score')
  21. plt.legend()
  22. # result
  23. # best param: 11; best score: 0.8212290502793296

a1bc36142ef99fed4546134e82159cdc.png

网格搜索

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

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

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

  1. from sklearn.model_selection import GridSearchCV
  2. threshholds = np.linspace(0, 0.5, 50)
  3. param_grid = {'criterion':['gini', 'entropy'],
  4. 'min_impurity_decrease':threshholds,
  5. 'max_depth':range(2, 15)}
  6. clf = GridSearchCV(DecisionTreeClassifier(), param_grid, cv=5)
  7. clf.fit(X, y)
  8. print("best param: {0}nbest score: {1}".format(clf.best_params_,
  9. clf.best_score_))
  10. # result
  11. # best param: {'criterion': 'entropy', 'max_depth': 8, 'min_impurity_decrease': 0.0}
  12. best score: 0.8204264870931538
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值