news 2026/9/30 3:38:11

PyTorch深度学习入门:从环境搭建到神经网络训练全流程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
PyTorch深度学习入门:从环境搭建到神经网络训练全流程

1. 工程起步:先把环境和目录搭顺手

刚接触 PyTorch 的时候,我吃过最大的亏不是模型写错,而是环境没弄干净。同一个机器上装了三套 Python,pip和conda混着用,最后import torch报的错五花八门,折腾一整天连第一个张量都没打印出来。后来我把这套流程固化下来,先解决环境,再谈模型。这篇内容就是把我这些年搭基础神经网络的完整路径拆开讲清楚,从环境搭建、张量操作、网络结构设计,一路到训练循环和问题排查,代码可以照着敲,参数我会解释为什么这么定。适合刚上手 PyTorch 想跑通第一个网络的读者,也适合写过几行代码但总在环境、形状、loss 上翻车的朋友。核心关键词围绕深度学习、PyTorch、神经网络展开,全程以能复现为标准。

1.1 框架选型:为什么大多数人的第一个网络都从 PyTorch 开始

选框架这件事,我的判断标准很简单:调试顺不顺手,出问题能不能一眼看到现场。PyTorch 用的是动态计算图,代码就是普通 Python,你可以像调试脚本一样在任意一行打断点、打印中间张量,这对新手极其友好。相比之下,静态图框架要先构图再执行,报错信息经常指向一个你根本没写过的内部节点,排查成本高出一截。

另一个现实原因是生态。pytorch官网的教程、动手深度学习这类公开资料、以及大量开源项目都默认用 PyTorch 写示例,遇到问题时能搜到的答案密度明显更高。我试过用别的框架跟着教程走,同一个网络要改好几处 API,学习的注意力全被语法占走了,反而没心思理解网络本身。

还有一点容易被忽略:PyTorch 的Tensor和 NumPy 的ndarray使用习惯几乎一致,你如果之前用matlab或者 NumPy 做过数值计算,迁移成本很低。前馈神经网络、bp神经网络、cnn卷积神经网络这些结构,在 PyTorch 里都能用很少的代码表达出来。所以我的建议是,第一个网络就用它,别纠结。

1.2 三种环境搭建路径与我的取舍

环境这块我总结成三条路,各有适用场景:

  • 全局安装:直接在系统 Python 里pip install torch。最省事,但一旦版本冲突,污染的是整个系统环境,我基本不用。
  • conda 虚拟环境:conda create -n dl python=3.10建一个独立环境。这是我推荐给新手的方案,隔离干净,切换方便,anaconda配置pytorch环境的教程也最多。
  • pip + venv:轻量,适合已经熟悉命令行的人。和 conda 比少了一层包管理,但速度更快。

我个人的习惯是 conda 建环境加 pip 装包,兼顾隔离和安装速度。装的时候有两点必须注意:第一,先确认 Python 版本,PyTorch 对版本有要求,太新的 Python 有时还没对应的轮子;第二,CPU 版和 GPU 版是两条不同的安装命令,官网首页会让你选Compute Platform,选 CPU 就装 CPU 版,别装完发现用不了显卡又回头重装。

注意:安装命令一定从官方页面按你的系统、包管理器、计算平台三个选项生成,别抄别人博客里的固定命令,系统和 CUDA 版本一变,命令就不一样了。

安装完验证是这样:

import torch print(torch.__version__) print(torch.cuda.is_available())

第二行返回True说明 GPU 可用,返回False而你确认有显卡,多半是驱动或版本对不上,这时候先别急着往下写模型。

1.3 目录结构与一个最小可跑工程

我见过太多人把所有代码塞进一个.py文件,跑通没问题,但想改个参数、换个数据集就乱成一团。我一般会这样组织:

project/ ├── data/ # 数据集 ├── models/ # 网络定义 │ └── mlp.py ├── utils/ # 工具函数 │ └── seed.py ├── config.py # 超参数 └── train.py # 训练入口

config.py里集中放超参数是个好习惯,学习率、批大小、训练轮数都放这里,改参数不用在代码里翻来翻去。utils/seed.py用来固定随机种子,保证结果可复现:

import random import numpy as np import torch def set_seed(seed=42): random.seed(seed) np.random.seed(seed) torch.manual_seed(seed) torch.cuda.manual_seed_all(seed)

