Python 如何防止编译keras模型后的反向传播?

Python 如何防止编译keras模型后的反向传播?,python,tensorflow,keras,keras-layer,Python,Tensorflow,Keras,Keras Layer,我有一个这样的多输出模型 input | hidden | / \ / \ output1 output2 我可以一个模型一个模型地训练这个模型。我最初尝试在模型中传递一个None值 AttributeError:“非类型”对象没有属性“形状” 然后我尝试传递一个输出1形状模型的NaN数组。在批输入=输入,输出=[NaN\U数组,输出2]上训练,然后损失变成NaN。如何在多输出keras模型中

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

       input
         |
      hidden
         |
        / \
       /   \
output1    output2
我可以一个模型一个模型地训练这个模型。我最初尝试在模型中传递一个None值

AttributeError:“非类型”对象没有属性“形状”

然后我尝试传递一个输出1形状模型的NaN数组。在批输入=输入,输出=[NaN\U数组,输出2]上训练,然后损失变成NaN。如何在多输出keras模型中只训练一个分支,而在另一个分支中防止反向传播

编辑 我试图找到这个问题的解决方案,遇到了K.stop_梯度函数。我试图在这样的单输出模型中停止反向传播

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”转换为张量,但失败。错误:不支持任何值

可以创建两个共享权重的模型对象。第一个模型在output=[output1,output2]上进行优化,而第二个模型只包含output2的分支。如果在第二个模型上调用批次上的列,则不会更新分支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]
可以创建两个共享权重的模型对象。第一个模型在output=[output1,output2]上进行优化,而第二个模型只包含output2的分支。如果在第二个模型上调用批次上的列,则不会更新分支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]
将图层设置为

layer.trainable=错误

因此,在训练过程中,这一层不会改变重量

将图层设置为

layer.trainable=错误

因此,在训练过程中,这一层不会改变重量

您是否尝试过传递None来编译您的模型,如下所示:

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

您是否尝试通过None来编译您的模型,如下所示:

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

您是否尝试仅传递模型。在批输入=输入,输出=输出2上训练?它抛出此错误,预期会看到2个数组,但得到以下1个数组列表:您是否尝试仅传递模型。在批输入=输入上训练,output=output2?它抛出了这个错误,期望看到2个数组,但得到了以下1个数组的列表:请原谅,如果我记得纠正它,它只冻结该特定层,在我的例子中是最后一个output1层。但是我仍然可以改变上面我不想改变的图层。我说的对吗?冻结你想在一个新的类集合部分的Fine tune InceptionV3上为基本层中的层冻结哪个层。层:层。可训练=错误请原谅,如果我记得它是正确的,它只冻结那个特定层,在我的例子中是最后一个ouput1层。但是我仍然可以改变上面我不想改变的图层。我说的对吗?冻结您想要在一组新的类部分上的微调接收v3中对基本模型中的层执行此操作。layers:layer.trainable=False