правильное использование tensorflow flow_from_dataframe с моделью с несколькими выводами / несколькими метками

#tensorflow #multilabel-classification #multiclass-classification

#tensorflow #классификация с несколькими метками #мультиклассовая классификация

Вопрос:

Я получаю несовместимость формы при попытке подогнать мою модель — не уверен, что проблема связана с моим созданием экземпляра DataIterator или чего-то в моем определении модели…

Вставка кода для воспроизведения

ПРИМЕЧАНИЕ: чтобы использовать приведенный выше пример кода с приведенными ниже примерами данных, вы должны изменить directory=None значение be directory=data_sample и untar data_sample.tgz в том же каталоге, из которого вы запускаете этот код

Запустите это, чтобы обучить модель возраста с одним прогнозом:

 python tf_train_copy.py --csv_file data_sample/dataframe.csv --count 100 --training_type age
 

Запустите это, чтобы обучить модель возраста и пола с двумя прогнозами, которая завершается неудачей из-за формы, связанной ValueError с этим вопросом:

 python tf_train_copy.py --csv_file data_sample/dataframe.csv --count 100 --training_type age_gender
 

Небольшая выборка из 100 изображений и связанного фрейма данных

У меня есть фрейм данных, который выглядит следующим образом — с двоичными gender данными {'m', 'f'} и age данными, имеющими 3 значения:

                                                  filename gender mask age_group
218069  /home/lrm/data/VGGFace2_cropped/n005204_0182_0...      f    f  (26, 39)
295315  /home/lrm/data/VGGFace2_cropped/n000162_0085_0...      m    f  (18, 25)
176301  /home/lrm/data/VGGFace2_cropped/n005378_0359_0...      f    f  (26, 39)
212662  /home/lrm/data/VGGFace2_cropped/n006412_0026_0...      m    f  (40, 55)
327910  /home/lrm/data/VGGFace2_cropped/n005114_0240_0...      m    f  (18, 25)
...                                                   ...    ...  ...       ...
283903  /home/lrm/data/VGGFace2_cropped/n002902_0158_0...      m    f  (26, 39)
156748  /home/lrm/data/VGGFace2_cropped/n003909_0464_0...      m    f  (40, 55)
89294   /home/lrm/data/VGGFace2_cropped/n000332_0195_0...      f    f  (18, 25)
156880  /home/lrm/data/VGGFace2_cropped/n005892_0122_0...      f    f  (18, 25)
304084  /home/lrm/data/VGGFace2_cropped/n002321_0114_0...      m    f  (18, 25)
 

и модель, определенная как таковая:

 dense_age = tf.keras.layers.Dense(units=64, activation=tf.keras.layers.ReLU(6.0), name='dense_age')(base_model.output)
dropout_age = tf.keras.layers.Dropout(rate=args.dropout)(dense_age)
pred_age = tf.keras.layers.Dense(units=3, activation='softmax', name='pred_age')(dropout_age)

dense_gender = tf.keras.layers.Dense(units=64, activation=tf.keras.layers.ReLU(6.0), name='dense_gender')(base_model.output)
dropout_gender = tf.keras.layers.Dropout(rate=args.dropout)(dense_gender)
# also tried units=2 for gender prediction
pred_gender = tf.keras.layers.Dense(units=1, activation='softmax', name='pred_gender')(dropout_gender)

model = tf.keras.models.Model(inputs=base_model.input, outputs=[pred_age, pred_gender])
model.compile(
        optimizer=optimizer,
        loss=[tf.keras.losses.CategoricalCrossentropy(from_logits=True, label_smoothing=0.1), tf.keras.losses.CategoricalCrossentropy(from_logits=True, label_smoothing=0.1)],
        metrics=[tf.keras.metrics.Accuracy(name='age_accuracy'), tf.keras.metrics.Accuracy(name='gender_accuracy')])
 

