发布时间:2026/8/25 10:22:36
python神经网络编程入门(五)----误差算出来了,权重到底怎么改? 上一期我们费了九牛二虎之力终于搞懂了误差是怎么甩锅回去的。误差就像一张传单从输出层一路传回了输入层告诉每一个权重你错了多少但光知道错了还不够啊我们到底该怎么改改多少这就好比一个学生拿到了考卷知道自己哪道题做错了误差反向传播但下一步呢难道要瞎蒙一个正确答案吗当然不是这一期我们就来解决这个最核心、最激动人心的问题如何利用这些误差精准地调整每一个权重让神经网络越学越聪明。这背后的魔法就叫——梯度下降。一、为什么不能一步到位让我们先冷静一下问问自己为啥我们不干脆点直接用数学算出那个完美的权重组合呢想想看我们的神经网络哪怕只有3层每层3个神经元它要算的数学公式已经复杂到让人想哭。更别提那些有几百层、几百万个参数的现代网络了。那不用数学算我们用笨办法——穷举呢假设每个权重有1000种可能的值对于一个有18个权重的网络就有18000种组合。每测试一种要1秒钟那更新一次就要5个小时如果是一个有500个节点的网络这个时间会飙升到1.6万年所以无论是精密的代数计算还是愚蠢的暴力穷举都走不通。我们需要一个更聪明、更实际的方法。二、摸黑下山梯度下降的智慧想象一下这个场景你被蒙上眼睛扔在了一片连绵起伏的群山中。你的任务是找到这片山区的最低点也就是全局最小值。你看不见路手里只有一个能探测脚下几米地形的手电筒。你会怎么做正确的做法是用脚探一探周围找到最陡的斜坡然后朝着下坡的方向迈出一小步。到了新地方再重复这个动作——探路、下坡、迈步。就这样一步一步你终将抵达某个山谷的底部。这个摸黑下山的过程就是梯度下降的核心思想这里的山就是我们的误差函数你的位置就是当前的权重组合最陡的下坡方向就是梯度的反方向。三、为什么选误差的平方当导航地图在摸黑下山的比喻里我们得先定义山在哪。这座山就是误差函数它告诉我们当前的权重组合有多糟糕。但我们该选哪个函数来当这座山呢这里有三个常见的选项直接相减 (目标值 - 实际值)比如两个节点的误差分别是0.1和-0.1加起来等于0这相当于告诉你你没犯错这显然是错误的导航。取绝对值 (|目标值 - 实际值|)解决了正负抵消的问题。但它的图像像一个V字在谷底有个尖角。如果你用梯度下降会在那个尖角附近反复横跳永远无法精准地停在最低点。取平方 ((目标值 - 实际值)²)这是最常用的选择因为它图像平滑像个光滑的碗没有尖角梯度下降可以稳稳地走到碗底。数学友好对平方函数求导非常简单这为后面的计算铺平了道路。自带减速越靠近谷底坡度越平缓你的步子会自动变小不容易冲过头。四、寻路神器计算梯度好地图选好了误差的平方也知道了方法梯度下降那最关键的一步来了我们怎么知道最陡的下坡方向在哪这个最陡的下坡方向在数学上就叫梯度。它是一个向量可以理解为一个带方向的箭头指明了误差函数上升最快的方向。而我们需要的是它相反的方向——也就是负梯度方向。这个方向就告诉了我们每一个权重具体应该调大还是调小以及调多少最有效。这个计算过程就是反向传播在做的事情。上一期我们费尽心思把误差传回去就是为了计算这个梯度做准备。五、解密核心公式权重到底怎么改现在我们要揭开神经网络最核心的秘密权重更新的数学公式。别怕我们一步步拆解它。我们关注的是隐藏层和输出层之间的一个权重叫它w_{j,k}。这个公式告诉我们w_{j,k}应该调整多少。这个神奇的公式长这样Δw_{j,k} -α × (目标值ₖ - 实际值ₖ) × S(信号ₖ) × 输出ⱼ看起来有点吓人别怕我们把它拆成四块每一块都有非常直观的含义。-α(负的学习率)这是我们的步长控制器。α(学习率)决定我们每次迈多大的步子。步子太大α太大容易冲过头步子太小α太小则走得太慢。负号-非常重要因为我们要往下坡走所以要在梯度的前面加个负号反着来。(目标值ₖ - 实际值ₖ)这是输出层的误差。误差越大说明错得越离谱需要调整的幅度自然就越大。S(信号ₖ)这是激活函数的斜率。S代表S型函数Sigmoid。信号ₖ是进入输出节点的加权和。这个部分告诉你在当前这个信号强度下改变权重对输出的影响有多大。如果S型函数已经饱和了比如输出接近0或1那它的斜率就接近0改变权重也没什么效果了。输出ⱼ这是前一个隐藏层节点的输出。这个权重连接的前一个节点贡献的信号越强调整它对最终结果的影响就越大。这个公式把误差、信号的敏感度和前一层的影响力完美地结合在一起告诉我们每一个权重具体该怎么调。六、从一个到一片矩阵的终极简化我们刚刚搞定了一个权重的调整公式。但一个神经网络里有成千上万个权重难道我们要用for循环一个一个算吗当然不这时候我们的老朋友——矩阵又登场了。我们可以把所有公式打包成一个优雅的矩阵运算权重更新矩阵 -α × (误差矩阵) × (S矩阵) × (上一层输出矩阵)ᵀ七、最终把一切都串起来现在我们把这一期和上一期的所有知识串起来看看神经网络的一次完整训练循环是怎样的前向传播输入数据通过现有的权重一路计算得到预测结果。计算误差用误差的平方作为地图计算预测结果和真实值的差距。反向传播从输出层开始将误差甩回每一层为计算梯度做准备。计算梯度用我们刚学的核心公式计算出每一个权重的调整方向梯度。更新权重朝着梯度的反方向迈出一小步由学习率α控制更新所有权重。然后拿着更新后的权重再去处理下一个数据样本。如此循环往复成千上万次。这就是神经网络学习的全部秘密它没有在思考只是在不断重复犯错-计算-调整的过程直到把误差这座山踩在脚下。现在你已经掌握了神经网络最核心的训练算法——反向传播和梯度下降。下一期我们将把这些公式变成可以运行的代码让你亲手训练出第一个能学习的神经网络代码片段1import numpy as np # 1. 设置固定数据保证可复现 # 输入样本来自前文 X np.array([0.5, 0.3]) # 输入层 (2,) target np.array([0.9, 0.1]) # 目标输出 (2,) # 初始权重延续前文的数值 # 输入层 - 隐藏层 权重矩阵 (行: 隐藏节点, 列: 输入节点) W_ih np.array([ [0.1, 0.2], # 隐藏节点1 [0.3, 0.4] # 隐藏节点2 ]) # 隐藏层 - 输出层 权重矩阵 (行: 输出节点, 列: 隐藏节点) W_ho np.array([ [0.4, 0.3], # 输出节点1 [0.6, 0.8] # 输出节点2 ]) # 学习率 alpha 0.1 # 2. 定义激活函数及其导数 def sigmoid(x): S型激活函数 return 1 / (1 np.exp(-x)) def sigmoid_derivative(x): S型函数的导数假设x已经是经过激活后的输出即 sigmoid(x) # 如果用输出值 o 表示则导数为 o * (1 - o) return x * (1 - x) # 3. 前向传播 print(--- 前向传播 ---) # 隐藏层加权和 激活 hidden_input W_ih X # 进入隐藏层的信号 (2,) hidden_output sigmoid(hidden_input) # 隐藏层输出 (2,) # 输出层加权和 激活 final_input W_ho hidden_output # 进入输出层的信号 (2,) final_output sigmoid(final_input) # 网络最终输出 (2,) print(f输入: {X}) print(f隐藏层输出: {hidden_output}) print(f网络输出: {final_output}) print(f目标输出: {target}) # 4. 计算输出层误差 output_error target - final_output # 输出层误差向量 (2,) print(f\n输出层误差: {output_error}) # 总误差平方和可作监控 loss np.sum(output_error ** 2) print(f总误差 (平方和): {loss:.4f}) # 5. 反向传播计算梯度并更新输出层权重 # 计算输出层梯度 # 公式: dE/dW_ho - (target - output) * sigmoid(input) * hidden_output # 其中 sigmoid(input) output * (1 - output) # 注意因为我们要做梯度下降减梯度所以直接计算负梯度即可。 # 这里我们计算 delta_output (output - target) * sigmoid(input) # 然后权重更新量 - alpha * delta_output * hidden_output^T delta_output (final_output - target) * sigmoid_derivative(final_output) # (2,) gradient_ho np.outer(delta_output, hidden_output) # (2,2) 外积 # 更新权重 (梯度下降) W_ho_new W_ho - alpha * gradient_ho print(\n--- 更新隐藏层-输出层权重 ---) print(更新前:\n, W_ho) print(梯度:\n, gradient_ho) print(更新后:\n, W_ho_new) # 6. 反向传播计算隐藏层误差并更新输入层权重 # 隐藏层误差 W_ho^T * delta_output (因为 delta_output 已经包含了输出层的梯度) # 注意这里隐藏层没有目标值误差由输出层反传回来。 hidden_error W_ho.T delta_output # (2,) # 计算隐藏层梯度 # delta_hidden hidden_error * sigmoid(hidden_output) delta_hidden hidden_error * sigmoid_derivative(hidden_output) # (2,) gradient_ih np.outer(delta_hidden, X) # (2,2) 外积 # 更新权重 W_ih_new W_ih - alpha * gradient_ih print(\n--- 更新输入层-隐藏层权重 ---) print(更新前:\n, W_ih) print(梯度:\n, gradient_ih) print(更新后:\n, W_ih_new) # 7. 验证更新后的效果可选 # 用新权重再次前向传播观察误差是否减小 hidden_input_new W_ih_new X hidden_output_new sigmoid(hidden_input_new) final_input_new W_ho_new hidden_output_new final_output_new sigmoid(final_input_new) new_error target - final_output_new new_loss np.sum(new_error ** 2) print(\n--- 更新后验证 ---) print(f更新后网络输出: {final_output_new}) print(f更新后误差: {new_error}) print(f更新前总误差: {loss:.4f}) print(f更新后总误差: {new_loss:.4f}) print(f误差减小: {loss - new_loss:.4f})注意由于初始权重是随机选取且网络规模很小单次更新的效果可能不明显甚至误差可能略微上升因为步长α0.1可能略大。在实际训练中经过多次迭代后误差会稳定下降。你可以将alpha调小如0.01并循环训练多次即可看到更明显的效果。代码结构说明步骤对应数学公式实现方式前向传播O sigmoid(W · X)矩阵乘法 sigmoid()输出层误差E target - output向量减法输出层梯度δ_out (output - target) * sigmoid(output)逐元素乘权重梯度∇W_ho δ_out · hidden^T外积np.outer权重更新W_new W - α · ∇W减法隐藏层误差δ_hidden (W_ho^T · δ_out) * sigmoid(hidden)矩阵乘 逐元素乘隐藏层权重梯度∇W_ih δ_hidden · X^T外积你可以在此基础上扩展成循环训练多轮或者加入批量样本处理但当前的代码已经完整展示了一次迭代的全流程非常适合配合文章学习。