这个函数看着不起眼,但做实验对比的时候,能不能复现直接决定了你的结论可不可信。我早期做bp神经网络拟合曲线的实验,两次跑出来差别很大,一度以为是模型问题,后来才发现是没固定种子,数据划分每次都不一样。

2. 张量、广播与自动求导:地基不能虚

很多人急着写网络,跳过张量直接看nn.Module,结果一遇到形状报错就懵。我的经验是,张量和自动求导这两块花半天时间吃透,后面省下的调试时间远超这半天。神经网络说到底就是对张量做一连串的加法和乘法,理解张量就理解了一半。

2.1 张量的形状语义与几种常用构造方式

张量可以简单理解成"带形状的数组",pytorch张量基础里最核心的概念就是shape。一维张量(3,)是向量,二维(2, 3)是矩阵,三维(batch, seq, feature)常用于序列,四维(batch, channel, height, width)是图像的标准格式。我看到形状就能大致判断数据处于哪个阶段,这是排查问题的第一直觉。

常用构造方式有几种:

import torch a = torch.tensor([[1.0, 2.0], [3.0, 4.0]]) # 从列表构造 b = torch.zeros(2, 3) # 全零 c = torch.ones(2, 3) # 全一 d = torch.randn(2, 3) # 标准正态 e = torch.arange(0, 10, 2) # 步长序列

这里有个细节容易被忽视:torch.tensor默认会从数据推断类型,整数列表会变成int64,而神经网络里的权重和输入几乎都要求float32。如果你把整数张量丢进线性层,会直接报类型不匹配的错。所以我在构造输入时习惯显式写dtype=torch.float32,或者用torch.tensor(data, dtype=torch.float32),省得后面到处找 bug。

还有一个高频坑是view和reshape的区别。view要求内存连续,reshape不要求。操作过transpose之后再view经常报错,这时候换reshape就行。我现在的习惯是,只要不确定内存布局就统一用reshape,虽然偶尔多一次拷贝,但省去了判断因果的时间。

2.2 广播机制:形状对不齐的锅大多在这里

广播是 PyTorch 里既强大又容易踩坑的机制。规则很简单:从最后一个维度往前对齐,维度相等或其中一个为 1 才能广播。比如(3, 4)和(4,)相加,后者会被当成(1, 4)再扩展到(3, 4)。听起来简单,但实际写网络时错误往往藏得很深。

我踩过的一个典型坑是做损失计算时,预测值形状是(batch, 1),标签形状是(batch,),两者相减后因为广播变成了(batch, batch),损失值看着正常,训练却不收敛。这类问题不会报错,只会让你怀疑人生。后来我养成了一个习惯:在关键的张量运算前后都打印一次shape,尤其在自定义损失函数里。

pred = model(x) # (batch, 1) label = y # (batch,) print(pred.shape, label.shape) loss = ((pred - label.unsqueeze(1)) ** 2).mean()

unsqueeze(1)把(batch,)变成(batch, 1),显式对齐维度。这种显式操作我强烈推荐,比依赖广播更安全,读代码的人也能一眼看懂你的意图。

2.3 autograd 与计算图:反向传播到底在算什么

pytorch基础框架里最优雅的设计就是自动求导。当你对张量做运算时,PyTorch 会默默记录一张计算图,反向调用backward()时沿着这张图算梯度。你不需要手推导数,但需要理解三件事。

第一,只有requires_grad=True的张量才会被追踪。模型参数默认开启,输入数据默认关闭,这是合理的,因为输入不需要梯度。

第二,计算图默认在每次反向传播后释放,如果你想连续反传两次会报错,需要设retain_graph=True,但正常训练用不到,看到这个参数说明你的训练逻辑可能有问题。

第三,梯度会累加,不会自动清零。所以每个训练批次里必须调用optimizer.zero_grad(),否则梯度会一直叠加,训练直接失控。这是我见过新手最容易漏的一行,症状是 loss 一开始就变成nan。

x = torch.tensor([2.0], requires_grad=True) y = x ** 2 + 3 * x y.backward() print(x.grad) # 2*x + 3 = 7

手动算一遍再对照输出,能帮你快速建立直觉。理解了这个例子,再看神经网络里成千上万个参数的梯度,本质是一样的,只是规模不同。