вот как создается мой DataIterator объект:

 train_generator = train_datagen.flow_from_dataframe(
        directory=None,
        dataframe=train_data,
        x_col='filename',
        y_col=['age_group', 'gender'],
        class_mode='multi_output',
        **dataflow_kwargs)
 

и я получаю ValueError высказывание о несовместимости формы:

 Traceback (most recent call last):
  File "tf_train.py", line 385, in <module>
    validation_steps=validation_steps)
  File "/home/lrm/.pyenv/versions/tf_training_231/lib/python3.7/site-packages/tensorflow/python/util/deprecation.py", line 324, in new_func
    return func(*args, **kwargs)
  File "/home/lrm/.pyenv/versions/tf_training_231/lib/python3.7/site-packages/tensorflow/python/keras/engine/training.py", line 1829, in fit_generator
    initial_epoch=initial_epoch)
  File "/home/lrm/.pyenv/versions/tf_training_231/lib/python3.7/site-packages/tensorflow/python/keras/engine/training.py", line 108, in _method_wrapper
    return method(self, *args, **kwargs)
  File "/home/lrm/.pyenv/versions/tf_training_231/lib/python3.7/site-packages/tensorflow/python/keras/engine/training.py", line 1098, in fit
    tmp_logs = train_function(iterator)
  File "/home/lrm/.pyenv/versions/tf_training_231/lib/python3.7/site-packages/tensorflow/python/eager/def_function.py", line 780, in __call__
    result = self._call(*args, **kwds)
  File "/home/lrm/.pyenv/versions/tf_training_231/lib/python3.7/site-packages/tensorflow/python/eager/def_function.py", line 823, in _call
    self._initialize(args, kwds, add_initializers_to=initializers)
  File "/home/lrm/.pyenv/versions/tf_training_231/lib/python3.7/site-packages/tensorflow/python/eager/def_function.py", line 697, in _initialize
    *args, **kwds))
  File "/home/lrm/.pyenv/versions/tf_training_231/lib/python3.7/site-packages/tensorflow/python/eager/function.py", line 2855, in _get_concrete_function_internal_garbage_collected
    graph_function, _, _ = self._maybe_define_function(args, kwargs)
  File "/home/lrm/.pyenv/versions/tf_training_231/lib/python3.7/site-packages/tensorflow/python/eager/function.py", line 3213, in _maybe_define_function
    graph_function = self._create_graph_function(args, kwargs)
  File "/home/lrm/.pyenv/versions/tf_training_231/lib/python3.7/site-packages/tensorflow/python/eager/function.py", line 3075, in _create_graph_function
    capture_by_value=self._capture_by_value),
  File "/home/lrm/.pyenv/versions/tf_training_231/lib/python3.7/site-packages/tensorflow/python/framework/func_graph.py", line 986, in func_graph_from_py_func
    func_outputs = python_func(*func_args, **func_kwargs)
  File "/home/lrm/.pyenv/versions/tf_training_231/lib/python3.7/site-packages/tensorflow/python/eager/def_function.py", line 600, in wrapped_fn
    return weak_wrapped_fn().__wrapped__(*args, **kwds)
  File "/home/lrm/.pyenv/versions/tf_training_231/lib/python3.7/site-packages/tensorflow/python/framework/func_graph.py", line 973, in wrapper
    raise e.ag_error_metadata.to_exception(e)
