鸢尾花分类是机器学习领域的经典入门项目,相当于编程界的"Hello World"。这个项目通过测量鸢尾花的四个特征(萼片长度、萼片宽度、花瓣长度、花瓣宽度)来预测其所属品种。作为初学者接触机器学习的第一个实战案例,它完美展示了从数据加载到模型评估的完整流程。
我在实际教学中发现,很多新手虽然能跑通这个案例,但对每个步骤背后的原理和最佳实践缺乏深入理解。本文将基于scikit-learn框架,不仅展示基础代码实现,更会深入剖析每个环节的技术细节和工程考量。通过这个项目,你将掌握机器学习项目的基本方法论,这些经验可以迁移到任何分类任务中。
scikit-learn内置了鸢尾花数据集,这是机器学习社区的标准数据集之一。通过load_iris()函数加载的数据实际上是一个Bunch对象(类似字典),包含以下关键字段:
data: 特征矩阵 (150个样本×4个特征)target: 标签向量 (0,1,2分别对应setosa, versicolor, virginica)feature_names: 特征名称列表target_names: 类别名称列表DESCR: 数据集的完整描述提示:在Jupyter Notebook中运行
print(iris.DESCR)可以查看数据集的完整统计信息,包括各特征的均值、极值等,这对理解数据分布非常有帮助。
在建模前进行数据探索是必不可少的步骤。使用seaborn的pairplot可以直观看到特征间的关系:
python复制import seaborn as sns
import pandas as pd
iris = load_iris()
iris_df = pd.DataFrame(iris.data, columns=iris.feature_names)
iris_df['target'] = iris.target
sns.pairplot(iris_df, hue='target', palette='husl')
plt.show()
从散点矩阵可以明显看出:
使用train_test_split划分数据集时需要注意:
test_size=0.2表示保留20%数据作为测试集random_state=42确保每次划分结果一致(便于结果复现)python复制from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(
iris.data, iris.target,
test_size=0.2,
random_state=42,
stratify=iris.target # 保持类别比例
)
KNN算法对特征尺度敏感,因此需要进行标准化处理。StandardScaler的运作原理是:
python复制from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train) # 拟合+转换训练集
X_test_scaled = scaler.transform(X_test) # 仅转换测试集
重要:绝对不要在测试集上调用fit方法!这会导致数据泄露,使评估结果过于乐观。
K近邻(KNN)是一种惰性学习算法,其预测基于以下公式:
ŷ = mode(y_i | x_i ∈ N_k(x))
其中N_k(x)表示x的k个最近邻。距离通常采用欧氏距离:
d(x,y) = √Σ(x_i - y_i)²
在scikit-learn中,KNeighborsClassifier的主要参数包括:
n_neighbors: 近邻数k(关键参数)weights: 距离加权方式(uniform或distance)metric: 距离度量(欧氏、曼哈顿等)使用网格搜索+交叉验证寻找最优参数:
python复制from sklearn.model_selection import GridSearchCV
param_grid = {
'n_neighbors': range(1, 11),
'weights': ['uniform', 'distance'],
'metric': ['euclidean', 'manhattan']
}
knn = KNeighborsClassifier()
grid_search = GridSearchCV(knn, param_grid, cv=5, n_jobs=-1)
grid_search.fit(X_train_scaled, y_train)
print(f"最佳参数: {grid_search.best_params_}")
print(f"交叉验证最佳得分: {grid_search.best_score_:.3f}")
典型输出结果:
code复制最佳参数: {'metric': 'euclidean', 'n_neighbors': 3, 'weights': 'uniform'}
交叉验证最佳得分: 0.967
除了准确率,分类问题还应考虑:
python复制from sklearn.metrics import classification_report
y_pred = grid_search.best_estimator_.predict(X_test_scaled)
print(classification_report(y_test, y_pred))
将训练好的模型持久化以便后续使用:
python复制import joblib
# 保存模型和scaler
joblib.dump(grid_search.best_estimator_, 'iris_knn_model.pkl')
joblib.dump(scaler, 'iris_scaler.pkl')
# 加载使用示例
model = joblib.load('iris_knn_model.pkl')
scaler = joblib.load('iris_scaler.pkl')
new_data = [[5.1, 3.5, 1.4, 0.2]] # 新样本
new_data_scaled = scaler.transform(new_data)
prediction = model.predict(new_data_scaled)
print(f"预测类别: {iris.target_names[prediction][0]}")
尝试以下方法提升模型性能:
与其他分类算法进行对比实验:
python复制from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC
from sklearn.ensemble import RandomForestClassifier
models = {
"Logistic Regression": LogisticRegression(max_iter=1000),
"SVM": SVC(),
"Random Forest": RandomForestClassifier()
}
for name, model in models.items():
model.fit(X_train_scaled, y_train)
score = model.score(X_test_scaled, y_test)
print(f"{name}测试准确率: {score:.3f}")
虽然鸢尾花数据集很纯净,但实际项目中会遇到:
建议下一步尝试更复杂的数据集(如MNIST或Titanic)来巩固这些技能。