绘制决策树尝试3
目录
代码解读AI
随机状态
种子
定义决策树回归模型 tree的decision regressor
fit
还可用来预测
export
效果图
我的X只有一个特征 为何这么多分支 ???
这是CART回归
CART回归
为什么说代码是CART回归?
不是所有的决策树都是CART
回归中mse的具体
步骤 1: 选择最优分割点
步骤 2: 比较分割点
步骤 3: 构建树节点
步骤 4: 递归构建树
从零开始的决策树
关于特征的选择顺序(:众生平等,每个特征的每个特征值作为分叉点时都是平等的比较)
实例1
想要的文字——feature name
实例2
书本复现成功
这会跟着书上来,代码差不多懂了
代码解读AI
from sklearn.datasets import make_regression
- 这行代码是从 scikit-learn 库的 datasets 模块中导入
make_regression
函数。make_regression
函数用于生成回归分析用的数据集。
from sklearn.model_selection import train_test_split
- 这行代码是从 scikit-learn 库的 model_selection 模块中导入
train_test_split
函数。train_test_split
函数用于将数据集分割成训练集和测试集。
from sklearn.tree import DecisionTreeRegressor
- 这行代码是从 scikit-learn 库的 tree 模块中导入
DecisionTreeRegressor
类。DecisionTreeRegressor
是一个用于回归任务的决策树模型。
MSE
from sklearn.metrics import mean_squared_error
- 这行代码是从 scikit-learn 库的 metrics 模块中导入
mean_squared_error
函数。mean_squared_error
函数用于计算预测值和实际值之间的均方误差。
import numpy as np
- 这行代码是导入 numpy 库,并将其命名为 np。Numpy 是一个用于数值计算的库,广泛用于处理数组。
# 生成数据集
X, y = make_regression(n_samples=100, n_features=1, noise=0.1, random_state=42)
- 这行代码使用
make_regression
函数生成一个回归数据集,其中包含 100 个样本,每个样本有 1 个特征,添加了 0.1 的噪声,并且设置随机状态为 42 以确保结果的可重复性。
随机状态
在机器学习和数据科学中,random_state
参数是一个用于控制随机性的种子值。当算法中涉及到随机性时,比如数据的随机打乱(洗牌)、随机分割、或者算法中的一些随机过程(比如随机森林中的树选择),设置 random_state
参数可以确保你的结果是可复现的。
以下是 random_state
参数的几个关键点:
-
可复现性:设置一个固定的
random_state
值可以确保每次运行代码时,随机过程的结果都是一样的。这对于调试代码、比较不同模型的表现以及与他人分享研究成果时非常有用。 -
随机性:如果不设置
random_state
,则每次运行代码时,随机过程都会产生不同的结果,因为它们会使用不同的随机种子。 -
数值:
random_state
可以是一个整数,也可以是None
。如果设置为整数,比如 42,那么每次使用该种子时,随机数生成器都会产生相同的随机数序列。如果设置为None
,则每次运行时都会使用不同的种子,导致结果可能不同。 -
不同上下文:在不同的库和函数中,
random_state
的行为可能略有不同。但基本概念是相同的,即控制随机数生成器的种子。
例如,在使用 train_test_split
函数时,设置 random_state
确保每次分割数据集时,训练集和测试集的内容都是一样的。这有助于确保实验结果的一致性,使得模型评估更加可靠。
种子
random_state
参数在功能上类似于种子(seed)。在许多编程环境和库中,设置随机数生成器的种子是为了确保随机过程的可复现性。以下是两者之间的相似之处:
-
控制随机性:
random_state
和种子(seed)都是用来初始化随机数生成器的,确保每次生成的随机数序列是相同的。 -
可复现性:使用固定的
random_state
或种子值,你可以确保在多次运行同一代码时,随机事件的结果是一致的。 -
数值输入:
random_state
和种子通常都是一个整数,这个整数作为随机数生成算法的起始点。 -
默认行为:如果不设置
random_state
或种子,那么每次运行代码时,都会使用不同的随机种子,导致随机结果不同。
不同之处在于,random_state
是某些库(如scikit-learn)中的参数名称,而“种子”通常是在更基础的随机数生成函数(如Python的random.seed()
或numpy.random.seed()
)中使用的术语。但它们的核心目的是相同的,即为了控制随机数生成过程的可复现性。
例如:
-
在使用
numpy
生成随机数时,你会使用numpy.random.seed()
:import numpy as np np.random.seed(42)
-
在使用 scikit-learn 的
train_test_split
函数时,你会使用random_state
参数:尺寸
from sklearn.model_selection import train_test_split X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
在这两个例子中,无论是设置 numpy
的种子还是设置 train_test_split
的 random_state
,目的都是为了确保随机操作的可复现性。
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
在上面的代码中,random_state=42
确保每次执行分割操作时,都会得到相同的 X_train
、X_test
、y_train
和 y_test
。
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
简而言之,random_state
是特定于某些库和函数的参数,用于控制那些函数的随机行为,而种子(seed)是一个更通用的概念,用于控制整个程序或脚本中的随机数生成。两者都是为了确保随机操作的复现性,但它们的应用范围和上下文有所不同。
- 这行代码使用
train_test_split
函数将数据集划分为训练集和测试集,其中测试集占总数据的 20%,并且设置随机状态为 42 以确保可重复性。random_state
和种子(seed)在概念上是相似的,但它们的使用场景和上下文有所不同。以下是它们之间的主要区别: -
上下文:
- 种子(Seed):通常指的是在较低级别的随机数生成函数中使用的参数,如 Python 的
random.seed()
或 NumPy 的numpy.random.seed()
。这些函数直接控制随机数生成器的状态。 - random_state:这个参数通常出现在机器学习库(如 scikit-learn)中的模型或函数中,用于确保模型训练过程中的随机性是可复现的。它通常用于初始化随机数生成器,但不是直接与底层随机数生成器交互。
- 种子(Seed):通常指的是在较低级别的随机数生成函数中使用的参数,如 Python 的
-
使用目的:
- 种子:用于确保整个程序或脚本中的随机数生成是可复现的。设置种子后,所有依赖于随机数生成的操作都会产生相同的序列。
- random_state:通常用于特定的函数或模型,确保该函数或模型的行为是可复现的,而不影响程序中其他部分的随机数生成。
-
范围:
- 种子:设置后,会影响所有后续的随机数生成操作,除非再次设置种子。
- random_state:只影响设置了该参数的特定函数或模型,不会影响程序中其他部分的随机数生成。
-
实现方式:
- 种子:在底层库中直接设置随机数生成器的状态。
- random_state:在机器学习库中,可能是一个参数,它在内部用来设置随机数生成器的种子,但是对用户来说是一个更高级别的抽象。
定义决策树回归模型 tree的decision regressor
# 创建决策树回归模型
tree_regressor = DecisionTreeRegressor(random_state=42)
- 这行代码创建了一个
DecisionTreeRegressor
对象,用于进行回归分析,并设置随机状态为 42。
fit
tree_regressor.fit(X_train, y_train)
- 这行代码使用训练集数据
X_train
和y_train
来训练决策树回归模型。
还可用来预测
# 预测
y_pred_tree = tree_regressor.predict(X_test)
- 这行代码使用训练好的决策树模型对测试集
X_test
进行预测,得到预测结果y_pred_tree
。
v
# 计算均方误差
mse_tree = mean_squared_error(y_test, y_pred_tree)
- 这行代码使用
mean_squared_error
函数计算测试集的实际值y_test
和预测值y_pred_tree
之间的均方误差。
python
复制
# 输出结果
X_train[:5], y_train[:5], mse_tree # 显示部分训练数据和决策树回归的均方误差
- 这行代码打印出训练集中的前 5 个样本及其标签,以及决策树回归模型的均方误差。这有助于了解模型训练的数据以及模型在测试集上的性能。
数据大小约为——
export
import pydotplus
这行代码导入了pydotplus
库,它是一个用于生成Graphviz图形的Python接口。Graphviz是一个开源的图形可视化软件,可以用来生成结构化的图形。
from IPython.display import Image
这行代码从IPython.display
模块导入了Image
类,用于在Jupyter Notebook中显示图像。
from six import StringIO
这行代码导入了StringIO
类,它来自six
库。StringIO
是一个在内存中读写字符串的类,这里用于存储Graphviz的DOT语言描述。
from sklearn import tree
这行代码导入了scikit-learn库中的tree
模块,它包含了决策树相关的类和函数。
tree_regressor = tree.DecisionTreeRegressor()
tree_regressor.fit(X_train, y_train)
这两行代码创建了一个决策树回归器对象,并使用训练数据X_train
和相应的目标值y_train
来训练这个模型。
dot_data = StringIO()
这行代码创建了一个StringIO
对象,用于存储决策树的Graphviz描述。
tree.export_graphviz(tree_regressor, out_file=dot_data,
filled=True, rounded=True)
这行代码调用了export_graphviz
函数,
它将决策树模型转换为Graphviz的DOT语言格式,并将其写入dot_data
对象。
filled=True
表示节点应该有颜色填充,
rounded=True
表示节点应该有圆角。
graph = pydotplus.graph_from_dot_data(dot_data.getvalue())
这行代码使用pydotplus
库将DOT语言描述转换为Graphviz图形对象。
Image(graph.create_png())
这行代码使用Image
类来显示Graphviz图形对象生成的PNG图像。在Jupyter Notebook中,这将直接显示决策树的图像。
需要注意的是,上述代码片段中的tree_regressor
变量似乎是在代码中定义的,但实际上并没有在您提供的代码中定义。正确的代码应该先创建一个决策树回归器实例,然后才能使用它来拟合数据和导出图形。例如:
tree_regressor = tree.DecisionTreeRegressor()
tree_regressor.fit(X_train, y_train)
效果图
我的X只有一个特征 为何这么多分支 ???
大概原因是:
判断是否分叉的依据是样本数多少,有那么多样本当然要分叉,而分那个叉?哪一个特征的那一个点,everywhere都会测试!没有说那个特征优先的说法
这是CART回归
这段代码使用了CART(分类与回归树)算法。具体来说,它是通过Scikit-Learn库中的DecisionTreeRegressor
类实现的。CART是一种流行的机器学习方法,用于构建决策树来进行分类和回归任务。在这个例子中,它被用作回归树,因为DecisionTreeRegressor
专门用于回归问题。
CART(Classification And Regression Trees)是一种决策树学习方法,它可以用于分类(Classification)问题,也可以用于回归(Regression)问题。以下是关于CART回归的详细解释:
CART回归
-
基本概念:
- 回归树:在CART回归中,决策树被用来预测一个连续的目标变量(即数值型输出)。
- 分割准则:CART使用"基尼不纯度"(Gini impurity)作为分类问题的分割准则,
而回归问题使用的是最小化平方误差(平方损失)。
-
工作原理:
- 在构建回归树时,CART算法会寻找能够将数据分割成两个子集的特征和阈值,使得这两个子集的均方误差(MSE, Mean Squared Error)最小。
- 对于每个节点,算法会计算分割后的子节点的平均响应值(通常是目标变量的平均值)。需要解读原理
- 树的每个叶节点都会被赋予一个预测值,通常是落在该叶节点中的所有样本的目标变量的平均值。
-
特点:
- 非参数方法:CART不需要对数据的分布做出假设,因此是一种非参数方法。
- 处理不同类型的数据:它可以处理数值型和类别型特征。
- 易于理解:生成的决策树结构直观,易于解释。
为什么说代码是CART回归?
如果在代码中看到了DecisionTreeRegressor
类的使用,那么可以判断这是在实现CART回归。以下是一个简单的例子:
from sklearn.tree import DecisionTreeRegressor
# 假设X是特征矩阵,y是目标变量
X = [[...], [...], ...] # 特征数据
y = [...] # 目标变量数据
# 创建一个CART回归模型
regressor = DecisionTreeRegressor()
# 训练模型
regressor.fit(X, y)
# 使用模型进行预测
predictions = regressor.predict(X)
在这个例子中,DecisionTreeRegressor
就是用来实现CART回归的类。当调用fit
方法时,算法会根据X和y训练一个回归树,这个过程就是CART回归的核心。预测时,模型会根据训练好的树结构来预测目标变量的值。
不是所有的决策树都是CART
不是所有的决策树都是CART(Classification And Regression Trees)。决策树是一种广泛使用的机器学习算法,可以根据不同的分割标准和构建方法分为多种类型。以下是一些常见的决策树类型:
-
ID3(Iterative Dichotomiser 3):
- ID3算法使用信息增益(Information Gain)作为分割标准。
- 主要用于分类问题。
- ID3算法倾向于选择具有大量值的属性。
-
C4.5:
- C4.5是ID3的改进版,使用增益率(Gain Ratio)作为分割标准,以减少偏向于选择具有大量值的属性的问题。
- 既可以用于分类问题也可以用于回归问题,但更常用于分类。
-
CART:
- 如前所述,CART既可以用于分类也可以用于回归。
- 分类树使用基尼不纯度(Gini Impurity)作为分割标准。
- 回归树使用最小化平方误差(平方损失)作为分割标准。
-
CHAID(Chi-squared Automatic Interaction Detection):
- CHAID使用卡方检验来确定最佳分割点。
- 通常用于市场研究,特别是预测消费者行为。
-
MARS(Multivariate Adaptive Regression Splines):
- MARS是一种回归方法,它使用分段线性回归模型来适应数据。
-
Conditional Inference Trees:
- 这种类型的决策树使用统计测试来确定分割标准,而不是信息论或基尼不纯度。
- 它可以更好地处理数据中的噪声和非平稳性。
每种决策树算法都有其独特的特点、优势和局限性。CART是其中一种流行的算法,但不是唯一的一种。在选择决策树算法时,需要根据具体的应用场景和数据特性来决定使用哪一种。
CART(Classification And Regression Trees)是一种决策树算法,它既可以用于分类问题也可以用于回归问题。
-
分类树(Classification Trees):当CART用于分类问题时,它通过基尼不纯度(Gini Impurity)来选择最优的分割点,从而将数据集分成不同的类别。
-
回归树(Regression Trees):当CART用于回归问题时,它通过最小化平方误差(即每个子节点的数据点与该节点平均值之差的平方和)来选择最优的分割点,目的是预测一个连续的目标变量。
CART算法的核心在于递归地分割数据集,直到满足某些停止条件,如节点的纯度达到一定程度、节点中的样本数量低于某个阈值或者树的深度达到预设的最大值等。在分类树中,最终的叶子节点代表一个分类,而在回归树中,叶子节点通常输出一个预测值,这个值通常是落在该叶子节点内所有训练样本目标值的平均值
回归中mse的具体
以下是一个简化的例子,详细解释了CART回归树如何通过最小化平方误差来选择最优分割点。
假设我们有以下一组数据,每个数据点包含一个特征X
和一个连续的目标变量Y
:
复制
X: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Y: [2, 3, 2, 5, 7, 8, 8, 9, 10, 12]
我们的目标是构建一个回归树来预测Y
的值。
步骤 1: 选择最优分割点
首先,我们需要找到最优的分割点。我们考虑将数据集分成两部分,并计算分割前后的平方误差。
假设我们考虑在X=5
处分割数据:
- 左子节点(X <= 5): [1, 2, 3, 4, 5]
- 右子节点(X > 5): [6, 7, 8, 9, 10]
对于左子节点,计算所有Y
值的平均值:
平均值 = (2 + 3 + 2 + 5 + 7) / 5 = 4
左子节点的平方误差:
复制
平方误差 = (2-4)^2 + (3-4)^2 + (2-4)^2 + (5-4)^2 + (7-4)^2 = 10
对于右子节点,计算所有Y
值的平均值:
【分割点左侧所有的Y平均值作为分割点左侧预测值】 【分割点右侧侧所有的Y平均值作为分割点右侧侧预测值】
平均值 = (8 + 8 + 9 + 10 + 12) / 5 = 9.4
右子节点的平方误差:
平方误差 = (8-9.4)^2 + (8-9.4)^2 + (9-9.4)^2 + (10-9.4)^2 + (12-9.4)^2 = 2.8
总平方误差(分割后):
总平方误差 = 左子节点平方误差 + 右子节点平方误差 = 10 + 2.8 = 12.8
我们重复这个过程,考虑不同的分割点(例如X=3
, X=6
等),并计算每个分割点的总平方误差。
步骤 2: 比较分割点
假设我们计算了所有可能的分割点,并得到了以下总平方误差:
- 分割点
X=3
: 总平方误差 = 15.6 - 分割点
X=5
: 总平方误差 = 12.8 - 分割点
X=7
: 总平方误差 = 14.0
在这些分割点中,X=5
给出了最小的总平方误差(12.8),因此我们选择X=5
作为最优分割点。
步骤 3: 构建树节点
现在我们使用X=5
来构建树的第一个节点,并将数据分为左右两个子节点。每个子节点将包含分割点一侧的数据点。
步骤 4: 递归构建树
接下来,我们递归地对每个子节点重复上述步骤,直到满足停止条件(例如,节点的样本数量小于某个阈值,或者平方误差不再显著减少)。
最终,我们得到了一个回归树,它可以用来预测新的数据点。例如,如果有一个新的数据点X=4
,它将被分配到X=5
左边的子节点,并且预测值将是该子节点所有Y
值的平均值,即4。
从零开始的决策树
关于特征的选择顺序(:众生平等,每个特征的每个特征值作为分叉点时都是平等的比较)
在分类与回归树(CART)算法中,特征选择的过程遵循以下步骤来构建决策树:
-
计算不纯度:
- 对于分类树,CART算法通常使用基尼不纯度(Gini Impurity)来评估数据集的纯度。
- 对于回归树,CART算法使用最小二乘回归(Least Squares Regression)来评估数据集的方差。
-
分割特征的选择:
- 对于每个特征,算法会尝试所有可能的分割点。分割点通常是特征值的中点。
- 对于分类问题,算法会计算每个特征在每个可能的分割点处的基尼不纯度,并找到能够最大程度减少基尼不纯度的分割点。
- 对于回归问题,算法会计算每个特征在每个可能的分割点处的平方误差,并找到能够最小化平方误差的分割点。
-
比较特征:
- 一旦找到了每个特征的最佳分割点,算法会比较这些分割点,选择能够最大程度减少不纯度(分类树)或最小化平方误差(回归树)的特征作为节点的分割特征。
-
递归过程:
- 使用选定的特征和分割点对数据进行分割,生成两个子节点。
- 对每个子节点重复上述过程,直到满足停止条件(例如,节点的样本数量小于预定的阈值,或者节点的纯度已经足够高)。
以下是CART算法在特征选择上的关键点:
- 贪婪算法: CART算法是一个贪婪算法,它在每一步选择当前最佳的特征和分割点,而不考虑后续步骤的可能影响。
- 特征重要性: 在CART中,特征的重要性可以通过它在树中的使用频率以及在分割点处减少的不纯度或平方误差的量来衡量。
- 处理高维数据: 当特征数量非常多时,CART算法的计算开销会很大,因为它需要评估每个特征的所有可能分割点。为了处理高维数据,可能需要使用特征选择技术来预先筛选出最重要的特征,或者使用随机森林等集成方法来提高效率。
总的来说,CART算法通过递归地选择在每个步骤上最佳的特征和分割点来构建决策树,直到达到预定的停止条件。
实例1
import pandas as pd
# 客户信息 DataFrame
customers_df = pd.DataFrame({
'CustomerID': [1, 2, 3, 4], 'CustomerID2': [8, 2, 3, 4],
# 'CustomerName': ['Alice', 'Bob', 'Charlie', 'David'],
'CustomerID3': [8, 2, 7, 4],
'Time':[10,20,10,40]
})
pd.DataFrame(customers_df.groupby(["Time"]).sum(["CustomerID"])).reset_index()
from sklearn.datasets import make_regression
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeRegressor
from sklearn.metrics import mean_squared_error
import numpy as np
# 生成数据集
# X, y = make_regression(n_samples=100, n_features=4, noise=0.1, random_state=42)
# # 划分训练集和测试集
# X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
X_train=customers_df
y_train=X_train.Time
# 创建决策树回归模型
tree_regressor = DecisionTreeRegressor(random_state=42,max_depth=2)
tree_regressor.fit(X_train, y_train)
# 预测
y_pred_tree = tree_regressor.predict(X_test)
# 计算均方误差
mse_tree = mean_squared_error(y_test, y_pred_tree)
# 输出结果
X_train[:5], y_train[:5], mse_tree # 显示部分训练数据和决策树回归的均方误差
import pydotplus
from IPython.display import Image
from six import StringIO
from sklearn import tree
tree_regressor=tree_regressor.fit(X_train, y_train)
dot_data=StringIO()
tree.export_graphviz(tree_regressor,feature_names=['f1','f2','f3','f4'] ,out_file=dot_data,
filled=True, rounded=True)
graph = pydotplus.graph_from_dot_data(dot_data.getvalue())
Image(graph.create_png())
想要的文字——feature name
实例2
from sklearn.datasets import make_regression
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeRegressor
from sklearn.metrics import mean_squared_error
import numpy as np
# 生成数据集
X, y = make_regression(n_samples=100, n_features=1, noise=0.1, random_state=42)
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# X_train=customers_df
# y_train=X_train.Time
# 创建决策树回归模型
tree_regressor = DecisionTreeRegressor(random_state=42,max_depth=4)
tree_regressor.fit(X_train, y_train)
# 预测
y_pred_tree = tree_regressor.predict(X_test)
# 计算均方误差
mse_tree = mean_squared_error(y_test, y_pred_tree)
# 输出结果
X_train[:5], y_train[:5], mse_tree # 显示部分训练数据和决策树回归的均方误差
import pydotplus
from IPython.display import Image
from six import StringIO
from sklearn import tree
tree_regressor=tree_regressor.fit(X_train, y_train)
dot_data=StringIO()
tree.export_graphviz(tree_regressor,
#feature_names=['f1','f2','f3','f4'] ,
out_file=dot_data,
filled=True, rounded=True)
graph = pydotplus.graph_from_dot_data(dot_data.getvalue())
Image(graph.create_png())