相关新闻

2026/8/25 11:47:56

让 Claude Code 直接操作 ChatGPT:一个零成本的网页自动化方案

让 Claude Code 直接操作 ChatGPT:一个零成本的网页自动化方案 如果你在用 Claude Code 写代码,同时又需要时不时请教 ChatGPT,你大概率经历过这个场景: > 停下编码 → 打开浏览器 → 复制粘贴问题 → 等回复 → 再把结果搬回来…

2026/8/26 3:29:41

UE5材质工作流进阶:从PBR通道到分层混合与实例化复用

这篇是 UE5 材质大师班的下篇。上篇我们把 PBR 的基础通道理了一遍,也就是 Base Color、Roughness、Metallic、Normal 这套东西到底在模拟什么物理现象。这篇直接进入另一件事:当贴图不再是单独一张图,而是需要把一个物体拆成十几层信息叠加、…

2026/8/26 3:29:41

磁珠选型实战:高频噪声抑制与EMI整改核心指南

1. 磁珠(Bead)不是装饰品,是电路里最沉默的“噪声清道夫”你拆过手机主板吗?有没有注意过那些贴在USB接口、HDMI走线旁、电源输入端附近的小圆柱体——颜色多为灰黑或深绿,表面光滑,尺寸比米粒还小&#xf…

