我想用Keras编写一个神经网络,它既可以作为自动编码器,也可以作为半监督学习的分类器。以此数据集为例,其中有一些标记图像和大量未标记图像:https://cs.stanford.edu/~acoates/stl10/
列出here的一些论文成功地完成了这些或非常相似的事情。
总结一下:如果模型具有相同的输入数据形状和相同的"编码"卷积层,但会分成两个头(叉式),所以有一个分类头和一个解码头,无人监督的自动编码器将有助于分类头的良好学习。
使用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"功能
答案 0 :(得分:1)
有时,当您没有标签时,您可以传递零向量而不是一个热编码向量。它不应该改变你的结果,因为零向量没有任何带有分类交叉熵损失的错误信号。
我的自定义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}
如果在此dictinary中找不到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)以防止零矩阵更新,因为它可能会使您的准确度指标变得疯狂,我不知道为什么
替代解决方案
使用伪标签:)
答案 1 :(得分:0)
你可以联合训练,你必须通过一个单一标签阵列。
我使用了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]