Производительность модели не улучшается во время обучения федеративному обучению - PullRequest
1 голос
/ 08 мая 2020

Я выполнил этот учебник emnist , чтобы создать эксперимент по классификации изображений (7 классов) с целью обучения классификатора на 3-х хранилищах данных с помощью TFF framework. начинается, я конвертирую модель в модель tf keras, используя tff.learning.assign_weights_to_keras_model(model,state.model) для оценки на моем наборе проверки. Независимо от метки модель предсказывает только один класс. Этого следовало ожидать, поскольку обучение модели еще не произошло. Однако я повторяю этот шаг после каждого раунда федеративного усреднения, и проблема остается. Все проверочные изображения относятся к одному классу. Я также сохраняю веса модели tf keras после каждого раунда и делаю прогнозы на тестовом наборе - без изменений.

Некоторые шаги, которые я предпринял для проверки источника проблемы:

  1. Проверено, обновляются ли веса модели tf keras при преобразовании модели FL после каждого раунда - они обновляются.
  2. Гарантировано, что размер буфера больше, чем размер обучающего набора данных для каждого клиента.
  3. Сравнил прогнозы с распределением классов в обучающих наборах данных. Существует дисбаланс классов, но тот класс, который предсказывает модель, не обязательно является классом большинства. Кроме того, это не всегда один и тот же класс. По большей части, он предсказывает только класс 0.
  4. Увеличено количество раундов до 5 и эпох за раунд до 10. Это требует больших вычислительных ресурсов, так как это довольно большая модель, обучаемая примерно с 1500 изображениями на каждый. client.
  5. Исследовал журналы TensorBoard после каждой попытки обучения. Потери при обучении уменьшаются по мере прохождения раунда.
  6. Пробовал гораздо более простую модель - basi c CNN с 2 сверточными слоями. Это позволило мне значительно увеличить количество эпох и раундов. При оценке этой модели на тестовом наборе она предсказала 4 разных класса, но производительность остается очень плохой. Это означало бы, что мне просто нужно было бы увеличить количество раундов и эпох для моей исходной модели, чтобы увеличить разброс прогнозов. Это сложно из-за большого времени обучения, которое могло бы быть результатом.

Детали модели:

Модель использует Xceptio nNet в качестве базовой модели с размороженными грузами. Это хорошо работает с задачей классификации, когда все обучающие изображения объединены в глобальный набор данных. Мы надеемся достичь сопоставимой производительности с FL.

base_model = Xception(include_top=False,
                      weights=weights,
                      pooling='max',
                      input_shape=input_shape)
x = GlobalAveragePooling2D()( x )
predictions = Dense( num_classes, activation='softmax' )( x )
model = Model( base_model.input, outputs=predictions )

Вот мой тренировочный код:

def fit(self):
    """Train FL model"""
    # self.load_data()
    summary_writer = tf.summary.create_file_writer(
        self.logs_dir
    )
    federated_averaging = self._construct_iterative_process()
    state = federated_averaging.initialize()
    tfkeras_model = self._convert_to_tfkeras_model( state )
    print( np.argmax( tfkeras_model.predict( self.val_data ), axis=-1 ) )
    val_loss, val_acc = tfkeras_model.evaluate( self.val_data, steps=100 )

    with summary_writer.as_default():
        for round_num in tqdm( range( 1, self.num_rounds ), ascii=True, desc="FedAvg Rounds" ):

            print( "Beginning fed avg round..." )
            # Round of federated averaging
            state, metrics = federated_averaging.next(
                state,
                self.training_data
            )
            print( "Fed avg round complete" )
            # Saving logs
            for name, value in metrics._asdict().items():
                tf.summary.scalar(
                    name,
                    value,
                    step=round_num
                )
            print( "round {:2d}, metrics={}".format( round_num, metrics ) )
            tff.learning.assign_weights_to_keras_model(
                tfkeras_model,
                state.model
            )
            # tfkeras_model = self._convert_to_tfkeras_model(
            #     state
            # )
            val_metrics = {}
            val_metrics["val_loss"], val_metrics["val_acc"] = tfkeras_model.evaluate(
                self.val_data,
                steps=100
            )
            for name, metric in val_metrics.items():
                tf.summary.scalar(
                    name=name,
                    data=metric,
                    step=round_num
                )
            self._checkpoint_tfkeras_model(
                tfkeras_model,
                round_num,
                self.checkpoint_dir
            )
