如何通过索引访问PyTorch模型参数并更新指定层权重?
解决方案
这里提供两种可直接生效的实现方式,均不需要额外的回写操作:
方案1:直接访问第一层属性(最稳妥)
你的Actor类中第一层全连接层明确命名为fc1,直接操作它的内部张量即可:
# 直接获取第一层权重的底层数据引用 fc1_weight = myModel.fc1.weight.data # 执行你的修改逻辑,原地修改会直接同步到模型参数中 fc1_weight[ind_cr, :] = 目标值 # 举个修改示例 # 如果需要修改第一层偏置,操作myModel.fc1.bias.data即可
方案2:通过参数列表索引修改
如果你需要通过parameters()返回的列表操作,注意做原地修改:
# 仅生成一次参数列表即可,不要放在循环中重复生成 params = list(myModel.parameters()) # params[0]对应fc1的权重,params[1]对应fc1的偏置 first_layer_weight = params[0].data # 用[:]做原地赋值,不要直接给first_layer_weight变量赋新张量,否则会断开和原模型的引用 first_layer_weight[:] = 修改后的张量
交叉操作代码优化版
你原有的交叉逻辑不需要遍历named_parameters,也不需要重复生成参数列表,直接操作两个模型的fc1层权重即可:
import random # 直接获取两个模型第一层权重的底层引用,原地修改直接生效 y1 = gene1.fc1.weight.data y2 = gene2.fc1.weight.data try: num_cross_overs = random.randint(0, int(y1.shape[0] * 0.3)) except: num_cross_overs = 1 for i in range(num_cross_overs): receiver_choice = random.random() if receiver_choice < 0.5: ind_cr = random.randint(0, y1.shape[0]-1) y1[ind_cr, :] = y2[ind_cr, :] else: ind_cr = random.randint(0, y1.shape[0]-1) y2[ind_cr, :] = y1[ind_cr, :] # 执行完成后两个gene的第一层权重已经完成更新,可直接作为子代使用
原代码不生效的原因
- 将生成参数列表的逻辑放在了遍历
parameter的循环中,每次循环都会重新生成列表,容易出现操作对象不一致的问题 - 如果直接给
y1/y2变量赋值了新的张量,会断开和原模型参数的引用,导致修改无法同步到模型中
内容的提问来源于stack exchange,提问作者BiozterzCodes
相关产品推荐
相关产品推荐

