鸢尾花分类的6种机器学习方法综合分析与实现
首先我们来看一下对应的实验结果。
数据准备与环境配置
在开始机器学习项目前,首先需要准备编程环境和加载数据。以下代码导入必要的库并加载鸢尾花数据集:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.datasets import load_iris
# 加载数据集
iris = load_iris()
X = iris.data # 特征矩阵(150x4)
y = iris.target # 目标变量
feature_names = iris.feature_names # 特征名称列表
target_names = iris.target_names # 类别名称列表
该部分代码完成了基础环境设置,其中numpy
和pandas
用于数据处理,matplotlib
和seaborn
负责可视化展示。通过load_iris()
函数获取经典数据集,该数据集包含三种鸢尾花的四个形态特征测量值。特征矩阵X
存储150个样本的花萼长度、花萼宽度、花瓣长度和花瓣宽度数据,目标变量y
对应三个类别标签。打印特征和类别名称有助于确认数据正确加载,例如输出显示特征为"sepal length (cm)"等四个测量维度,类别对应setosa、versicolor和virginica三个品种。
数据预处理与特征工程
数据预处理是机器学习流程中的关键步骤,以下代码完成数据划分与标准化:
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
# 划分训练测试集
X_train, X_test, y_train, y_test = train_test_split(
X, y,
test_size=0.3,
random_state=42,
stratify=y
)
# 特征标准化
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
数据划分采用分层抽样策略,保留30%样本作为测试集,stratify=y
参数确保各类别比例一致,避免因随机划分导致样本偏差。random_state=42
固定随机种子保证结果可复现。标准化处理通过StandardScaler
将特征缩放至均值为0、方差为1的分布,这对基于距离计算的算法(如SVM、KNN)尤为重要。训练集的fit_transform
同时计算参数并转换数据,而测试集仅使用训练集的参数进行转换,防止数据泄露。实际应用中可根据特征分布尝试其他预处理方法,例如对偏态分布特征使用对数变换,或对存在类别型特征时采用独热编码。
多模型实现与训练
本实验选取六种典型机器学习算法进行对比:
from sklearn.linear_model import LogisticRegression
from sklearn.tree import DecisionTreeClassifier
from sklearn.svm import SVC
from sklearn.ensemble import RandomForestClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.naive_bayes import GaussianNB
models = {
"逻辑回归": LogisticRegression(max_iter=1000),
"决策树": DecisionTreeClassifier(max_depth=3),
"支持向量机": SVC(kernel='rbf', probability=True),
"随机森林": RandomForestClassifier(n_estimators=100),
"K近邻": KNeighborsClassifier(n_neighbors=5),
"朴素贝叶斯": GaussianNB()
}
模型选择涵盖不同学习范式:逻辑回归作为基础线性分类器,适合处理线性可分问题;决策树通过设置最大深度3控制模型复杂度;支持向量机采用RBF核处理非线性边界;随机森林集成多棵决策树提升泛化能力;K近邻基于局部相似性进行预测;朴素贝叶斯依赖特征条件独立假设。扩展时可以考虑添加梯度提升树(如XGBoost)或神经网络(MLPClassifier),例如:
from xgboost import XGBClassifier
from sklearn.neural_network import MLPClassifier
models.update({
"XGBoost": XGBClassifier(n_estimators=100),
"神经网络": MLPClassifier(hidden_layer_sizes=(64,32), max_iter=1000)
})
模型评估与验证
采用交叉验证与测试集评估相结合的方式:
from sklearn.model_selection import cross_val_score
from sklearn.metrics import accuracy_score, confusion_matrix, classification_report
results = {}
for name, model in models.items():
# 交叉验证
cv_scores = cross_val_score(model, X_train_scaled, y_train, cv=5)
# 完整训练
model.fit(X_train_scaled, y_train)
y_pred = model.predict(X_test_scaled)
# 结果存储
results[name] = {
'cv_mean': cv_scores.mean(),
'cv_std': cv_scores.std(),
'test_accuracy': accuracy_score(y_test, y_pred),
'confusion_matrix': confusion_matrix(y_test, y_pred),
'classification_report': classification_report(y_test, y_pred, target_names=target_names)
}
五折交叉验证通过五次数据划分评估模型稳定性,交叉验证准确率的均值和标准差反映模型泛化能力。测试集评估使用准确率、混淆矩阵和包含精确率、召回率、F1值的分类报告进行全方位评价。对于类别不平衡问题,建议补充ROC曲线和AUC值评估,例如:
from sklearn.metrics import roc_curve, auc
from sklearn.preprocessing import label_binarize
# 对目标变量进行二值化处理
y_test_bin = label_binarize(y_test, classes=[0,1,2])
# 计算每个类别的ROC曲线
plt.figure(figsize=(10,8))
for name, model in results.items():
if hasattr(model, "predict_proba"):
y_score = model.predict_proba(X_test_scaled)
for i in range(3):
fpr, tpr, _ = roc_curve(y_test_bin[:,i], y_score[:,i])
roc_auc = auc(fpr, tpr)
plt.plot(fpr, tpr, label=f'{name} (Class {i}, AUC={roc_auc:.2f})')
plt.plot([0,1], [0,1], 'k--')
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('多类别ROC曲线')
plt.legend(loc="lower right")
plt.show()
模型对比如下所示。
结果可视化与解释
通过可视化直观对比模型表现:
# 准确率对比
plt.figure(figsize=(12,6))
models_list = list(models.keys())
x = np.arange(len(models_list))
plt.barh(x, [results[name]['test_accuracy'] for name in models_list], color='steelblue')
plt.yticks(x, models_list)
plt.xlabel('测试集准确率')
plt.xlim(0.8, 1.0)
plt.title('分类模型性能对比')
plt.show()
# 最佳模型混淆矩阵
best_model = max(results, key=lambda k: results[k]['test_accuracy'])
cm = results[best_model]['confusion_matrix']
plt.figure(figsize=(8,6))
sns.heatmap(cm, annot=True, fmt='d', cmap='Blues',
xticklabels=target_names,
yticklabels=target_names)
plt.title(f'{best_model}混淆矩阵\n准确率:{results[best_model]["test_accuracy"]:.3f}')
plt.xlabel('预测类别')
plt.ylabel('真实类别')
plt.show()
准确率对比图横向排列各模型表现,深蓝色柱体长度反映测试集准确率高低,x轴范围限定在0.8-1.0区间以突出差异。混淆矩阵采用颜色渐变的热力图形式,对角线深色方块表示正确分类数量,非对角线元素显示类别间误分情况。
from sklearn.model_selection import learning_curve
def plot_learning_curve(estimator, title, X, y, cv=5):
train_sizes, train_scores, test_scores = learning_curve(
estimator, X, y, cv=cv, n_jobs=-1,
train_sizes=np.linspace(0.1, 1.0, 5)
)
plt.figure(figsize=(10,6))
plt.plot(train_sizes, np.mean(train_scores, axis=1), 'o-', label="训练得分")
plt.plot(train_sizes, np.mean(test_scores, axis=1), 'o-', label="验证得分")
plt.xlabel("训练样本数")
plt.ylabel("准确率")
plt.title(title)
plt.legend()
plt.grid(True)
plt.show()
# 示例:绘制随机森林学习曲线
plot_learning_curve(RandomForestClassifier(n_estimators=100),
"随机森林学习曲线", X_train_scaled, y_train)
热力图对比如下所示。
特征重要性分析
基于树模型的特征重要性评估:
# 随机森林特征重要性
rf_model = models["随机森林"].fit(X_train_scaled, y_train)
importances = rf_model.feature_importances_
plt.figure(figsize=(10,6))
indices = np.argsort(importances)[::-1]
plt.barh(range(X.shape[1]), importances[indices], align='center')
plt.yticks(range(X.shape[1]), [feature_names[i] for i in indices])
plt.gca().invert_yaxis()
plt.xlabel('特征重要性')
plt.title('随机森林特征重要性排序')
plt.show()
该分析显示花瓣相关特征(特别是花瓣长度)对分类贡献最大,这与生物学事实一致——不同鸢尾花品种的花瓣形态差异显著。对于线性模型,可通过系数大小分析特征重要性:
# 逻辑回归系数分析
lr_model = models["逻辑回归"].fit(X_train_scaled, y_train)
coefficients = lr_model.coef_
plt.figure(figsize=(10,6))
for i in range(3):
plt.barh(feature_names, coefficients[i], label=f'Class {target_names[i]}')
plt.xlabel('系数大小')
plt.title('逻辑回归特征系数')
plt.legend()
plt.tight_layout()
plt.show()
特征重要性可视化如下所示。
模型部署与应用建议
在完成模型评估后,可将最佳模型序列化保存:
import joblib
# 保存最佳模型
best_model = max(results, key=lambda k: results[k]['test_accuracy'])
joblib.dump(models[best_model], 'best_iris_classifier.pkl')
# 加载模型进行预测示例
loaded_model = joblib.load('best_iris_classifier.pkl')
sample = X_test_scaled[0].reshape(1,-1)
prediction = loaded_model.predict(sample)
print(f"预测类别: {target_names[prediction[0]]}")
总结与展望
本实验系统实现了鸢尾花分类任务的机器学习流程,通过对比不同算法揭示了模型性能差异的原因——数据分布特性与算法假设的匹配程度。实验表明,基于核方法的SVM和集成学习随机森林在该数据集上表现优异,测试准确率接近100%。