3. 把一个前馈神经网络拆开看

前馈神经网络是入门的第一站,虽然结构简单,但把它的每个部件搞清楚,卷积、循环网络都是在此基础上的延伸。我的建议是不要一上来就抄一个多层网络,而是先搞明白单层是怎么算的,再往上叠。

3.1 线性层:参数量是怎么算出来的

线性层做的是y = xW^T + b,输入维度in_features,输出维度out_features。它的参数量是in_features * out_features + out_features,前面是权重,后面是偏置。比如输入 784、输出 128 的层,参数量是784*128 + 128 = 100480。

能心算参数量是个实用技能。当你看到模型有上千万参数时,心里要有个数这些参数分布在哪几层,否则调模型就是盲猜。我在设计网络时经常先估算总参数量,判断是不是超过数据量能支撑的范围,参数过多而数据太少,过拟合几乎是必然的。

import torch.nn as nn layer = nn.Linear(784, 128) print(sum(p.numel() for p in layer.parameters())) # 100480

偏置这一项很多人会忽略,觉得它不重要,但在输入全零的情况下,没有偏置网络输出恒为零,学不动。所以除非有特殊理由,bias保持默认的True。

3.2 激活函数与非线性从哪来

如果只有线性层堆叠,不管叠多少层,整体等价于一个线性变换,模型表达能力极其有限。激活函数的作用就是引入非线性,让网络能拟合曲线、边界这些复杂关系。这也是为什么用深度学习cnn处理图像比用纯前馈网络效果好,卷积本身引入了局部连接,再叠加非线性,才能学到图像的层次特征。

常用激活函数我按场景推荐:

激活函数特点适用场景
ReLU计算快,缓解梯度消失隐藏层默认选择
LeakyReLU负半轴有斜率ReLU 出现死亡神经元时
Sigmoid输出 0 到 1二分类输出层
Tanh输出 -1 到 1早期网络,现在少用
Softmax输出归一化为概率多分类输出层

用 ReLU 有个经典问题叫"死亡 ReLU",某些神经元输出恒为负,梯度永远是零,再也不更新。表现是训练一段时间后 loss 不再下降。解决办法是把学习率调小,或者换 LeakyReLU。我一般在隐藏层用 ReLU 起步,如果发现训练卡住再换。

3.3 用 nn.Module 组织网络

PyTorch 组织网络的标准方式是继承nn.Module,在__init__里定义层,在forward里定义数据流。这种写法把参数管理和前向逻辑分开,结构清晰。

import torch.nn as nn class MLP(nn.Module): def __init__(self, in_dim, hidden_dim, out_dim): super().__init__() self.net = nn.Sequential( nn.Linear(in_dim, hidden_dim), nn.ReLU(), nn.Linear(hidden_dim, hidden_dim), nn.ReLU(), nn.Linear(hidden_dim, out_dim) ) def forward(self, x): return self.net(x)

nn.Sequential适合这种直线型结构,如果网络有分支、跳跃连接,就要在forward里显式写调用顺序。有一点必须注意:不要在forward里定义层,那样每次前向都会新建参数,模型根本学不到东西。这是新手常见错误,症状是参数量每次打印都不一样。

3.4 损失函数与优化器的搭配

损失函数衡量预测和真实值的差距,回归任务常用MSELoss,二分类用BCEWithLogitsLoss,多分类用CrossEntropyLoss。这里有个容易混淆的点:CrossEntropyLoss内部已经包含了 softmax,所以模型输出层不要再加 softmax,否则相当于做了两次,梯度会变小,训练变慢。

优化器负责根据梯度更新参数,最常用的是 Adam 和 SGD。Adam 收敛快,对学习率不敏感,适合快速验证想法;SGD 加动量在精细调优时有时能拿到更好的最终精度,但需要仔细调学习率。我的习惯是先用 Adam 跑通,确认流程没问题再尝试 SGD。

criterion = nn.MSELoss() optimizer = torch.optim.Adam(model.parameters(), lr=1e-3)

学习率1e-3是 Adam 的常用起点。如果 loss 震荡厉害就调小到1e-4,如果下降太慢就试3e-3。这些数值不是金科玉律,是我实践中比较稳的起点。

4. 完整训练流程:从数据到可复现的结果

