Python机器学习-决策树篇

Python机器学习之-决策树篇

决策树作为机器学习常用算法,更是作为集成学习的基础,不可谓不重要,在这里简单介绍决策树的原理及应用

一:决策树原理

顾名思义决策树是一个树状结构(由于算法的不同也决定了是二叉树还是多叉树,后面会详细描述),从根节点走向叶子节点,实际上决策树就相当于是if-else,便于理解,下图形象的展示了决策树的学习过程,从上到下的节点顺序代表了特征对结果的重要性顺序
图片来源:https://www.jianshu.com/p/14a9e8d1f2a3

二:决策树的三种算法

在介绍决策树的是三种算法之前,简单接受一下信息增益以及基尼系数
熵:熵是描述数据的不确定程度,熵越大代表数据的混乱程度越大,对决策树的作用就越小
信息增益:信息增益越大代表这个特征分类的能力越强,对结果的影响越大,也可以理解为熵的变化越小,对决策树的作用越大
基尼系数:基尼系数代表了模型的不纯度,基尼系数越小,纯度越高,特征越好。这和信息增益(比)相反。

1.ID3算法

ID3算法是基于信息增益划分的算法(构成多叉树)

1.1 ID3算法的缺点

(1)不支持连续特征
(2)采用信息增益大的特征优先建立决策树的节点。在相同条件下,取值比较多的特征比取值少的特征信息增益大。
(3)不支持缺失值处理
(4)没有应对过拟合的策略

2.C4.5算法

C4.5算法是基于信息增益比的算法,并且改进了ID3的各项缺点(构成多叉树)

2.1 C4.5算法的缺点

C4.5缺点
虽然C4.5改善了ID3的各项缺点,但是又造成了新的缺点
(1)剪枝的算法有非常多,C4.5的剪枝方法有优化的空间
(2)C4.5生成的是多叉树,很多时候,在计算机中二叉树模型会比多叉树运算效率高。如果采用二叉树,可以提高效率
(3)C4.5只能用于分类
(4)C4.5使用了熵模型,里面有大量的耗时的对数运算,如果是连续值还有大量的排序运算

3.CART算法

CART算法是基于基尼系数的算法,对C4.5算法进行了优化,不仅可以用于分类也可以用于回归,还提供了剪枝的策略,绝大多数时候都是选择CART算法作为决策树算法

决策树的优缺点

决策树的优势

1.决策树可以用于回归和分类,用途广泛且十分常用
2.决策树简单易理解
3.决策树可使用可视化模型,画出特征重要性图
4.下次使用决策树可直接调用,不需再次训练

决策树的劣势

1.决策树不稳定,极小的变化也会给结果带来很大的变化
2.决策树易造成过拟合(使用随机森林就不会有这个问题了)
3.决策树的变现相对于集成学习来说,效果并不是特别理想
4.决策树对大数据量处理速度会很慢,决策树会把数据加载到内存中,训练速度会很感人

加州房价决策树

数据源来自加州房价
import warnings
import pandas as pd
import numpy as np
from sklearn import tree
import pydotplus
from sklearn.decomposition import PCA
from sklearn.linear_model import LinearRegression, LassoCV, RidgeCV
from sklearn.model_selection import train_test_split
from sklearn.model_selection import GridSearchCV
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import MinMaxScaler
from sklearn.tree import DecisionTreeRegressor
import matplotlib as mpl
import matplotlib.pyplot as plt

def notEmpty(s):
    return s != ''

# mpl包中解决中文显示问题
mpl.rcParams['font.sans-serif']=[u'simHei']
mpl.rcParams['axes.unicode_minus']=False

# 拦截异常
warnings.filterwarnings(action = 'ignore')

# 取列名
names = ['CRIM','ZN', 'INDUS','CHAS','NOX','RM','AGE','DIS','RAD','TAX','PTRATIO','B','LSTAT']
# 指定路径
path = "housing.data"

