【问题标题】:How to prevent backpropagation after compiling a keras model?编译 keras 模型后如何防止反向传播?
【发布时间】:2018-01-19 06:20:09
【问题描述】:

我有一个这样的多输出模型

       input
         |
      hidden
         |
        / \
       /   \
output1    output2

我可以通过model.train_on_batch(input=input,output=[output1,output2]) 训练这个模型,但是在我训练的某个特定阶段,我只想训练这个模型的一个分支(输出 2)并防止输出 1 的反向传播。我最初尝试在模型 model.train_on_batch(input=input,output=[None,output2]) 中传递 None 值,但它的显示

AttributeError: 'NoneType' 对象没有属性 'shape'

然后我尝试传递一个输出 1 形状 model.train_on_batch(input=input,output=[Nan_array,output2]) 的 NaN 数组,然后损失变为 NaN。如何在多输出 keras 模型中只训练一个分支并防止另一个分支的反向传播?

编辑

我试图找到解决此问题的方法并遇到了K.stop_gradient 函数。我试图在这样的一个输出模型中停止反向传播

import numpy as np
from keras.models import Sequential
from keras.layers import Dense, Dropout
import keras.backend as K

def loss(y_true, y_pred):
    return K.stop_gradient(y_pred)
    
# Generate dummy data
x_train = np.random.random((10, 20))
y_train = np.random.randint(2, size=(10, 1))
x_test = np.random.random((10, 20))
y_test = np.random.randint(2, size=(10, 1))

model = Sequential()
model.add(Dense(64, input_dim=20, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(64, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(1, activation='sigmoid'))

model.compile(loss=loss,
              optimizer='rmsprop',
              metrics=['accuracy'])

model.fit(x_train, y_train,
          epochs=1,
          batch_size=128)

score = model.evaluate(x_test, y_test, batch_size=128)

但是得到这个错误

ValueError: 试图将 'x' 转换为张量并失败。错误:不支持任何值。

【问题讨论】:

  • 你试过只是传递model.train_on_batch(input=input,output=output2)吗?
  • 它会抛出这个错误Expected to see 2 arrays but instead got the following list of 1 arrays:

标签: python tensorflow keras keras-layer


【解决方案1】:

您可以创建两个具有共享权重的Model 对象。第一个模型在output=[output1, output2] 上进行优化,而第二个模型只包含output2 的分支。如果您在第二个模型上调用train_on_batch,则不会更新分支 1 中的权重。

例如,

x = Input(shape=(32,))
hidden = Dense(32)(x)
output1 = Dense(1)(hidden)
output2 = Dense(1)(hidden)

model = Model(x, [output1, output2])
model.compile(loss='mse', optimizer='adam')

model_only2 = Model(x, output2)
model_only2.compile(loss='mse', optimizer='adam')

X = np.random.rand(2, 32)
y1 = np.random.rand(2)
y2 = np.random.rand(2)

# verify: all the weights will change if we train on `model`
w0 = model.get_weights()
model.train_on_batch(X, [y1, y2])
w1 = model.get_weights()
print([np.allclose(x, y) for x, y in zip(w0, w1)])
# => [False, False, False, False, False, False]

# verify: branch 1 will not change if we train on `model_only2`
model_only2.train_on_batch(X, y2)
w2 = model.get_weights()
print([np.allclose(x, y) for x, y in zip(w1, w2)])
# => [False, False, True, True, False, False]

【讨论】:

    【解决方案2】:

    像这样设置图层

    layer.trainable = False

    所以在训练期间这一层不要改变权重。

    https://keras.io/getting-started/faq/#how-can-i-freeze-keras-layers

    【讨论】:

    • 原谅我,如果我记得它是正确的,它只会冻结那个特定的层,在我的例子中是最后一个 ouput1 层。但是仍然可以更改我不想更改的上述图层。我说的对吗?
    • 冻结你想要的图层
    • 在 base_model.layers 中的层的“在一组新的类上微调 InceptionV3”部分阅读keras.io/applications:layer.trainable = False
    【解决方案3】:

    您是否尝试过传递None 来编译您的模型:

    model.compile(loss=loss,
                  optimizer='rmsprop',
                  metrics=[None, 'accuracy'])
    

    ?

    【讨论】:

      猜你喜欢
      • 2010-12-11
      • 2012-01-11
      • 2018-05-05
      • 1970-01-01
      • 2020-06-12
      • 2010-10-18
      • 2014-02-07
      • 2018-01-13
      相关资源
      最近更新 更多