网络定义只是骨架,真正让它学起来的是训练循环。我把整个流程拆成数据准备、循环步骤、验证保存、实验记录四块,每块都有固定动作,照着走不容易出错。

4.1 数据构造与 DataLoader

为了聚焦网络本身,我用一个合成数据做回归演示,拟合一条带噪声的正弦曲线,对应bp神经网络拟合曲线的场景。用TensorDataset和DataLoader打包,好处是自动批处理、可打乱、可多进程加载。

import numpy as np import torch from torch.utils.data import TensorDataset, DataLoader np.random.seed(42) x = np.linspace(-3, 3, 2000).astype(np.float32) y = np.sin(x) + np.random.normal(0, 0.1, x.shape).astype(np.float32) x_tensor = torch.from_numpy(x).unsqueeze(1) # (2000, 1) y_tensor = torch.from_numpy(y).unsqueeze(1) # (2000, 1) dataset = TensorDataset(x_tensor, y_tensor) loader = DataLoader(dataset, batch_size=64, shuffle=True)

unsqueeze(1)把一维输入变成二维,因为线性层期望输入是(batch, features)。这一步漏了会直接报维度错误。shuffle=True让每个 epoch 的批次顺序不同,有助于泛化,训练集一定要开,验证集可以关。

注意:输入和标签必须同为 float32。用 NumPy 生成数据时默认可能是 float64,torch.from_numpy会保留 dtype,喂给线性层就会类型不匹配,记得统一转换。

4.2 训练循环的五个固定动作

一个标准训练批次包含五个动作,顺序不能乱:

  1. optimizer.zero_grad()清空上一批梯度
  2. pred = model(x)前向计算
  3. loss = criterion(pred, y)计算损失
  4. loss.backward()反向传播求梯度
  5. optimizer.step()更新参数
model = MLP(1, 64, 1) criterion = nn.MSELoss() optimizer = torch.optim.Adam(model.parameters(), lr=1e-3) for epoch in range(200): model.train() total_loss = 0.0 for xb, yb in loader: optimizer.zero_grad() pred = model(xb) loss = criterion(pred, yb) loss.backward() optimizer.step() total_loss += loss.item() * xb.size(0) avg_loss = total_loss / len(dataset) if (epoch + 1) % 20 == 0: print(f"epoch {epoch+1}, loss {avg_loss:.5f}")

这里的loss.item()是把单元素张量取出 Python 数值,累加时记得乘上批次大小才是这批的总损失,最后除以样本总数得到平均损失。用total_loss += loss.item()而不乘批次大小是很常见的错误,会导致打印出来的 loss 随批大小变化,误导判断。

4.3 验证、指标记录与模型保存

训练集 loss 下降不代表模型好,必须留一部分数据做验证。我一般按 8:2 划分,训练完每个 epoch 在验证集上跑一次,但要注意切换模式:

model.eval() with torch.no_grad(): val_pred = model(val_x) val_loss = criterion(val_pred, val_y)

model.eval()会关闭 dropout 和 batch norm 的训练行为,torch.no_grad()关闭梯度记录,省显存也更快。这两行在验证和推理时都要加,漏掉的话验证结果会不稳定,显存也浪费。

模型保存推荐保存参数字典而不是整个模型对象:

torch.save(model.state_dict(), "mlp.pth") # 加载 model = MLP(1, 64, 1) model.load_state_dict(torch.load("mlp.pth"))

保存整个模型对象依赖代码结构,换个目录或改了类定义就加载不了,保存state_dict更稳。

4.4 一次完整的拟合曲线实验记录

我把上面代码跑一遍,记录几个关键节点。200 个 epoch、批大小 64、Adam 学习率 1e-3,损失从最初的约 0.32 降到 0.011 左右,拟合出的曲线和真实正弦基本重合。中途我试过把学习率设成 0.1,结果 loss 在 0.5 附近剧烈震荡,说明步子太大,直接跳过了低点;换成 1e-4 后曲线平滑但 200 轮只降到 0.15,收敛太慢。

这组实验说明一个直观道理:学习率太大走过头,太小走太慢。1e-3 是 Adam 的甜点区,不是随便写的。另外我注意到,隐藏层从 64 加到 256 后,训练损失降到 0.008,但验证损失反而略升,这是过拟合的早期信号,此时应该减小网络或加正则,而不是继续堆参数。