2026/8/26 3:29:41

LeetCode 605种花问题:数组遍历解法与面试技巧

1. 项目背景与问题拆解这道LeetCode 605题"种花问题"是典型的数组模拟类题目,经常出现在大厂初级算法面试中。题目要求在一个由0和1组成的一维数组中(0表示空位,1表示已种花),判断能否在不违反相邻种植规则的…

2026/8/26 3:29:41

从antirez的ds4仓库看数据结构设计与C语言源码阅读

antirez 这个名字,对 Redis 用户来说几乎等同于“开源作者”这四个字。作为 Redis 的创造者,他当初用一份简洁的 C 代码改变了缓存、队列、消息中间件的工作方式;而最近,他的 GitHub 上出现了一个叫 ds4 的仓库。项目名很短&#…

2026/8/26 3:29:41

AI招聘筛选技术解析与测试工程师转型指南

1. AI招聘筛选的技术变革与测试行业冲击2026年的招聘市场正在经历一场由AI驱动的技术革命。作为从业十年的软件测试工程师,我亲眼见证了传统招聘流程从人工筛选到算法决策的转变过程。目前主流招聘平台的AI筛选系统主要基于三大技术支柱:自然语言处理&am…

2026/8/26 3:24:41

基于腾讯位置服务与AI的智能找厕应用开发实践