def _checkpoint_tfkeras_model(self,
                              model,
                              round_number,
                              checkpoint_dir):
    # Obtaining model dir path
    model_dir = os.path.join(
        checkpoint_dir,
        f'round_{round_number}',
    )
    # Creating directory
    pathlib.Path(
        model_dir
    ).mkdir(
        parents=True
    )
    model_path = os.path.join(
        model_dir,
        f'model_file_round{round_number}.h5'
    )
    # Saving model
    model.save(
        model_path
    )

def _convert_to_tfkeras_model(self, state):
    """Converts global TFF modle of TF keras model

    Takes the weights of the global model
    and pushes them back into a standard
    Keras model

    Args:
        state: The state of the FL server
            containing the model and
            optimization state

    Returns:
        (model); TF Keras model

    """
    model = self._load_tf_keras_model()
    model.compile(
        loss=self.loss,
        metrics=self.metrics
    )
    tff.learning.assign_weights_to_keras_model(
        model,
        state.model
    )
    return model

def _load_tf_keras_model(self):
    """Loads tf keras models

    Raises:
        KeyError: A model name was not defined
            correctly

    Returns:
        (model): TF keras model object

    """
    model = create_models(
        model_type=self.model_type,
        input_shape=[self.img_h, self.img_w, 3],
        freeze_base_weights=self.freeze_weights,
        num_classes=self.num_classes,
        compile_model=False
    )

    return model

def _define_model(self):
    """Model creation function"""
    model = self._load_tf_keras_model()

    tff_model = tff.learning.from_keras_model(
        model,
        dummy_batch=self.sample_batch,
        loss=self.loss,
        # Using self.metrics throws an error
        metrics=[tf.keras.metrics.CategoricalAccuracy()] )

    return tff_model

def _construct_iterative_process(self):
    """Constructing federated averaging process"""
    iterative_process = tff.learning.build_federated_averaging_process(
        self._define_model,
        client_optimizer_fn=lambda: tf.keras.optimizers.SGD( learning_rate=0.02 ),
        server_optimizer_fn=lambda: tf.keras.optimizers.SGD( learning_rate=1.0 ) )
    return iterative_process

Ответы [ 2 ]

0 голосов
/ 28 мая 2020

Обратите внимание, что это ответ, но скорее понравившееся наблюдение.

Я пытался охарактеризовать процесс обучения (точность и потери) в Федеративном обучении для классификации изображений учебник по ноутбуку с TFF.

Я наблюдаю значительное улучшение скорости сходимости путем изменения гиперпараметра эпохи. Смена эпох от 5, 10, 20 и c. Но я также вижу значительное повышение точности тренировок. Я подозреваю, что происходит переобучение, хотя затем я оцениваю, что точность набора тестов все еще высока.

Интересно, что происходит. ?

Насколько я понимаю, параметр эпохи управляет числом прямых / обратных опор для каждого клиента за раунд обучения. Это верно ? Итак, ie 10 раундов обучения на 10 клиентах с 10 эпохами будут 10 эпох на 10 клиентов на 10 раундов. Поймите, что необходим более широкий круг клиентов и c, но я ожидал увидеть худшую точность на тестовом наборе.

Что я могу сделать, чтобы увидеть, что происходит. Могу ли я использовать оценочную проверку с чем-то вроде кривых обучения, чтобы узнать, происходит ли переоснащение? Проверка точности каждого тестового примера подтверждена?

Оцените любые мысли, которые могут у вас возникнуть по этому поводу, Колин. . .

0 голосов
/ 08 мая 2020
Увеличено количество раундов до 5 ...

Выполнение только нескольких раундов звуков федеративного обучения недостаточно. Одна из самых ранних работ по федеративному усреднению ( McMahan 2016 ) требовала выполнения сотен раундов, когда данные MNIST не были разделены на iid. Совсем недавно ( Reddi 2020 ) требовались тысячи раундов для CIFAR-100. Следует отметить, что каждый «раунд» - это один «шаг» глобальной модели. Этот шаг может быть больше с большим количеством клиентских эпох, но они усреднены, и расходящиеся клиенты могут уменьшить величину глобального шага.

Я также сохраняю веса модели tf keras после каждого раунда и делаю прогнозы на набор тестов - без изменений.

Это может быть касательно. Было бы легче отлаживать, если бы вы могли поделиться кодом, используемым в обучении FL l oop.

...