# 由于数据文件格式不统一,所以读取的时候,先按照一行一个字段属性读取数据,然后再按照每行数据进行处理
fd = pd.read_csv(path, header=None)
data = np.empty((len(fd), 14))
# enumerate为python中内置函数 作用是将 一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,
# 同时列出数据和数据下标,一般用在 for 循环当中
for i, d in enumerate(fd.values):
    d = map(float, filter(notEmpty, d[0].split(' ')))
    data[i] = list(d)

x, y = np.split(data, (13,), axis=1)
y = y.ravel()

print ("样本数据量:%d, 特征个数:%d" % x.shape)
print ("target样本数据量:%d" % y.shape[0])

#数据的分割
x_train1, x_test1, y_train1, y_test1 = train_test_split(x, y, train_size=0.8, random_state=14)
x_train, x_test, y_train, y_test = x_train1, x_test1, y_train1, y_test1
print ("训练数据集样本数目:%d, 测试数据集样本数目:%d" % (x_train.shape[0], x_test.shape[0]))

#标准化
ss = MinMaxScaler()

x_train = ss.fit_transform(x_train, y_train)
x_test = ss.transform(x_test)

print ("原始数据各个特征属性的调整最小值:",ss.min_)
print ("原始数据各个特征属性的缩放数据值:",ss.scale_)

#构建决策树模型(回归)
model = DecisionTreeRegressor(criterion='mae',max_depth=7)
#模型训练
model.fit(x_train, y_train)
#模型预测
y_test_hat = model.predict(x_test)

#评估模型
score = model.score(x_test, y_test)
print ("Score:", score)
#
# #构建线性回归
lr = LinearRegression()
lr.fit(x_train,y_train)
lr_y_test_hat = lr.predict(x_test)
lr_score = lr.score(x_test, y_test)
print ("lr:", lr_score)

# #构建lasso
lasso = LassoCV(alphas=np.logspace(-3,1,20))
lasso.fit(x_train, y_train)
lasso_y_test_hat = lasso.predict(x_test)
lasso_score = lasso.score(x_test, y_test)
print ("lasso:", lasso_score)

# #构建岭回归
ridge = RidgeCV(alphas=np.logspace(-3,1,20))
ridge.fit(x_train, y_train)
ridge_y_test_hat = ridge.predict(x_test)
ridge_score = ridge.score(x_test, y_test)
print ("ridge:", ridge_score)

# 7. 画图
plt.figure(figsize=(12,6), facecolor='w')
ln_x_test = range(len(x_test))

plt.plot(ln_x_test, y_test, ls="-", lw=2, label=u'实际值')
plt.plot(ln_x_test, lr_y_test_hat, ls="-", lw=2, label=u'Linear回归,$R^2$=%.3f' % lr_score)
plt.plot(ln_x_test, lasso_y_test_hat, ls="-", lw=2, label=u'Lasso回归,$R^2$=%.3f' % lasso_score)
plt.plot(ln_x_test, ridge_y_test_hat, ls="-", lw=2, label=u'Ridge回归,$R^2$=%.3f' % ridge_score)
plt.plot(ln_x_test, y_test_hat, ls="-", lw=2, label=u'回归决策树预测值,$R^2$=%.3f' % score)
plt.xlabel(u'数据编码')
plt.ylabel(u'租赁价格')
plt.legend(loc = 'lower right')
plt.grid(True)
plt.title(u'波士顿房屋租赁数据预测')
plt.show()

# 参数优化
pipes = [
    Pipeline([
        ('mms', MinMaxScaler()),  ## 归一化操作
        ('pca', PCA()),  ## 降纬
        ('decision', DecisionTreeRegressor(criterion='mse'))
    ]),
    Pipeline([
        ('mms', MinMaxScaler()),
        ('decision', DecisionTreeRegressor(criterion='mse'))
    ]),
    Pipeline([
        ('decision', DecisionTreeRegressor(criterion='mse'))
    ])
]