1. 项目缘起:一个“急”出来的产品构想不知道你有没有过这样的经历:在一个陌生的商圈、公园或者大型交通枢纽,突然内急,却怎么也找不到公共厕所的指示牌。打开手机地图,搜索“厕所”,要么结果寥寥无几&…

2026/8/25 1:04:19

[光学原理与应用-521]:对光的错误理解与纠偏

首先光是一种能量的载体和形态,宏观上观察到的光是由无数个微观的光量子组成的,每个光子在产生的瞬间,其在真空的空间中以确定不变的速度沿着一个初始的方向一直向前,在微观层面,每个光量子的运动轨迹是以波函数所展现…

2026/8/25 11:48:27

SIP通话转接原理与REFER方法实战解析

1. 通话转接不是“挂断再拨号”,而是SIP会话的动态重定向你有没有遇到过这样的场景:客服坐席A正在和客户通电话,突然需要把这通对话无缝转给专家坐席B,客户完全感知不到中间的断连——既没听到忙音,也没被要求重新拨号…

2026/8/25 16:56:43

Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

1. 为什么选择Kolla-ansible来部署单节点OpenStack?如果你正在寻找一种能把OpenStack从“概念”快速变成“可用的实验环境”的方法,那么Kolla-ansible几乎是当前最主流、最省心的选择。我见过太多人卡在手动编译依赖、配置服务、处理版本冲突的泥潭里&am…

2026/8/26 0:04:32

Python random 模块常用函数详解:从入门到实战

目录 1. 引言2. 准备工作3. 基础随机函数4. 序列相关函数5. 随机种子与复现6. 实战案例7. 注意事项8. 常见问题与排查9. 总结 1. 引言 摘要: 本文系统介绍 Python 标准库 random 模块中最常用的随机数生成函数。内容涵盖基础随机函数(random()、unifor…

2026/8/26 1:19:35

JSON总结

JSON概念 JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式,主要用于跟服务器进行交换数据。它基于ECMAScript的一个子集。 JSON采用完全独立于语言的文本格式,但是也使用了类似于C语言家族的习惯(包括C、C、C#、Java、JavaScr…

2026/8/26 1:19:35

保存连接sse 是什么原理,为什么不会一直请求

“保持连接”用的是 SSE(Server-Sent Events),本质是一个没有马上结束的 HTTP 请求。 过程是: 拷贝机发送一次请求: GET /api/code-sync/events服务器返回: Content-Type: text/event-stream但不关闭响应&…

2026/8/24 13:42:17

实测才敢推 AI论文网站 2026最新测评与推荐

2026年真正好用的AI论文网站,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。一、综…

2026/8/24 18:13:48

2026必备!AI论文网站测评:最新推荐与深度对比

2026年真正好用的AI论文网站,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。 一、…

2026/8/25 1:08:14

摆脱论文困扰!盘点2026年全网爆红的的AI论文写作工具

一天写完毕业论文在2026年已不再是天方夜谭。2026年最炸裂、实测能大幅提速的AI论文写作工具,覆盖选题构思、文献整理、内容生成、格式排版等核心场景,真正帮你高效搞定论文难题。 一、全流程王者:一站式搞定论文全链路(一天定稿首…