机器学习之决策树

一、决策树的基本认识

决策树(Decision Tree)是在已知各种情况发生概率的基础上,通过构成决策树来求取净现值的期望值大于等于零的概率,评价项目风险,判断其可行性的决策分析方法,是直观运用概率分析的一种图解法。由于这种决策分支画成图形很像一棵树的枝干,故称决策树。在机器学习中,决策树是一个预测模型,他代表的是对象属性与对象值之间的一种映射关系。

二、算法简介

决策树是一种经典的机器学习算法,它通过对数据集进行递归地分割,构建一个树形结构,每个节点代表一个属性测试,每个分支代表一个测试结果,叶子节点表示最终的决策结果或类别。ID3、C4.5和CART是三种常见的决策树算法,下面简要介绍它们:

  1. ID3(Iterative Dichotomiser 3)

    • ID3是最早的决策树学习算法之一,由Ross Quinlan在1986年提出。
    • ID3算法使用信息增益作为属性选择的准则,即选择能够最大程度地降低数据集整体不确定性的属性作为当前节点的分裂属性。
    • 该算法在每个节点上都选择当前数据集中信息增益最大的属性进行分裂,直到所有属性都用完或者达到了停止条件(如所有样本属于同一类别)为止。
  2. C4.5

    • C4.5是ID3算法的改进版本,同样由Ross Quinlan于1993年提出。
    • 与ID3相比,C4.5算法使用信息增益比(Gain Ratio)来代替信息增益作为属性选择的准则。信息增益比对取值数目较多的属性进行了一定的惩罚,更倾向于选择取值较少、更简单的属性,以防止过拟合。
    • 此外,C4.5还能处理缺失值,并能够对连续值属性进行离散化处理。
  3. CART(Classification and Regression Trees)

    • CART是由Breiman等人于1984年提出的一种决策树算法,既可以用于分类(Classification)也可以用于回归(Regression)。
    • 与ID3和C4.5不同,CART算法是一种二叉树,每个非叶子节点只有两个分支,分别表示对应属性的取值为是或否。
    • CART算法通过基尼指数(Gini Index)来进行属性选择,即选择能够最大程度地降低数据集纯度(类别不确定性)的属性作为当前节点的分裂属性。
    • 对于分类问题,CART算法会递归地生成一个分类树,每个叶子节点代表一个类别;对于回归问题,CART算法会生成一个回归树,叶子节点代表一个数值。

这三种算法都是基于贪心策略构建决策树,它们在属性选择、处理缺失值、处理连续值等方面有所不同,适用于不同的数据情况和任务需求。

三、ID3算法

让我们考虑一个简单的二元分类数据集,关于天气状况以及是否适合打高尔夫球。

  1. 计算整个数据集的熵:

    根据“Play”和“Don't Play”的比例,计算整个数据集的熵。这表示了数据集的不确定性或混乱程度。
  2. 计算每个特征的信息增益:

    针对每个特征(Outlook、Temperature、Humidity、Wind),计算在该特征条件下数据集的熵,并计算信息增益。信息增益表示了在特征条件下对数据集的分类带来的纯度提升。
  3. 选择最佳分裂特征:

    从所有特征中选择具有最高信息增益的特征作为节点分裂特征。
  4. 递归构建决策树:

    以选择的分裂特征为节点,将数据集划分成子集,并对每个子集重复上述过程,直到满足停止条件为止。

通过计算每个特征的信息增益,我们可以选择具有最大信息增益的特征作为节点进行分裂。这样逐步构建决策树,直到满足停止条件(如达到最大深度或节点样本数少于阈值)。这就是ID3算法的基本过程。

以下是python代码实现:

import pandas as pd
from sklearn import tree
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
import matplotlib.pyplot as plt

