PyTorch自定义类中如何创建可让符号乘法生效的新权重参数
问题核心原因
你遇到的情况本质是没有将符号乘法的结果原地写回原参数:PyTorch中常规的张量乘法*属于非原地操作,执行后会返回一个全新的张量,不会修改原self.fixed_fb_weights的内存值。而所有带下划线后缀的张量方法(比如uniform_、mul_)才是直接修改原张量值的原地操作,你之前只完成了生成新张量的计算步骤,没有将结果写回原参数,所以原参数里始终保留的只有之前uniform初始化的结果。
可直接落地的修复方案
方案1:原地乘法(最省显存)
直接调用张量的原地乘法方法mul_(),不需要生成临时中间张量,直接在原参数的内存上完成符号相乘:
def reset_weights(self): # 关闭自动求导追踪,减少初始化阶段的冗余计算图开销 with torch.no_grad(): # 原有uniform初始化逻辑保持不变 torch.nn.init.uniform_(self.fixed_fb_weights) # 直接对原参数执行原地乘法,写入符号计算结果 self.fixed_fb_weights.mul_(self.sign)
方案2:拷贝结果回原参数
如果需要先校验计算出的带符号权重,再写回参数,可以用copy_()方法将计算结果覆盖到原参数上,全程不改变原nn.Parameter的模块注册属性:
def reset_weights(self): with torch.no_grad(): torch.nn.init.uniform_(self.fixed_fb_weights) # 先计算带符号权重,校验、逻辑判断等步骤可以加在这里 signed_w = self.sign * self.fixed_fb_weights # 将计算结果拷贝回原参数 self.fixed_fb_weights.copy_(signed_w)
必须避开的踩坑点
- 禁止直接写
self.fixed_fb_weights = self.sign * self.fixed_fb_weights:这种写法会把原有的nn.Parameter对象替换为普通Tensor,导致优化器、模块参数注册表无法识别这个参数,后续权重更新、设备迁移都会出现异常。 - 初始化阶段记得用
torch.no_grad()包裹操作:避免无意义的梯度追踪带来的显存/算力浪费。
内容的提问来源于stack exchange,提问作者Soha Lee
相关产品推荐
相关产品推荐

