KERAS:具有一个输入和两个输出的模型,对不同数据(半监督学习)进行了培训



我想与keras编码一个神经网络,该神经网络既可以用作自动编码器,又是半监督学习的分类器。以此数据集为例,那里有一些标记的图像和许多未标记的图像:https://cs.stanford.edu/~acoates/stl10/

这里列出的一些论文成功地取得了成功或非常相似的事情。

总结:如果模型具有相同的输入数据形状和相同的"编码"卷积层,但是将分为两个头(叉形(,因此有一个分类头和一个解码头,无监督的自动编码器将为分类负责人提供良好的学习方式。

使用TensorFlow,这样做没有问题,因为我们对计算图有完全控制。

但是,对于Keras,情况更加高级,我觉得所有" .fit"的电话必须始终立即提供所有数据(因此,这会迫使我将分类头和自动编码的头部绑在一起一个时间步(。

凯拉斯(Keras(的一种方法几乎可以做到这样的事情:

input = Input(shape=(32, 32, 3))
cnn_feature_map = sequential_cnn_trunk(input)
classification_predictions = Dense(10, activation='sigmoid')(cnn_feature_map)
autoencoded_predictions = decode_cnn_head_sequential(cnn_feature_map)
model = Model(inputs=[input], outputs=[classification_predictions, ])
model.compile(optimizer='rmsprop',
              loss='binary_crossentropy',
              metrics=['accuracy'])
model.fit([images], [labels, images], epochs=10)

但是,我认为,我担心,如果我只想以这种方式适应事物,它将失败并要求缺失的头:

for epoch in range(10):
    # classifications step
    model.fit([images], [labels, None], epochs=1)
    # "semi-unsupervised" autoencoding step
    model.fit([images], [None, images], epochs=1)
    # note: ".train_on_batch" could probably be used rather than ".fit" to avoid doing a whole epoch each time.

一个人应该如何与Keras实施这种行为?可以共同完成培训,而不必将两个呼叫分开到" .fit"功能?

有时当您没有标签时,您可以通过零向量而不是一个热编码的向量。它不应改变您的结果,因为零向量没有任何错误信号,并且具有分类的交叉熵损失。

我的自定义to_categorical函数看起来像:

def tricky_to_categorical(y, translator_dict):
    encoded = np.zeros((y.shape[0], len(translator_dict)))
    for i in range(y.shape[0]):
        if y[i] in translator_dict:
            encoded[i][translator_dict[y[i]]] = 1
    return encoded

y时包含标签,而translator_dict是python词典女巫,其中包含标签及其独特的键:

{'unisex':2, 'female': 1, 'male': 0}

如果在此指数中找不到UNK标签,则其编码标签将为零矢量

如果您使用此技巧,则还必须修改精度功能才能查看实际准确性数字。您必须从我们的指标中滤除所有零向量

def tricky_accuracy(y_true, y_pred):
    mask = K.not_equal(K.sum(y_true, axis=-1), K.constant(0))  # zero vector mask
    y_true = tf.boolean_mask(y_true, mask)
    y_pred = tf.boolean_mask(y_pred, mask)
    return K.cast(K.equal(K.argmax(y_true, axis=-1), K.argmax(y_pred, axis=-1)), K.floatx())

注意:您必须使用较大的批次(例如32(才能防止零矩阵更新,因为它可以使您的准确度指标发疯,我不知道为什么

替代解决方案

使用伪标签:(

您可以共同训练,您必须通过单个标签的数组。

我使用了fit_generator,例如

model.fit_generator(
batch_generator(),
steps_per_epoch=len(dataset) / batch_size,
epochs=epochs)

def batch_generator():
batch_x = np.empty((batch_size, img_height, img_width, 3))
gender_label_batch = np.empty((batch_size, len(gender_dict)))
category_label_batch = np.empty((batch_size, len(category_dict)))
while True:
    i = 0
    for idx in np.random.choice(len(dataset), batch_size):
        image_id = dataset[idx][0]
        batch_x[i] = load_and_convert_image(image_id)
        gender_label_batch[i] = gender_labels[idx]
        category_label_batch[i] = category_labels[idx]
        i += 1
    yield batch_x, [gender_label_batch, category_label_batch]

最新更新