看到 tensor_of_ice 这个名字,你第一反应是什么?Tensor 是张量,ice 是冰,合在一起难道是指“冰的张量”?如果你按字面意思去理解,很容易一头雾水。但如果把 ice 读作一个动作——冻结(freeze)——整个思路立刻就清晰了: tensor_of_ice 讲的其实是“被冻结的张量”,也就是深度学习里那些不再参与梯度更新、参数保持固定不变的张量。
这个话题在模型训练和部署中太常遇到了。迁移学习时要冻结骨干网络,参数高效微调(LoRA、Adapter)时要冻结原始权重,显存不足时要靠冻结参数来省内存,甚至模型评测时也要保证某些权重不动。可以说,怎么控制张量的“冻结”状态,几乎决定了你从“能跑通代码”到“能设计训练策略”的差距。
这篇文章就以 tensor_of_ice 为切入点,系统讲清楚三件事: 为什么要冻结张量、如何在 PyTorch 里正确地冻结、冻结后怎么验证和排错 。文中的完整示例基于随机数据即可运行,不需要你提前准备数据集,适合第一次接触参数冻结的读者直接照着跑一遍。
1. 为什么讲“冻结的张量”:它解决的真实痛点
很多初学者刚开始写训练脚本时,习惯直接用一个优化器包住 model.parameters() ,然后从头训练。这种方式在小模型、大数据集上没有问题,但一旦进入真实项目,立刻会撞上四个痛点。
第一个痛点是显存不够。 反向传播时,PyTorch 需要为每个参与梯度计算的参数保存中间状态。模型越大,显存开销越大。一个几亿参数的模型,即使输入数据很小,也可能在 loss.backward() 这一步直接 OOM。而如果把这些参数冻结,autograd 就不会为它们记录梯度,显存占用能明显降下来。
第二个痛点是数据量不够。 用预训练模型做下游任务时,比如把 ResNet 迁移到一个小规模医学影像数据集上,数据量可能只有几千张。这时如果放开全部参数训练,很容易过拟合;冻结大部分参数只训练最后的分类头,反而更稳。这不是玄学,而是因为预训练模型已经学到了通用的特征提取能力,小数据不足以支撑它再做大规模调整。
第三个痛点是训练成本。 每次参数更新都要计算梯度,而梯度计算是训练中最贵的部分。冻结骨干网络后,反向传播只在最后几层生效,训练速度会明显提升。对于需要反复实验的团队来说,这个时间收益非常可观。
第四个痛点是多任务和持续学习。 在推荐系统、多任务模型里,经常希望某些底层特征提取模块保持稳定,只更新任务相关分支。如果不冻结共享部分,一个任务的梯度更新可能会破坏另一个任务已经学好的表示。
所以, tensor_of_ice 表面上看是一个有趣的项目名,实际上指向的是一个通用工程能力: 明确地控制模型里哪些张量参与优化,哪些张量保持冻结 。这个能力在迁移学习、参数高效微调、推理加速里都会用到。
2. Tensor 基础:先搞清楚张量是什么,以及“冻结”的本质
2.1 从标量到张量
在讲冻结之前,必须先把 Tensor 本身说清楚。张量(Tensor)是深度学习框架中的核心数据结构,你可以把它理解为“可以放在 GPU 上计算的多维数组”。
- 标量是 0 维张量:
1.0 - 向量是 1 维张量:
[1.0, 2.0, 3.0] - 矩阵是 2 维张量:
[[1.0, 2.0], [3.0, 4.0]] - 3 维及以上就统一叫张量,比如一张彩色图片可以表示成
(3, H, W)的张量,一个批次的多张图片可以表示成(B, 3, H, W)的张量
在 PyTorch 里,模型的每一层权重都是一个 Tensor,输入数据是一个 Tensor,梯度是一个 Tensor,优化器的状态也围绕 Tensor 展开。可以说, Tensor 是深度学习世界里的“通用货币” 。
2.2 张量与梯度:冻结的本质是控制 autograd
张量本身只是一个数据容器,真正让张量“活”起来的是自动求导机制(autograd)。当我们设置 x.requires_grad = True 时,PyTorch 会开始追踪所有对 x 的操作,并在反向传播时回传梯度。
那么“冻结”发生在哪一层?其实有两条路径。
第一条路径是 不计算梯度 。设置 param.requires_grad = False ,等于告诉 autograd:这个参数不需要追踪梯度,反向传播时请绕开它。这样,即使模型调用了 loss.backward() ,这个参数对应的 .grad 也是空的,优化器自然无法更新它。
第二条路径是 计算了梯度,但不放进优化器 。优化器只会更新它持有的参数列表。有些参数虽然 requires_grad = True ,只要不传给 optimizer ,就永远不会被更新。这两条路径合起来,才是工程上完整的“冻结”。
所以, tensor_of_ice 里的 ice 并不是一个具体的算法,而是一种控制策略: 你决定哪些 Tensor 保持“冷”状态,不参与梯度流动。
2.3 Tensor 的常用元信息
在实际写代码前,先熟悉三个最常见的 Tensor 属性和方法,后面示例都会用到:
| 属性/方法 | 含义 | 典型用途 |
|---|---|---|
.shape |
张量每个维度的大小 | 查看参数形状、检查维度是否匹配 |
.dtype |
张量数据类型(float32、int64 等) | 排查精度问题、混合精度训练 |
.requires_grad |
是否需要梯度 | 判断参数是否被冻结 |
.numel() </ |
319



被折叠的 条评论
为什么被折叠?



