--- title: 决策树算法 tags: decisiontree categories: machinelearning abbrlink: 95 date: 2025-01-24 12:39:59 cover: https://th.bing.com/th/id/OIP.XaPUn6eccfS_z_wTLQNFzgHaEK?w=240&h=180&c=7&r=0&o=5&dpr=1.9&pid=1.7 --- ### C4.5 C4.5 是一种用于生成决策树的算法,不再使用信息增益,而是使用信息增益比,来避免偏向于选择取值较多的特征。信息增益比是信息增益与特征的熵的比值。 ### ID3 D3 是一种基于信息增益(Information Gain)的决策树算法 ### Cart CART(分类与回归树)一种决策树算法,,CART 使用 **二叉树结构**,即每个节点只能有两个子节点。 ### cart剪枝 CART 决策树的剪枝方法分为 **预剪枝**(Pre-pruning)和 **后剪枝**(Post-pruning)两种: #### **预剪枝**: 预剪枝是在构建决策树时就决定是否停止进一步划分某个节点。主要通过以下标准来控制: - 当某个节点的样本数小于某个阈值时,不再继续划分。 - 当某个节点的 Gini 不纯度小于某个阈值时,不再继续划分。 预剪枝的优点是能够减少计算量,但缺点是可能会导致模型不够复杂,从而产生欠拟合。 #### **后剪枝**: 后剪枝是在决策树完全构建出来之后,对树进行修剪。具体过程如下: - 构建完整的决策树。 - 从叶子节点开始,逐渐向上遍历树的每个节点。 - 对每个节点进行判断,是否合适剪去该节点及其子树。如果剪去该子树后,模型的性能没有显著下降,就可以剪枝。 后剪枝通过避免过度拟合来提高模型的泛化能力,但其计算开销较大。 ### 特征工程(特征提取) - **字典特征提取** 主要用于处理包含键值对(key-value pairs)的数据结构    ```python    from sklearn.feature_extraction import DictVectorizer    # 字典特征提取    data = [        {'city': 'beijing', 'temperature': 100},        {'city': 'shanghai', 'temperature': 95},        {'city': 'guangzhou', 'temperature': 98}    ]    transfer = DictVectorizer(sparse=False)    new_data = transfer.fit_transform(data)    print(transfer.feature_names_)    print(new_data)    ``` - **文本特征提取** 主要用于将文本数据(如句子、段落、文章等)转换成数值型特征。这对于文本分类、信息检索等任务非常重要。    ```python    from sklearn.feature_extraction.text import CountVectorizer    # 示例文本数据    data = [        "I love programming",        "Python is great",        "I love machine learning"    ]    # 创建 CountVectorizer 对象    transfer = CountVectorizer()    # 将文本数据转换为特征向量    new_data = transfer.fit_transform(data)    # 输出特征名称    print("Feature Names:", transfer.get_feature_names_out())    # 输出转换后的特征矩阵    print("Transformed Data:", new_data.toarray())    ``` - 文本特征提取(中文文本) ```python   from sklearn.feature_extraction.text import CountVectorizer   import jieba   # 中文文本数据(大于20个字)   data = [     "我热爱编程,学习编程语言是一件非常有趣的事情,它能够提升我们解决问题的能力,编程让我变得更加有创意。",     "Python语言是一门非常强大的编程语言,具有简洁的语法和丰富的库,可以帮助开发者更高效地完成任务。",     "机器学习是一项非常有前途的技术,它能够让计算机从数据中自动学习,逐步提高模型的精确度,解决实际问题。"   ]   # 使用jieba分词   text_list = []   for line in data:     text_list.append(" ".join(list(jieba.cut(line))))   # 创建 CountVectorizer 对象   transfer = CountVectorizer()   # 将文本数据转换为特征向量   new_data = transfer.fit_transform(text_list)   # 输出特征名称   print("Feature Names:", transfer.get_feature_names_out())   # 输出转换后的特征矩阵   print("Transformed Data:", new_data.toarray()) ``` ### tf-idf > 词频 * 逆文档频率 ```python # tfi-df from sklearn.feature_extraction.text import TfidfVectorizer import jieba data=["一种还是一种今天很残酷,明天更残酷,后天很美好,但绝对大部分是死在明天晚上,所以每个人不要放弃今天。", "我们看到的从很远星系来的光是在几百万年之前发出的,这样当我们看到宇宙时,我们是在看它的过去", "如果只用一种方式了解某样事物,你就不会真正了解它。了解事物真正含义的秘密取决于如何将其与我们所了解的事物相联系"] list = [] for item in data: list.append(" ".join(jieba.cut(item))) transfer = TfidfVectorizer() new_data = transfer.fit_transform(list) print(f"特征名字:\n{transfer.get_feature_names_out()}") print(f"转换后的特征矩阵:\n{ new_data.toarray()}") print(f"转换后的数据:\n{new_data}") ``` ### 回归决策树 #### 决策树算法的应用 (泰坦尼克号沉船幸存者预测) ```python import seaborn as sns import pandas as pd import numpy as np from sklearn.model_selection import train_test_split from sklearn.feature_extraction import DictVectorizer from sklearn.tree import DecisionTreeClassifier,export_graphviz # 1.获取数据集 - 加载 Titanic 数据集 titanic = sns.load_dataset('titanic') missing_age_count = titanic['age'].isna().sum() # print(f"缺失的 age 数量: {missing_age_count}") # 2. 数据基本处理 # 2.1 确认特征值、目标值 X = titanic[['pclass','age','sex']] y = titanic['survived'] # 2.2 缺失值处理 X.loc[:, 'age'] = X['age'].fillna(value=X['age'].mean()) # 使用 .loc 进行修改 # 2.3 划分数据集 X_train,X_test,y_train,y_test = train_test_split(X,y,random_state=22) # 3. 特征工程(字典特征提取) X_train = X_train.to_dict(orient="records") X_test= X_test.to_dict(orient="records") transfer = DictVectorizer() X_train = transfer.fit_transform(X_train) X_test = transfer.transform(X_test) # 4. 机器学习 决策树算法 estimator = DecisionTreeClassifier(criterion="gini") estimator.fit(X_train,y_train) y_pred = estimator.predict(X_test) print(f"模型的测试集的预测值:{y_pred}") ret = estimator.score(X_test,y_test) print(f"模型的评分:{ret}") print(X_test.toarray()) ``` 生成对应的图 ```python from sklearn.tree import export_graphviz import graphviz # 用于渲染图像 # 导出决策树的 Graphviz 表示 export_graphviz(estimator, out_file='./data/tree.dot', feature_names=transfer.get_feature_names_out()) # 特征名称 # 使用 graphviz 渲染 .dot 文件 with open('./data/tree.dot', 'r') as f: dot_graph = f.read() # 渲染决策树 graph = graphviz.Source(dot_graph) # 设置保存路径 output_path = './data/decision_tree' # 自定义保存路径 # 保存图像到指定路径,格式可以是 .png, .pdf, .jpg 等 # graph.render(output_path, format='png') # 保存为 .png 文件 # 显示图像 graph.view(output_path) # 打开图像,path为保存路径,不需要加后缀 ``` [Webgraphviz](http://webgraphviz.com/),这个网站可以将`tree.dot`文件的内容生成对应的可视化树 #### 回归决策树与线性回归的对比 ```python import numpy as np import matplotlib.pyplot as plt from sklearn.linear_model import LinearRegression from sklearn.tree import DecisionTreeRegressor from matplotlib import rcParams # 设置matplotlib使用的字体为SimHei(黑体) rcParams['font.sans-serif'] = ['SimHei'] # 也可以使用 'Microsoft YaHei' rcParams['axes.unicode_minus'] = False # 正常显示负号 x = np.array(list(range(1,11))).reshape(-1,1) y = ([5.56,5.70,5.91,6.40,6.80,7.05,8.90,8.70,9.00,9.05]) m1 = DecisionTreeRegressor(max_depth=1) m2 = DecisionTreeRegressor(max_depth=3) m3 = DecisionTreeRegressor() # 模型训练 m1.fit(x,y) m2.fit(x,y) m3.fit(x,y) # 模型预测 x_test = np.arange(0,10,0.01).reshape(-1,1) y_1 = m1.predict(x_test) y_2 = m2.predict(x_test) y_3 = m3.predict(x_test) # 结果展示 plt.figure(figsize=(10,6),dpi=100) plt.scatter(x,y ,label = "data") plt.plot(x_test,y_1,label = "max_depth=1") plt.plot(x_test,y_2,label = "max_depth=3") plt.plot(x_test,y_3,label = "linearregression") plt.xlabel("数据") plt.ylabel("预测值") plt.legend() plt.show() ```