如果你想在自己机器上复现,记得跑之前调用set_seed(42),否则曲线每次都不一样,你没法判断改动到底有没有效果。

5. 训练不收敛?常见问题排查实录

训练出问题不可怕,可怕的是没有排查顺序。下面这套流程是我踩坑攒出来的,从现象到原因逐步缩小范围。

5.1 损失不降反升的排查顺序

遇到 loss 不降,我按这个顺序查:

  • 先看数据和标签对不对齐:打印几个批次的输入和标签,确认它们是一一对应的。数据打乱时如果只打乱了一个张量,标签就对错了,模型学的是噪声。
  • 再看学习率:这是最常见的元凶。太大导致震荡甚至发散,太小导致几乎不动。换成 1e-4 或 1e-3 试一轮。
  • 检查是否忘了 zero_grad:漏了这行,梯度累加,loss 会迅速变成 nan。
  • 确认输出层和损失函数匹配:回归用 MSE,多分类用 CrossEntropy,别混用。
  • 看输入是否归一化:输入数值范围过大(比如上万)会让梯度爆炸,训练前做标准化是常规操作。

我印象最深的一次是标签用了int64,损失函数算出来的值完全不对,改成 float 后立刻正常。这种问题不会报错,只能靠排查确认。

5.2 报错速查表

报错信息常见原因解决方式
shape mismatch输入维度与层不匹配检查 unsqueeze 和 in_features
expected scalar type Float张量是 int 类型转 float32
CUDA out of memory批太大或没清缓存调小 batch,删无用变量
leaf variable requires grad对非叶子张量赋值用 with torch.no_grad()
device mismatch数据和模型不在同一设备统一 .to(device)

设备不匹配这个坑我要多说一句。当你把模型.cuda()之后,输入数据也必须.to(device),否则一个在 CPU 一个在 GPU,运算直接报错。我的习惯是定义device = torch.device("cuda" if torch.cuda.is_available() else "cpu"),然后模型和数据都往这个变量上靠,代码在有无显卡的机器上都能跑。

5.3 几个容易忽略但影响很大的细节

第一个是model.train()和model.eval()的切换。如果你的网络里有 dropout 或 batchnorm,忘了切换会让训练和验证行为不一致,结果不可信。即使暂时没有这些层,我也建议养成切换的习惯。

第二个是速度监控。pytorch支持torch.cuda.synchronize(),GPU 运算默认异步,不看同步时间你测出来的速度是假的。做性能对比时先同步再计时。

第三个是数据在 CPU 和 GPU 之间的搬运开销。小批次频繁搬运反而比在 CPU 上慢,批大小太小时要留意这点。

第四个是随机种子的范围。只固定了torch.manual_seed是不够的,NumPy 和数据划分的随机也要固定,否则依然不可复现。

6. 从基础网络向 CNN 与序列任务延伸

把前馈网络跑通之后,往哪个方向走取决于你的任务。图像、文本、时序各有对应的结构,但底层的训练流程完全一样,换的是网络定义部分。我这里给两条延伸路径,帮你少走弯路。

6.1 图像任务为什么要换卷积

用纯前馈网络处理图像有两个硬伤。一是参数量爆炸,一张224x224x3的图展平成向量就是 150528 维,接一个 256 的隐藏层就要三千多万参数;二是丢失空间结构,图像相邻像素的关联被彻底打散,模型学不到局部特征。

卷积通过局部连接和权值共享解决这两个问题。一个3x3的卷积核只有 9 个权重,滑动时共享,参数量骤降,同时保留了空间邻域关系。这就是深度学习cnn在图像上碾压前馈网络的根本原因。我早年也疑惑过图像明明可以用前馈网络,为什么要费劲搞卷积,想通权值共享这一点后就豁然了。

6.2 一个最小 CNN 的结构拆解

class SmallCNN(nn.Module): def __init__(self, num_classes=10): super().__init__() self.features = nn.Sequential( nn.Conv2d(1, 16, kernel_size=3, padding=1), nn.ReLU(), nn.MaxPool2d(2), nn.Conv2d(16, 32, kernel_size=3, padding=1), nn.ReLU(), nn.MaxPool2d(2) ) self.classifier = nn.Sequential( nn.Flatten(), nn.Linear(32 * 7 * 7, 128), nn.ReLU(), nn.Linear(128, num_classes) ) def forward(self, x): return self.classifier(self.features(x))

