共计 3406 个字符,预计需要花费 9 分钟才能阅读完成。
背景介绍
BP 神经网络(Back Propagation Neural Network)是一种多层前馈神经网络,通过误差反向传播算法进行训练。它的核心思想是利用梯度下降法,通过反向传播误差来调整网络的权重和偏置,从而最小化预测误差。

鸢尾花数据集(Iris Dataset)是机器学习中常用的分类数据集,包含 150 个样本,分为 3 类(Setosa、Versicolor、Virginica),每类 50 个样本。每个样本有 4 个特征:花萼长度、花萼宽度、花瓣长度、花瓣宽度。
技术实现
数据预处理
- 数据标准化 :将特征数据缩放到均值为 0、方差为 1 的范围内,以加速模型收敛。
- 训练集 / 测试集划分 :通常按 7:3 或 8:2 的比例划分数据集,确保模型评估的客观性。
网络结构设计
- 输入层 :4 个节点(对应 4 个特征)。
- 隐藏层 :通常选择 1 - 2 层,每层节点数可实验调整(如 5 -10 个)。
- 输出层 :3 个节点(对应 3 个类别),使用 Softmax 函数输出概率分布。
激活函数与损失函数
- 激活函数 :隐藏层常用 Sigmoid 或 ReLU,输出层用 Softmax。
- 损失函数 :分类任务常用交叉熵损失函数(Cross-Entropy Loss)。
完整代码示例
import numpy as np
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
# 数据加载与预处理
iris = load_iris()
X, y = iris.data, iris.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)
# 标签转为 one-hot 编码
def to_one_hot(y, num_classes):
return np.eye(num_classes)[y]
y_train_one_hot = to_one_hot(y_train, 3)
y_test_one_hot = to_one_hot(y_test, 3)
# BP 神经网络实现
class NeuralNetwork:
def __init__(self, input_size, hidden_size, output_size):
self.W1 = np.random.randn(input_size, hidden_size) * 0.01
self.b1 = np.zeros((1, hidden_size))
self.W2 = np.random.randn(hidden_size, output_size) * 0.01
self.b2 = np.zeros((1, output_size))
def sigmoid(self, x):
return 1 / (1 + np.exp(-x))
def softmax(self, x):
exps = np.exp(x - np.max(x, axis=1, keepdims=True))
return exps / np.sum(exps, axis=1, keepdims=True)
def forward(self, X):
self.z1 = np.dot(X, self.W1) + self.b1
self.a1 = self.sigmoid(self.z1)
self.z2 = np.dot(self.a1, self.W2) + self.b2
self.a2 = self.softmax(self.z2)
return self.a2
def backward(self, X, y, learning_rate):
m = X.shape[0]
# 输出层误差
delta2 = self.a2 - y
dW2 = np.dot(self.a1.T, delta2) / m
db2 = np.sum(delta2, axis=0, keepdims=True) / m
# 隐藏层误差
delta1 = np.dot(delta2, self.W2.T) * (self.a1 * (1 - self.a1))
dW1 = np.dot(X.T, delta1) / m
db1 = np.sum(delta1, axis=0, keepdims=True) / m
# 参数更新
self.W2 -= learning_rate * dW2
self.b2 -= learning_rate * db2
self.W1 -= learning_rate * dW1
self.b1 -= learning_rate * db1
def compute_loss(self, y_pred, y_true):
m = y_true.shape[0]
log_likelihood = -np.log(y_pred[range(m), y_true.argmax(axis=1)])
return np.sum(log_likelihood) / m
# 模型训练
input_size = 4
hidden_size = 8
output_size = 3
model = NeuralNetwork(input_size, hidden_size, output_size)
epochs = 1000
learning_rate = 0.1
losses = []
for epoch in range(epochs):
# 前向传播
y_pred = model.forward(X_train)
# 计算损失
loss = model.compute_loss(y_pred, y_train_one_hot)
losses.append(loss)
# 反向传播
model.backward(X_train, y_train_one_hot, learning_rate)
if epoch % 100 == 0:
print(f'Epoch {epoch}, Loss: {loss:.4f}')
# 测试集评估
y_test_pred = model.forward(X_test)
test_accuracy = np.mean(np.argmax(y_test_pred, axis=1) == np.argmax(y_test_one_hot, axis=1))
print(f'Test Accuracy: {test_accuracy:.4f}')
模型训练
学习率设置策略
- 初始学习率通常设为 0.1 或 0.01,根据训练情况调整。
- 可使用学习率衰减策略,如每 100 轮衰减 10%。
迭代次数与早停法
- 监控验证集准确率,当连续多轮不再提升时停止训练。
- 保存最佳模型参数,防止过拟合。
训练过程可视化
import matplotlib.pyplot as plt
plt.plot(losses)
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.title('Training Loss Curve')
plt.show()
避坑指南
梯度消失问题应对
- 使用 ReLU 激活函数替代 Sigmoid。
- 采用 Batch Normalization 层。
过拟合解决方法
- 增加 L2 正则化项。
- 使用 Dropout 技术。
参数初始化技巧
- 权重初始化为小随机数(如乘以 0.01)。
- 偏置初始化为 0。
性能评估
评估指标
- 准确率(Accuracy):正确分类样本占总样本比例。
- 混淆矩阵(Confusion Matrix):展示各类别的分类情况。
与 sklearn 实现对比
from sklearn.neural_network import MLPClassifier
mlp = MLPClassifier(hidden_layer_sizes=(8,), max_iter=1000, learning_rate_init=0.1)
mlp.fit(X_train, y_train)
print(f'sklearn Test Accuracy: {mlp.score(X_test, y_test):.4f}')
延伸思考
- 如何通过增加隐藏层数量或节点数提升模型性能?
- 尝试不同的优化算法(如 Adam、RMSprop)会有何影响?
- 如何将模型部署为 Web 服务供他人使用?
通过本文的学习,相信你已经掌握了 BP 神经网络的基本实现方法。在实际应用中,可以继续探索更多优化技巧和高级网络结构,进一步提升模型性能。
正文完