# 创建数据集
data = {
    'Weather': ['Sunny', 'Sunny', 'Overcast', 'Rain', 'Rain', 'Rain', 'Overcast', 'Sunny', 'Sunny', 'Rain', 'Sunny', 'Overcast', 'Overcast', 'Rain'],
    'Temperature': ['Hot', 'Hot', 'Hot', 'Mild', 'Cool', 'Cool', 'Cool', 'Mild', 'Cool', 'Mild', 'Mild', 'Mild', 'Hot', 'Mild'],
    'Humidity': ['High', 'High', 'High', 'High', 'Normal', 'Normal', 'Normal', 'High', 'Normal', 'Normal', 'Normal', 'High', 'Normal', 'High'],
    'Wind': ['Weak', 'Strong', 'Weak', 'Weak', 'Weak', 'Strong', 'Strong', 'Weak', 'Weak', 'Weak', 'Strong', 'Strong', 'Weak', 'Strong'],
    'Play Golf': ['No', 'No', 'Yes', 'Yes', 'Yes', 'No', 'Yes', 'No', 'Yes', 'Yes', 'Yes', 'Yes', 'Yes', 'No']
}

df = pd.DataFrame(data)

# 将分类特征转换为数字
df_encoded = pd.get_dummies(df[['Weather', 'Temperature', 'Humidity', 'Wind']])

# 分割数据集
X = df_encoded
y = df['Play Golf'].apply(lambda x: 1 if x == 'Yes' else 0)

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 创建决策树分类器(使用entropy作为分裂准则,这类似于ID3)
clf = tree.DecisionTreeClassifier(criterion='entropy')

# 训练决策树
clf.fit(X_train, y_train)

# 预测
y_pred = clf.predict(X_test)

# 测试准确度
accuracy = accuracy_score(y_test, y_pred)

print(f"Test accuracy: {accuracy:.2%}")

# 绘制决策树
plt.figure(figsize=(12, 8))
tree.plot_tree(clf, feature_names=list(X.columns), class_names=['No', 'Yes'], filled=True, fontsize=10)
plt.show()

运行结果:

四、C4.5算法

同样以上述数据集为例。

  1. 计算整个数据集的熵:

    根据“Play”和“Don't Play”的比例,计算整个数据集的熵。这表示了数据集的不确定性或混乱程度。
  2. 计算每个特征的信息增益:

    针对每个特征(Outlook、Temperature、Humidity、Wind),计算在该特征条件下数据集的熵,并计算信息增益。信息增益表示了在特征条件下对数据集的分类带来的纯度提升。
  3. 选择最佳分裂特征:

    从所有特征中选择具有最高信息增益的特征作为节点分裂特征。
  4. 递归构建决策树:

    以选择的分裂特征为节点,将数据集划分成子集,并对每个子集重复上述过程,直到满足停止条件为止。

以下是python代码实现:

from math import log

def entropy(data):
    # 计算数据集的熵
    total_samples = len(data)
    label_counts = {}
    for sample in data:
        label = sample[-1]
        if label not in label_counts:
            label_counts[label] = 0
        label_counts[label] += 1
    entropy = 0
    for label in label_counts:
        probability = label_counts[label] / total_samples
        entropy -= probability * log(probability, 2)
    return entropy

def split_data(data, feature_index):
    # 根据特征将数据集划分成子集
    split_data = {}
    for sample in data:
        value = sample[feature_index]
        if value not in split_data:
            split_data[value] = []
        split_data[value].append(sample)
    return split_data

def information_gain(data, feature_index):
    # 计算特征的信息增益
    total_entropy = entropy(data)
    split_data_dict = split_data(data, feature_index)
    new_entropy = 0
    for value in split_data_dict:
        value_samples = split_data_dict[value]
        probability = len(value_samples) / len(data)
        new_entropy += probability * entropy(value_samples)
    information_gain = total_entropy - new_entropy
    return information_gain

def intrinsic_value(data, feature_index):
    # 计算特征的固有值
    split_data_dict = split_data(data, feature_index)
    iv = 0
    for value in split_data_dict:
        probability = len(split_data_dict[value]) / len(data)
        iv -= probability * log(probability, 2)
    return iv

def gain_ratio(data, feature_index):
    # 计算特征的信息增益比
    ig = information_gain(data, feature_index)
    iv = intrinsic_value(data, feature_index)
    gain_ratio = ig / iv if iv != 0 else 0
    return gain_ratio

