【机器学习】任务五:葡萄酒和鸢尾花数据集分类任务
LightGBM最佳参数: {'learning_rate': 0.01, 'n_estimators': 200, 'num_leaves': 31}XGBoost最佳参数: {'learning_rate': 0.01, 'max_depth': 3, 'n_estimators': 200}最佳参数: {'max_depth': None, 'min_samples_split': 2, '
目录
3.4 对 XGBoost 和LightGBM 模型进行参数优化
1.分类算法相关概念
1.1 集成学习
集成学习是一种通过组合多个基学习器来提高模型预测性能的技术。主要有两类方法:
- Bagging:通过对数据进行重采样,构建多个独立的模型,然后将这些模型的预测结果进行平均(回归)或投票(分类)。典型的算法包括随机森林。
- Boosting:通过串行训练多个模型,每个模型都在前一个模型的基础上进行改进。常用算法包括GBDT、XGBoost 和 LightGBM。
(1)随机森林
- 随机森林是 Bagging 的一种具体实现,通过随机选择样本和特征构建多个决策树,并通过投票(分类)或平均(回归)进行预测。随机森林减少了过拟合,增强了模型的稳定性和准确性。
(2)梯度提升决策树(GBDT)
- GBDT 是 Boosting 的一种,通过逐步构建树模型,每棵新树都是在前一棵树的基础上通过最小化残差来改进模型。GBDT 在处理非线性关系和特征交互时表现良好。
(3)XGBoost
- XGBoost 是 GBDT 的高效实现,具有更快的训练速度和更好的性能。通过正则化和并行计算加速模型训练,同时减少过拟合,XGBoost 还可以处理缺失值。
(4)LightGBM
- LightGBM 是微软开发的高效 GBDT 实现,使用基于直方图的决策树算法,显著提高了训练速度和内存效率,适用于大规模数据集和高维特征场景。
1.2 参数优化
为了提升模型性能,参数优化是关键步骤。常用的参数优化方法有:
(1)网格搜索
- 网格搜索是一种穷举法,通过在预定义的参数空间中列出所有可能的参数组合,逐一训练模型并评估其性能。虽然计算开销较大,但简单易懂,适用于小规模参数优化。
(2)随机搜索
- 随机搜索随机选择参数组合来进行训练,相比网格搜索能更高效地探索高维空间,常在较短时间内找到较优的参数。
(3)贝叶斯优化
- 贝叶斯优化通过构建目标函数的概率模型,逐步更新该模型来找到最优参数,适合计算成本较高的模型训练,能减少评估次数。
(4)遗传算法
- 遗传算法模拟自然选择的过程,通过选择、交叉和变异操作在参数空间内进行全局搜索,适合复杂的优化问题。
(5)超参数优化工具
- Optuna、Hyperopt 和 Ray Tune 等工具集成了多种优化算法,可以自动化参数搜索过程,并提供可视化和分析功能。
1.3 模型解释
理解模型的决策过程对于确保模型透明性和解释性至关重要。常用的解释方法包括:
(1)特征重要性分析
- 通过评估特征对模型预测结果的影响,分析哪些特征在模型决策中起到了关键作用。随机森林和 XGBoost 提供了基于树模型的特征重要性评估。
(2)SHAP
- SHAP 值基于合作博弈论,通过计算特征对预测结果的贡献来解释模型。它能够量化每个特征对单个预测的影响,也能通过全局解释分析模型行为。
(3)部分依赖图(PDP)
- PDP 用于可视化单个或多个特征对预测的影响,揭示特征与预测结果之间的关系。
(4)对抗性样本分析
- 通过生成对抗性样本并观察模型的预测变化,可以评估模型的脆弱性和决策边界。
(5)LIME
- LIME 是一种模型无关的解释方法,能通过生成局部线性模型来近似复杂模型的行为,提供单个预测的可解释性。
2.葡萄酒数据集分类任务
2.1 导入必要的库文件并加载数据集
(1)目标:
- 该代码的目标是使用随机森林分类器对酒数据集进行训练,并通过网格搜索调优超参数,最终评估模型性能。通过特征选择(使用
SelectFromModel
)来优化特征集,提升模型的准确性。
(2)代码:
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, confusion_matrix, classification_report
from sklearn.datasets import load_wine
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import GridSearchCV
from sklearn.feature_selection import SelectFromModel
from sklearn.metrics import f1_score
import numpy as np
(3)解释:
-
导入数据处理与可视化库:
matplotlib.pyplot
和seaborn
:用于数据可视化。pandas
:用于数据操作和分析。
-
导入机器学习相关模块:
train_test_split
:划分训练集和测试集。accuracy_score
、confusion_matrix
、classification_report
、f1_score
:评估分类模型性能。RandomForestClassifier
:随机森林分类器,用于分类任务。GridSearchCV
:网格搜索,优化模型超参数。SelectFromModel
:特征选择工具。load_wine
:加载内置的葡萄酒数据集。
-
导入
numpy
:- 提供数组和数学计算功能。
2.2 导入数据集,并分割为特征和标签
(1)目标:
- 该代码的目标是加载酒数据集(Wine dataset),并提取其中的特征(
X
)和标签(y
)。这些数据将用于后续的模型训练和分类任务。
(2)代码:
wine = load_wine()
X = wine.data
y = wine.target
(3)解释:
-
wine = load_wine()
:- 加载酒数据集,返回一个包含数据和目标标签的对象。
-
X = wine.data
:- 提取数据集中的特征部分(13个物理化学特征),赋值给
X
。这是训练模型时的输入。
- 提取数据集中的特征部分(13个物理化学特征),赋值给
-
y = wine.target
:- 提取数据集中的标签部分(葡萄酒类型),赋值给
y
。这是模型的输出目标。
- 提取数据集中的标签部分(葡萄酒类型),赋值给
2.3 将数据集分为训练集和测试集
(1)目标:
- 这段代码的目标是将酒数据集划分为训练集和测试集,并输出每个数据集的特征和标签的形状。
(2)代码:
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 输出训练集和测试集的形状
print("训练集特征形状:", X_train.shape)
print("测试集特征形状:", X_test.shape)
print("训练集标签形状:", y_train.shape)
print("测试集标签形状:", y_test.shape)
(3)解释:
-
train_test_split(X, y, test_size=0.2, random_state=42)
:- 作用:将数据集
X
和目标变量y
分割为训练集和测试集。 - 解释:
X
是输入特征,y
是目标标签。test_size=0.2
表示将数据的 20% 用作测试集,剩下 80% 用作训练集。random_state=42
设置随机种子,确保每次划分的数据集相同,以便复现结果。
- 作用:将数据集
-
X_train.shape
和X_test.shape
:- 作用:输出训练集和测试集的特征矩阵的形状。
- 解释:
X_train.shape
返回训练集中特征的维度,通常是(样本数, 特征数)
。X_test.shape
返回测试集中特征的维度。
-
y_train.shape
和y_test.shape
:- 作用:输出训练集和测试集的标签的形状。
- 解释:
y_train.shape
返回训练集标签的维度,通常是一维数组(样本数,)
。y_test.shape
返回测试集标签的维度。
(4)结果分析:
训练集特征形状: (142, 13)
测试集特征形状: (36, 13)
训练集标签形状: (142,)
测试集标签形状: (36,)
-
训练集特征形状: (142, 13):
- 训练集包含142个样本,每个样本有13个特征。特征数13与酒数据集中的13个物理化学特征一致。
-
测试集特征形状: (36, 13):
- 测试集包含36个样本,每个样本同样有13个特征。划分比例为80%(训练集)和20%(测试集),符合设定的
test_size=0.2
。
- 测试集包含36个样本,每个样本同样有13个特征。划分比例为80%(训练集)和20%(测试集),符合设定的
-
训练集标签形状: (142,):
- 训练集包含142个标签,每个标签对应一个样本的分类结果(酒的类型),标签数与训练集样本数一致。
-
测试集标签形状: (36,):
- 测试集包含36个标签,每个标签对应测试集样本的分类结果,标签数与测试集样本数一致。
2.4 定义随机森林分类器并进行参数优化
(1)目标:
- 这段代码的目标是使用网格搜索 (
GridSearchCV
) 来调优随机森林分类器 (RandomForestClassifier
) 的超参数,并打印出最优的超参数配置。
(2)代码:
# 定义XGBoost模型和参数网格
xgb_model_wine = xgb.XGBClassifier(random_state=42)
xgb_param_grid_wine = {
'n_estimators': [50, 100, 200],
'max_depth': [3, 5, 7],
'learning_rate': [0.01, 0.1, 0.3]
}
# 进行网格搜索和交叉验证
xgb_grid_search_wine = GridSearchCV(estimator=xgb_model_wine, param_grid=xgb_param_grid_wine, scoring='accuracy', cv=3)
xgb_grid_search_wine.fit(X_train_wine, y_train_wine)
# 打印最佳参数
print("XGBoost最佳参数(葡萄酒数据集):", xgb_grid_search_wine.best_params_)
(3)解释:
-
rf = RandomForestClassifier(random_state=42)
:- 作用:初始化一个随机森林分类器对象。
- 解释:
random_state=42
保证模型的随机性可复现,每次训练时使用相同的随机种子。
-
param_grid = {...}
:- 作用:定义一个字典,指定要在网格搜索中测试的超参数组合。
- 解释:
'n_estimators': [50, 100, 200]
:指定要测试的树的数量(即森林中决策树的数量)。'max_depth': [None, 10, 20]
:指定树的最大深度,None
表示没有限制。'min_samples_split': [2, 5]
:指定分裂内部节点所需的最小样本数。
-
grid_search = GridSearchCV(...)
:- 作用:初始化一个网格搜索对象,搜索最佳超参数组合。
- 解释:
estimator=rf
:指定使用的基础模型是RandomForestClassifier
。param_grid=param_grid
:传入要搜索的超参数组合。scoring='accuracy'
:使用准确率作为评估指标来评估每个超参数组合的表现。cv=3
:指定3折交叉验证,用于评估模型在不同超参数组合下的性能。
-
grid_search.fit(X_train, y_train)
:- 作用:进行网格搜索并拟合模型。
- 解释:
- 通过调用
.fit()
方法,GridSearchCV
会在训练集上遍历param_grid
中的每一个超参数组合,并使用交叉验证来评估每种组合的性能。
- 通过调用
-
print("最佳参数:", grid_search.best_params_)
:- 作用:输出网格搜索找到的最佳超参数配置。
- 解释:
.best_params_
返回在交叉验证中表现最佳的超参数组合。
(4)结果分析:
{'max_depth': None, 'min_samples_split': 2, 'n_estimators': 100}
-
max_depth: None
:- 含义:表示决策树的深度没有限制,树会一直生长,直到所有叶子节点都包含至少一个样本,或者进一步分裂无法改善节点的纯度。
- 影响:树深度不受限制可能导致过拟合,尤其是在数据集比较复杂或者样本较少时。
-
min_samples_split: 2
:- 含义:表示每个节点在进行分裂时,最小样本数为2。
- 影响:这个值较小意味着模型会更加细致地分裂节点,可能导致过拟合,因为即使某个节点只有很少的样本,也会被继续分裂。
-
n_estimators: 100
:- 含义:表示随机森林中决策树的数量为100棵。
- 影响:更多的树通常能提高模型的稳定性和准确性,减少单棵树可能带来的过拟合或欠拟合问题。100棵树是一个常用的默认值,通常能提供良好的平衡。
2.5 使用最佳参数训练模型
(1)目标:
- 使用网格搜索找到的最佳模型进行训练
(2)代码:
best_model = grid_search.best_estimator_
best_model.fit(X_train, y_train)
(3)解释:
-
best_model = grid_search.best_estimator_
:- 作用:从网格搜索对象中提取出性能最佳的模型。
- 解释:
grid_search.best_estimator_
返回在网格搜索中表现最佳的模型(即在指定的超参数组合下训练的模型)。- 该模型已经包含了最优的超参数配置。
-
best_model.fit(X_train, y_train)
:- 作用:使用训练数据拟合最佳模型。
- 解释:
- 调用
.fit()
方法在训练集X_train
和y_train
上训练最佳模型。 - 训练完成后,模型会根据训练数据更新其内部参数,准备好进行预测。
- 调用
(4)结果分析:
RandomForestClassifier
的初始化信息,其中参数为random_state=42
。这表明您初始化了一个随机森林分类器,并设置了随机种子为42,以确保模型训练过程中的随机性可重复。
2.6 打印出分类器的混淆矩阵
(1)目标:
- 使用最佳模型对测试集数据进行预测,生成混淆矩阵以评估模型分类的表现,并通过热力图直观展示分类结果。
(2)代码:
y_pred = best_model.predict(X_test)
conf_matrix = confusion_matrix(y_test, y_pred)
print("混淆矩阵:\n", conf_matrix)
# 绘制混淆矩阵热力图
sns.heatmap(conf_matrix, annot=True, fmt='d', cmap='Blues')
plt.title('Confusion Matrix')
plt.xlabel('Predicted label')
plt.ylabel('True label')
plt.show()
(3)解释:
-
y_pred = best_model.predict(X_test)
:- 使用
best_model
对测试集X_test
进行预测,生成预测标签y_pred
。
- 使用
-
conf_matrix = confusion_matrix(y_test, y_pred)
:- 计算混淆矩阵
conf_matrix
,用于比较真实标签y_test
和预测标签y_pred
。 - 混淆矩阵显示了分类的正确和错误情况:
- 行表示真实类别。
- 列表示预测类别。
- 计算混淆矩阵
-
sns.heatmap(conf_matrix, annot=True, fmt='d', cmap='Blues')
:- 使用 Seaborn 绘制混淆矩阵的热力图。
- 参数说明:
annot=True
:显示每个单元格中的数值。fmt='d'
:将单元格中的数值显示为整数。cmap='Blues'
:使用蓝色渐变作为配色。
-
plt.title('Confusion Matrix')
、plt.xlabel
和plt.ylabel
:- 设置热力图的标题和坐标轴标签,分别标注为:
- 标题:
Confusion Matrix
。 - 横轴(预测标签):
Predicted label
。 - 纵轴(真实标签):
True label
。
- 标题:
- 设置热力图的标题和坐标轴标签,分别标注为:
-
plt.show()
:- 显示绘制的混淆矩阵热力图。
(4)结果分析:
混淆矩阵:
[[14 0 0]
[ 0 14 0]
[ 0 0 8]]
-
结构解读:
- 行表示真实标签(True label)。
- 列表示预测标签(Predicted label)。
- 对角线上的数字表示正确分类的样本数。
- 非对角线上的数字表示错误分类的样本数。
-
具体分析:
- 类别 0:
- 真实类别为 0 的样本共有 14 个,全部被正确分类为 0。
- 错误分类数为 0,模型对类别 0 的预测完全正确。
- 类别 1:
- 真实类别为 1 的样本共有 14 个,全部被正确分类为 1。
- 错误分类数为 0,模型对类别 1 的预测也完全正确。
- 类别 2:
- 真实类别为 2 的样本共有 8 个,全部被正确分类为 2。
- 错误分类数为 0,模型对类别 2 的预测同样完全正确。
- 类别 0:
-
整体表现:
- 模型分类结果完全正确,没有任何错误分类。
- 对角线上的数字总和为
14 + 14 + 8 = 36
,这与测试集样本总数一致,说明模型的测试集准确率为 100%。
-
可视化的热力图:
- 热力图显示了混淆矩阵的分布,深蓝色对角线表明所有分类都正确,没有分类错误。
-
结论:
- 模型在测试集上的分类表现非常优异,准确率为 100%。
- 由于测试集样本量较少(36个),100% 准确率可能与数据集的分布和规模有关,需要进一步验证模型的泛化能力(例如在更大的数据集上)。
2.7 获取特征重要性并排序可视化
(1)目标:
- 该代码的目标是从随机森林分类器中提取特征重要性(
feature_importances_
),并以条形图形式可视化每个特征的重要性,从而更直观地了解哪些特征对模型的预测结果贡献最大。
(2)代码:
feature_importances = best_model.feature_importances_
feature_names = wine.feature_names
feature_importance_df = pd.DataFrame({'Feature': feature_names, 'Importance': feature_importances})
feature_importance_df = feature_importance_df.sort_values(by='Importance', ascending=False)
# 绘制特征重要性条形图
plt.figure(figsize=(10, 6))
sns.barplot(x='Importance', y='Feature', data=feature_importance_df)
plt.title('Feature Importance from Random Forest')
plt.show()
(3)解释:
-
best_model.feature_importances_
:- 从最佳模型中提取特征的重要性。
- 特征重要性值表示每个特征在模型中的相对重要性,数值越大,表示该特征对模型预测的贡献越大。
-
wine.feature_names
:- 提取酒数据集中的特征名称,用于标注每个特征的重要性。
-
创建数据框:
feature_importance_df = pd.DataFrame({'Feature': feature_names, 'Importance': feature_importances}) feature_importance_df = feature_importance_df.sort_values(by='Importance', ascending=False)
- 创建一个数据框
feature_importance_df
,包含两列:Feature
:特征名称。Importance
:对应的特征重要性值。
- 按照
Importance
列降序排序,以便最重要的特征排在前面。
- 创建一个数据框
-
绘制条形图:
plt.figure(figsize=(10, 6)) sns.barplot(x='Importance', y='Feature', data=feature_importance_df) plt.title('Feature Importance from Random Forest') plt.show()
- 使用 Seaborn 绘制条形图。
- 参数解释:
x='Importance'
:特征重要性值作为横轴。y='Feature'
:特征名称作为纵轴。data=feature_importance_df
:数据来源是排序后的feature_importance_df
。plt.title('Feature Importance from Random Forest')
设置图表标题。
plt.show()
:显示绘制的图表。
输出结果(预期):
- 条形图按特征重要性降序排列,最重要的特征位于顶部。
- 图表标题为 "Feature Importance from Random Forest",直观展示模型认为最重要的特征。
作用:
- 帮助了解模型的决策依据。
- 识别对预测结果贡献最大的特征,为特征选择或进一步优化提供参考。
(4)结果分析:
从图中可以看出:
-
最重要的特征:
flavanoids
是对模型预测贡献最大的特征,其重要性明显高于其他特征。color_intensity
和proline
也是非常重要的特征,排名第二和第三。
-
中等重要的特征:
alcohol
和od280/od315_of_diluted_wines
在重要性上紧随其后,对模型预测有较大的贡献。
-
较低重要性的特征:
ash
和nonflavanoid_phenols
的重要性最低,对模型预测的影响较小。
- 总结:
- 模型主要依赖于
flavanoids
和color_intensity
等特征来区分数据。 - 这些特征可能对葡萄酒分类有较高的相关性,而较低重要性的特征在未来可以考虑是否需要保留以简化模型。
- 模型主要依赖于
2.8 进行特征选择
(1)目标:
- 使用特征选择器(
SelectFromModel
)从训练好的随机森林模型中选择重要特征,以降低数据维度,提高模型的效率和泛化能力。
(2)代码:
selector = SelectFromModel(best_model, threshold='mean', prefit=True)
X_train_selected = selector.transform(X_train)
X_test_selected = selector.transform(X_test)
(3)解释:
-
selector = SelectFromModel(best_model, threshold='mean', prefit=True)
:- 作用:基于
best_model
提取重要特征。 - 参数解释:
best_model
:训练好的随机森林分类器,使用其特征重要性来筛选特征。threshold='mean'
:特征重要性的阈值设置为特征重要性的平均值,只有重要性大于平均值的特征会被选中。prefit=True
:表示模型已经预先拟合好,因此可以直接使用特征重要性来选择特征,而不需要重新训练。
- 作用:基于
-
X_train_selected = selector.transform(X_train)
:- 作用:对训练集
X_train
进行特征选择,保留重要特征。 - 结果:返回一个新的训练特征矩阵
X_train_selected
,仅包含被选中的重要特征。
- 作用:对训练集
-
X_test_selected = selector.transform(X_test)
:- 作用:对测试集
X_test
进行特征选择,保留重要特征。 - 结果:返回一个新的测试特征矩阵
X_test_selected
,仅包含被选中的重要特征。
- 作用:对测试集
2.9 使用选择后的特征训练模型并评估
(1)目标:
- 使用特征选择后的数据集重新训练随机森林模型,并评估其性能,包括准确率和加权 F1 得分。
(2)代码:
rf_selected = RandomForestClassifier(random_state=42)
rf_selected.fit(X_train_selected, y_train)
y_pred_selected = rf_selected.predict(X_test_selected)
accuracy_selected = accuracy_score(y_test, y_pred_selected)
f1_selected = f1_score(y_test, y_pred_selected, average='weighted')
print("选择后模型的准确率:", accuracy_selected)
print("选择后模型的F1得分:", f1_selected)
(3)解释:
-
rf_selected = RandomForestClassifier(random_state=42)
:- 作用:初始化一个新的随机森林分类器。
random_state=42
确保结果的可复现性。
-
rf_selected.fit(X_train_selected, y_train)
:- 作用:用特征选择后的训练集(
X_train_selected
和y_train
)训练新的随机森林模型。 - 说明:训练数据仅包含被特征选择器筛选出的重要特征。
- 作用:用特征选择后的训练集(
-
y_pred_selected = rf_selected.predict(X_test_selected)
:- 作用:使用训练好的模型对特征选择后的测试集(
X_test_selected
)进行预测。 - 结果:生成预测标签
y_pred_selected
。
- 作用:使用训练好的模型对特征选择后的测试集(
-
accuracy_score(y_test, y_pred_selected)
:- 作用:计算选择后模型的测试集准确率。
- 说明:准确率表示模型正确预测的样本比例。
-
f1_score(y_test, y_pred_selected, average='weighted')
:- 作用:计算选择后模型的加权 F1 得分。
- 说明:
- F1 得分是精确度和召回率的调和平均值。
average='weighted'
计算每个类别的 F1 得分,并根据类别样本数加权平均。
(4)结果分析:
选择后模型的准确率: 0.9722222222222222
选择后模型的F1得分: 0.9717752234993614
分析结果:
-
选择后模型的准确率:0.9722
- 模型在测试集上的准确率达到了 97.22%,表明经过特征选择后,模型仍然能够非常准确地分类测试数据。
- 与未选择特征的模型(可能是 100% 准确率)相比,这个结果非常接近,说明特征选择并没有明显降低模型的性能。
-
选择后模型的 F1 得分:0.9718
- 加权 F1 得分接近于准确率,说明模型在各个类别上的表现比较均衡,没有某些类别的预测结果特别差。
- 这一结果表明特征选择后的模型在处理类别不平衡的情况下依然表现良好。
结论:
-
特征选择的成功:
- 特征选择后,模型的性能(准确率和 F1 得分)与原始模型非常接近,但使用了更少的特征,简化了模型,提高了效率。
- 这说明通过选择重要特征,去除了对分类无关或影响较小的特征,模型仍然能够很好地拟合数据。
-
下一步建议:
- 如果目标是进一步提高效率,可以尝试使用更严格的特征选择阈值,进一步减少特征数量。
- 若追求更高的准确率,可结合交叉验证或更复杂的调参策略来优化模型性能。
2.10 绘制性能对比图
(1)目标:
- 比较原始特征和经过特征选择后的模型性能(准确率和 F1 得分),通过条形图直观展示两者的性能差异。
(2)代码:
performance_metrics = ['Accuracy', 'F1 Score']
original_performance = [accuracy_score(y_test, y_pred), f1_score(y_test, y_pred, average='weighted')]
selected_performance = [accuracy_selected, f1_selected]
fig, ax = plt.subplots(figsize=(10, 6))
bar_width = 0.35
index = np.arange(len(performance_metrics))
bar1 = ax.bar(index, original_performance, bar_width, label='Original Features')
bar2 = ax.bar(index + bar_width, selected_performance, bar_width, label='Selected Features')
ax.set_xlabel('Performance Metrics')
ax.set_title('Classifier Performance Comparison Before and After Feature Selection')
ax.set_xticks(index + bar_width / 2)
ax.set_xticklabels(performance_metrics)
ax.legend()
for bar in bar1 + bar2:
height = bar.get_height()
ax.annotate('%.2f' % height, xy=(bar.get_x() + bar.get_width() / 2, height),
xytext=(0, 3), textcoords="offset points", ha='center', va='bottom')
plt.show()
(3)解释:
-
定义性能指标和数据:
performance_metrics = ['Accuracy', 'F1 Score'] original_performance = [accuracy_score(y_test, y_pred), f1_score(y_test, y_pred, average='weighted')] selected_performance = [accuracy_selected, f1_selected]
performance_metrics
:表示性能指标,包括准确率(Accuracy)和 F1 得分。original_performance
:原始模型在测试集上的性能,包括准确率和 F1 得分。selected_performance
:特征选择后模型在测试集上的性能,包括准确率和 F1 得分。
-
绘制条形图:
fig, ax = plt.subplots(figsize=(10, 6)) bar_width = 0.35 index = np.arange(len(performance_metrics))
bar_width=0.35
:每个条形图的宽度。index
:为每个性能指标创建索引,便于对齐条形图。
-
绘制两组条形图:
bar1 = ax.bar(index, original_performance, bar_width, label='Original Features') bar2 = ax.bar(index + bar_width, selected_performance, bar_width, label='Selected Features')
bar1
:表示原始特征模型的性能。bar2
:表示特征选择后模型的性能。
-
设置图表属性:
ax.set_xlabel('Performance Metrics') ax.set_title('Classifier Performance Comparison Before and After Feature Selection') ax.set_xticks(index + bar_width / 2) ax.set_xticklabels(performance_metrics) ax.legend()
- 设置图表标题、横轴标签和性能指标作为横轴刻度。
- 使用
legend()
添加图例,区分两组条形图。
-
为每个条形图添加数值标注:
for bar in bar1 + bar2: height = bar.get_height() ax.annotate('%.2f' % height, xy=(bar.get_x() + bar.get_width() / 2, height), xytext=(0, 3), textcoords="offset points", ha='center', va='bottom')
- 遍历
bar1
和bar2
中的条形图,为每个条形添加数值标注(保留两位小数)。 xytext=(0, 3)
:设置数值标注与条形图顶部的距离。
- 遍历
-
显示图表:
plt.show()
- 显示性能比较的条形图。
(4)结果分析:
分析结果:
-
准确率比较:
- 原始特征的准确率为 1.00(100%)。
- 特征选择后的准确率为 0.97(97%)。
- 分析:特征选择后,准确率略有下降,但下降幅度较小(3%),表明模型在去除部分不重要特征后仍能保持较高的准确率。
-
F1 得分比较:
- 原始特征的 F1 得分为 1.00(100%)。
- 特征选择后的 F1 得分为 0.97(97%)。
- 分析:F1 得分也略有下降,与准确率一致,说明特征选择后模型在各类别上的分类表现依然均衡且较好。
-
条形图分析:
- 蓝色条形:代表原始特征模型的性能。
- 橙色条形:代表特征选择后模型的性能。
- 条形高度的差异很小,说明特征选择的效果较好,用更少的特征实现了接近原始模型的性能。
结论:
- 特征选择的效果:特征选择后,模型性能仅略微下降,说明选择的重要特征对分类任务有足够的代表性。
- 推荐应用:在实际应用中,可以使用特征选择后的模型,因为它简化了特征空间,可能减少计算资源的占用,同时仍能提供高水平的分类性能。
- 下一步优化:可以尝试调整特征选择的阈值或探索更高效的模型结构,进一步提升性能。
3.鸢尾花数据集分类任务报告
3.1 导入必要的库文件并加载数据集
(1)目标:
- 导入必要的库文件(如
pandas
、numpy
、matplotlib
、seaborn
、sklearn
、xgboost
和lightgbm
等)。 - 加载
scikit-learn
提供的鸢尾花数据集。
(2)代码:
# 导入必要的库
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.metrics import accuracy_score, f1_score
import xgboost as xgb
import lightgbm as lgb
# 加载鸢尾花数据集
iris = load_iris()
# 提取特征矩阵(X)和目标变量(y)
X_iris, y_iris = iris.data, iris.target
(3)解释:
- 导入库文件:导入数据处理、可视化、机器学习和模型评估所需的库。
pandas
用于数据处理,numpy
用于数值计算,matplotlib
和seaborn
用于绘图。xgboost
和lightgbm
是两种常用的集成学习方法,用于分类任务。
- 加载鸢尾花数据集:使用
scikit-learn
提供的load_iris()
函数加载鸢尾花数据集。该数据集包含 150 个样本,4 个特征,以及 3 种不同的鸢尾花类别。 - 提取特征矩阵和目标变量:
X_iris
保存特征数据,y_iris
保存目标类别标签。
3.2 对数据进行初步探索和可视化
(1)目标:
- 查看数据集的基本信息和统计摘要,确保数据集没有缺失值或异常。
- 使用
seaborn
进行数据可视化,了解特征与目标标签之间的关系。
(2)代码:
# 将数据转为DataFrame
df_iris = pd.DataFrame(X_iris, columns=iris.feature_names)
df_iris['target'] = y_iris
# 查看数据集信息
print(df_iris.info())
print(df_iris.describe())
# 可视化鸢尾花数据集特征与目标的关系
sns.pairplot(df_iris, hue="target", markers=["o", "s", "D"])
plt.show()
(3)解释:
- 转换为 DataFrame:将
numpy
数组转换为pandas
数据框,以便更方便地查看和处理数据。 - 数据集探索:使用
info()
和describe()
查看数据的基本信息,包括数据类型、缺失值和统计摘要。info()
显示数据集的结构信息,确保没有缺失值。describe()
提供特征的统计描述,如均值、标准差、最大值和最小值等。
- 数据可视化:使用
seaborn
的pairplot()
绘制多变量散点图,观察特征与目标变量(鸢尾花种类)之间的关系。hue="target"
使用不同颜色区分不同类别的鸢尾花。
(4)结果分析:
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 150 entries, 0 to 149
Data columns (total 5 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 sepal length (cm) 150 non-null float64
1 sepal width (cm) 150 non-null float64
2 petal length (cm) 150 non-null float64
3 petal width (cm) 150 non-null float64
4 target 150 non-null int32
dtypes: float64(4), int32(1)
memory usage: 5.4 KB
None
sepal length (cm) sepal width (cm) petal length (cm) \
count 150.000000 150.000000 150.000000
mean 5.843333 3.057333 3.758000
std 0.828066 0.435866 1.765298
min 4.300000 2.000000 1.000000
25% 5.100000 2.800000 1.600000
50% 5.800000 3.000000 4.350000
75% 6.400000 3.300000 5.100000
max 7.900000 4.400000 6.900000petal width (cm) target
count 150.000000 150.000000
mean 1.199333 1.000000
std 0.762238 0.819232
min 0.100000 0.000000
25% 0.300000 0.000000
50% 1.300000 1.000000
75% 1.800000 2.000000
max 2.500000 2.000000
数据分析:
1. 数据概况:
-
数据集包含 150 条记录,共有 5 个列:
- 4 个特征列:
sepal length (cm)
、sepal width (cm)
、petal length (cm)
、petal width (cm)
。 - 1 个目标列:
target
,表示分类标签(0、1、2,对应三个类别的花种)。
- 4 个特征列:
-
数据类型:
- 特征列:
float64
(浮点数)。 - 目标列:
int32
(整数,表示分类)。
- 特征列:
-
数据完整性:
- 所有列均无缺失值(
Non-Null Count
为 150)。
- 所有列均无缺失值(
-
内存使用:5.4 KB。
2. 数据描述性统计:
-
sepal length (cm)
:- 平均值:5.84 cm,范围:4.3 cm 至 7.9 cm。
- 分布较宽,标准差为 0.83。
-
sepal width (cm)
:- 平均值:3.06 cm,范围:2.0 cm 至 4.4 cm。
- 分布较窄,标准差为 0.43。
-
petal length (cm)
:- 平均值:3.76 cm,范围:1.0 cm 至 6.9 cm。
- 分布跨度较大,标准差为 1.77。
-
petal width (cm)
:- 平均值:1.20 cm,范围:0.1 cm 至 2.5 cm。
- 分布跨度较大,标准差为 0.76。
-
target
:- 三个类别(0, 1, 2)分布均衡,中位数为 1.0。
3. 可视化分析(图示分析):
- 图表类型:
- 图示是一个 pairplot(成对关系图),展示了特征之间的两两关系和类别的分布。
- 图表观察:
- 不同类别的花在特定特征上有明显的分布差异:
petal length
和petal width
:- 类别 0 和其他类别之间有明显的分离(类别 0 的花瓣明显较短和较窄)。
sepal length
和sepal width
:- 类别之间分布有一定重叠,但仍然存在一定的区分。
- 单变量分布:
- 类别 0 的分布相对集中,而类别 1 和类别 2 的分布较分散。
- 不同类别的花在特定特征上有明显的分布差异:
结论:
- 数据质量良好,无缺失值,特征列和目标列的数据类型符合预期。
- 特征
petal length
和petal width
对类别区分度较高,可作为重要特征。 - 数据分布显示类别之间存在明显差异,适合使用分类模型进一步分析。
3.3 将数据集分为训练集和测试集
(1)目标:
- 将鸢尾花数据集划分为训练集和测试集,以便训练模型并验证其性能。
- 采用 80:20 的比例划分,80% 的数据用于训练,20% 用于测试。
(2)代码:
# 将鸢尾花数据集划分为训练集和测试集
X_train_iris, X_test_iris, y_train_iris, y_test_iris = train_test_split(X_iris, y_iris, test_size=0.2, random_state=42)
(3)解释:
train_test_split()
:用于将数据集划分为训练集和测试集。这里使用 80% 的数据用于模型训练,20% 的数据用于测试模型。random_state=42
:确保数据集划分的随机性保持一致,便于结果复现。X_train_iris
,y_train_iris
分别表示鸢尾花训练集的特征和标签,X_test_iris
,y_test_iris
为测试集。
3.4 对 XGBoost 和LightGBM
模型进行参数优化
(1)目标:
- 对 XGBoost 和 LightGBM 分类器分别进行参数优化,使用网格搜索(
GridSearchCV
)寻找每种模型的最佳超参数组合。
(2)代码:
# 1. XGBoost参数优化
xgb_model = xgb.XGBClassifier(random_state=42)
xgb_param_grid = {
'n_estimators': [50, 100, 200],
'max_depth': [3, 5, 7],
'learning_rate': [0.01, 0.1, 0.3]
}
xgb_grid_search = GridSearchCV(estimator=xgb_model, param_grid=xgb_param_grid, scoring='accuracy', cv=3)
xgb_grid_search.fit(X_train, y_train)
xgb_best_model = xgb_grid_search.best_estimator_
print(f"XGBoost最佳参数: {xgb_grid_search.best_params_}")
# 2. LightGBM参数优化
# 使用 verbosity=-1 来消除警告
lgb_model = lgb.LGBMClassifier(random_state=42, verbosity=-1)
# LightGBM参数优化
lgb_param_grid = {
'n_estimators': [50, 100, 200],
'num_leaves': [31, 50, 100],
'learning_rate': [0.01, 0.1, 0.3]
}
lgb_grid_search = GridSearchCV(estimator=lgb_model, param_grid=lgb_param_grid, scoring='accuracy', cv=3)
lgb_grid_search.fit(X_train, y_train)
lgb_best_model = lgb_grid_search.best_estimator_
print(f"LightGBM最佳参数: {lgb_grid_search.best_params_}")
(3)解释:
1. XGBoost 参数优化:
-
初始化模型:
xgb_model
是一个 XGBoost 分类器。random_state=42
确保结果可复现。
-
定义参数网格:
n_estimators
:树的数量(50, 100, 200)。max_depth
:树的最大深度(3, 5, 7)。learning_rate
:学习率(0.01, 0.1, 0.3)。
-
网格搜索:
- 使用
GridSearchCV
对参数组合进行 3 折交叉验证(cv=3
)。 scoring='accuracy'
使用准确率作为评估指标。fit(X_train, y_train)
:在训练集上进行网格搜索并训练模型。
- 使用
-
获取最佳模型和参数:
xgb_best_model
:使用最佳参数的 XGBoost 模型。xgb_grid_search.best_params_
:输出最佳参数组合。
2. LightGBM 参数优化:
-
初始化模型:
lgb_model
是一个 LightGBM 分类器。verbosity=-1
:消除训练过程中不必要的警告信息。
-
定义参数网格:
n_estimators
:树的数量(50, 100, 200)。num_leaves
:每棵树的叶子节点数(31, 50, 100)。learning_rate
:学习率(0.01, 0.1, 0.3)。
-
网格搜索:
- 与 XGBoost 类似,使用
GridSearchCV
对参数组合进行 3 折交叉验证,目标是找到最佳的参数组合。
- 与 XGBoost 类似,使用
-
获取最佳模型和参数:
lgb_best_model
:使用最佳参数的 LightGBM 模型。lgb_grid_search.best_params_
:输出最佳参数组合。
(4)结果分析:
XGBoost最佳参数: {'learning_rate': 0.01, 'max_depth': 3, 'n_estimators': 200}
LightGBM最佳参数: {'learning_rate': 0.01, 'n_estimators': 200, 'num_leaves': 31}
1. XGBoost最佳参数:
-
learning_rate: 0.01
:- 表示学习率较低,模型训练更稳定,但可能需要更多的迭代次数来收敛。
- 通常适用于更复杂的数据集,能够更细致地学习数据分布。
-
max_depth: 3
:- 每棵决策树的最大深度为 3,限制了模型的复杂度,减少过拟合风险。
- 较小的深度适用于数据量小或较简单的数据集。
-
n_estimators: 200
:- 表示使用 200 棵树,增加了模型的容量,适合搭配较低的学习率(
learning_rate=0.01
)。
- 表示使用 200 棵树,增加了模型的容量,适合搭配较低的学习率(
2. LightGBM最佳参数:
-
learning_rate: 0.01
:- 与 XGBoost 相同,学习率低,模型更稳健。
-
n_estimators: 200
:- 使用 200 次迭代,与 XGBoost 一致,适合较低的学习率。
-
num_leaves: 31
:- LightGBM 的一个关键参数,表示每棵树的叶子节点数。
- 31 是默认值,适中且适合深度较浅的树(如 max_depth 为 3 时)。
比较 XGBoost 和 LightGBM 的最佳参数:
-
共同点:
- 两者都使用较低的学习率(
learning_rate=0.01
)和较多的迭代次数(n_estimators=200
),表明数据可能需要细致的学习过程。
- 两者都使用较低的学习率(
-
差异点:
- XGBoost 使用了显式的
max_depth=3
限制树的深度。 - LightGBM 使用了
num_leaves=31
来限制树的结构,而不是直接限制深度。
- XGBoost 使用了显式的
建议:
-
使用场景:
- XGBoost 通常在小数据集或对模型精度要求较高时表现更好。
- LightGBM 在大规模数据集上效率更高,训练速度更快。
-
下一步优化:
- 可以进一步调整
learning_rate
和n_estimators
,测试更高的树数和不同的学习率组合。 - 结合交叉验证(cross-validation)评估模型在验证集上
- 可以进一步调整
3.5 使用测试集进行预测并评估模型性能
(1)目标:
- 对 XGBoost 和 LightGBM 分类器进行预测,并评估其性能。
- 将预测结果保存为 CSV 文件,以便进一步分析。
(2)代码:
xgb_y_pred = xgb_best_model.predict(X_test)
lgb_y_pred = lgb_best_model.predict(X_test)
# 保存结果到CSV文件
pd.DataFrame({'XGBoost预测结果': xgb_y_pred, 'LightGBM预测结果': lgb_y_pred}).to_csv('classification_results.csv', index=False)
# 对XGBoost分类器的性能评估
xgb_accuracy = accuracy_score(y_test, xgb_y_pred)
xgb_f1 = f1_score(y_test, xgb_y_pred, average='weighted')
print(f"XGBoost分类器 - 准确率: {xgb_accuracy}, F1得分: {xgb_f1}")
# 对LightGBM分类器的性能评估
lgb_accuracy = accuracy_score(y_test, lgb_y_pred)
lgb_f1 = f1_score(y_test, lgb_y_pred, average='weighted')
print(f"LightGBM分类器 - 准确率: {lgb_accuracy}, F1得分: {lgb_f1}")
(3)解释:
-
预测结果生成:
xgb_y_pred = xgb_best_model.predict(X_test) lgb_y_pred = lgb_best_model.predict(X_test)
- 作用:
- 使用训练好的 XGBoost 和 LightGBM 模型分别对测试集
X_test
进行预测。 - 生成预测标签
xgb_y_pred
和lgb_y_pred
。
- 使用训练好的 XGBoost 和 LightGBM 模型分别对测试集
- 作用:
-
保存结果到 CSV 文件:
pd.DataFrame({'XGBoost预测结果': xgb_y_pred, 'LightGBM预测结果': lgb_y_pred}).to_csv('classification_results.csv', index=False)
- 作用:
- 将两种模型的预测结果整理为一个 DataFrame。
- 保存为
classification_results.csv
文件,便于进一步查看或共享结果。
- 作用:
-
性能评估(XGBoost 分类器):
xgb_accuracy = accuracy_score(y_test, xgb_y_pred) xgb_f1 = f1_score(y_test, xgb_y_pred, average='weighted') print(f"XGBoost分类器 - 准确率: {xgb_accuracy}, F1得分: {xgb_f1}")
accuracy_score(y_test, xgb_y_pred)
:- 计算 XGBoost 分类器在测试集上的准确率。
f1_score(y_test, xgb_y_pred, average='weighted')
:- 计算加权 F1 得分,考虑各类别样本数的权重,综合评估模型的分类性能。
-
性能评估(LightGBM 分类器):
lgb_accuracy = accuracy_score(y_test, lgb_y_pred) lgb_f1 = f1_score(y_test, lgb_y_pred, average='weighted') print(f"LightGBM分类器 - 准确率: {lgb_accuracy}, F1得分: {lgb_f1}")
- 与 XGBoost 类似,对 LightGBM 分类器的预测结果进行准确率和 F1 得分评估。
(4)结果分析:
XGBoost分类器 - 准确率: 1.0, F1得分: 1.0
LightGBM分类器 - 准确率: 1.0, F1得分: 1.0
分析结果:
1. 模型表现:
-
XGBoost分类器:
- 准确率:1.0,F1得分:1.0。
- 说明 XGBoost 模型在测试集上对所有样本分类均正确,无任何误差。
-
LightGBM分类器:
- 准确率:1.0,F1得分:1.0。
- 同样说明 LightGBM 模型在测试集上的分类结果完全正确。
2. 结果解读:
- 分类器性能一致:
- 两种模型在测试集上表现均为完美分类,表明数据特征较容易区分或两种模型参数优化到位。
- 原因可能包括:
- 数据集分布良好:
- 数据特征对目标分类标签区分度高,例如特征之间可能存在线性或非线性分割边界。
- 模型调优得当:
- 使用了最佳参数(低学习率、适中的树深度和树数量),使模型能够充分学习而不过拟合。
- 测试集样本规模较小:
- 如果测试集样本较小且分布与训练集相似,模型可能会表现出极高的准确性。
- 数据集分布良好:
3. 下一步建议:
-
验证模型泛化能力:
- 通过交叉验证(Cross-Validation)进一步验证模型在更大范围数据上的性能,避免仅因测试集小而导致的“完美”结果。
-
测试更多数据集:
- 如果可能,尝试在完全不同的验证集上测试模型,观察其表现是否依然保持一致。
-
模型效率对比:
- 当两种模型性能相同时,可比较训练时间和预测速度,以确定更适合实际场景的模型:
- XGBoost 通常更耗时但精度较高。
- LightGBM 更快,适合大规模数据。
- 当两种模型性能相同时,可比较训练时间和预测速度,以确定更适合实际场景的模型:
总结:
- 两种模型在当前测试集上的表现完全一致,均达到完美分类。
- 可以考虑进一步验证模型的泛化能力,并根据实际需求选择更高效的模型(如 LightGBM)。
3.6 可视化模型性能
(1)目标:
- 比较 XGBoost 和 LightGBM 两种分类器的性能(准确率和 F1 得分),并通过柱状图直观展示性能差异。
(2)代码:
performance_metrics = ['Accuracy', 'F1 Score']
xgb_performance = [xgb_accuracy, xgb_f1]
lgb_performance = [lgb_accuracy, lgb_f1]
fig, ax = plt.subplots(figsize=(10, 6))
bar_width = 0.35
index = np.arange(len(performance_metrics))
bar1 = ax.bar(index, xgb_performance, bar_width, label='XGBoost')
bar2 = ax.bar(index + bar_width, lgb_performance, bar_width, label='LightGBM')
ax.set_xlabel('性能指标', fontproperties=my_font)
ax.set_title('XGBoost vs LightGBM 性能比较', fontproperties=my_font)
ax.set_xticks(index + bar_width / 2)
ax.set_xticklabels(performance_metrics, fontproperties=my_font)
ax.legend()
# 在柱状图上标注数值
for bar in bar1 + bar2:
height = bar.get_height()
ax.annotate('%.2f' % height, xy=(bar.get_x() + bar.get_width() / 2, height),
xytext=(0, 3), textcoords="offset points", ha='center', va='bottom')
plt.show()
(3)解释:
-
性能数据:
performance_metrics = ['Accuracy', 'F1 Score'] xgb_performance = [xgb_accuracy, xgb_f1] lgb_performance = [lgb_accuracy, lgb_f1]
- 定义性能指标和每个模型的性能数据:
performance_metrics
:包括Accuracy
和F1 Score
两个指标。xgb_performance
:存储 XGBoost 分类器的准确率和 F1 得分。lgb_performance
:存储 LightGBM 分类器的准确率和 F1 得分。
- 定义性能指标和每个模型的性能数据:
-
绘制柱状图:
fig, ax = plt.subplots(figsize=(10, 6)) bar_width = 0.35 index = np.arange(len(performance_metrics)) bar1 = ax.bar(index, xgb_performance, bar_width, label='XGBoost') bar2 = ax.bar(index + bar_width, lgb_performance, bar_width, label='LightGBM')
- 柱宽(
bar_width=0.35
):设置每个柱的宽度。 - 索引(
index
):根据性能指标生成柱的位置。 ax.bar()
:- 第一个柱状图(
bar1
)表示 XGBoost 的性能。 - 第二个柱状图(
bar2
)表示 LightGBM 的性能。
- 第一个柱状图(
- 柱宽(
-
图表设置:
ax.set_xlabel('性能指标', fontproperties=my_font) ax.set_title('XGBoost vs LightGBM 性能比较', fontproperties=my_font) ax.set_xticks(index + bar_width / 2) ax.set_xticklabels(performance_metrics, fontproperties=my_font) ax.legend()
- 设置横轴标签、标题和刻度标签。
- 添加图例区分两种模型。
-
柱状图标注数值:
for bar in bar1 + bar2: height = bar.get_height() ax.annotate('%.2f' % height, xy=(bar.get_x() + bar.get_width() / 2, height), xytext=(0, 3), textcoords="offset points", ha='center', va='bottom')
- 遍历两个柱状图(
bar1
和bar2
),在每个柱的顶部标注对应的数值,保留两位小数。
- 遍历两个柱状图(
-
显示图表:
plt.show()
- 显示绘制的性能比较柱状图。
(4)结果分析:
图表分析:
-
图表内容:
- 蓝色柱子:表示 XGBoost 分类器的性能。
- 橙色柱子:表示 LightGBM 分类器的性能。
- 性能指标:Accuracy(准确率) 和 F1 Score(F1 得分)。
-
结果分析:
- 两种分类器在 Accuracy 和 F1 Score 上的表现完全一致,均为 1.00。
- 这表明在当前测试集上,XGBoost 和 LightGBM 都实现了完美分类,没有任何误差。
-
图表意义:
- 性能一致的原因可能包括:
- 数据集特征区分度高,分类任务较为简单。
- 两种模型的参数调优到位,模型均能充分学习数据分布。
- 性能一致的原因可能包括:
总结:
-
选择建议:
- 如果在性能相同的情况下,建议根据应用场景选择:
- LightGBM:更快的训练和预测速度,适合大规模数据。
- XGBoost:可能在更复杂的任务中表现更稳定。
- 如果在性能相同的情况下,建议根据应用场景选择:
-
下一步优化:
- 在更大的验证集或不同的数据集上测试模型,以验证泛化能力。
- 如果两者仍表现一致,可以进一步优化训练效率或降低资源消耗。
4.总体代码和结果
Deep-Learning/Deep Learning at main · FHY26828/Deep-Learning
更多推荐
所有评论(0)