新闻详情

新闻详情

首页 / 资讯中心 / 详情

用NumPy手写线性回归,彻底搞懂梯度下降与反向传播

发布时间:2026/9/29 16:49:03来源:尧图网络
用NumPy手写线性回归,彻底搞懂梯度下降与反向传播
从my开头给项目命名这件事几乎是每个自学编程的人都会干的事。当年我写第一个爬虫脚本时文件名就叫my_spider后来学前端搞了个my_web再到接触深度学习第一个亲手从零搭出来的线性回归项目理所当然就成了mylinear。这个项目的名字很朴素但它在我的学习路径里的分量比后来做过的任何花哨项目都重。因为它逼着我搞清楚了深度学习的底层逻辑——所谓训练到底是在做什么、损失到底损的是什么、梯度下降到底是怎么一步步找到答案的。所以我特别想把这个项目掰开揉碎了讲一讲它适合所有刚开始接触深度学习、被各种框架封装搞得一头雾水、想知道背后到底发生了什么的人。这个项目解决的痛点很明确市面上99%的深度学习入门教程上来就让你用PyTorch或TensorFlow搭个模型调个API跑通一个MNIST手写识别就完事学了三个月还是只会套模板。而Mylinear没有用任何深度学习框架只用基础Python语法和NumPy库手写了一个完整的线性回归模型从数据生成、前向传播、损失计算、梯度推导、参数更新到可视化评估全流程亲手实现一遍。跑通它的那一刻你对模型训练这四个字的理解会远超刷一百个教程。1. 项目定位与整体设计思路1.1 为什么第一个项目选线性回归很多人在B站、知乎上被各种眼花缭乱的深度学习项目吸引什么风格迁移、AI作画、目标检测恨不得第一天就上手一个能吹牛的项目。我可以负责任地说这条路九成九走不通。深度学习领域有一个很残酷的规律底层原理没吃透上层应用永远只是调包侠。线性回归作为第一个深度学习项目地位相当于编程界的Hello World但它又比Hello World值钱得多。它麻雀虽小五脏俱全一个完整的深度学习训练流程该有的元素它全都有模型参数、前向传播、损失函数、反向传播、梯度下降优化器、训练循环、评估指标。你把线性回归彻底搞懂了后面再学逻辑回归、Softmax分类、多层感知机就会发现所有东西都是同一个骨架换皮。我当时选它的逻辑也很实际线性回归的数学原理足够简单简单到我可以用手推的方式把每一个梯度算出来。这就保证了在调试代码的时候我能从数学上预先知道正确的答案应该是什么从而能100%确定我的代码是对是错。这个可校验性在学习阶段是无价之宝。你做个图像识别模型跑出来准确率90%你很难说是代码写对了还是运气好但线性回归这种任务我手算都能算出结果代码跑偏了立刻就能定位问题是出在前向传播还是梯度更新。1.2 技术选型弃框架用NumPy手写一切Mylinear项目最核心的决策就是不引入任何深度学习框架。我当时已经装了PyTorch也知道一行torch.nn.Linear(1, 1)就能搞定模型定义但我在认真对比后决定放弃这条看起来的捷径。我的想法是这样的PyTorch、TensorFlow这类框架本质上是一个黑盒自动微分引擎。你用loss.backward()梯度就自动算好了参数就自动更新了一切都像魔术。但问题恰恰出在像魔术上。如果你从来没有手动实现过反向传播你根本不知道backward()在背后做了什么不知道为什么梯度要乘以学习率不知道为什么权重会往某个方向调整。一旦模型训练不收敛你连从哪里排查都不知道。用NumPy手写就完全不一样了。你写的每一行代码都是显式的前向传播就是矩阵乘法损失函数就是求均方误差反向传播就是你亲手推导出来的梯度公式参数更新就是把梯度乘上学习率再减掉。没有魔法没有隐藏层每一个计算步骤都是透明的。这种透明感对于建立正确的直觉模型极其重要。就像学驾驶你可能是自动挡考出来的驾照但如果你连离合器的工作原理都没见过车一旦在路上出点小毛病你就彻底抓瞎了。1.3 项目结构规划Mylinear整体的文件结构很简单但麻雀虽小该有的层次都有mylinear/ ├── data.py # 数据生成与预处理 ├── model.py # 模型定义与前向传播 ├── loss.py # 损失函数定义 ├── optimizer.py # 梯度下降优化器 ├── train.py # 训练主循环 └── utils.py # 可视化与评估工具这种分模块的设计我是刻意模仿PyTorch的源码结构来做的。PyTorch里面就是nn.Module、loss_fn、optimizer这样的分层我把这个结构用手写的方式复刻了一遍等于提前预习了框架的组织思想。后面我真的开始用PyTorch之后发现自己的代码组织习惯跟框架的设计哲学天然契合完全没有别人初学框架时那种雾里看花的感觉。2. 核心概念拆解模型、损失与优化2.1 线性回归模型的数学本质线性回归的任务用一句话说就是找到一条直线让它尽可能拟合给定的数据点。数学表达就是y wx b其中w是权重斜率b是偏置截距。咱们用生活场景来类比一下。假设你要预测一套房子的价格你收集了很多数据面积80平米的房子卖100万100平米的卖130万120平米的卖155万……这些数据在坐标系里就是一个个点。线性回归要做的就是找一条直线让这条直线尽量贴近所有的数据点。有了这条线你拿着150平米的面积一算就知道大概能卖多少钱。在这个场景里x是房子面积y是房价w和b是要找的参数。深度学习的学习过程本质上就是不断调整w和b的值直到找到一组能让预测最准的参数。这里面就引出了两个核心问题怎么定义预测得准不准怎么调整参数让它越来越准第一个问题的答案是损失函数第二个问题的答案是梯度下降。这两者是所有深度学习模型的灵魂。2.2 损失函数把好坏量化成数字深度学习模型的训练必须有一个标尺来衡量当前模型有多烂。这个标尺就是损失函数Loss Function。Mylinear用的是回归任务最经典的均方误差Mean Squared Error, MSE。公式长这样L (1/N) * Σ(y_pred - y_true)²其中N是样本数y_pred是模型预测值y_true是真实值。每一项(y_pred - y_true)²是单个样本的预测误差的平方把所有样本的误差平方求平均就得到整体损失。为什么误差要平方而不是直接用绝对值我在学的时候也困惑过这个问题。关键在于两点第一平方操作把负误差和正误差统一成了正数避免正负抵消——你不可能预测多了和预测少了互相将功补过第二平方放大了大误差的惩罚力度。预测偏差1个单位损失是1偏差2个单位损失是4偏差越大惩罚越重。这个特性会促使模型优先去解决那些错得离谱的样本。MSE这个函数还有一个特别好的性质它是一个凸函数。凸函数的意思是整个函数图像像一个碗只有一个全局最低点。这意味着对线性回归来说我们理论上一定可以找到全局最优解不会像那些复杂的深度神经网络那样陷入局部最优的泥潭。这也是初学者应该从线性回归入门的原因之一——你不需要分心去处理优化上那些玄学问题。2.3 梯度下降沿着坡往下走有了损失函数这个标尺接下来就是优化问题了怎么调整w和b让损失值变小这里的关键认知是损失函数L是关于参数w和b的函数。改变了w的值L就会变。我们的任务是在L这个地形图上找到最低点。你可以把L想象成一座山谷w和b的不同取值对应山谷上的不同位置L的数值就是那个位置的海拔。怎么从山上下来最本能的方式就是看看我脚下哪个方向是下坡往那个方向迈一步到了新位置再判断方向再迈一步重复这个过程直到走到谷底。这就是梯度下降的直观逻辑。梯度数学上就是对每个参数求偏导数后组成的向量。它有一个极其重要的性质梯度的方向是函数值增长最快的方向那么负梯度方向自然就是函数值下降最快的方向。所以我们沿着负梯度方向更新参数就是在走下坡路。参数更新公式长这样w w - learning_rate * ∂L/∂w b b - learning_rate * ∂L/∂b这个公式里有个新面孔learning_rate也就是学习率。它代表的是每一步迈多大。学习率太大步子大可能直接跨过谷底跳到对面山坡甚至越走越远学习率太小步子太小虽然方向对但走半天也下不来训练速度极慢。关于学习率怎么调后面我会专门细讲这是训练过程中最常踩的坑。3. 实战用NumPy从零搭建Mylinear3.1 造数据先得有个标准答案当靶子训练模型得有数据。真实数据集往往包含各种噪声和异常值作为第一个项目我更倾向于先造一份带标准答案的合成数据。这样做的妙处在于因为我造数据的时候用的就是y 3x 2这样的规则所以我知道最优参数是w3、b2。模型训练完之后我直接对比一下就能知道自己写得到底对不对。数据生成的代码如下import numpy as np def generate_data(n_samples100, w_true3.0, b_true2.0, noise0.5): 生成线性数据: y w_true * x b_true noise noise是高斯噪声模拟真实世界中的随机干扰 np.random.seed(42) x np.linspace(0, 10, n_samples).reshape(-1, 1) y_true w_true * x b_true y y_true np.random.normal(0, noise, sizex.shape) return x, y这里有几个关键细节值得说一下np.random.seed(42)固定随机种子这是数据科学里必须养成的好习惯。不固定种子的话每次运行生成的噪声都不一样实验结果没法复现排查问题会非常痛苦。reshape(-1, 1)把x变成列向量。这是模拟真实场景中训练数据通常是二维的batch维、特征维的格式。Mylinear一开始就坚持用这种格式处理数据后面迁移到真正的深度学习框架时非常丝滑。噪声参数noise我刻意设置了一个比较合理的值数据本身有明显趋势但又不是完全一条直线这样模型有得学也能直观看到预测线不可能完全穿过所有点——因为有些噪声是模型无法预测的。3.2 模型与前向传播实现模型部分的代码干净简洁但每一行都有明确的功能定位class LinearModel: def __init__(self): # 参数初始化 self.w np.random.randn() * 0.01 # 权重初始化为接近0的小随机数 self.b np.zeros_like(self.w) # 偏置初始化为0 def forward(self, x): 前向传播: y_pred w * x b # x shape: (n_samples, 1) return self.w * x self.b参数初始化这里有个细节我要单独拎出来讲。为什么w要乘个0.01让它初始值很小如果w初始值设成10那么y_pred一开始就会很大损失值会是一个天文数字。这种情况下梯度下降要跑非常多轮才能把参数拉回来。如果把初始化的值压得很小相当于让模型从一个很平坦的起点开始下山一开始的损失就不会过分离谱。这个细节的重要性在后面扩展到神经网络时会更加凸显。初始化决定了训练的起点起点选不好模型可能根本不收敛甚至梯度爆炸。在Mylinear里因为模型简单初始化的影响不致命但我建议所有初学者都养成用np.random.randn() * 0.01做初始化的肌肉记忆后面你会感谢自己这个习惯。3.3 反向传播手推梯度公式这是Mylinear项目的灵魂环节。别的框架里一个backward()就搞定的事情在这里我得亲手把梯度公式推出来、写进代码里。整个过程很有仪式感但我保证把这个流程走一遍之后反向传播这个词在你脑子里就不再是一个抽象概念了。我们来推导一下。设预测值为y_pred wx b损失函数为L (1/N) * Σ(y_pred - y_true)²。先对w求偏导。根据链式法则∂L/∂w (1/N) * Σ 2(y_pred - y_true) * ∂(y_pred)/∂w (2/N) * Σ (y_pred - y_true) * x同理对b求偏导∂L/∂b (2/N) * Σ (y_pred - y_true) * 1写成代码def backward(self, x, y_true, y_pred): 反向传播计算梯度 grad_w: 损失对w的偏导数 grad_b: 损失对b的偏导数 n_samples x.shape[0] error y_pred - y_true # shape: (n_samples, 1) grad_w (2 / n_samples) * np.sum(error * x) grad_b (2 / n_samples) * np.sum(error) return grad_w, grad_b注意这里面梯度的计算方式error * x是逐元素乘法然后求和。这背后是有数学逻辑的——每个样本对梯度的贡献是它的误差乘上它的特征值x。直观理解就是误差越大而且这个样本的x值越大那么w的调整力度就应该越大。我一直觉得这段代码值得所有初学者反复看三遍。它的意义在于让你亲眼看到误差是如何通过链式法则一层一层传回参数的。等以后你用PyTorch看到loss.backward()你知道它内部干的就是这件事只不过它用了自动微分技术能处理复杂任意深的网络。3.4 训练主循环让参数动起来有了前向传播和反向传播训练循环本身非常简单就是反复重复预测-算损失-算梯度-更新参数四个步骤def train(x, y, model, epochs1000, lr0.01): losses [] for epoch in range(epochs): # 前向传播 y_pred model.forward(x) # 计算损失 loss np.mean((y_pred - y) ** 2) losses.append(loss) # 反向传播求梯度 grad_w, grad_b model.backward(x, y, y_pred) # 梯度下降更新参数 model.w - lr * grad_w model.b - lr * grad_b # 每100轮打印一次训练信息 if epoch % 100 0: print(fEpoch {epoch:4d} | Loss: {loss:.6f} | w: {model.w:.4f} | b: {model.b:.4f}) return losses这段两个关键点我要重点解释model.w - lr * grad_w这个减法操作的数学含义。为什么是减因为梯度指向的是函数值上升最快的方向我们要下降就得反着来。这个负号是整个深度学习中最重要的符号之一很多新手写代码时漏掉它结果发现训练完损失越来越大就是这里出了问题。训练循环的epoch概念。一个epoch表示把整个数据集过了一遍。这里迭代了1000轮意味着模型把100个样本看了1000遍通过反复观察和调整参数从初始值逐渐趋近于最优值。跑一下这个训练你会看到类似这样的输出Epoch 0 | Loss: 55.7143 | w: 2.0161 | b: 0.1318 Epoch 100 | Loss: 0.2617 | w: 2.9982 | b: 1.9502 Epoch 200 | Loss: 0.2542 | w: 3.0001 | b: 1.9966 Epoch 300 | Loss: 0.2541 | w: 3.0003 | b: 2.0011 ... Epoch 1000 | Loss: 0.2541 | w: 3.0002 | b: 2.0003看到这组输出的时候我那天晚上差点从椅子上蹦起来。w最终停在3.0002b停在2.0003而我造数据时的真实参数就是w3、b2。一个连深度学习框架都没用、纯手写的模型靠梯度下降自己找到了几乎完全正确的答案。那种我亲手创造了一个会学习的东西的感觉至今记忆犹新。4. 训练细节调优那些决定成败的小事4.1 学习率步子太大扯着蛋步子太小挪不动学习率是深度学习里最玄学也最重要的超参数。我在Mylinear里面试了几组不同的学习率表现差异之大足以让初学者直观理解它的威力。以1000轮训练为例学习率分别设为0.1、0.01、0.001和0.9结果天差地别lr0.01最稳妥收敛速度适中最终loss稳定在0.255附近参数接近最优值。lr0.1收敛极快前100轮就逼近最优解但最终的loss会在最优值附近小幅震荡因为步子太大刹不住车。lr0.001收敛非常慢1000轮还没完全走到最优值loss依然在下降中需要更多轮次。lr0.9训练直接崩溃loss变成NaN。因为更新幅度太大参数在最优解附近来回横跳而且跳动越来越剧烈数值溢出。这里lr0.9的失败案例特别值得拿出来说。我当时的参数初始化是w≈0.01b≈0第一轮算出来的损失大约90多。此时梯度非常大按lr * grad的公式一次更新就能把w从0.01推飞出去。等到下一轮w已经是个很大的数预测值疯了一样大损失变成天文数字梯度也变成天文数字再更新一次w直接溢出成NaN。NaN一旦出现训练就彻底废了因为NaN参与任何计算结果都是NaN。你会发现损失曲线在中途突然断掉后面的输出全是NaN。排查这个问题很简单打印每一轮的梯度值看到梯度值异常大基本就能锁定问题。给新手的建议是在项目初期宁可把学习率设小一点多跑几轮。训练时间长一点好过直接跑崩。等模型架构稳定之后再去做学习率调优也不迟。4.2 数据标准化让参数站在同一起跑线Mylinear的数据是单特征的x的范围是0到10y的范围大概在2到32。这里特征尺度差异还不算大没出什么乱子。但真实项目中一个特征可能是温度20~30摄氏度另一个特征可能是房价300万~1000万数值范围差几万倍都是常事。数值范围差异大的问题在梯度下降里会被放大。如果一个特征的数值大它对应的梯度也会大学习率按这个特征的尺度调整合适了另一个特征可能就差太多。多个特征的不平衡会让训练过程变得非常拧巴参数更新在个别方向上跳跃在其他方向上蠕动。解决方案是数据标准化Standardization——把每个特征都减去均值、除以标准差让它们都变成均值0、方差1的标准分布。我自己用过之后的心得是标准化之后损失函数的等高线从细长的椭圆变成近乎正圆梯度下降走的是捷径收敛速度会肉眼可见地加快。在Mylinear里加上标准化只需要几行代码# 数据标准化 mean_x, std_x np.mean(x), np.std(x) x_scaled (x - mean_x) / std_x # 训练完成之后预测时要对新的x做同样的标准化处理 x_new_scaled (x_new - mean_x) / std_x y_pred model.forward(x_new_scaled)注意最后一步标准化不是一个训练中顺手做的操作它是个管道操作——训练数据怎么处理推理数据也必须做完全相同的处理。我见过太多初学者在训练时做了标准化预测时忘记对新样本做同样的操作导致结果完全错误然后对着代码百思不得其解。这个坑我先帮你踩了看到这里的朋友务必记住。4.3 训练轮次如何判断模型学够了训练轮次epoch的设置也很讲究。设置太少模型还没收敛设置太多模型在最优解附近反复震荡白费算力而且可能过拟合。判断收敛有两个实用的观察方法第一看损失值。如果连续几百轮loss基本不再下降就说明模型已经收敛了。在Mylinear中从输出可以看到第300轮之后loss基本稳定在0.2541附近再训练只是微幅抖动没有任何实质提升。第二看参数值。当w和b不再明显变化就说明梯度已经很接近0了模型找到了近似的最优解。比如我那个实验里w停在3.0002b停在2.0003跟真实值3和2只差千分位了再迭代一万次可能还是会停在附近因为噪声的存在让loss曲面在谷底附近有微小的起伏。一个更高级的做法是设置早停机制Early Stopping——每跑几轮就评估一次验证集损失如果验证集损失连续多轮不降反升就停止训练。这个技巧在深度学习中防止过拟合极其重要Mylinear里虽然用不上但提前了解概念以后学复杂模型时会省很多力气。5. 常见问题与排查技巧实录5.1 Loss变成NaN的快速定位思路Loss输出中出现NaN这是新手训练的第一杀。排查思路按我的经验可以分几步一是检查学习率。这是最常见的原因像我前面说的lr0.9的惨剧。先降到0.001试试如果正常了就是学习率过大。二是检查数据。看数据中是否有NaN或无穷大值。有时候从文件读入的数据缺了一块没处理成为NaN然后梯度计算时把NaN传播到了整个网络。用np.isnan(x).any()就能快速检查。三是检查参数更新公式。看是否忘记除以样本数N或者是否有代码逻辑错误导致梯度被异常放大。5.2 损失不降反升的检查清单如果loss不仅没变小反而越来越大那基本可以断定是方向性错误。我经常帮人排查这类问题清单如下第一确认参数更新方向。这也是我前面强调过的必须是w - lr * grad如果写成w lr * grad恭喜你你在做梯度上升专门找损失最大的方向走模型越训越烂。第二确认损失函数公式。检查y_pred - y_true是不是写反了。如果写反了虽然梯度方向会反但在某些情况下比如预测值恰好很接近真实值训练还能勉强进行但一旦误差变大方向就完全错了loss曲线会剧烈震荡。第三确认梯度公式里有没有遗漏项。链式法则容易在多个因子上整个漏掉。比如忘记乘2/N这个系数learning rate相当于被放大了N倍行为会和lr过大一样。排查思路核心就一条从错误现象倒推逐步缩小范围。先验证输入输出数据的shape对不对再验证计算图的每个中间变量是否符合预期最后才怀疑数学公式。5.3 我的调试小技巧打印关键中间量受限于第一个项目的复杂度我采用了最朴素的Debug方式——把公式里的每一个关键中间量都print出来。从代码里看我觉得这可能不够优雅但你用的时候会发现它真的很管用。每一轮训练我打印这几个值y_pred的前5个值、error的前5个值、grad_w、grad_b、更新后的w和b。比如打印出y_pred的范围和y的范围差距很大那就是初始化或前向传播有问题如果error全部是正数或者全部是负数说明预测系统性地偏移了偏置b的梯度方向没问题但幅度可能不对。后来我学了更专业的工具比如Python的pdb调试器还有专门用于可视化训练过程的TensorBoard。但对于第一个项目来说打印足够解决99%的问题。条件不允许的话暴力print反而是最快的方式。5.4 一条心法九九归一回到数学在整个Mylinear的项目过程中我最大的心得就是深度学习的代码难题80%最终要回到数学上找答案。初学时你会觉得代码层面问题千奇百怪什么shape对不上、广播错误、梯度爆炸看起来都是工程问题。但仔细往下挖一层绝大多数都是因为你没有真正理解公式里每个符号的含义np.sum是对哪个维度求和为什么要reshape梯度向量应该是什么形状这些问题的答案全都在数学里。所以给所有初学者的建议是拿起纸笔把公式推一遍再回头改代码。这个笨办法看起来浪费时间实际上是最快的路。我在Mylinear项目里手推了梯度公式这个过程花了我一个小时但它让我在之后的几个月里几乎再没有因为不知道梯度怎么来的而卡壳过。6. 项目扩展从线性到非线性从手写到框架6.1 加一个非线性激活函数向神经网络迈一步Mylinear跑通之后最自然的进阶方向是把它扩展成一个单隐层神经网络。思路很简单在输入和输出之间加一层隐层隐层的输出经过一个非线性激活函数比如ReLU或Sigmoid再进入输出层。这个扩展的意义巨大。线性回归再强也只能拟合线性关系现实世界的绝大多数数据房价、股票、图像都不是线性的。而神经网络的万能逼近定理告诉我们只要隐层神经元够多哪怕只有一个隐层网络就能以任意精度逼近任何连续函数。我当时做了一个简单的实验数据仍然用y 3x 2但给x加了一个sin变换让数据变成y 3x 2 0.5*sin(10x)。线性回归模型拟合这个数据loss降不下来但我加上一个包含32个神经元的隐层、用ReLU做激活函数之后模型拟合效果立竿见影。那一刻我真的感受到了神经网络这个东西的威力——它不只是线性模型的简单升级它的拟合能力是质的飞跃。6.2 NumPy手写向PyTorch的平滑迁移当你手写过一遍前向、反向、参数更新之后迁移到PyTorch或者TensorFlow的体验会完全不一样。PyTorch版的线性回归核心代码长这样import torch.nn as nn import torch.nn.functional as F model nn.Linear(1, 1) optimizer torch.optim.SGD(model.parameters(), lr0.01) loss_fn nn.MSELoss() for epoch in range(1000): y_pred model(x_tensor) loss loss_fn(y_pred, y_tensor) optimizer.zero_grad() loss.backward() optimizer.step()这段代码在没写过Mylinear的人眼里是五在你眼里是熟。你看每一行都知道它在干什么nn.Linear(1, 1)就是定义了一个y wx b的线性层loss_fn里面的数学表达式你已经亲手推过loss.backward()背后是链式法则optimizer.step()就是执行w - lr * grad。框架只是把你要做的事情自动化了而不是替你做了一件你完全不理解的事情。6.3 下一步学习路径建议Mylinear之后我的学习路径是这样的首先把梯度下降的各种变体学一遍批量梯度下降BGD、随机梯度下降SGD、小批量梯度下降Mini-batch SGD。这个阶段以理论为主你不需要手写实现而是要理解它们之间的区别和适用场景。然后学习逻辑回归理解Sigmoid函数如何把线性输出映射成概率以及二分类任务中交叉熵损失相比MSE的优势。这一步是通往分类世界的门槛。接着上多层感知机MLP用NumPy和PyTorch各实现一遍。到这里你已经具备了理解深度学习所有核心概念的基础激活函数、隐藏层、反向传播、过拟合、正则化。最后再进军CNN和RNN就会发现它们无非是在原有骨架上换了不同的算子而已。到了这一步你已经不是初学者了你可以独立阅读论文、复现开源代码了。我这套学习路线走下来最大的感觉就是前面手写Mylinear花掉的那些额外时间在后面的学习里十倍百倍地赚了回来。因为核心概念已经内化成直觉了别人还在对着API文档发本身的你已经知道原理是什么。写在最后Mylinear这个小项目技术难度不高代码量几百行跟今天动不动几万行的深度学习工程比起来微不足道。但它的价值不在代码量而在它替你搭建的心智模型。它让我真正理解了所谓深度学习学习的过程并不神秘它就是一轮又一轮的预测-对比-修正是在高维空间里沿着梯度的方向走下山。这个过程枯燥吗挺枯燥的。刺激吗当你看到自己写的纯Python代码真的从数据中学出了一个规律看到参数从随机值逐渐逼近真实值那种刺激感会推着你继续往前走。如果你的第一个深度学习项目也打算叫Myxxx那我建议你别犹豫了动手吧。做出来跑通它然后凝视屏幕上的训练曲线和参数收敛过程你会上瘾的。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

