共计 2117 个字符,预计需要花费 6 分钟才能阅读完成。
背景痛点
鸢尾花分类是机器学习入门的经典案例,传统方法如决策树或 SVM 在小数据集上表现尚可,但面临两个主要问题:

- 特征交互能力有限:花瓣和萼片的尺寸关系需要手工构造组合特征
- 泛化能力不足:当出现介于两个类别之间的样本时,线性分类边界效果下降
BP 神经网络通过多层非线性变换自动学习特征组合,其优势在于:
- 自动特征工程:隐藏层能自主发现更有判别性的特征表示
- 非线性分类边界:通过激活函数拟合复杂决策面
- 端到端训练:从原始数据到分类结果一体化优化
技术实现
数据准备
from sklearn.datasets import load_iris
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
# 加载数据
iris = load_iris()
X, y = iris.data, iris.target
# 标准化(重要!神经网络对输入尺度敏感)scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# 划分训练测试集(保持类别比例)X_train, X_test, y_train, y_test = train_test_split(X_scaled, y, test_size=0.2, stratify=y, random_state=42)
网络架构设计
选择单隐藏层结构(平衡效果与复杂度):
- 输入层:4 个节点(对应 4 个特征)
- 隐藏层:经验公式
(输入 + 输出)/2取整得 6 个节点 - 输出层:3 个节点(softmax 输出概率分布)
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
model = Sequential([Dense(6, activation='relu', input_shape=(4,)), # 隐藏层
Dense(3, activation='softmax') # 输出层
])
模型训练
关键配置
model.compile(
optimizer='adam', # 自适应学习率优化器
loss='sparse_categorical_crossentropy', # 整数标签专用损失
metrics=['accuracy']
)
history = model.fit(
X_train, y_train,
validation_split=0.1, # 从训练集再划分验证集
epochs=200,
batch_size=16,
verbose=0 # 不打印进度条
)
训练过程可视化
import matplotlib.pyplot as plt
plt.plot(history.history['accuracy'], label='train')
plt.plot(history.history['val_accuracy'], label='val')
plt.legend()
plt.show()
性能评估
测试集评估
from sklearn.metrics import classification_report, confusion_matrix
import seaborn as sns
y_pred = model.predict(X_test).argmax(axis=1)
print(classification_report(y_test, y_pred))
# 混淆矩阵热力图
cm = confusion_matrix(y_test, y_pred)
sns.heatmap(cm, annot=True, fmt='d')
避坑指南
常见问题及对策
- 过拟合:
-
添加 Dropout 层(推荐率 0.2-0.5)
from tensorflow.keras.layers import Dropout model.add(Dropout(0.3)) # 加在隐藏层后 -
梯度消失:
- 使用 BatchNorm 层稳定训练
from tensorflow.keras.layers import BatchNormalization model.add(BatchNormalization()) # 加在激活函数前
进阶优化
-
动态学习率:
from tensorflow.keras.callbacks import ReduceLROnPlateau reduce_lr = ReduceLROnPlateau( monitor='val_loss', factor=0.2, patience=5 ) model.fit(..., callbacks=[reduce_lr]) -
早停法:
from tensorflow.keras.callbacks import EarlyStopping es = EarlyStopping( monitor='val_accuracy', patience=10, restore_best_weights=True )
结语
建议尝试以下调参实验观察效果变化:
- 隐藏层节点数调整为 4 或 8
- 更换激活函数为 sigmoid 或 tanh
- 增加第二个隐藏层(注意可能导致过拟合)
完整代码已上传至 GitHub(伪链接),欢迎在评论区分享你的调参心得!
正文完
