江西省住房和城乡建设厅网站,能制作网站的公司联系方式,加强网站内容建设,怎么建设官方网站1. 理解决策树的基本概念
决策树是一种监督学习算法#xff0c;可以用于分类和回归任务。决策树通过一系列规则将数据划分为不同的类别或值。树的每个节点表示一个特征#xff0c;节点之间的分支表示特征的可能取值#xff0c;叶节点表示分类或回归结果。
2. 决策树的构建…1. 理解决策树的基本概念
决策树是一种监督学习算法可以用于分类和回归任务。决策树通过一系列规则将数据划分为不同的类别或值。树的每个节点表示一个特征节点之间的分支表示特征的可能取值叶节点表示分类或回归结果。
2. 决策树的构建过程
2.1. 特征选择
特征选择是构建决策树的第一步通常使用信息增益、基尼指数或增益率等指标。
信息增益Information Gain
信息增益表示通过某个特征将数据集划分后的纯度增加量公式如下 其中
D 是数据集。
A 是特征。
V(A) 是特征 A 的所有可能取值。
Dv 是数据集中特征 A 取值为 v 的子集。
∣Dv∣ 是 Dv 中样本的数量。
∣D∣ 是数据集 D 中样本的总数量。
Entropy(D) 是数据集 D 的熵表示数据集本身的纯度。选择信息增益最大的特征作为当前节点的划分特征。
熵的计算公式为 其中
c 是类别的数量。
pi 是数据集中属于第 i 类的样本所占的比例。以下代码展示了如何计算熵、信息增益并选择最优特征。
import numpy as np
from collections import Counter
from sklearn.datasets import load_irisdef entropy(y):hist np.bincount(y)ps hist / len(y)return -np.sum([p * np.log2(p) for p in ps if p 0])def information_gain(X, y, feature):# Entropy before splitentropy_before entropy(y)# Values and countsvalues, counts np.unique(X[:, feature], return_countsTrue)# Weighted entropy after splitentropy_after 0for v, count in zip(values, counts):entropy_after (count / len(y)) * entropy(y[X[:, feature] v])return entropy_before - entropy_afterdef best_feature_by_information_gain(X, y):features X.shape[1]gains [information_gain(X, y, feature) for feature in range(features)]return np.argmax(gains), max(gains)# Load dataset
iris load_iris()
X iris.data
y iris.target# Find best feature
best_feature, best_gain best_feature_by_information_gain(X, y)
print(fBest feature: {iris.feature_names[best_feature]}, Information Gain: {best_gain})
基尼指数Gini Index 也称为基尼不纯度Gini Impurity是一种衡量数据集纯度的指标。基尼指数越小数据集的纯度越高。
基尼指数的计算公式 对于一个包含 k 个类别的分类问题基尼指数 G(D) 定义如下 其中
D 是数据集。
k 是类别的数量。
pi 是数据集中属于第 i 类的样本所占的比例。条件基尼指数 在某个特征 A 的条件下数据集 D 的条件基尼指数 G(D∣A) 定义如下 其中
values(A) 是特征 A 的所有可能取值。
Dv 是数据集中特征 A 取值为 v 的子集。
∣Dv∣ 是 Dv 中样本的数量。
∣D∣ 是数据集 D 中样本的总数量。
G(Dv) 是子集 Dv 的基尼指数。基尼增益Gini Gain 基尼增益 GG(D,A) 是通过特征 A 划分数据集 D 后基尼指数的减少量。计算公式如下 参数解释
D整个数据集包含了所有的样本。
A某个特征用于划分数据集。
G(D)数据集 D 的基尼指数表示数据集本身的纯度。
G(D∣A)在特征 A 的条件下数据集 D 的条件基尼指数表示在特征 A 的条件下数据集的纯度。选择基尼增益最大的特征及其分割点作为当前节点的划分特征。
以下代码展示如何使用上述步骤来选择基尼增益最大的特征
import numpy as np
from sklearn.datasets import load_irisdef gini(y):hist np.bincount(y)ps hist / len(y)return 1 - np.sum([p**2 for p in ps if p 0])def gini_gain(X, y, feature):# Gini index before splitgini_before gini(y)# Values and countsvalues, counts np.unique(X[:, feature], return_countsTrue)# Weighted gini after splitgini_after 0for v, count in zip(values, counts):gini_after (count / len(y)) * gini(y[X[:, feature] v])return gini_before - gini_afterdef best_feature_by_gini_gain(X, y):features X.shape[1]gains [gini_gain(X, y, feature) for feature in range(features)]return np.argmax(gains), max(gains)# Load dataset
iris load_iris()
X iris.data
y iris.target# Find best feature
best_feature, best_gain best_feature_by_gini_gain(X, y)
print(fBest feature: {iris.feature_names[best_feature]}, Gini Gain: {best_gain})
增益率Gain Ratio 决策树中的增益率Gain Ratio用于选择最优的划分属性以便构建决策树。增益率是基于信息增益Information Gain的一个修正版本用于克服信息增益在处理属性取值多样性时可能出现的偏向问题。
信息增益是指选择某一属性划分数据集后信息熵的减少量。信息增益公式为 其中
IG(T,A)属性 A 对数据集 T 的信息增益。
H(T)数据集 T 的熵。
H(T∣A)在给定属性 A 的条件下数据集 T 的条件熵。增益率通过将信息增益除以属性的固有值Intrinsic Value来计算。固有值是衡量属性取值多样性的一种指标。增益率公式为 其中
GR(T,A)属性 A 对数据集 T 的增益率。
IG(T,A)属性 A 对数据集 T 的信息增益。
IV(A)属性 A 的固有值。固有值Intrinsic Value
固有值反映了属性的取值多样性计算公式为 其中
Ti属性 A 的第 i 个取值所对应的样本子集。
∣Ti∣属性 A 的第 i 个取值所对应的样本子集的样本数量。
∣T∣数据集 T 的总样本数量。
n属性 A 取值的个数。通过计算每个属性的增益率选择增益率最高的属性作为决策树节点的划分属性从而构建最优的决策树。
2.2. 划分节点
根据选定的特征和阈值数据集被划分成多个子集。
2.3. 递归构建
递归地对每个子集进行特征选择和划分直到满足停止条件如当前数据子集中的所有实例都属于同一个类别或达到预设的最大树深度。 特征选择以增益率为例在决策树构建过程中选择每个节点的分裂特征是基于当前数据集的增益率计算结果的。对于每个分裂点我们都会重新计算剩余特征的增益率并选择其中最高的作为下一个分裂特征。
import numpy as np
import pandas as pd# 计算熵
def entropy(y):unique_labels, counts np.unique(y, return_countsTrue)probabilities counts / counts.sum()return -np.sum(probabilities * np.log2(probabilities))# 计算信息增益
def information_gain(data, split_attribute, target_attribute):total_entropy entropy(data[target_attribute])values, counts np.unique(data[split_attribute], return_countsTrue)weighted_entropy np.sum([(counts[i] / np.sum(counts)) * entropy(data[data[split_attribute] values[i]][target_attribute])for i in range(len(values))])info_gain total_entropy - weighted_entropyreturn info_gain# 计算固有值
def intrinsic_value(data, split_attribute):values, counts np.unique(data[split_attribute], return_countsTrue)probabilities counts / counts.sum()return -np.sum(probabilities * np.log2(probabilities))# 计算增益率
def gain_ratio(data, split_attribute, target_attribute):info_gain information_gain(data, split_attribute, target_attribute)iv intrinsic_value(data, split_attribute)return info_gain / iv if iv ! 0 else 0# 递归构建决策树
def build_decision_tree(data, original_data, features, target_attribute, parent_node_classNone):# 条件1: 所有数据点属于同一类别if len(np.unique(data[target_attribute])) 1:return np.unique(data[target_attribute])[0]# 条件2: 数据子集为空elif len(data) 0:return np.unique(original_data[target_attribute])[np.argmax(np.unique(original_data[target_attribute], return_countsTrue)[1])]# 条件3: 没有更多的特征可以分裂elif len(features) 0:return parent_node_classelse:parent_node_class np.unique(data[target_attribute])[np.argmax(np.unique(data[target_attribute], return_countsTrue)[1])]gain_ratios {feature: gain_ratio(data, feature, target_attribute) for feature in features}best_feature max(gain_ratios, keygain_ratios.get)tree {best_feature: {}}features [i for i in features if i ! best_feature]for value in np.unique(data[best_feature]):sub_data data[data[best_feature] value]subtree build_decision_tree(sub_data, original_data, features, target_attribute, parent_node_class)tree[best_feature][value] subtreereturn tree# 可视化决策树
def visualize_tree(tree, depth0):if isinstance(tree, dict):for attribute, subtree in tree.items():if isinstance(subtree, dict):for value, subsubtree in subtree.items():print(f{| * depth}|--- {attribute} {value})visualize_tree(subsubtree, depth 1)else:print(f{| * depth}|--- {attribute} {value}: {subtree})else:print(f{| * depth}|--- {tree})# 示例数据
data pd.DataFrame({Outlook: [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],PlayTennis: [No, No, Yes, Yes, Yes, No, Yes, No, Yes, Yes, Yes, Yes, Yes, No]
})# 构建决策树
features [Outlook, Temperature, Humidity, Wind]
target_attribute PlayTennis
tree build_decision_tree(data, data, features, target_attribute)# 可视化决策树
print(Decision Tree:)
visualize_tree(tree)
通过运行代码可以看到每个节点选择的分裂特征以及决策树的结构
Decision Tree:
|--- Temperature Cool
| |--- PlayTennis Yes
|--- Temperature Hot
| |--- PlayTennis No
|--- Temperature Mild
| |--- Outlook Sunny
| | |--- Humidity High
| | | |--- PlayTennis No
| | |--- Humidity Normal
| | | |--- PlayTennis Yes
| |--- Outlook Rain
| | |--- Wind Weak
| | | |--- PlayTennis Yes
| | |--- Wind Strong
| | | |--- PlayTennis No
| |--- Outlook Overcast
| | |--- PlayTennis Yes解释决策树的结构
根节点是 Temperature这是第一个选择的分裂特征。
Temperature 的每个取值Cool, Hot, Mild对应一个子节点。
如果 Temperature 是 Cool则 PlayTennis 是 Yes。
如果 Temperature 是 Hot则 PlayTennis 是 No。
如果 Temperature 是 Mild则继续分裂 Outlook 属性Outlook 是 Sunny 时进一步分裂 Humidity 属性Humidity 是 High 时PlayTennis 是 No。Humidity 是 Normal 时PlayTennis 是 Yes。Outlook 是 Rain 时进一步分裂 Wind 属性Wind 是 Weak 时PlayTennis 是 Yes。Wind 是 Strong 时PlayTennis 是 No。Outlook 是 Overcast 时PlayTennis 是 Yes。通过这种方式决策树会根据每个节点选择最佳的分裂特征直到所有数据点都被正确分类或没有更多的特征可供分裂。
2.4. 防止过拟合
防止决策树过拟合的方法主要包括剪枝、设置深度限制和样本数量限制。以下是一些常用的方法及其实现
预剪枝 (Pre-pruning)
预剪枝是在构建决策树时限制树的增长。常用的方法包括
设置最大深度限制树的深度防止树过深导致过拟合。
设置最小样本分裂数如果节点中的样本数小于某个阈值则不再分裂该节点。
设置最小信息增益如果信息增益小于某个阈值则不再分裂该节点。后剪枝 (Post-pruning)
后剪枝是在决策树完全生长后剪去一些不重要的分支。常用的方法包括
代价复杂度剪枝 (Cost Complexity Pruning)基于一个代价复杂度参数 α剪去那些对降低训练误差贡献较小但增加了模型复杂度的分支。代价复杂度剪枝 (CCP) 是一种后剪枝技术用于简化已经完全生长的决策树。CCP 通过引入一个复杂度惩罚参数 α 来权衡决策树的复杂度与其在训练集上的误差。通过调整 α我们可以控制模型的复杂度防止过拟合。 原理
CCP 的基本思想是通过最小化以下代价复杂度函数来选择最佳的子树 其中
Rα(T) 是带有复杂度惩罚项的代价复杂度。
R(T)是子树 T 的误差。
α 是复杂度惩罚项控制模型复杂度与误差之间的权衡。
∣T∣ 是子树 T 的叶节点数量。较小的 α 值允许更多的节点使树更加复杂较大的 α 值会剪去更多的节点使树更加简单。 代价复杂度剪枝步骤
构建完全生长的决策树首先生成一棵完全生长的决策树使其充分拟合训练数据。
计算每个子树的误差对子树中的所有节点计算其误差 R(T)。
计算代价复杂度对于每个子树计算其代价复杂度 Rα(T)。
选择合适的 α通过关系图或交叉验证结果选择最佳的 α 值。
剪枝根据选定的 α 值剪去那些对降低误差贡献不大但增加了复杂度的节点。import numpy as np
import pandas as pd
from sklearn.tree import DecisionTreeClassifier, export_text
import matplotlib.pyplot as plt# 示例数据
data pd.DataFrame({Outlook: [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],PlayTennis: [No, No, Yes, Yes, Yes, No, Yes, No, Yes, Yes, Yes, Yes, Yes, No]
})# 将特征和目标变量转换为数值编码
data_encoded pd.get_dummies(data[[Outlook, Temperature, Humidity, Wind]])
target data[PlayTennis].apply(lambda x: 1 if x Yes else 0)# 拆分数据集
X data_encoded
y target# 构建完全生长的决策树
clf DecisionTreeClassifier(random_state0)
clf.fit(X, y)# 导出决策树规则
tree_rules export_text(clf, feature_nameslist(data_encoded.columns))
print(Original Decision Tree Rules:)
print(tree_rules)# 计算代价复杂度剪枝路径
path clf.cost_complexity_pruning_path(X, y)
ccp_alphas, impurities path.ccp_alphas, path.impurities# 训练不同复杂度惩罚项的决策树
clfs []
for ccp_alpha in ccp_alphas:clf DecisionTreeClassifier(random_state0, ccp_alphaccp_alpha)clf.fit(X, y)clfs.append(clf)# 绘制复杂度惩罚项与树结构的关系图
node_counts [clf.tree_.node_count for clf in clfs]
depth [clf.tree_.max_depth for clf in clfs]fig, ax plt.subplots(3, 1, figsize(10, 10))
ax[0].plot(ccp_alphas, node_counts, markero, drawstylesteps-post)
ax[0].set_xlabel(alpha)
ax[0].set_ylabel(number of nodes)
ax[0].set_title(Number of nodes vs alpha)ax[1].plot(ccp_alphas, depth, markero, drawstylesteps-post)
ax[1].set_xlabel(alpha)
ax[1].set_ylabel(depth)
ax[1].set_title(Depth vs alpha)ax[2].plot(ccp_alphas, impurities, markero, drawstylesteps-post)
ax[2].set_xlabel(alpha)
ax[2].set_ylabel(impurity)
ax[2].set_title(Impurity vs alpha)plt.tight_layout()
plt.show()# 选择合适的 alpha 进行剪枝并可视化决策树例如选择 impurity 最小对应的 alpha
# Impurity 反映了决策树在分裂节点时的纯度纯度越高impurity 越低节点中样本越一致分类效果越好。
optimal_alpha ccp_alphas[np.argmin(impurities)]
pruned_tree DecisionTreeClassifier(random_state0, ccp_alphaoptimal_alpha)
pruned_tree.fit(X, y)# 导出剪枝后的决策树规则
pruned_tree_rules export_text(pruned_tree, feature_nameslist(data_encoded.columns))print(Pruned Decision Tree Rules:)
print(pruned_tree_rules)
3. 使用集成方法
随机森林通过构建多棵决策树并结合它们的预测结果可以减少单棵树的过拟合。
使用随机森林Random Forest是一种有效的方法来防止单个决策树模型的过拟合问题。随机森林通过构建多棵决策树并集成它们的预测结果从而提高模型的泛化能力。 随机森林防止过拟合的机制
1. 集成学习随机森林是一种集成学习方法通过构建多棵决策树并将它们的预测结果进行投票或平均从而得到最终的预测结果。这种方式可以有效地减少单棵决策树的高方差提高模型的稳定性和泛化能力。2. 随机特征选择在每棵决策树的节点分裂时随机森林不会考虑所有特征而是从所有特征中随机选择一个子集来进行分裂。这样可以减少树之间的相关性提高集成效果。3. Bootstrap 重采样每棵决策树都是通过对原始训练数据进行 bootstrap 重采样有放回抽样得到的不同样本集进行训练。这样每棵树都有不同的训练数据进一步减少了树之间的相关性。梯度提升树通过逐步构建一系列决策树每棵树修正前一棵树的错误可以提高模型的泛化能力。
梯度提升树Gradient Boosting Trees, GBT是一种集成学习方法通过逐步构建一系列决策树来提高模型的预测性能。每棵新树的构建是为了修正之前所有树的误差。 梯度提升树防止过拟合的机制
1. 分阶段训练梯度提升树采用逐步训练的方法。每次构建新树时模型会根据之前所有树的预测误差来调整新树的结构。这种逐步优化的方法可以有效减少过拟合。2. 学习率学习率learning rate控制每棵树对最终模型的贡献。较小的学习率使得每棵树的影响较小从而需要更多的树来拟合训练数据。尽管这会增加计算成本但可以显著降低过拟合的风险。3. 树的深度限制每棵树的最大深度可以防止单棵树过于复杂从而避免过拟合。浅层树通常 3-5 层虽然不能完全拟合数据但可以捕捉到数据的主要结构从而与其他树一起构成一个强大的集成模型。4. 子样本采样在构建每棵树时梯度提升树可以对训练数据进行子样本采样subsampling。这种方法通过引入训练数据的随机性减少了模型的方差从而防止过拟合。5. 正则化梯度提升树可以引入正则化参数如 L1 和 L2 正则化来进一步防止模型的过拟合。4. 实际应用中的决策树
决策树可以用于多个实际应用如客户分类、疾病诊断、风险评估等。在实际应用中需要根据具体问题调整决策树的参数如树的最大深度、最小样本分裂数等以达到最佳效果。
使用 TensorFlow 和 NumPy 实现一个简单的决策树分类器