从 Loop 到 Graph:用 LangGraph 搭建多 Agent 协作骨架,TaoToken 配置你跟上了吗? 2026/9/29 21:16:38

从 Loop 到 Graph:用 LangGraph 搭建多 Agent 协作骨架,TaoToken 配置你跟上了吗?

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
one-api 安装使用简单操作即可完成!TaoToken 统一 Key 通道配置实战 2026/9/29 21:16:38

one-api 安装使用简单操作即可完成!TaoToken 统一 Key 通道配置实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
VSCode 插件开发:终端集成避坑与 TaoToken 配置实战 2026/9/29 21:16:38

VSCode 插件开发:终端集成避坑与 TaoToken 配置实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
ComfyUI 中为什么叫 Checkpoint:从模型加载机制到 TaoToken 统一 Key 配置 2026/9/29 21:16:38

ComfyUI 中为什么叫 Checkpoint:从模型加载机制到 TaoToken 统一 Key 配置

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
Linux 下 Git 命令学习:TaoToken 统一 Key 接入 AI 助手的 config.toml 骨架 2026/9/29 21:16:37

Linux 下 Git 命令学习:TaoToken 统一 Key 接入 AI 助手的 config.toml 骨架

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
RK3576 I3C 总线实战:从 I2C 迁移到 DTS 配置与调试 2026/9/29 21:16:31

RK3576 I3C 总线实战:从 I2C 迁移到 DTS 配置与调试

1. 从 I2C 到 I3C:一次接口升级背后的真实动机第一次在 RK3576 的 datasheet 里看到 I3C 的时候,我的反应和大多数人一样:I2C 用了这么多年,传感器、EEPROM、PMIC 全都跑得好好的,为什么还要折腾一个新总线&#xff1f…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