LeNet-5结合SOM训练MNIST时遇PyTorch反向传播二次遍历错误
解决PyTorch反向传播错误的方案
问题根源
错误的核心原因是SOM的质心(centroids)张量在更新后被纳入了计算图,导致后续的反向传播尝试复用已释放的计算图节点。具体逻辑链:
- 初始
centroids的requires_grad为False(默认状态)。 - 计算
delta时,它依赖于模型输出z(requires_grad=True),因此delta会带有梯度追踪属性。 new_weights = centroids + delta会继承delta的requires_grad=True,直接赋值给centroids后,质心开始成为计算图的一部分。- 下一轮迭代中,使用该带梯度追踪的
centroids计算距离时,计算图会包含前序迭代的节点;调用backward()时,就会触发"重复反向传播"的错误。
修复方案
由于SOM质心是通过传统邻域规则手动更新的,不需要对其进行梯度追踪。在更新质心时,将其从计算图中分离即可:
将代码中的:
centroids = new_weights
替换为:
centroids = new_weights.detach()
detach()方法会返回一个与原张量数据一致但不追踪梯度的新张量,这样centroids就不会再被纳入计算图,后续反向传播只会针对LeNet模型的参数进行,彻底避免重复使用计算图的问题。
额外验证
确认你的优化器optimizer仅针对LeNet模型参数初始化(例如optimizer = torch.optim.Adam(model.parameters(), lr=...)),不要将centroids加入优化器——质心的更新逻辑是独立的SOM规则,不需要梯度下降参与。
内容的提问来源于stack exchange,提问作者Arun
相关产品推荐
相关产品推荐

