Я уже сталкивался с подобной проблемой ранее в Python. Надеюсь, это полезно, и вы можете придумать альтернативную реализацию в Matlab, если это то, что вы используете.
После всего, что было сказано и сделано, я остановился на единой модели для всех прогнозов. Для вашей цели у вас может быть один двоичный выход для собак и кошек, другой мультиклассовый выход для пород собак и другой мультиклассовый выход для пород кошек.
Используя Tensorflow, я создал маску для нерелевантных классов. Например, если изображение было кошкой, то все породы собак не имеют значения, и они не должны влиять на обучение модели для этого примера. Это потребовало настраиваемого набора данных TF (который преобразовал 0 в -1 для маски) и настраиваемой функции потерь, которая возвращала ошибку 0, когда маска присутствовала для этого примера.
Наконец-то для тренировочного процесса. Специфично для вашего вопроса , вам придется создавать пользовательские функции точности, которые могут обрабатывать значения маски так, как вы хотите, но в остальном эта часть процесса должна быть стандартной. Лучше всего было равномерно распределить занятия по данным обучения, но все они могут быть обучены вместе.
Если вы пользуетесь Google "Multi-Task Training", вы можете найти дополнительные ресурсы для этой проблемы.
Вот некоторые фрагменты кода, если вам интересно:
Для настройки набора данных 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
это бэкэнд керас.
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 выхода на одну модель. Маска является основной частью этого, поскольку она позволяет сети корректировать только те веса, которые соответствуют данному примеру. Если изображение было кошкой, то предсказание породы собаки не приводит к потере.