我正在处理一个类别间和类别内的分类问题,例如,首先,有两个类别,猫和狗,而在猫中,有三种不同品种的猫,在狗中,有五种不同的狗。
我还没有尝试过编码,如果可行的话,我只是在研究它的可行性。我的问题是,对于这类问题,什么是可行的设计。我正在考虑为训练设计第一个CNN-1网络,它将区分猫和狗,并收集所有训练图像的图像数据。猫和狗分离后,CNN-2和CNN-3将为每种狗和猫进一步训练这些图像。我只是不确定在这种情况下测试将如何工作。
发布于 2019-04-10 01:15:32
希望这会对你有所帮助,如果你正在使用Matlab,你可以想出一个替代的实现。
出于您的目的,您可以有一个用于狗与猫的二进制输出,另一个用于狗品种的多类输出,以及另一个用于猫品种的多类输出。
使用Tensorflow,我为不相关的类创建了一个掩码。例如,如果图像是一只猫,那么所有的狗品种都是无关紧要的,它们不应该影响该示例的模型训练。这需要定制的TF数据集(将掩码的0转换为-1 )和定制的损失函数,该损失函数在该示例的掩码存在时返回0错误。
最后是训练过程。对于您的问题,您必须创建自定义精度函数,该函数可以按您希望的方式处理掩码值,但除此之外,该过程的这一部分应该是标准的。最佳实践是在训练数据中均匀分布类,但它们都可以一起训练。
如果你在谷歌上搜索“多任务训练”,你可以找到更多关于这个问题的资源。
# Replace 0's with -1 for mask when there aren't any labels
def produce_mask(features):
for filt, tensor in features.items():
if "target" in filt:
condition = tf.equal(tf.math.reduce_sum(tensor), 0)
features[filt] = tf.where(condition, tf.ones_like(tensor) * -1, tensor)
return features
def create_dataset(filepath, batch_size=10):
...
# **** This is where the mask was applied to the dataset
dataset = dataset.map(produce_mask, num_parallel_calls=cpu_count())
...
return parsed_features自定义损失函数。我之所以使用二进制交叉标记,是因为我的问题是多标签。您可能希望将其调整为分类交叉。
# Custom loss function
def masked_binary_crossentropy(y_true, y_pred):
mask = backend.cast(backend.not_equal(y_true, -1), backend.floatx())
return backend.binary_crossentropy(y_true * mask, y_pred * mask)然后是自定义精度指标。我使用的是top-k精确度,您可能需要根据您的目的进行修改,但这将给您大体的概念。将此函数与损失函数进行比较时,此函数会将这些值完全过滤掉,而不是将全部转换为0,这会过度膨胀精度。这是可行的,因为输出是单独测量的,因此每个输出(二进制、猫品种、狗品种)将具有不同的精度度量,仅针对相关示例进行过滤。
backend是keras的后台。
def top_5_acc(y_true, y_pred, k=5):
mask = backend.cast(backend.not_equal(y_true, -1), tf.bool)
mask = tf.math.reduce_any(mask, axis=1)
masked_true = tf.boolean_mask(y_true, mask)
masked_pred = tf.boolean_mask(y_pred, mask)
return top_k_categorical_accuracy(masked_true, masked_pred, k)编辑
不,在我上面描述的场景中,只有一个模型,它是用所有数据一起训练的。单个模型有3个输出。掩码是这一点的主要部分,因为它允许网络仅调整与示例相关的权重。如果图像是一只猫,那么狗的品种预测不会导致损失。
https://stackoverflow.com/questions/55584863
复制相似问题