在python中制作keras模型的深度副本

在python中制作keras模型的深度副本,python,keras,Python,Keras,我想制作我的keras模型(称为model1)的深度副本,以便能够在for-a循环中使用它,然后为每个for-a循环迭代重新初始化,并使用模型的一个附加样本执行fit。我希望能够在每次迭代后初始化模型,因为在执行fit之后(我的模型已被修改,但我希望在使用加载权重从路径加载时保持原样) 我的代码如下所示: model1= create_Model() model1.compile(optimizer='rmsprop', loss='categorical_crossentropy') mode

我想制作我的keras模型(称为
model1
)的深度副本,以便能够在for-a循环中使用它,然后为每个for-a循环迭代重新初始化,并使用模型的一个附加样本执行
fit
。我希望能够在每次迭代后初始化模型,因为在执行
fit
之后(我的模型已被修改,但我希望在使用加载权重从路径加载时保持原样)

我的代码如下所示:

model1= create_Model()
model1.compile(optimizer='rmsprop', loss='categorical_crossentropy')
model1.load_weights('my_weights')

model_copy= create_Model()
model_copy.compile(optimizer='rmsprop', loss='categorical_crossentropy')

model_copy= keras.models.clone_model(model1)
for j in range(0, image_size):
      model_copy.fit(sample[j], sample_lbl[j])
      prediction= model_copy.predict(sample[j])
而且,每次在for循环中加载模型对我来说并不是很有效,因为这很耗时。在我的情况下,如何正确地进行深度复制?我发布的代码给出了与function.fit和我的参考模型model_copy有关的以下错误:

RuntimeError:您必须在培训/测试之前编译模型。使用
model.compile(优化器,loss)


问题是克隆后可能不会编译model_副本。事实上,有几个问题:

  • 显然,克隆不会复制丢失函数、优化器信息等

  • 在编译之前,还需要构建模型

  • 此外,克隆不会复制重量

  • 所以你需要在克隆后多做几行。例如,对于10个输入变量:

    model_copy= keras.models.clone_model(model1)
    model_copy.build((None, 10)) # replace 10 with number of variables in input layer
    model_copy.compile(optimizer='rmsprop', loss='categorical_crossentropy')
    model_copy.set_weights(model.get_weights())
    
    

    更简单的方法1:从文件加载权重 如果我对你的问题理解正确,有一个更简单的方法。您不需要克隆模型,只需要保存旧的_权重并在循环开始时设置权重。您可以简单地从文件中加载权重

    for _ in range(10):
        model1= create_Model()
        model1.compile(optimizer='rmsprop', loss='categorical_crossentropy')
        model1.load_weights('my_weights')
    
        for j in range(0, image_size):
              model1.fit(sample[j], sample_lbl[j])
              prediction= model1.predict(sample[j])
    

    更简单的方法2:从以前的get_weights()加载权重 或者,如果您不希望从文件加载:

    model1= create_Model()
    model1.compile(optimizer='rmsprop', loss='categorical_crossentropy')
    model1.load_weights('my_weights')
    old_weights = model1.get_weights()
    
    for _ in range(10):
        model1.set_weights(old_weights)
        for j in range(0, image_size):
              model1.fit(sample[j], sample_lbl[j])
              prediction= model1.predict(sample[j])
    

    如今,这是微不足道的:

    model2 = tf.keras.models.clone_model(model1)
    
    这将为您提供新模型、新图层和新权重。如果由于某种原因无法工作(我没有测试),此旧解决方案将:

    model1 = Model(...)
    model1.compile(...)
    model1.save(savepath) # saves compiled state
    model2 = keras.models.load_model(savepath)
    

    指标的状态如何?我也会在循环中每次调用
    reset\u metrics
    ,但我发现整个方案令人困惑。@JamesHirschorn,如果您谈论的是历史,则每次拟合后都会重置它,请参见此处:。至于每个层的状态,则取决于网络是否有状态,请参见此处:。我同意这是一个令人尴尬的问题。可以在当前模型1之前添加一个附加层,以拆分样本并并行运行。@Tim关于第二个更简单的方法:如果我有两个独立的网络(具有相同的体系结构),然后在一段时间后,我使用set_weights进入第一个网络,从第二个网络收集get_权重。现在,我有两个权重相同的网络。如果我修改第二个网络的权重(通过训练),而不直接修改第一个网络,它会影响第一个网络的权重吗?基本上,我要问的是set_weights/get_weights是否做“浅/深复制”,而不是仅仅“指向”同一个对象(如Python中的“a=b”)。我高度怀疑它是深复制,因为Keras只是tensorflow的包装器。@Tim所以在我的示例中,如果我编辑第一个网络的权重,它会影响第二个网络的权重吗?