【零基础学AI】第 21 章——神经网络怎样工作

第 21 章 神经网络怎样工作

文章目录

  • [第 21 章 神经网络怎样工作](#第 21 章 神经网络怎样工作)
    • [🌈 关于《AI 零基础 36 讲》](#🌈 关于《AI 零基础 36 讲》)
    • [1. 从一个加权计算开始](#1. 从一个加权计算开始)
    • [2. 沿着图算到输出](#2. 沿着图算到输出)
    • [3. 把图翻译成数组](#3. 把图翻译成数组)
    • [4. 改一项权重观察输出](#4. 改一项权重观察输出)
    • [5. 激活函数增加了什么能力](#5. 激活函数增加了什么能力)
    • [6. 根据损失更新参数](#6. 根据损失更新参数)
    • [7. 连续更新与实验范围](#7. 连续更新与实验范围)
    • [8. 运行与常见错误](#8. 运行与常见错误)
    • [9. 独立练习](#9. 独立练习)

先给出两个数字 1 和 2,按几组权重算下去,得到 5.5。目标值是 4,当前偏高。调整参数后重新计算,一次更新就能得到约 3.733。这是本章神经网络实验实际发生的变化。

我们从一个两个输入、两个隐藏节点、一个输出的网络开始。它小到可以拿纸笔算完,也能用 NumPy 验证。读完本章,你会得到网络结构图、逐步手算表、参数修改对照、二十次更新记录,并能说明每层的输入输出形状。请先完成第 16 章的梯度下降与第 20 章的评估,熟悉第 13 章数组计算。

🌈 关于《AI 零基础 36 讲》

🧠 零基础也能开始学 AI

《AI 零基础 36 讲》是一套面向初学者的 AI 入门教程。课程从认识和使用 AI 开始,逐步学习

Python、数据处理、机器学习与深度学习,再进入大模型应用开发,最后完成个人知识库助手的综合实践。

📖 本篇是正式讲解文章

通过具体例子、原创图示和操作结果讲清概念。涉及编程的章节提供可运行代码,方便你边读边试。

🎯 读完以后,动手检验

建议按专栏顺序学习,并完成对应的课后训练,检查自己能否独立运用本章知识。

博客专栏:《AI 零基础 36 讲》

1. 从一个加权计算开始

线性回归已经用过"输入乘系数,再加截距"的计算。一个神经元也可以先做类似动作,将收到的数字分别乘权重,求和后加偏置,再经过激活函数得到输出。这里的神经元是一个计算单元,名称不要求我们把程序想成真实大脑。

权重决定某个输入对当前加权和的影响,偏置提供一个不依赖输入的可调整常数。激活函数是对加权和继续做的一次变换。本章用 ReLU,它将负数变成零,正数保持原值。中文可以直接理解为"保留正值,截去负值"。

第一隐藏节点收到输入 1、2,对应权重 0.5、1.0,偏置为零。加权和为 1 × 0.5 + 2 × 1.0 + 0 = 2.5。经过 ReLU 后仍是 2.5。

第二隐藏节点收到同样两个输入,权重为 -1.0、0.5,偏置为 -0.5。加权和为 1 × (-1.0) + 2 × 0.5 - 0.5 = -0.5。经过 ReLU 后是零。

这两个节点属于同一层,使用同一份输入,各自算出一个结果。层就是这样一组计算单元。隐藏层位于输入与最终输出之间,当前计算得到两个中间数值,所以这一层宽度为 2。

2. 沿着图算到输出

图的方向从左到右。连线数字表示权重,隐藏节点下方写着偏置。输出节点接收 2.5 和 0,权重为 2.0、-1.0,输出偏置为 0.5。最终结果是 2.5 × 2.0 + 0 × (-1.0) + 0.5 = 5.5。

输出层没有额外使用 ReLU。本章做的是单个数值输出,5.5 没有分类概率含义。如果任务换成分类,还需要匹配类别的输出形式与损失。先把这一条计算走顺,下一章再让框架帮助处理参数。

量 手算过程 结果
z₁ 1 × 0.5 + 2 × 1.0 + 0 2.5
z₂ 1 × (-1.0) + 2 × 0.5 - 0.5 -0.5
h₁ max(0, z₁) 2.5
h₂ max(0, z₂) 0
预测 h₁ × 2.0 + h₂ × (-1.0) + 0.5 5.5
平方损失 (5.5 - 4)² 2.25

z 表示激活前的加权和,h 表示隐藏层激活后的输出。这两个记号用来区分计算阶段。前向计算就是按输入、隐藏层、输出层的方向依次算出结果。

损失函数将预测与目标之间的差异变成一个数,训练时希望它变小。本章采用平方损失,偏差 1.5,平方后为 2.25。第 20 章讨论过训练损失与最终评估的用途,在这里只观察训练变化。

3. 把图翻译成数组

先固定矩阵的含义。W1 的行对应输入,列对应隐藏节点。第零列 [0.5, 1.0] 是第一节点的两项权重,第一列 [-1.0, 0.5] 是第二节点的权重。

python 复制代码
import numpy as np

x = np.array([1.0, 2.0])
W1 = np.array([[0.5, -1.0], [1.0, 0.5]])
b1 = np.array([0.0, -0.5])
W2 = np.array([2.0, -1.0])
b2 = 0.5
z = x @ W1 + b1
h = np.maximum(0, z)
prediction = h @ W2 + b2
print("加权和", z)
print("激活后", h)
print("预测", prediction)
print("损失", (prediction - 4) ** 2)

输出依次为 [2.5 -0.5]、[2.5 0.]、5.5、2.25,与表格一致。@ 是矩阵乘法运算符,会按对应方向相乘求和。* 默认逐元素相乘,不会自动完成每个神经元的加权求和。

数组 本章形状 对应含义
x (2,) 一条记录的两个输入
W1 (2, 2) 两输入到两隐藏节点的权重
b1、z、h (2,) 每个隐藏节点一个数
W2 (2,) 两个隐藏结果到单输出的权重
b2、预测 标量 一个数值

本章只支持单条记录,因此没有批次维度。若一次输入三条记录,通常使用 (3, 2) 的矩阵,第一项表示记录条数,第二项表示每条特征数。下一章会实际使用一批数据,不能直接把本章限定单条的入口当成批量训练函数。

W1 恰好为方阵,转置后形状仍为 (2, 2),程序可能运行却含义改变。维度检查不能代替检查"行列各指什么",本章手算表和数值测试同时核对了这个约定。

4. 改一项权重观察输出

先不训练,只人工改变第一输入到第一隐藏节点的权重,将 0.5 改成零。第一节点加权和从 2.5 变成 2.0,第二节点不变,最终输出变成 4.5,平方损失降为 0.25。

python 复制代码
from examples.network_core import X, TARGET, initial_parameters, forward, loss

parameters = initial_parameters()
print("原输出与损失", forward(X, parameters)["output"], loss(X, TARGET, parameters))
parameters["W1"][0, 0] = 0.0
print("改动后输出与损失", forward(X, parameters)["output"], loss(X, TARGET, parameters))

输出两行分别为 5.5 2.25 与 4.5 0.25。这个实验给了你一条具体影响关系。某条连接的权重改变,会先影响相应节点,再影响后面的计算。

改另一节点的权重时,结果未必立刻变化。第二节点当前加权和为负,ReLU 输出为零。在改动还没使它跨过零的范围里,下游接到的仍是零。这与一个始终按同样比例响应输入的线性模型有差别。

5. 激活函数增加了什么能力

把两层纯加权求和连接起来,并不会仅凭层数就得到非线性关系。将第二层表达式代入第一层后,输入仍然只乘一个合并后的系数,再加一个合并后的常数。这个关系常被称为仿射变换,指线性计算加上偏置。

用一维教学例子看 ReLU 的影响。两个隐藏节点分别计算 ReLU(x) 和 ReLU(-x),输出将两项相加。当 x 为负,第二项保留;当 x 为正,第一项保留,最终得到绝对值函数 |x|。

图中的实线出现了折点。删去两个 ReLU 后,输出变成 x + (-x),在所有位置都为零。权重和连接都相同,激活函数改变了整段输入输出关系。

python 复制代码
import numpy as np

x = np.array([-2.0, -1.0, 0.0, 1.0, 2.0])
with_activation = np.maximum(x, 0) + np.maximum(-x, 0)
without_activation = x + (-x)
print("加入激活", with_activation)
print("移除激活", without_activation)

输出为 [2. 1. 0. 1. 2.] 与五个零。这里的权重由我们设定,没有进行训练。这个小例子只说明网络能够表达一种带折点的函数,无法证明任意网络都能顺利学到任意目标。

多层网络将前一层的输出交给后一层,不同层可以形成不同的中间表示。中间数值的实际含义由任务、数据与学到的参数共同决定,本章两个隐藏节点仅承担明确写出的数学计算。

6. 根据损失更新参数

手改 0.5 为零降低了损失,但参数很多时,需要一种可重复的规则。第 16 章的梯度下降可以继续使用。梯度告诉我们参数在当前位置小幅变化时,损失怎样变化;更新时用原参数减去学习率乘梯度。

反向计算从损失开始,沿计算关系往回求每个参数的梯度。这个过程常称为反向传播。本章用明确的链式计算实现,再用每个参数左右各改一小步的数值差分独立核对,九个参数的解析梯度与差分结果一致。

先看输出偏置。损失为 (预测 - 4)²,对预测的导数为 2 × (5.5 - 4) = 3。输出偏置每增加一点,预测增加同样一点,所以它的梯度也是 3。学习率取 0.02,偏置从 0.5 更新为 0.5 - 0.02 × 3 = 0.44。

输出权重第一项的梯度为 3 × h₁ = 7.5,从 2.0 更新为 1.85。沿着第一隐藏节点往回求,得到输入层第一列权重梯度 [6, 12],偏置梯度为 6。当前第二节点加权和为 -0.5,ReLU 在负半轴局部导数为零,这条路径的梯度为零。

参数 原值 梯度 一次更新后
W1 第一列 0.5, 1.0 6, 12 0.38, 0.76
b1 第一项 0 6 -0.12
W2 第一项 2.0 7.5 1.85
b2 0.5 3 0.44

所有梯度都在同一组旧参数上计算完,再一起更新。若改一个参数后立刻用新值计算下一个参数的梯度,会变成另一种过程。本章函数返回一组新参数,保留旧值,测试也确认了这个顺序。

python 复制代码
from examples.network_core import X, TARGET, initial_parameters, gradients, update, forward, loss

parameters = initial_parameters()
new_parameters = update(parameters, gradients(X, TARGET, parameters), rate=0.02)
print("新加权和", forward(X, new_parameters)["z"])
print("新预测", forward(X, new_parameters)["output"])
print("新损失", loss(X, TARGET, new_parameters))

新加权和约为 [1.78, -0.5],新预测约为 3.733,新损失约为 0.071289。它越过了目标 4,但偏离的距离比原来小。梯度下降不要求每一步恰好停在目标上,学习率控制本次更新幅度。

ReLU 在零点没有普通导数。本章代码采用零次梯度约定,差分核验选择的初始点远离零,避免把不可导位置的差分当作唯一正确导数。PyTorch 在下一章会自动处理相应计算图,具体边界约定仍要以框架文档为准。

7. 连续更新与实验范围

从初始参数开始,学习率保持 0.02,连续更新二十次。图的横轴是已完成更新次数,纵轴是平方损失。

末次预测接近 4,损失约为 7.89e-31。这是接近浮点计算精度的结果,展示时可以写"接近零",不用把它宣传成完全没有误差。

这里只有一条训练记录,许多不同参数都能使它输出 4,结果无法唯一解释每项权重应是什么。没有验证集,也没有独立测试数据。下一章会使用一组数据练习训练循环,图片分类与泛化评估留到之后。

8. 运行与常见错误

从本章目录运行,无需显卡,也无需下载数据。

powershell 复制代码
py -3.12 -m venv .venv
.\.venv\Scripts\python.exe -m pip install -r requirements.txt
.\.venv\Scripts\python.exe examples/run_network.py
.\.venv\Scripts\python.exe -m unittest discover -s tests -v

主程序保存手算表、更新 CSV、梯度差分对照和三张原创图,八项测试通过。绘图需要中文字体,Windows 使用微软雅黑,其他系统可以安装 Noto Sans CJK SC。

矩阵乘法提示维度不匹配时,先写出每项形状。本章输入长度为 2,W1 第一维也必须为 2。若误用 *,程序可能输出一个 (2, 2) 的表而没有立刻报错;这个形状已经暴露了加权求和没有完成。

损失上升时,先确认梯度与更新方向,再尝试减小学习率。若只看到零梯度,查看激活前的数值是否落在 ReLU 负半轴。当前负节点的零梯度符合计算,不能因此断言所有框架求导都失败了。

9. 独立练习

保持初始参数,把输入改成 [2, 1]。先算两项加权和、ReLU 输出与最终预测,再用程序核对。尝试只改输出偏置,解释为什么预测会同步变化。

答案与另外五道练习见【零基础学AI】第 21 章课后练习与答案。下一章用 PyTorch 自动求导,让本章人工计算的更新过程成为一个完整训练循环。

相关推荐
zwc32104320551 小时前
Day 8:Canny边缘检测
人工智能·计算机视觉
郝学胜-神的一滴1 小时前
游戏设计:原型与开发 19:U3D工位布置与性格说明书
人工智能·算法·unity·unreal engine·游戏策划·游戏设计
Data-Miner1 小时前
AI和Excel怎么结合才能真提效
人工智能·excel
七夜zippoe1 小时前
Spring AI 函数调用:让 Java 方法变成 Agent 的工具(实战全流程)
java·人工智能·spring·ai·agent·函数调用
wflynn1 小时前
DeepSeek 开源 Super-agent 架构:AI 主动发现 Bug 并提交 PR
人工智能·ai
rolt2 小时前
[鉴赏]02 DHH-摇身一变鼓吹软件工程
人工智能·软件工程·uml
天天代码码天天2 小时前
我用 C# 做了个拍照测量小工具:贴一张标记,量长度和面积
人工智能
聪明蛋子哟2 小时前
高扩展性AI应用架构指南:融合RAG检索、Agent编排与OpenAPI/RPC工具网关的设计模式
人工智能·rpc·架构
一水鉴天2 小时前
决策树、三支决策与随机森林:从精确值到能所双亡双活 20261030(元宝)
人工智能·机器学习