ValueError: in user code:

    /home/lrm/.pyenv/versions/tf_training_231/lib/python3.7/site-packages/tensorflow/python/keras/engine/training.py:806 train_function  *
        return step_function(self, iterator)
    /home/lrm/.pyenv/versions/tf_training_231/lib/python3.7/site-packages/tensorflow/python/keras/engine/training.py:796 step_function  **
        outputs = model.distribute_strategy.run(run_step, args=(data,))
    /home/lrm/.pyenv/versions/tf_training_231/lib/python3.7/site-packages/tensorflow/python/distribute/distribute_lib.py:1211 run
        return self._extended.call_for_each_replica(fn, args=args, kwargs=kwargs)
    /home/lrm/.pyenv/versions/tf_training_231/lib/python3.7/site-packages/tensorflow/python/distribute/distribute_lib.py:2585 call_for_each_replica
        return self._call_for_each_replica(fn, args, kwargs)
    /home/lrm/.pyenv/versions/tf_training_231/lib/python3.7/site-packages/tensorflow/python/distribute/distribute_lib.py:2945 _call_for_each_replica
        return fn(*args, **kwargs)
    /home/lrm/.pyenv/versions/tf_training_231/lib/python3.7/site-packages/tensorflow/python/keras/engine/training.py:789 run_step  **
        outputs = model.train_step(data)
    /home/lrm/.pyenv/versions/tf_training_231/lib/python3.7/site-packages/tensorflow/python/keras/engine/training.py:749 train_step
        y, y_pred, sample_weight, regularization_losses=self.losses)
    /home/lrm/.pyenv/versions/tf_training_231/lib/python3.7/site-packages/tensorflow/python/keras/engine/compile_utils.py:204 __call__
        loss_value = loss_obj(y_t, y_p, sample_weight=sw)
    /home/lrm/.pyenv/versions/tf_training_231/lib/python3.7/site-packages/tensorflow/python/keras/losses.py:149 __call__
        losses = ag_call(y_true, y_pred)
    /home/lrm/.pyenv/versions/tf_training_231/lib/python3.7/site-packages/tensorflow/python/keras/losses.py:253 call  **
        return ag_fn(y_true, y_pred, **self._fn_kwargs)
    /home/lrm/.pyenv/versions/tf_training_231/lib/python3.7/site-packages/tensorflow/python/util/dispatch.py:201 wrapper
        return target(*args, **kwargs)
    /home/lrm/.pyenv/versions/tf_training_231/lib/python3.7/site-packages/tensorflow/python/keras/losses.py:1535 categorical_crossentropy
        return K.categorical_crossentropy(y_true, y_pred, from_logits=from_logits)
    /home/lrm/.pyenv/versions/tf_training_231/lib/python3.7/site-packages/tensorflow/python/util/dispatch.py:201 wrapper
        return target(*args, **kwargs)
    /home/lrm/.pyenv/versions/tf_training_231/lib/python3.7/site-packages/tensorflow/python/keras/backend.py:4687 categorical_crossentropy
        target.shape.assert_is_compatible_with(output.shape)
    /home/lrm/.pyenv/versions/tf_training_231/lib/python3.7/site-packages/tensorflow/python/framework/tensor_shape.py:1134 assert_is_compatible_with
        raise ValueError("Shapes %s and %s are incompatible" % (self, other))

    ValueError: Shapes (None, 1) and (None, 3) are incompatible
 

Комментарии:

1. почему directory None ? Встроена ли информация о файле в метафайлы?

2. x_col является абсолютным путем, поэтому directory не нужен

3. Ладно, я понимаю. Я думаю, что активация pred_gender должна быть sigmoid , предполагая, что столбец с кодировкой 0 и 1 относится к мужчине и женщине. И о том pred_age , содержит ли он 3 значения или 2 значения в кортеже?

4. Я могу воспроизвести вашу проблему. У меня нет точного решения, но я думаю, что что-то не так с загрузчиком данных. Попробуйте for i, (x,y) in generator: print(y[0], y[0].shape; if i == 0: break режим класса с несколькими выходами. Это не создает вектор с одним горячим вектором. Возможно, вам придется разобраться в этом.

5. Кроме того, если class_mode=multioutput это не делается автоматически, то вам, возможно, сначала придется это сделать. Тем не менее, я бы рекомендовал вам написать пользовательский генератор данных. ИМО, множественный вывод с flow_from_dataframe неоднозначен.