Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/316.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 无法完全分离TensorFlow中模型的输出_Python_Tensorflow_Keras_Conv Neural Network - Fatal编程技术网

Python 无法完全分离TensorFlow中模型的输出

Python 无法完全分离TensorFlow中模型的输出,python,tensorflow,keras,conv-neural-network,Python,Tensorflow,Keras,Conv Neural Network,我试图创建一个卷积神经网络,它有两个回归输出,一个分数和一个置信度。我已经冻结了他们共同拥有的层,希望增加信心输出不会改变分数,但在我的实验中确实如此。对于只有分数的模型,我使用了Exception并添加了一个简单的GlobalAveragePoolig2D和Dense(512)层,然后输出一个数字 base_model = Xception(input_shape=(224, 224, 3), weights='imagenet', include_top=False) x = base_m

我试图创建一个卷积神经网络,它有两个回归输出,一个分数和一个置信度。我已经冻结了他们共同拥有的层,希望增加信心输出不会改变分数,但在我的实验中确实如此。对于只有分数的模型,我使用了Exception并添加了一个简单的
GlobalAveragePoolig2D
Dense(512)
层,然后输出一个数字

base_model = Xception(input_shape=(224, 224, 3), weights='imagenet', include_top=False)

x = base_model.output
x = GlobalAveragePooling2D()(x)
x = Dense(512, activation='relu')(x)
predictions = Dense(1, activation='sigmoid')(x)

model = Model(inputs=base_model.input, outputs=predictions)

for layer in base_model.layers:
    layer.trainable = False

optimizer = Adam(learning_rate=learning_rate)
model.compile(loss='mae', optimizer=optimizer, metrics=['mse','mae'], run_eagerly=True)
下面是
model.summary()
的结尾:

当我拟合它时,模型产生了良好的结果

但当我尝试添加第二个输出时,第一个输出的结果会变得更糟。新模型通过元组进行训练,其中第一个数字与第一个模型相同,第二个数字是置信值。该模型与上面的模型非常相似

base_model = Xception(input_shape=(224, 224, 3), weights='imagenet', include_top=False)

x = base_model.output
x = GlobalAveragePooling2D()(x)

score_x = Dense(512, activation='relu')(x)
score_out = Dense(1, activation='sigmoid', name='score_model')(score_x)

confidence_x = Dense(512, activation='relu')(x)
confidence_out = Dense(1, name='confidence_model')(confidence_x)

model = Model(inputs=base_model.input, outputs=[score_out, confidence_out])

for layer in base_model.layers:
    layer.trainable = False

losses = {'score_model': 'mae', 'confidence_model': 'mae'}
loss_weights = {'score_model': 1, 'confidence_model': 1} 

model.compile(loss=losses, loss_weights=loss_weights, optimizer=optimizer, metrics=['mse','mae'], run_eagerly=True)
当我查看
model.summary()
时,它的可训练参数是前一个模型的两倍,这正是我所期望的。到目前为止,我觉得一切都很好


但是当我训练这个模型时,分数上的表现要差得多。我在想这是一样的(在随机变化中)。在第一个历元之后,第一个模型的损失约为0.125。来自第二个模型的
评分\u模型\u损失
约为0.554。很明显,我没有完全分离模型。我遗漏了什么?

注意:这个答案很有效,因为进行特征提取的图层被冻结了。正如@Akshay Sehgal在评论中所述:

同时优化两个目标实际上与单独优化两个独立目标完全不同

在这种情况下,我们分别针对两个目标进行优化


最简单的解决方案可能是编写一个带有2个tf.GradientTape的定制训练循环,每个目标一个。让我们考虑一下这个简单的例子:

虚拟数据 让我们创建一些随机数据

import tensorflow as tf

X = tf.random.normal((1000,1))
y1= 3*X + 1
y2 = -2*X +2

ds = tf.data.Dataset.from_tensor_slices((X,y1,y2)).batch(10)
创建具有2个输出的模型 在那个例子中,我跳过了特征提取步骤,因为简单的线性回归可以处理数据。但由于您的功能提取器网络已冻结,示例与此类似

inp = tf.keras.Input((1,))
dense_1 = tf.keras.layers.Dense(1, name="objective1")(inp)
dense_2 = tf.keras.layers.Dense(1, name="objective2")(inp)
model = tf.keras.Model(inputs=inp, outputs=[dense_1, dense_2])

# setting up the loss functions as well as the optimizer
opt = tf.optimizers.SGD()
loss_func1 = tf.losses.mean_squared_error
loss_func2 = tf.losses.mean_absolute_error
请注意两个密集层的名称:稍后我将使用它们来检索适当的权重

获取要优化的权重 我们可以使用前面设置的名称来检索属于每个目标的变量:

var1, var2 = [],[]
for l in model.layers:
    if "objective1" in l.name:
        var1 += l.trainable_variables
    if "objective2" in l.name:
        var2 += l.trainable_variables
训练循环 你只需要制作一盘磁带,每个目标一盘。如果使培训更好,您也可以使用不同的优化器

counter = 0
for x, y1, y2 in ds:
    counter += 1
    with tf.GradientTape() as tape1, tf.GradientTape() as tape2:
        pred1, pred2 = model(x)
        loss1 = loss_func1(y1, pred1)
        loss2 = loss_func2(y2, pred2)
    grad1 = tape1.gradient(loss1, var1)
    grad2 = tape2.gradient(loss2, var2)
    opt.apply_gradients(zip(grad1, var1))
    opt.apply_gradients(zip(grad2, var2))
    if counter % 10:
        print(f"Step : {counter}, objective1: {tf.reduce_mean(loss1)}, objective2: {tf.reduce_mean(loss2)}")
如果我们进行培训,我们将获得:

Step : 1, objective1: 4.609124183654785, objective2: 2.6634981632232666
[...]
Step : 99, objective1: 7.176481902227555e-14, objective2: 0.030187154188752174

这种方法的主要优点是,您只需要为两个目标提取一次特征。

您的优化过程不会被分离。优化两个目标比优化1难。我能想到两件事。。1) 仔细检查基本模型层是否确实冻结在
模型中,2)尝试设置
损失权重['confidence\u model']=0。
以查看这是否会使情况变得更好(如果是,请尝试缓慢增加)如果目标不是同时优化它们,那么只构建两个单独的模型是否有意义?@AkshaySehgal为了提高效率,我希望使用一个模型同时生成两个输出。缩小一点,我不知道您的具体应用,但我永远不会尝试将置信度/方差作为点估计(MSE、MAE等)。相反,我会使用像KL发散这样的目标。共同拟合均值和方差。这看起来不错。我还在测试,但我会确保在悬赏期结束前做出回应。