简介这份资源面向深度学习入门者与希望夯实神经网络底层原理的开发者提供一套用Python与numpy从零实现简单全连接神经网络多层感知器的完整代码。包内共7个文件全部为py脚本压缩包约4KB涵盖网络结构定义、数据生成与处理、前向传播、反向传播、训练与预测等模块代码按功能拆分清晰便于逐文件阅读与调试。资源围绕激活函数、权重初始化、均方误差损失、梯度计算与权重更新等核心环节展开读者可借此理解神经网络逐层传递信息的工作机制并在此基础上尝试调整隐藏层规模、学习率与训练轮数观察模型表现变化。目前已有4213人学习下载适合作为进一步学习TensorFlow、Keras或PyTorch等框架前的原理铺垫也可用于课程实验与自学练手。1. 零基础也能跑通神经网络到底是个什么东西你可能听过「神经网络」这四个字第一反应是这玩意儿是不是得数学特别好、得先学一堆公式才能碰我刚开始接触的时候也这么想甚至一度觉得这是研究生才玩得转的东西。后来真正动手写了几行 Python 才发现入门阶段根本不需要你懂反向传播的推导你只需要先搞明白它在干嘛——它就是一个「帮你找规律」的工具。打个比方你给一个从没见过猫的小孩看一百张猫的照片告诉他「这是猫」再看一百张狗的照片告诉他「这是狗」。看得多了下次给他一张新照片他大概率能认出来。神经网络干的就是类似的事——你喂给它一堆数据它自己从里面找规律然后拿学到的规律去判断新数据。所谓「全连接」你可以理解成每一层里的每个小格子都和上一层的所有格子连在一起信息传得最彻底结构也最简单特别适合拿来入门。这份 Python 实现就是帮你迈出第一步的不用装复杂的框架不用配环境配到崩溃跟着敲就能看到一个能跑起来的小网络。适合谁完全没碰过神经网络、但会一点点 Python 的人。如果你连print都还没写过建议先花半天把 Python 基础过一遍再回来会顺很多。2. 为什么值得从全连接入手先搞懂一个概念2.1 全连接网络是神经网络的「最小可用模型」很多人一上来就想搞卷积、搞 Transformer结果被各种维度变换绕晕最后连「训练」到底在训练什么都没搞清。全连接网络Fully Connected Network是所有神经网络里结构最直白的一种输入层接收数据中间若干隐藏层做变换输出层给出结果层与层之间每个节点都相连。它没有卷积的滑动窗口、没有循环网络的时序记忆你看到的每一个数字怎么来的都能一步步追下去。我第一次学的时候导师跟我说过一句话先把最简单的跑通再往上加复杂度你的信心才不会崩。全连接网络就是那个「最简单的」。你在它上面搞懂了什么是权重、什么是损失、什么是梯度下降后面学任何复杂结构都只是换积木底层逻辑不变。而且它并不是「玩具」。很多实际问题——比如根据几个特征预测房价、根据用户行为做二分类——用全连接网络就能解决得不错。入门阶段拿它练手既不会太简单到没收获也不会难到劝退。2.2 用 Python 实现意味着你不需要先啃框架市面上的深度学习框架确实强大但对零基础的人来说它们把太多细节藏起来了。你写三行代码就能建一个网络可你根本不知道里面发生了什么出了问题也不知道从哪查。这份 Python 实现走的是另一条路用最基础的语法和运算把前向传播、损失计算、反向传播一步步写出来。这样做的好处是你敲的每一行代码都对应一个真实的计算动作。比如下面这段前向传播的核心逻辑import numpy as np # 初始化一个简单的两层网络参数 # 输入维度 2隐藏层 3 个神经元输出 1 个值 W1 np.random.randn(2, 3) * 0.1 # 第一层权重 b1 np.zeros((1, 3)) # 第一层偏置 W2 np.random.randn(3, 1) * 0.1 # 第二层权重 b2 np.zeros((1, 1)) # 第二层偏置 def forward(x): # 第一层线性变换 激活函数 z1 np.dot(x, W1) b1 a1 np.maximum(0, z1) # ReLU 激活负数变 0 # 第二层线性变换得到输出 z2 np.dot(a1, W2) b2 return z2, a1这段代码里np.dot做的就是「全连接」——输入的每个特征都乘上对应的权重再加起来。np.maximum(0, z1)是激活函数作用是让网络能拟合非线性关系不然堆再多层也等于一层。W1、W2是权重b1、b2是偏置它们就是网络要「学」的东西。你不需要背公式只要知道权重决定每个输入有多重要偏置决定整体偏移多少。跑通这段你就已经完成了神经网络最核心的一步。剩下的训练过程无非是反复调整这些权重让输出越来越接近正确答案。3. 第一个能跑的例子从零写一个训练循环3.1 准备数据先让网络有东西可学没有数据网络就是个空壳。入门阶段我们不用去找真实数据集自己造一批最简单的就行。假设我们要让网络学会一个规律输入两个数输出它们的和是否大于 1。这是一个二分类问题数据简单到你能一眼看出对错方便验证网络到底学没学会。# 构造 100 条简单数据 np.random.seed(42) # 固定随机种子保证每次结果一样 X np.random.randn(100, 2) # 100 个样本每个样本 2 个特征 y (X[:, 0] X[:, 1] 1).astype(float).reshape(-1, 1) # y 是标签两个特征之和大于 1 记为 1否则记为 0np.random.seed(42)这行很重要。不固定种子的话每次运行数据都不一样你没法判断网络变好是因为训练有效还是因为运气好。X是输入形状是 100 行 2 列y是标签形状是 100 行 1 列。标签只有 0 和 1 两个值这就是最典型的二分类。提示入门阶段数据越简单越好不要一上来就搞图片或文本光数据预处理就能耗掉你半天热情。3.2 训练循环让网络自己调整权重有了数据接下来就是让网络反复看这些数据每次看完调整一下权重。这个过程叫「训练」核心步骤就四步前向传播算输出、算损失、反向传播算梯度、更新权重。learning_rate 0.1 # 学习率控制每次调整的幅度 for epoch in range(1000): # 把所有数据看 1000 遍 # 1. 前向传播 z2, a1 forward(X) y_pred 1 / (1 np.exp(-z2)) # Sigmoid 把输出压到 0~1 之间 # 2. 计算损失交叉熵 loss -np.mean(y * np.log(y_pred 1e-8) (1 - y) * np.log(1 - y_pred 1e-8)) # 3. 反向传播手动推导的梯度 dz2 y_pred - y # 输出层误差 dW2 np.dot(a1.T, dz2) / len(X) db2 np.mean(dz2, axis0, keepdimsTrue) da1 np.dot(dz2, W2.T) dz1 da1 * (a1 0) # ReLU 的导数 dW1 np.dot(X.T, dz1) / len(X) db1 np.mean(dz1, axis0, keepdimsTrue) # 4. 更新权重 W1 - learning_rate * dW1 b1 - learning_rate * db1 W2 - learning_rate * dW2 b2 - learning_rate * db2 if epoch % 200 0: print(f第 {epoch} 轮损失值{loss:.4f})learning_rate是学习率你可以理解成「每次调整步子迈多大」。太大容易跨过最优点太小又学得太慢0.1 是个入门常用的起点。epoch是训练轮数1000 轮意味着整个数据集被完整看了 1000 遍。损失值loss越小说明网络输出和真实标签越接近。反向传播那几行看起来吓人其实你只需要知道dz2 y_pred - y是输出层的误差然后这个误差一层层往前传算出每个权重该负多少责任最后按责任大小去调整。1e-8是为了防止log(0)报错属于工程上的小保护。跑完这段你会看到损失值从最初的 0.7 左右慢慢降到 0.1 以下。这说明网络确实学到了「两个数之和大于 1」这个规律。你可以拿几条新数据试一下test_x np.array([[0.5, 0.8], [-0.2, 0.3]]) test_z, _ forward(test_x) test_pred 1 / (1 np.exp(-test_z)) print(test_pred) # 输出接近 1 表示预测为“大于 1”接近 0 则相反第一条[0.5, 0.8]和为 1.3应该输出接近 1第二条[-0.2, 0.3]和为 0.1应该输出接近 0。如果结果符合预期恭喜你你已经亲手训练了一个神经网络。4. 新手避坑这五个地方最容易翻车4.1 现象损失值不降反升 → 原因学习率太大 → 解决调小学习率这是最经典的翻车现场。你满怀期待跑完 1000 轮结果损失值从 0.7 飙到 3.0 甚至变成nan。原因几乎都是学习率设太大了每次更新步子迈得太猛直接跨过了最低点越跑越偏。解决办法很简单把learning_rate从 0.1 改成 0.01 或 0.001 再试。如果还是不行检查一下数据有没有做归一化——输入值范围差太多也会导致训练不稳定。4.2 现象输出全是 0.5 → 原因权重初始化太小或激活函数选错 → 解决换初始化方式如果你的网络对任何输入都输出 0.5 左右说明它根本没学到东西。常见原因是权重初始化得太小信号传着传着就消失了或者你在隐藏层用了 Sigmoid深层网络里梯度会变得极小。入门阶段隐藏层统一用 ReLU权重用np.random.randn(...) * 0.1这种小随机数基本不会出这个问题。4.3 现象训练时好时坏每次结果都不一样 → 原因没固定随机种子 → 解决设 seed神经网络里有大量随机操作初始化权重、打乱数据顺序等。不固定种子的话每次运行结果都不同你根本分不清是代码改了有效还是单纯运气好。养成习惯在代码最开头写np.random.seed(42)保证每次运行起点一致。等调通了再取消固定看模型在随机情况下的平均表现。4.4 现象训练集表现很好新数据一塌糊涂 → 原因过拟合 → 解决加数据或加正则网络在训练数据上准确率 99%换一批新数据直接掉到 50%这叫过拟合。入门阶段最常见的原因是数据太少、网络太大。解决办法要么多造点数据要么把隐藏层神经元数量减少要么在损失函数里加一个 L2 正则项。别一上来就追求复杂模型简单问题用简单网络。4.5 现象代码报错shapes not aligned→ 原因矩阵维度对不上 → 解决打印形状逐个检查矩阵乘法对维度有严格要求(100, 2)的输入只能和(2, 3)的权重相乘。新手经常在改网络结构时忘了同步改维度导致报错。遇到这种问题在每一行矩阵运算前加print(x.shape)把维度打出来看一眼就能找到哪里对不上。这是最笨但最有效的排查方法。5. 下一步学什么从跑通到真正会用5.1 先把这个例子改三遍比看十篇教程都管用跑通第一个例子只是起点真正让你从「抄代码」变成「会写代码」的是动手改。我建议你按下面三个方向各改一遍第一遍改网络结构。把隐藏层从 3 个神经元改成 10 个看看损失下降是变快了还是变慢了再加一层隐藏层观察训练效果有没有提升。第二遍改数据规律。现在学的是「和大于 1」你改成「第一个数大于第二个数」或者「两个数乘积为正」重新训练看网络还能不能学会。第三遍改激活函数。把 ReLU 换成 Sigmoid 或 Tanh对比训练速度和最终损失。每改一次你都会对「权重在学什么」「层数多了有什么影响」有更具体的感受。这种感受看教程是看不来的。5.2 入门之后的学习路径当你把全连接网络跑顺了可以按这个顺序往下走阶段学什么大概花多久巩固把反向传播的梯度推导自己推一遍3~5 天扩展学用现成框架搭同样的网络1 周进阶卷积网络处理图像、循环网络处理序列2~3 周实战找一个自己感兴趣的小数据集完整做一遍持续不要跳步。我见过太多人全连接还没搞明白就去搞目标检测结果调参调了两周连损失函数为什么用交叉熵都说不清。基础打牢了后面学什么都快。5.3 一个让我少走弯路的习惯从那以后我每次写完训练代码都强制自己先在小数据上跑一遍——比如只取 10 条样本、训练 50 轮看损失能不能降到接近 0。如果能说明代码逻辑没问题再换全量数据如果不能说明网络结构或超参数有硬伤这时候去调参才有意义。这个习惯帮我省掉了大量「跑了一小时发现代码写错了」的时间。希望帮到你。本文还有配套的精品资源点击获取