目录
简介
定义:是一种树形结构,本质上是一颗由多个判断节点组成的树。
信息熵:信息熵可以看作是信息混乱程度或无序度的度量。一个系统越是混乱,信息熵就越高;反之,系统越有序,信息熵就越低。因此,信息熵也可以看作是系统有序化程度的一个度量。
计算公式:
H(X)=−i=1∑np(xi)log2(p(xi))
其中,p(xi) 表示随机变量X取值为xi的概率,log2表示以2为底的对数运算。
决策树的划分:
一、信息增益
- 定义:信息增益是指以某特征划分数据集前后的熵的差值。熵可以表示样本集合的不确定性,熵越大,样本的不确定性就越大。因此,可以使用划分前后集合熵的差值来衡量使用当前特征对于样本集合划分效果的好坏。
- 计算公式:信息增益 = 初始信息熵 - 条件熵。 初始信息熵表示划分前数据集的不确定性,条件熵表示在给定某个特征取值的情况下,数据集的不确定性。
二、信息增益率
- 定义:信息增益率是为了解决信息增益准则对可取值数目较多的属性有所偏好的问题而提出的。它使用信息增益和属性对应的“固有值”的比值来共同定义。
- 计算公式:增益率 = 信息增益 / 固有值。 其中,固有值表示属性分裂信息度量,与信息熵的计算类似,但反映的是属性取值的分布情况。
-
算法过程:
为什么使用C4.5要好:
-
处理缺失值:C4.5对缺失值有很强的处理能力。在决策树构建过程中,如果遇到具有缺失值的实例,C4.5能够采用一种策略来估计这些缺失值对分类决策的影响。
-
使用信息增益率:C4.5使用信息增益率作为选择划分属性的标准。通过选择信息增益率最高的属性作为划分属性,C4.5能够构建出更加简洁和有效的决策树。
-
剪枝技术:C4.5进行后剪枝(在树完全生长后进行剪枝)。避免过拟合。
三、基尼值
- 定义:基尼值是从数据集中随机抽取两个样本,其类别标记不一致的概率。基尼值越小,表示数据集纯度越高。
- 计算公式:基尼值 = 1 - ∑(每个类别的概率的平方)。
算法流程:
决策树划分依据的对比
划分依据 | 定义 | 计算公式 | 应用算法 |
---|---|---|---|
信息增益 | 划分数据集前后的熵的差值 | 信息增益 = 初始信息熵 - 条件熵 | ID3 |
信息增益率 | 信息增益与属性固有值的比值 | 增益率 = 信息增益 / 固有值 | C4.5 |
基尼值 | 随机抽取两个样本类别标记不一致的概率 | 基尼值 = 1 - ∑(每个类别的概率的平方) | CART |
cart剪枝
剪枝在决策树学习算法中是一个关键步骤,主要目的是减少模型的复杂度,防止过拟合。
常见的CART剪枝方法主要包括预剪枝和后剪枝两种策略。
一、预剪枝
预剪枝是在决策树完全生成之前,通过提前停止树的进一步生长来防止过拟合。具体方法包括:
- 设置最大深度:限制树的最大深度,当达到这个深度时停止分裂。
- 设置最小样本分裂:要求一个节点中的样本数必须大于某个阈值,才考虑进一步分裂。
- 设置最小增益:在分裂节点之前,要求分裂带来的信息增益(或基尼指数、均方误差等,取决于是分类树还是回归树)必须大于某个阈值。
- 设置节点的最小样本数:在分裂之前,要求节点中的样本数必须大于或等于设定的最小样本数。
预剪枝的优点是减少了计算量,因为它避免了对整个学习空间的深入探索。然而,它也可能导致模型过早停止生长,从而忽略了某些重要特征,导致模型具有较高的偏差。
二、后剪枝
后剪枝是在决策树完全生成之后,通过移除一些不必要的分支来简化模型。
后剪枝的优点是通常能保留更多的分枝,生成的决策树泛化能力较强,欠拟合风险较小。然而,后剪枝过程需要在完整决策树生成之后才进行,且需要自底向上地检查树中的所有非叶节点,因此训练时间开销较大。
特征工程-特征提取
一、定义
特征提取是一个特征空间上的映射,可以是线性和非线性的。将原始数据(如文本或图像)转换为可用于机器学习的数字特征。
特征提取API:sklearn.feature_extraction
二、方法分类
字典特征提取
在scikit-learn中,使用DictVectorizer
类可以实现字典特征提取。以下是该方法的基本步骤:
-
导入必要的库:
from sklearn.feature_extraction import DictVectorizer
-
准备字典类型的数据:
数据应该是一个列表,列表中的每个元素都是一个字典,字典的键对应于特征的名称,值对应于该特征的具体取值(可能是类别型或数值型)。 -
实例化
DictVectorizer
类:vec = DictVectorizer(sparse=True) # sparse参数控制输出是否为稀疏矩阵,默认为True
-
转换数据:
使用fit_transform
方法将字典类型的数据转换为数值型特征矩阵。该方法会先对数据进行拟合(fit),然后将数据转换为特征矩阵(transform)。X = vec.fit_transform(data)
-
获取特征名称:
使用get_feature_names_out
方法(在较新版本的scikit-learn中)或get_feature_names
方法(在旧版本中)获取转换后的特征名称(会报出警告)。feature_names = vec.get_feature_names_out()
代码示例:
from sklearn.feature_extraction import DictVectorizer def dict_demo(): """ 字典特征提取 :return: None """ # 1获取数据 data = [{'city': '北京', 'temperature': 100}, {'city': '上海 ', 'temperature': 60}, {'city': '深圳', 'temperature': 30}] # 2.字典特征提取 # 2.1实例化 transfer = DictVectorizer(sparse=True) # 2.2转换 new_data = transfer.fit_transform(data) print(new_data) #2.3获取具体属性名 names = transfer.get_feature_names() print("属性名字是:\n", names) if __name__ == '__main__': dict_demo()
文本特征提取
对文本数据进行特征值化。中文文本需要进行分词处理,而英文文本则通常以空格作为单词之间的分隔符。
对于英文文本,我们可以使用scikit-learn库中的CountVectorizer
导入必要的库:
from sklearn.feature_extraction.text import CountVectorizer | |
# 示例文本数据 | |
texts = [ | |
"This is the first document.", | |
"This document is the second document.", | |
"And this is the third one.", | |
"Is this the first document?", | |
] | |
# 初始化CountVectorizer | |
vectorizer = CountVectorizer() | |
# 拟合并转换数据 | |
X = vectorizer.fit_transform(texts) | |
# 查看词汇表 | |
print(vectorizer.get_feature_names_out()) | |
# 查看转换后的稀疏矩阵 | |
print(X.toarray()) |
fit_transform
方法首先学习了词汇表(即文档中出现的所有唯一词的集合),然后将文档转换为词频矩阵。
get_feature_names_out()
方法返回了词汇表中的词。
toarray()
方法则将稀疏矩阵转换为NumPy数组,以便于查看。
CountVectorizer
默认会去除英文文本中的标点符号,并将其转换为小写字母。
代码示例:
def english_count_deom( ): """ 文本特征提取-英文 :return: None """ #获取数据 data = ["life is short,i like python", "life is too long,ifdislike python"] #文本特征转换 # transfer = CountVectorizer(sparse=True)#注意:没有sparse这个参数 transfer = CountVectorizer() new_data = transfer.fit_transform(data) #查看特征名字 names = transfer.get_feature_names_out() print("特征名字是:\n",names) print(new_data.toarray()) print(new_data) if __name__ == '__main__': english_count_deom()
中文特征提取
需要进行分词处理。这里可以使用jieba
分词库。分词后,可以使用与英文文本相同的TfidfVectorizer
,但需要将analyzer
参数设置为'word'
(对于中文来说,默认是'char'
,即按字符分割),并可能需要自定义分词器。
代码示例:
import jieba
def cut_word(text):
"""
中文分词
:param text: 输入的文本
:return: 分词后并用空格分隔的字符串
"""
return " ".join(list(jieba.cut(text)))
def chinese_count_demo2():
"""
文本特征提取-中文
:return: None
"""
data = [
"一种还是一种今天很残酷,明天更残酷,后天很美好,但绝对大音部分是死在明天晚上,所以每个人不要放弃今天。",
"我们看到的从很远星系来的光是在几百万年之前发出的,这样当我们看到宇宙时,我们是在看它的过去。",
"如果只用一种方式了解某样事物,你就不会真正了解它。了解事物真正含义的秘密取决于如何将其与我们所了解的事物相联系"
]
# 2. 文本分词
texts = []
for temp in data:
texts.append(cut_word(temp))
print(texts)
# 3. 文本特征转换
# 3.1 实例化+转换
transfer = CountVectorizer()
new_data = transfer.fit_transform(texts)
# 3.2 查看特征名字
names = transfer.get_feature_names_out()
print("特征名字是:\n", names)
# 3.3 输出转换后的稀疏矩阵
print(new_data.toarray())
print(new_data)
Tf-idf文本特征提取
TF-IDF是一种统计方法,用以评估一个词语对于一个文件集或一个语料库中的其中一份文件的重要程度。
公式:
与中文一样,在实例化中使用TfidfVectorizer。
from sklearn.feature_extraction.text import TfidfVectorizer |
TfidfVectorizer
首先被实例化,然后调用fit_transform
方法将文本数据转换为TF-IDF特征矩阵。get_feature_names_out()
方法用于获取词汇表(即特征名),它对应于TF-IDF矩阵中的列。
决策树算法
参数
max_depth
:树的最大深度。增加这个值会使模型更复杂,也更容易过拟合。min_samples_split
:分裂内部节点所需的最小样本数。min_samples_leaf
:叶节点必须具有的最小样本数。criterion
- 说明:特征选择的标准,用于衡量分割点的质量。
- 取值:"gini"(默认值)或"entropy"。
- "gini":使用基尼不纯度作为分割标准。
- "entropy":使用信息增益作为分割标准。
random_state:随机数种子
案例:泰坦尼克号乘客生存预测
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 # 2.数据基本处理 # 2.1 确定特征值,目标值 # 2.2缺失值处理 # 2.3 数据集划分 # 3.特征工程(字典特征抽取) # 4.机器学习(决策树) # 5.模型评估 # 1.获取数据 titan = pd.read_csv("https://hbiostat.org/data/repo/titanic.txt") print(titan) # 2.数据基本处理 # 2.1 确定特征值,目标值 x = titan[["pclass","age","sex"]] y = titan["survived"] # 2.2缺失值处理 x['age'].fillna(value=titan["age"].mean(), inplace=True) #2.3数据集划分 x_train, x_test, y_train, y_test = train_test_split(x, y, random_state = 22, test_size = 0.2) # 3.特征工程(字典特征抽取) print(x_train.head()) transfer = DictVectorizer(separator=True) x_train = x_train.to_dict(orient="records") x_test = x_test.to_dict(orient="records") #4,机器学习(决策树) estimator = DecisionTreeClassifier() estimator.fit(x_train, y_train) # 5.模型评估 y_pre = estimator.predict(x_test) print(y_pre) ret = estimator.score(x_test,y_test) print(ret)
(会报错显示远程主机强迫关闭一个现有的连接)
决策树可视化
sklearn.tree.export_graphviz()
简单的理解,树木可视化。
export_graphviz(estimator, out_file="tree.dot", feature_names=['age', 'pclass=lst', 'pclass=2nd', 'pclass=3rd', '女性', '男性']) \\\\\\连接上面的案例 示例代码:
from sklearn.datasets import load_iris | |
from sklearn.tree import DecisionTreeClassifier, export_graphviz | |
import graphviz | |
# 加载鸢尾花数据集 | |
iris = load_iris() | |
X = iris.data | |
y = iris.target | |
# 创建决策树模型 | |
clf = DecisionTreeClassifier(random_state=0) | |
clf.fit(X, y) | |
# 使用export_graphviz导出决策树为DOT格式 | |
dot_data = export_graphviz(clf, out_file=None, | |
feature_names=iris.feature_names, | |
class_names=iris.target_names, | |
filled=True, rounded=True, | |
special_characters=True) | |
# 使用graphviz的Source类来渲染DOT数据 | |
graph = graphviz.Source(dot_data) | |
# 渲染并保存图形到文件 | |
graph.render("iris_tree", view=True) # view=True将在支持的环境中直接打开图形 | |
# 或者简单地打印DOT数据 | |
print(dot_data) |
回归决策树
原理:在构建回归决策树时,算法会递归地将数据集分割成更小的子集,直到满足某个停止条件(如达到最大深度、最小样本数等)。在每个分割点,算法会选择一个特征和一个阈值,以最小化分割后子集的预测误差。
算法描述:
1. 准备数据集
- 输入:准备包含输入特征和对应连续数值型输出值的数据集。(每个样本都有一组特征值)。
- 输出:回归树f(x)
2. 选择最佳特征和划分点
- 方法:遍历所有特征和可能的划分点,计算每个划分点下的误差,并选择使误差最小的特征和划分点。
3. 划分数据集
- 操作:根据选定的特征和划分点,将数据集划分为两个或多个子集。
- 结果:每个子集包含具有相似特征值的样本,并且这些样本的输出值在某个范围内相对接近。
4. 递归构建子树
- 过程:对每个子集重复步骤2和步骤3,即继续选择最佳特征和划分点,并划分数据集,直到满足停止条件(如达到最大深度、节点中样本数量小于阈值等)。
- 结果:构建出一棵完整的决策树,其中每个叶子节点对应一个预测值(通常是该叶子节点中所有样本输出值的平均值)。
5. 预测
- 输入:给定一个新的输入特征向量。
- 过程:通过沿着决策树的路径进行判断,最终到达一个叶子节点。
- 输出:将该叶子节点的预测值作为对新输入特征向量的预测结果。
回归决策树和线性回归对比
代码:
import numpy as np import matplotlib.pyplot as plt from sklearn.tree import DecisionTreeRegressor from sklearn import linear_model # 生成数据 x = np.array(list(range(1,11))).reshape(-1,1) y = np.array([5.56, 5.70, 5.91, 6.40, 6.80, 7.05, 8.90, 8.70, 9.00, 9.05]) # 训练模型 model1 = DecisionTreeRegressor(max_depth=1) model2 = DecisionTreeRegressor(max_depth=3) model3 = linear_model.LinearRegression() model1.fit(x,y) model2.fit(x,y) model3.fit(x,y) # 模型预测 X_test = np.arange(0.0, 10.0, 0.01).reshape(-1, 1)#生成1000个数,用于训练模型 print(X_test.shape) y_1 = model1.predict(X_test) y_2 = model2.predict(X_test) y_3 = model3.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='liner regression') plt.xlabel("数据") plt.ylabel("预测值") plt.title("决策树回归") plt.legend() plt.show()