这个网络针对28x28的灰度图。两次池化把尺寸从 28 降到 14 再降到 7,通道从 1 升到 32,所以全连接层输入是32*7*7。padding=1保证卷积后尺寸不变,只在池化时降采样。这个尺寸推导一定要会算,否则全连接层维度写错直接报错。

训练流程和前面的前馈网络完全一致,只是损失函数换成CrossEntropyLoss,输入换成四维图像张量。这也印证了我一直强调的:流程是通用的,变的是网络结构。

6.3 序列任务的入门思路

处理文本、时间序列这类数据,前馈网络同样能作为基线,但丢失了顺序信息。循环网络通过隐藏状态在时间步之间传递信息,能捕捉序列依赖。入门阶段我建议先用前馈网络跑一个基线,再换 RNN 对比效果,这样能直观感受到结构带来的差异。

不管用哪种网络,你都会发现环境、数据、训练循环、问题排查这套方法论是共通的。基础网络的价值就在这里,它是所有复杂模型的底座。

最后分享一个我在实际使用中的体会:不要追求一次写出完美模型,先把流程跑通,哪怕准确率很低,只要 loss 在稳定下降,说明数据流和梯度都是通的,剩下的就是调参和换结构。我见过太多人卡在第一步,想一次性写出最优网络,结果连报错都定位不到。跑通最小闭环,再逐步加复杂度,这是我这些年最受用的一条经验。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/30 3:37:58

天线技术核心原理与工程实践:从选型到调试全面解析

天线这个行当,说大不大,说小不小。做了这么多年射频和通信系统,我最大的体会是:很多人把天线当成一个“买来即用”的配件,但他们往往忽略了天线是整个无线链路里唯一以“辐射电磁波”为目的的器件。换句话说&#xff0…

作者头像 李华
网站建设 2026/9/30 3:37:58

Android 14 AOSP定制:去掉录屏确认弹窗的完整指南

做AOSP定制的兄弟应该都懂,系统录屏时的确认弹窗是个很烦人的东西。不管你是给教学平板做自动录屏,还是给企业设备做远程协助,只要产品需要无人值守地采集屏幕内容,这个弹窗就会一遍遍打断自动化流程。Android 14里这个情况还更特…

作者头像 李华
网站建设 2026/9/30 3:37:57

YOLOv11多尺度包裹识别与姿态估计在物流分拣线的实战指南

简介:这份34页PDF技术文档聚焦物流分拣系统的智能化升级,面向从事计算机视觉、物流自动化或目标检测开发的工程师与研究者,可作为YOLOv11落地的系统参考。内容从传统分拣系统的准确性与效率瓶颈切入,详细讲解YOLOv11的骨干网络、颈…

作者头像 李华
网站建设 2026/9/30 3:37:17

宝塔面板+Docker部署青龙面板:完整流程与避坑指南

青龙面板这类定时任务管理工具,这两年玩的人特别多。我见过不少人第一次部署时,直接在服务器上装Node环境、clone代码、手动改端口、用screen挂着进程,一套操作下来,依赖版本冲突、进程守护、开机自启这些问题轮番折腾&#xff0c…

作者头像 李华
网站建设 2026/9/30 3:36:41

MySQL调优最重要的两个参数:缓冲池与刷盘策略

1. 先说结论:为什么我把“最重要”框死在两个参数上前阵子帮朋友接手一台“已经调优过”的MySQL服务器。配置文件翻开来,洋洋洒洒改了三十多个参数,从max_connections到tmp_table_size,从query_cache_type到key_buffer_size&#…

作者头像 李华
网站建设 2026/9/30 3:36:09

IEEE 802.1Qca-2015解析:TSN显式路径控制、带宽预留与冗余保护

简介:IEEE 802.1Qca-2015 是 IEEE 802.1Q-2014 的修订版,全称即“局域网与城域网——桥与桥接网络 第24号修正案:路径控制与预留”,为以太网桥接网络增加显式路径控制、带宽预留与冗余保护能力,是 TSN 时间敏感网络协议…

作者头像 李华