机器学习经典算法:决策树原理详解
在机器学习领域,决策树是一种简单而强大的分类和回归算法。它通过构建树形模型来进行决策,具有易于理解和解释的特点。本文将详细介绍决策树的原理,并使用C++语言实现一个简单的决策树模型。
一、决策树的基本原理
决策树的核心思想是通过递归地将数据集划分为不同的子集,直到每个子集中的数据足够“纯净”或达到了预设的停止条件。其主要步骤包括特征选择、数据集划分以及递归构建树。
(一)特征选择
特征选择是决策树算法的关键步骤之一。每次划分数据时,算法需要选择一个最佳特征和该特征的一个阈值(对于连续特征)来划分数据。特征的选择标准通常是基于信息增益或基尼指数来衡量每个特征在区分数据上的效果。
1. 计算熵 (Entropy)
熵用于衡量数据集的不确定性或纯度。熵越低,数据集越纯。其公式为:
其中,( p_i )是类别 ( i ) 在数据集 ( S ) 中的比例,( c ) 是类别的总数。
2. 计算信息增益 (Information Gain)
信息增益是通过选择一个特征进行数据划分所带来的熵的减少量。信息增益越高,表示特征的分类能力越强。其公式为:
其中,( S ) 是数据集,( A ) 是待选择的特征,( S_v ) 是根据特征 ( A ) 的值 ( v ) 划分后的子集。
(二)数据集划分
在选择了最优特征后,算法需要根据该特征的取值将数据集分为两个子集。对于分类问题,这通常涉及将数据按照某个特征值的阈值分成“左子集”和“右子集”。对于连续特征,决策树会寻找一个最佳的阈值来分割数据;对于离散特征,则可以直接根据特征的不同取值进行分割。
(三)递归构建决策树
决策树是一个递归结构。当数据集被划分后,每个子集会被进一步划分,直到满足以下条件之一:
- 数据集纯度高:如果一个节点中的数据样本全部属于同一个类别,停止划分。
- 特征用尽:如果没有剩余的特征可以用于划分,停止划分。
- 达到预设的停止条件:例如达到最大树深度或最小样本节点数量。
二、C++实现决策树
接下来,我们将使用C++语言实现一个简单的决策树模型。为了简化实现,我们将使用ID3算法,基于信息增益进行特征选择。
(一)数据结构定义
首先,定义决策树的节点结构:
#include <iostream>
#include <vector>
#include <cmath>
#include <map>
#include <algorithm>
using namespace std;
struct TreeNode {
int feature_index = -1; // 特征索引
double threshold = 0; // 阈值
int label = -1; // 叶节点标签
TreeNode* left = nullptr; // 左子树
TreeNode* right = nullptr; // 右子树
};
(二)熵和信息增益的计算
实现熵和信息增益的计算函数:
double entropy(const vector<int>& labels) {
map<int, int> label_counts;
for (int label : labels) {
label_counts[label]++;
}
double total = labels.size();
double ent = 0.0;
for (const auto& pair : label_counts) {
double p = pair.second / total