def choose_best_feature(data, features):
    # 选择信息增益比最高的特征作为节点分裂特征
    best_feature_index = -1
    best_gain_ratio = -1
    for idx, feature in enumerate(features):
        if feature == 'Play':  # 最后一列是标签,跳过
            continue
        ratio = gain_ratio(data, idx)
        if ratio > best_gain_ratio:
            best_gain_ratio = ratio
            best_feature_index = idx
    return best_feature_index

def majority_class(labels):
    # 返回子集中样本数最多的类别
    label_counts = {}
    for label in labels:
        if label not in label_counts:
            label_counts[label] = 0
        label_counts[label] += 1
    majority_label = max(label_counts, key=label_counts.get)
    return majority_label

def build_tree(data, features):
    labels = [sample[-1] for sample in data]
    if len(set(labels)) == 1:
        return labels[0]  # 所有样本属于同一类别,返回该类别
    if len(data[0]) == 1:
        return majority_class(labels)  # 所有特征已经用完,返回子集中样本数最多的类别
    best_feature_index = choose_best_feature(data, features)
    best_feature = features[best_feature_index]
    decision_tree = {best_feature: {}}
    del features[best_feature_index]
    split_data_dict = split_data(data, best_feature_index)
    for value in split_data_dict:
        value_samples = split_data_dict[value]
        decision_tree[best_feature][value] = build_tree(value_samples, features[:])
    return decision_tree

dataset = [
    ['Sunny', 85, 85, 'Weak', 'No'],
    ['Sunny', 80, 90, 'Strong', 'No'],
    ['Overcast', 83, 78, 'Weak', 'Yes'],
    ['Rain', 70, 96, 'Weak', 'Yes'],
    ['Rain', 68, 80, 'Weak', 'Yes'],
    ['Rain', 65, 70, 'Strong', 'No'],
    ['Overcast', 64, 65, 'Strong', 'Yes'],
    ['Sunny', 72, 95, 'Weak', 'No'],
    ['Sunny', 69, 70, 'Weak', 'Yes'],
    ['Rain', 75, 80, 'Weak', 'Yes'],
    ['Sunny', 75, 70, 'Strong', 'Yes'],
    ['Overcast', 72, 90, 'Strong', 'Yes'],
    ['Overcast', 81, 75, 'Weak', 'Yes'],
    ['Rain', 71, 80, 'Strong', 'No']
]
headers = ['Outlook', 'Temperature', 'Humidity', 'Wind', 'Play']

decision_tree = build_tree(dataset, headers[:-1])  # 构建决策树
print(decision_tree)

运行结果:

{'Temperature': {85: 'No', 80: 'No', 83: 'Yes', 70: 'Yes', 68: 'Yes', 65: 'No', 64: 'Yes', 72: {'Outlook': {'Sunny': 'No', 'Overcast': 'Yes'}}, 69: 'Yes', 75: 'Yes', 81: 'Yes', 71: 'No'}}

  • 21
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
决策树是常用的机器学习算法之一,通过对数据的分类和特征值计算来完成对未知数据的预测。本文将介绍使用Python实现决策树算法的相关步骤。 首先,需要导入决策树算法工具包,使用以下代码: ```python from sklearn import tree ``` 然后,导入训练数据和测试数据,并进行预处理。为了方便起见,在本文中采用生成随机数的方式来生成样本数据,使用以下代码: ```python from sklearn.datasets import make_classification X, y = make_classification(n_samples=100, n_features=4, n_classes=2, n_informative=2, n_redundant=0, random_state=0, shuffle=False) ``` 接下来,使用生成的样本数据进行模型训练。这里使用scikit-learn中的DecisionTreeClassifier()函数。 ```python clf = tree.DecisionTreeClassifier() clf = clf.fit(X, y) ``` 训练后,调用predict()方法进行对测试数据的预测,使用以下代码: ```python y_pred = clf.predict(X) ``` 最后,评估模型的准确率,使用以下代码: ```python from sklearn.metrics import accuracy_score print(accuracy_score(y, y_pred)) ``` 这就是使用Python实现决策树算法的基本过程。决策树可以根据数据中的不同特征进行分类,是一个简单且常用的分类算法决策树算法也可用于回归问题,例如预测一个数的大小。与其他机器学习算法相比,决策树具有易于理解和可解释的优点,同时还可以处理非线性的分类问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值