【问题标题】:How add new class in saved keras sequential model如何在保存的 keras 顺序模型中添加新类
【发布时间】:2019-01-01 01:48:29
【问题描述】:

我有 10 个类别的数据集,我得到了 85% 的准确度,在保存的模型上得到了相同的准确度。 现在我想添加一个新类,如何将新类添加到保存的模型中。 我尝试删除最后一层并进行训练,但模型过拟合,并且在预测中每个图像都显示相同的结果(新添加的类)。

这就是我所做的

model.pop()
base_model_layers = model.output
pred = Dense(11, activation='softmax')(base_model_layers)
model = Model(inputs=model.input, outputs=pred)
# compile and fit step

我已经用 10 类训练了模型我想用 11 类数据加载模型训练并给出预测。

【问题讨论】:

  • 您可能希望冻结其他层以停止进一步训练
  • @SreeramTP 怎么做
  • 我觉得这和你的 issue learnopencv.com/…类似
  • 更多关于冻结和迁移学习的信息可以在这篇博文deeplearningsandbox.com/…上找到

标签: keras deep-learning conv-neural-network image-recognition


【解决方案1】:
model.pop()

base_model_layers = model.output
pred = Dense(11, activation='softmax')(base_model_layers)
model = Model(inputs=model.input, outputs=pred)

在训练前冻结第一层

for layer in model.layers[:-2]:
    layer.trainable = False

【讨论】:

    【解决方案2】:

    使用 model.pop() 方法,然后使用 Keras Model() API 会导致错误Model() API 没有 .pop() 方法,所以如果你想多次重新训练你的模型,就会出现这个错误。 p>

    但只有在重新训练后保存模型并在下次重新训练时使用新保存的模型时才会出现错误。

    另一个非常错误并且使用过的方法是使用 model.layers.pop()。这次的问题是该函数只删除了它返回的副本中的最后一层。所以,模型还是有层的,只是方法的返回没有层。

    我推荐以下解决方案:

    承认您已将已训练好的模型保存在模型变量中,例如:

    model = load_my_trained_model_function()
    
    # creating a new model
    model_2 = Sequential()
    
    # getting all the layers except the output one
    for layer in model.layers[:-1]: # just exclude last layer from copying
        model_2.add(layer)
    
    # prevent the already trained layers from being trained again 
    # (you can use layers[:-n] to only freeze the model layers until the nth layer)
    for layer in model_2.layers:
        layer.trainable = False
    
    # adding the new output layer, the name parameter is important 
    # otherwise, you will add a Dense_1 named layer, that normally already exists, leading to an error
    model_2.add(Dense(num_neurons_you_want, name='new_Dense', activation='softmax'))
    

    现在您应该指定编译和拟合方法来训练您的模型并完成:

    model_2.compile(loss='categorical_crossentropy',
                    optimizer='adam',
                    metrics=['accuracy'])
    
    # model.fit trains the model
    model_history = model_2.fit(x_train, y_train,
                                batch_size=batch_size,
                                epochs=epochs,
                                verbose=1,
                                validation_split=0.1)
    

    编辑:

    请注意,通过添加新的输出层,我们不会在上次训练中调整权重和偏差。

    因此,我们几乎失去了之前训练的所有内容。

    我们需要保存上一次训练的输出层的权重和偏差,然后我们必须将它们添加到新的输出层中。

    我们还必须考虑是否应该让所有层都训练,或者即使我们应该只允许训练一些插层。

    要使用 Keras 从输出层获取权重和偏差,我们可以使用以下方法:

    # weights_training[0] = layer weights
    # weights_training[1] = layer biases
    weights_training = model.layers[-1].get_weights()
    

    现在您应该指定新输出层的权重。例如,您可以将权重的平均值用于新类的权重。这取决于你。

    要使用 Keras 设置新输出层的权重和偏差,我们可以使用以下方法:

    model_2.layers[-1].set_weights(weights_re_training)
    

    【讨论】:

      【解决方案3】:

      我假设问题是单标签多类分类,即样本将仅属于 11 个类中的 1 个。

      这个答案将完全基于实现人类学习机器的方式。因此,这不会为您提供如何执行此操作的正确代码,但它会告诉您该做什么,您将能够轻松地在 keras 中实现它。

      当你教他新东西时,人类孩子如何学习?起初,我们要求他忘掉旧事,学习新事物。这并不是说旧的学习没有用,而是说在他学习新的时候,旧的知识不应该干扰,因为它会混淆大脑。所以,孩子只会学一段时间。

      但这里的问题是,事情是相关的。假设,孩子学习了 C 编程语言,然后学习了编译器。编译器和编程语言之间存在关系。如果单独学习这些科目,孩子就无法掌握计算机科学,对吗?在这一点上,我们引入了“智能”一词。

      知道他以前学到的东西和现在学到的东西之间存在关系的孩子是“聪明的”。找到两者之间实际关系的孩子是“聪明的”。 (深入这个是题外话)

      我想说的是:

      • 让模型单独学习新的类。
      • 然后,让模型找到之前学习的类和新类之间的关系。

      为此,您需要训练两个不同的模型:

      1. 学习对新类进行分类的模型:该模型将是一个二元分类器。如果样本属于第 11 类,它预测为 1,否则为 0。现在,您已经拥有属于 11 类的样本的训练数据,但您可能没有不属于 11 类的样本的数据。为此,您可以随机选择属于 1 到 10 类的样本。但请注意为了正确训练模型,属于第 11 类的样本与不属于第 11 类的样本的比例必须为 1:1。这意味着,50% 的样本必须属于第 11 类。
      2. 现在,您有两个单独的模型:一个预测类别 1-10,一个预测类别 11。现在,将这两个模型的输出(倒数第二层)与新创建的具有 11 个节点的密集层连接起来并让整个模型重新训练自己,调整预训练的两个模型的权重并学习密集层的新权重。保持较低的学习率。

      最终的模型是第三个模型,它是两个模型(没有最后一个 Dense 层)+一个新的 Dense 层的组合。

      谢谢你..

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-05-11
        • 1970-01-01
        • 2018-05-02
        • 2022-07-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多