# 参数
parameters = [
    {
        "pca__n_components": [0.25, 0.5, 0.75, 1],
        "decision__max_depth": np.linspace(1, 20, 20).astype(np.int8)
    },
    {
        "decision__max_depth": np.linspace(1, 20, 20).astype(np.int8)
    },
    {
        "decision__max_depth": np.linspace(1, 20, 20).astype(np.int8)
    }
]
# 获取数据
x_train2, x_test2, y_train2, y_test2 = x_train1, x_test1, y_train1, y_test1

for t in range(3):
    pipe = pipes[t]

    gscv = GridSearchCV(pipe, param_grid=parameters[t])

    gscv.fit(x_train2, y_train2)

    print(t, "score值:", gscv.best_score_, "最优参数列表:", gscv.best_params_)

#使用最优参数看看正确率
mms_best = MinMaxScaler()
decision3 = DecisionTreeRegressor(criterion='mse', max_depth=4)

x_train3, x_test3, y_train3, y_test3 = x_train1, x_test1, y_train1, y_test1
x_train3 = mms_best.fit_transform(x_train3, y_train3)
x_test3 = mms_best.transform(x_test3)
decision3.fit(x_train3, y_train3)

print ("正确率:", decision3.score(x_test3, y_test3))

# 查看各个不同深度的错误率
x_train4, x_test4, y_train4, y_test4 = x_train1, x_test1, y_train1, y_test1

depths = np.arange(1, 20)
err_list = []
for d in depths:
    clf = DecisionTreeRegressor(criterion='mse', max_depth=d)
    clf.fit(x_train4, y_train4)

    score1 = clf.score(x_test4, y_test4)
    err = 1 - score1
    err_list.append(err)
    print("%d深度,正确率%.5f" % (d, score1))

## 画图
plt.figure(facecolor='w')
plt.plot(depths, err_list, 'ro-', lw=3)
plt.xlabel(u'决策树深度', fontsize=16)
plt.ylabel(u'错误率', fontsize=16)
plt.grid(True)
plt.title(u'决策树层次太多导致的拟合问题(欠拟合和过拟合)', fontsize=18)
plt.show()

# 方式三:直接生成图片


dot_data = tree.export_graphviz(decision3, out_file=None,
                         filled=True, rounded=True,
                         special_characters=True)
graph = pydotplus.graph_from_dot_data(dot_data)
graph.write_pdf("housing.pdf")
决策树是一种基本的分类和回归方法,它可以通过训练数据集来建立一个树形结构的模型,用于预测新数据的分类或数值。 在Python中,我们可以使用scikit-learn库来实现决策树。下面是一个简单的例子,展示如何使用决策树来进行分类。 首先,我们需要准备训练数据集和测试数据集。假设我们有一个包含三个特征的数据集,其中每个样本都属于两个类别之一: ```python from sklearn.datasets import load_iris from sklearn.model_selection import train_test_split from sklearn.tree import DecisionTreeClassifier # 加载Iris数据集 iris = load_iris() # 创建训练数据集和测试数据集 X_train, X_test, y_train, y_test = train_test_split( iris.data, iris.target, test_size=0.3, random_state=42) # 创建决策树分类器 clf = DecisionTreeClassifier() # 训练模型 clf.fit(X_train, y_train) # 在测试数据集上进行预测 y_pred = clf.predict(X_test) # 计算准确率 accuracy = clf.score(X_test, y_test) print("Accuracy:", accuracy) ``` 上面的代码中,我们首先使用`load_iris()`函数加载了Iris数据集,然后使用`train_test_split()`函数将数据集分成训练数据集和测试数据集。接着,我们创建了一个`DecisionTreeClassifier`对象作为决策树分类器,并使用训练数据集来训练模型。最后,我们在测试数据集上进行了预测,并计算了模型的准确率。 需要注意的是,在实际应用中,我们通常需要对训练数据集进行一些预处理工作,比如特征选择、特征缩放等。 决策树的优点在于它们易于理解和解释,可以处理离散和连续特征,适用于多类别问题,且能够自动进行特征选择。但是,决策树也有一些缺点,比如容易过拟合、对噪声敏感等。在实际应用中,我们通常需要结合其他方法来提高模型的性能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值