从 0 到 1 写一个神经网络训练循环:别再只会 `model.fit()` 了

举报
Echo_Wish 发表于 2026/03/08 20:59:23 2026/03/08
【摘要】 从 0 到 1 写一个神经网络训练循环:别再只会 `model.fit()` 了

从 0 到 1 写一个神经网络训练循环:别再只会 model.fit()

作者 | Echo_Wish


很多人学深度学习的时候,其实都经历过一个阶段:

刚接触的时候,觉得 神经网络特别神秘

后来接触到 PyTorch / TensorFlow,写代码越来越简单:

model.fit(x, y)

训练就开始了。

准确率还挺高。

于是很多人就停在这里了。

但如果你问一句:

神经网络到底是怎么训练的?

很多人就开始沉默了。

其实说白了,神经网络训练本质就做三件事:

1️⃣ 前向计算(Forward)
2️⃣ 计算损失(Loss)
3️⃣ 反向传播更新参数(Backward)

今天这篇文章,我想带大家 不用任何深度学习框架,只用 Python + NumPy,从零写一个 神经网络训练循环

你会发现:

神经网络其实没有那么神秘,它本质上就是一堆数学计算。

我们一步一步来。


一、先看整体结构:训练循环到底在干什么

在正式写代码之前,先看一个训练循环的逻辑结构。

一个完整的训练循环其实就是:

数据输入
   ↓
前向传播
   ↓
计算损失
   ↓
反向传播
   ↓
更新参数
   ↓
重复很多次

所以我们接下来要做的事情就是:

把这五步用 Python 写出来。


二、先实现一个最简单的神经网络

我们先做一个最简单的网络:

输入层 (2)隐藏层 (3)输出层 (1)

也就是:

231

先初始化参数。

import numpy as np

np.random.seed(42)

# 输入 -> 隐藏层
W1 = np.random.randn(2, 3)
b1 = np.zeros((1, 3))

# 隐藏层 -> 输出层
W2 = np.random.randn(3, 1)
b2 = np.zeros((1, 1))

这里我们用 随机数初始化权重

这是神经网络的常见做法。

如果全部初始化为 0,模型就学不出东西。


三、实现前向传播(Forward)

神经网络本质上就是:

y = activation(Wx + b)

我们先实现一个 ReLU 激活函数

def relu(x):
    return np.maximum(0, x)

然后写前向传播:

def forward(X):

    global W1, b1, W2, b2

    # 第一层
    z1 = X @ W1 + b1
    a1 = relu(z1)

    # 第二层
    z2 = a1 @ W2 + b2
    y_pred = z2

    cache = (X, z1, a1, z2)

    return y_pred, cache

这里的 cache 很重要。

因为 反向传播需要用到前向传播的中间结果

所以要把它们保存下来。


四、定义损失函数

我们用最简单的 均方误差(MSE)

Loss = (y_pred - y)^2

代码实现:

def mse_loss(y_pred, y_true):

    loss = np.mean((y_pred - y_true) ** 2)

    return loss

如果预测和真实值差距越大,loss 就越大。

训练的目标就是:

让 loss 变小。


五、手写反向传播(核心)

这是很多人觉得最难的地方。

其实逻辑非常简单:

我们只需要计算 梯度

先写一个简单版本。

def backward(cache, y_pred, y_true, lr=0.01):

    global W1, b1, W2, b2

    X, z1, a1, z2 = cache

    m = y_true.shape[0]

    # dLoss/dz2
    dz2 = (y_pred - y_true) / m

    # 输出层梯度
    dW2 = a1.T @ dz2
    db2 = np.sum(dz2, axis=0, keepdims=True)

    # 传播到隐藏层
    da1 = dz2 @ W2.T

    dz1 = da1 * (z1 > 0)

    dW1 = X.T @ dz1
    db1 = np.sum(dz1, axis=0, keepdims=True)

    # 梯度下降更新参数
    W1 -= lr * dW1
    b1 -= lr * db1

    W2 -= lr * dW2
    b2 -= lr * db2

这段代码本质上就是在做:

梯度下降

公式其实很简单:

W = W - learning_rate * gradient

这就是深度学习最核心的优化方式。


六、写完整训练循环

现在我们可以把所有东西串起来。

先准备一点训练数据。

# 模拟数据
X = np.random.randn(100, 2)

y = (X[:,0] + X[:,1]).reshape(-1,1)

目标其实很简单:

y = x1 + x2

然后写训练循环。

epochs = 1000

for epoch in range(epochs):

    y_pred, cache = forward(X)

    loss = mse_loss(y_pred, y)

    backward(cache, y_pred, y, lr=0.01)

    if epoch % 100 == 0:
        print(f"epoch {epoch}, loss {loss}")

运行后你会看到:

loss 不断下降

说明网络正在 学习规律


七、为什么理解训练循环很重要

很多人学习深度学习的时候,一直在用:

model.fit()

其实这样会带来一个问题:

不理解模型是怎么训练的。

一旦遇到问题,比如:

  • 梯度爆炸
  • 模型不收敛
  • loss 不下降

就完全不知道怎么排查。

但如果你自己写过训练循环,就会发现:

神经网络其实就是:

矩阵乘法
+
激活函数
+
梯度下降

所有复杂的深度学习框架,本质上都是在做这些事情。


八、我个人的一点感受

这些年我见过很多做 AI 的工程师。

有些人非常依赖框架:

TensorFlow
PyTorch
Keras

模型一跑就几十层。

但如果你问:

反向传播是怎么实现的?

很多人其实说不清。

我一直觉得:

真正理解一件事情,最好的方式就是自己实现一遍。

哪怕只是一个最简单的版本。

当你从零写出一个神经网络训练循环时,你会突然发现:

原来深度学习没有那么神秘。

它只是把数学、算法和工程实现结合在一起而已。


结尾

今天我们做了一件非常有意思的事情:

纯 Python + NumPy,实现了一个完整的神经网络训练循环。

核心步骤其实只有五步:

初始化参数
前向传播
计算损失
反向传播
更新权重

理解了这些,你再去看:

  • PyTorch
  • TensorFlow
  • JAX

就会非常清晰。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。