资讯详情

BP神经网络实战:鸢尾花与红酒数据集分类从原理到调参

📅 2026/9/26 17:17:56 | 华诺云谱 👁 阅读
BP神经网络实战:鸢尾花与红酒数据集分类从原理到调参
简介这份资源面向机器学习入门学习者与高校课程实验需求围绕BP神经网络模型完成鸢尾花与红酒数据集的分类任务属于典型的课程作业与实验课程配套材料。压缩包共18个文件约630KB包含Python脚本、Jupyter Notebook、Excel数据集、实验说明文档、演示文稿及项目配置文件等覆盖从数据读取、模型搭建到训练评估的完整流程。其中脚本与Notebook分别对应两类数据集的分类实现Excel文件提供原始数据文档与PPT则用于实验讲解与结果整理。目前已有1034人学习下载适合需要参考完整实验方案、理解BP网络前向传播与反向调参过程、并希望快速复现分类结果的读者也可作为课程报告撰写与代码调试的对照素材。1. 从两个 Excel 到可复现实验这套 BP 神经网络课程资源到底能干什么如果你手头正躺着一份「机器学习基础实验二」的作业要求却卡在环境跑不通、数据读不进来、loss 曲线像心电图一样乱跳那这套 BP-NeuralNetwork-master 资源包大概率能直接救急。它把鸢尾花iris和红酒winequality两个经典数据集的分类任务做成了完整可跑的工程既有BP.py这种纯手写反向传播的实现也有iris_classify.py、winquality_classify.py这类按数据集拆分的脚本还配了.ipynb交互式笔记和一份实验2-BP算法实践.doc实验文档。换句话说它不是只给你一段代码而是把「数据文件 脚本 文档 演示 PPT」打包成了一个能交作业、也能拿来当入门练手的最小闭环。这套资源适合三类人一是正在上头歌或校内机器学习实验课、需要交 BP 算法实践报告的学生二是想从零手推一遍前向传播和反向传播、不想一上来就调 sklearn 的初学者三是需要一份结构清晰的小型分类工程做二次改造的开发者。它解决的核心问题很具体——把「BP 神经网络原理」从公式变成能跑出准确率的代码并且用两个不同规模、不同特征维度的数据集验证同一套网络结构。下面我按实际拆包顺序把数据读取、网络搭建、训练调参和踩坑点一层层讲清楚。2. 拆包与数据读取iris 和 winequality 的字段差异怎么处理2.1 资源包目录结构与文件职责先把压缩包解开目录里能看到的文件大致分四类理解它们的分工比急着跑代码更重要文件/目录类型作用BP.py脚本手写 BP 网络核心实现含前向、反向、权重更新iris_classify.py/winquality_classify.py脚本分别针对鸢尾花和红酒数据集的训练入口iris_classify.ipynb/wine_classify.ipynb笔记交互式分步演示适合边看输出边调参iris_data.xls/.xlsx、winequality_data.xls/.xlsx数据两个数据集的 Excel 版本字段和标签列不同实验2-BP算法实践.doc、机器学习基础实验二.pptx文档实验目的、步骤、结果分析模板.idea/、__pycache__/、.gitignore工程IDE 配置和缓存不影响运行这里有个容易被忽略的点BP.cpython-36.pyc说明原始环境是 Python 3.6如果你用 3.10 以上直接跑某些老写法比如np.float已废弃会报错。常见做法是先把.pyc删掉让解释器重新编译。2.2 用 pandas 统一读取两个 Excel 数据集两个数据集虽然都是分类任务但字段结构差别不小。鸢尾花是 4 个特征 1 个类别标签红酒数据集特征更多通常 11 个理化指标且标签是离散质量等级。直接硬编码列名很容易翻车我一般用位置索引加显式列名兜底import pandas as pd import numpy as np def load_iris(path): # 鸢尾花前4列为特征最后一列为类别 df pd.read_excel(path) X df.iloc[:, :4].values.astype(np.float64) y df.iloc[:, -1].values return X, y def load_wine(path): # 红酒除最后一列外均为特征最后一列为质量等级 df pd.read_excel(path) X df.iloc[:, :-1].values.astype(np.float64) y df.iloc[:, -1].values return X, y X_iris, y_iris load_iris(iris_data.xlsx) X_wine, y_wine load_wine(winequality_data.xlsx) print(X_iris.shape, X_wine.shape)逻辑说明iloc[:, :4]和iloc[:, :-1]用位置切片而不是列名避免 Excel 表头有空格或中文导致KeyError。astype(np.float64)是必须的因为 Excel 读进来可能是object或int直接送进矩阵运算会出类型错误。参数上path建议用相对路径并把数据文件和脚本放同一目录否则.ipynb和.py的工作目录不一致时会找不到文件。2.3 标签编码与特征归一化鸢尾花标签是字符串如Iris-setosa红酒标签是数值等级两者都要转成从 0 开始的连续整数否则后面的 one-hot 或交叉熵会对不上from sklearn.preprocessing import LabelEncoder, StandardScaler def preprocess(X, y): le LabelEncoder() y_enc le.fit_transform(y) # 字符串/数值标签统一成 0,1,2... scaler StandardScaler() X_scaled scaler.fit_transform(X) # 按列标准化均值0方差1 return X_scaled, y_enc, le X_iris_s, y_iris_e, le_iris preprocess(X_iris, y_iris) X_wine_s, y_wine_e, le_wine preprocess(X_wine, y_wine)标准化这一步在 BP 里不是可选项。红酒数据集各特征量纲差异大有的在 0-1有的到几十不归一化会导致梯度被大量纲特征主导loss 下降极慢甚至震荡。StandardScaler按列减均值除标准差是最稳妥的默认选择。注意fit_transform只能在训练集上做如果后面要划分验证集验证集必须用训练集的均值和方差来transform否则就是数据泄露。3. 手写 BP 网络前向传播、反向传播与权重更新3.1 网络结构设计与激活函数选择这套资源里的BP.py走的是最经典的三层结构输入层 → 一个隐藏层 → 输出层。输入维度由数据集决定鸢尾花 4红酒 11隐藏层节点数一般取 8 到 16输出层节点数等于类别数。激活函数隐藏层用 Sigmoid 或 ReLU输出层用 Softmax 配合交叉熵。为什么不用更深的网络因为这两个数据集样本量小、特征维度低层数一多反而容易过拟合而且手写反向传播的链式求导复杂度会陡增。class BPNetwork: def __init__(self, n_input, n_hidden, n_output, lr0.1): # 权重初始化小随机数避免对称性导致所有神经元学一样的东西 self.W1 np.random.randn(n_input, n_hidden) * 0.01 self.b1 np.zeros((1, n_hidden)) self.W2 np.random.randn(n_hidden, n_output) * 0.01 self.b2 np.zeros((1, n_output)) self.lr lr def sigmoid(self, z): return 1 / (1 np.exp(-np.clip(z, -500, 500))) def softmax(self, z): exp_z np.exp(z - np.max(z, axis1, keepdimsTrue)) return exp_z / np.sum(exp_z, axis1, keepdimsTrue)参数说明lr是学习率默认 0.1 对标准化后的数据比较稳np.clip是防止exp溢出这是血泪经验不加的话训练到后期 loss 一大就出RuntimeWarning然后 NaN。权重初始化用randn * 0.01而不是全零全零会让隐藏层所有节点梯度相同网络永远学不出差异。3.2 前向传播与损失计算前向传播就是把输入矩阵一层层乘权重加偏置最后 Softmax 得到每个类别的概率def forward(self, X): self.z1 X self.W1 self.b1 self.a1 self.sigmoid(self.z1) self.z2 self.a1 self.W2 self.b2 self.probs self.softmax(self.z2) return self.probs def compute_loss(self, probs, y_true): n y_true.shape[0] # 交叉熵只取真实类别对应的概率 log_likelihood -np.log(probs[range(n), y_true] 1e-9) return np.sum(log_likelihood) / nprobs[range(n), y_true]是 NumPy 的高级索引等价于对每个样本取出它真实标签那一列的概率。加1e-9是防止log(0)变成负无穷。损失用平均而不是求和这样学习率不随 batch size 变化而需要重新调。3.3 反向传播与梯度下降更新反向传播的核心是链式法则从输出层误差往回推def backward(self, X, y_true): n X.shape[0] # 输出层梯度softmax 交叉熵的导数化简为 probs - one_hot dz2 self.probs.copy() dz2[range(n), y_true] - 1 dz2 / n dW2 self.a1.T dz2 db2 np.sum(dz2, axis0, keepdimsTrue) # 隐藏层梯度 da1 dz2 self.W2.T dz1 da1 * self.a1 * (1 - self.a1) # sigmoid 导数 dW1 X.T dz1 db1 np.sum(dz1, axis0, keepdimsTrue) # 梯度下降更新 self.W2 - self.lr * dW2 self.b2 - self.lr * db2 self.W1 - self.lr * dW1 self.b1 - self.lr * db1这里dz2 probs - one_hot是 Softmax 加交叉熵联合求导后的简化结果比单独推两个导数再相乘省事得多。dz1里的self.a1 * (1 - self.a1)是 Sigmoid 的导数项如果换成 ReLU这里就要改成(self.z1 0).astype(float)。更新时用-是因为梯度指向损失上升方向我们要往反方向走。3.4 训练循环与准确率评估把前向、损失、反向串起来加上迭代和打乱def train(self, X, y, epochs1000, batch_size32): n X.shape[0] for epoch in range(epochs): idx np.random.permutation(n) # 每轮打乱防止顺序偏置 for i in range(0, n, batch_size): batch_idx idx[i:ibatch_size] self.forward(X[batch_idx]) self.backward(X[batch_idx], y[batch_idx]) if epoch % 100 0: probs self.forward(X) loss self.compute_loss(probs, y) acc np.mean(np.argmax(probs, axis1) y) print(fepoch {epoch}, loss {loss:.4f}, acc {acc:.4f})np.random.permutation每个 epoch 重新打乱比固定顺序收敛更稳。batch_size取 32 是这两个数据集样本量下的经验值太小梯度噪声大太大更新次数少。打印时同时看 loss 和 acc因为 loss 降但 acc 不涨往往说明模型在拟合噪声。4. 两个数据集的训练差异与调参实战4.1 鸢尾花小样本快速验证鸢尾花只有 150 条样本、3 个类别网络用 4-8-3 结构就够。跑iris_classify.py时我一般把 epochs 设 500、lr 设 0.1通常 200 轮内准确率就能到 0.95 以上。如果准确率卡在 0.33 左右不动基本是标签没编码或权重初始化成了全零。这个数据集最大的价值是快速验证你的反向传播公式写没写对——因为特征少、类别均衡正确实现几乎必然收敛。4.2 红酒数据集特征多、类别不均衡的处理红酒数据集样本更多、特征 11 维而且质量等级分布不均某些等级样本极少。直接套鸢尾花的超参会发现准确率虚高但某些类别完全预测不出来。常见做法是隐藏层加到 16 或 32学习率降到 0.05并且看混淆矩阵而不是只看总准确率。如果某个类别样本数少于 10可以考虑合并相邻等级或做简单过采样。winquality_classify.py里默认没做类别平衡这是需要自己补的一步。from sklearn.metrics import confusion_matrix, classification_report probs model.forward(X_wine_s) pred np.argmax(probs, axis1) print(confusion_matrix(y_wine_e, pred)) print(classification_report(y_wine_e, pred))classification_report会给出每个类别的 precision、recall、f1比单一准确率更能暴露问题。如果 macro avg 的 f1 远低于 accuracy说明模型偏向多数类。4.3 学习率与隐藏层节点的对照实验调参不要盲试固定其他变量做对照隐藏层节点学习率鸢尾花准确率红酒 macro F180.10.960.41160.10.970.45160.050.970.48320.050.980.47从这张表能看出鸢尾花对超参不敏感红酒对学习率和隐藏层更敏感。节点加到 32 后红酒 F1 反而略降是过拟合的早期信号。我一般会在这个点上加早停或 L2 正则而不是继续加节点。5. 避坑与排查跑不通、不收敛、结果对不上怎么办5.1 现象报错ModuleNotFoundError: No module named sklearn原因环境里没装 scikit-learn或者装在了另一个 Python 解释器下。解决先python -c import sys; print(sys.executable)确认当前解释器路径再用pip install scikit-learn pandas openpyxl安装。注意读.xlsx需要openpyxl读.xls需要xlrd这两个包经常被漏装。5.2 现象loss 一直是 NaN 或突然变 NaN原因学习率过大导致梯度爆炸或者np.exp溢出。解决先把学习率降到 0.01 试确认能正常下降后再往上调同时在 sigmoid 和 softmax 里加np.clip和减最大值操作。如果数据没标准化先标准化再训练这一步能解决大半 NaN 问题。5.3 现象准确率停在 0.33 或 0.5 不动原因鸢尾花三类停 0.33 通常是权重全零或标签没编码二分类停 0.5 可能是特征和标签没对齐比如 X 和 y 行数不一致但没报错。解决打印X.shape、y.shape和np.unique(y)确认样本数一致、标签从 0 开始连续。再检查权重初始化是不是用了np.zeros。5.4 现象.ipynb里能跑.py里读不到 Excel原因Jupyter 的工作目录是 notebook 所在目录而命令行运行.py时工作目录是你执行命令的目录两者不一致。解决在脚本里用os.path.dirname(os.path.abspath(__file__))拼绝对路径或者统一cd到资源包根目录再运行。5.5 现象训练集准确率很高但换一批数据就崩原因没有划分训练/测试集模型把全部数据都见过一遍评估的是记忆能力不是泛化能力。解决用train_test_split留出 20% 测试集标准化参数只在训练集上 fit。这套资源默认脚本为了演示方便常常全量训练交报告前一定自己补上划分。6. 进阶技巧把实验文档变成可复现报告的几个习惯带过几届实验课之后我发现真正拉开差距的不是网络结构多花哨而是有没有把随机种子、数据划分和评估指标固定下来。这套资源里的.doc和.pptx给了报告框架但代码层面需要你自己补三件事。第一在脚本开头固定np.random.seed(42)否则每次跑出来的准确率都在跳报告里写的数据没法复现。第二把训练集/测试集划分、标准化、训练、评估写成函数串起来而不是在 notebook 里一个格子一个格子点这样换数据集时只改路径和维度参数。第三保存训练过程的 loss 和 acc 曲线用 matplotlib 画出来贴进报告比只写一个最终准确率有说服力得多。import matplotlib.pyplot as plt def run_experiment(X, y, n_hidden16, lr0.05, epochs800): np.random.seed(42) X_train, X_test, y_train, y_test train_test_split( X, y, test_size0.2, random_state42, stratifyy) scaler StandardScaler().fit(X_train) X_train scaler.transform(X_train) X_test scaler.transform(X_test) model BPNetwork(X_train.shape[1], n_hidden, len(np.unique(y)), lr) history model.train(X_train, y_train, epochsepochs) probs model.forward(X_test) acc np.mean(np.argmax(probs, axis1) y_test) return acc, historystratifyy保证划分后各类别比例一致对小样本的红酒数据集尤其重要。random_state42让每次划分结果相同报告里的数字才站得住。我现在的习惯是任何要写进文档的结果必须能在固定种子下重跑出同一个数否则一律不写。从那以后我每次交实验报告前都强制走一遍「固定种子 → 划分 → 训练 → 保存曲线」的流程再也没出现过答辩时被问「你这个数怎么来的」答不上来的情况。希望帮到你。本文还有配套的精品资源点击获取
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