类函数执行时变量被覆盖求助:如何保留初始模型参数?
问题:存储的模型初始参数被训练函数修改的原因及解决办法
复现代码
import numpy as np class PlainLR: def __init__(self) -> None: rng = np.random.default_rng(42) init_range = 1.0 / np.sqrt(float(10)) self.weights = rng.uniform(low=-init_range, high=init_range, size=10) self.bias = rng.uniform(low=-init_range, high=init_range, size=1) self.plaintext_weights = self.weights self.plaintext_bias = self.bias def get_model_parameters(self): return self.plaintext_weights,self.plaintext_bias def train(self): self.weights -= 3* (1 / 5) + self.weights * 10 self.bias -= 4 * (1 / 5) plaintextLR = PlainLR() plaintext_weights, plaintext_bias = plaintextLR.get_model_parameters() # 此处存储初始参数 print(plaintext_weights, plaintext_bias) plaintextLR.train() print(plaintext_weights, plaintext_bias) # 期望此处输出与上一行一致,但实际不同
原因解释
核心问题在于NumPy数组是可变对象:
当你在__init__里执行self.plaintext_weights = self.weights时,并没有创建新的数组,只是让plaintext_weights和weights指向了同一个数组对象的内存引用。后续train函数修改self.weights的操作,是直接在这个共享的数组内存上修改内容,所以之前保存的plaintext_weights变量自然会跟着变化。
解决办法
要保留初始参数,本质是要创建参数数组的独立副本,避免共享引用,有两种常用方式:
方式1:在类内部初始化时创建副本
修改__init__中的赋值逻辑,使用NumPy数组的.copy()方法生成独立副本:
def __init__(self) -> None: rng = np.random.default_rng(42) init_range = 1.0 / np.sqrt(float(10)) self.weights = rng.uniform(low=-init_range, high=init_range, size=10) self.bias = rng.uniform(low=-init_range, high=init_range, size=1) # 创建数组副本存储初始参数 self.plaintext_weights = self.weights.copy() self.plaintext_bias = self.bias.copy()
这样plaintext_weights和weights就是两个完全独立的数组,后续train修改weights时,不会影响初始的副本。
方式2:在外部获取参数时创建副本
如果不想修改类的内部实现,也可以在获取初始参数后立即复制:
plaintextLR = PlainLR() # 获取参数后立即创建副本保存初始值 plaintext_weights, plaintext_bias = plaintextLR.get_model_parameters() initial_weights = plaintext_weights.copy() initial_bias = plaintext_bias.copy() print(initial_weights, initial_bias) # 输出初始值 plaintextLR.train() print(initial_weights, initial_bias) # 此处仍输出初始值,不会被修改
内容的提问来源于stack exchange,提问作者Jimakos
相关产品推荐
相关产品推荐

