我正在研究一个CNN的类间和类内分类问题,例如,首先有Cat和Dog两类,而在Cat中则有3种不同的猫分类,而Dog中有5种不同的品种小狗。
我还没有尝试过编码,只是在可行的情况下进行了可行性研究。 我的问题是对这种问题的可行设计。 我正在考虑为训练设计第一个CNN-1网络,该网络将区分猫和狗并收集所有训练图像的图像数据。猫和狗分离后,CNN-2和CNN-3将进一步训练每种犬和猫的图像。我只是不确定在这种情况下测试如何进行。
答案 0 :(得分:0)
我以前在Python中遇到过类似的问题。希望这会有所帮助,如果您正在使用Matlab,您可以在Matlab中提出一个替代实现。
说完一切之后,我就为所有预测找到了一个模型。出于您的目的,您可以为“狗对猫”有一个二进制输出,为狗的品种有另一个多类输出,而为“猫”品种有另一个多类输出。
使用Tensorflow,我为不相关的类创建了一个掩码。例如,如果图像是猫的,那么所有的犬种都不相关,因此它们不会影响该示例的模型训练。这需要一个自定义的TF数据集(将掩码的0转换为-1)和一个自定义的损失函数,当该示例存在掩码时,该函数将返回0错误。
最后是培训过程。 针对您的问题,您将必须创建自定义的精度函数,这些函数可以按照所需的方式处理掩码值,但除此之外,该过程的这一部分应该是标准的。最佳做法是在培训数据中平均分配课程,但可以一起培训。
如果您搜索“多任务培训”,则可以找到有关此问题的其他资源。
如果您感兴趣的话,这里有一些代码片段:
对于掩盖不相关标签的自定义TF数据集...
# 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个输出。遮罩是其中的主要部分,因为它允许网络仅调整与示例相关的权重。如果图像是猫,则狗的品种预测不会导致损失。