BP神经网络实战:从零实现鸢尾花分类模型

1次阅读
没有评论

共计 3406 个字符,预计需要花费 9 分钟才能阅读完成。

image.webp

背景介绍

BP 神经网络(Back Propagation Neural Network)是一种多层前馈神经网络,通过误差反向传播算法进行训练。它的核心思想是利用梯度下降法,通过反向传播误差来调整网络的权重和偏置,从而最小化预测误差。

BP 神经网络实战:从零实现鸢尾花分类模型

鸢尾花数据集(Iris Dataset)是机器学习中常用的分类数据集,包含 150 个样本,分为 3 类(Setosa、Versicolor、Virginica),每类 50 个样本。每个样本有 4 个特征:花萼长度、花萼宽度、花瓣长度、花瓣宽度。

技术实现

数据预处理

  1. 数据标准化 :将特征数据缩放到均值为 0、方差为 1 的范围内,以加速模型收敛。
  2. 训练集 / 测试集划分 :通常按 7:3 或 8:2 的比例划分数据集,确保模型评估的客观性。

网络结构设计

  1. 输入层 :4 个节点(对应 4 个特征)。
  2. 隐藏层 :通常选择 1 - 2 层,每层节点数可实验调整(如 5 -10 个)。
  3. 输出层 :3 个节点(对应 3 个类别),使用 Softmax 函数输出概率分布。

激活函数与损失函数

  1. 激活函数 :隐藏层常用 Sigmoid 或 ReLU,输出层用 Softmax。
  2. 损失函数 :分类任务常用交叉熵损失函数(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}')

模型训练

学习率设置策略

  1. 初始学习率通常设为 0.1 或 0.01,根据训练情况调整。
  2. 可使用学习率衰减策略,如每 100 轮衰减 10%。

迭代次数与早停法

  1. 监控验证集准确率,当连续多轮不再提升时停止训练。
  2. 保存最佳模型参数,防止过拟合。

训练过程可视化

import matplotlib.pyplot as plt

plt.plot(losses)
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.title('Training Loss Curve')
plt.show()

避坑指南

梯度消失问题应对

  1. 使用 ReLU 激活函数替代 Sigmoid。
  2. 采用 Batch Normalization 层。

过拟合解决方法

  1. 增加 L2 正则化项。
  2. 使用 Dropout 技术。

参数初始化技巧

  1. 权重初始化为小随机数(如乘以 0.01)。
  2. 偏置初始化为 0。

性能评估

评估指标

  1. 准确率(Accuracy):正确分类样本占总样本比例。
  2. 混淆矩阵(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}')

延伸思考

  1. 如何通过增加隐藏层数量或节点数提升模型性能?
  2. 尝试不同的优化算法(如 Adam、RMSprop)会有何影响?
  3. 如何将模型部署为 Web 服务供他人使用?

通过本文的学习,相信你已经掌握了 BP 神经网络的基本实现方法。在实际应用中,可以继续探索更多优化技巧和高级网络结构,进一步提升模型性能。

正文完
 0
评论(没有评论)