Я выполнил этот учебник emnist , чтобы создать эксперимент по классификации изображений (7 классов) с целью обучения классификатора на 3-х хранилищах данных с помощью TFF framework. начинается, я конвертирую модель в модель tf keras, используя tff.learning.assign_weights_to_keras_model(model,state.model)
для оценки на моем наборе проверки. Независимо от метки модель предсказывает только один класс. Этого следовало ожидать, поскольку обучение модели еще не произошло. Однако я повторяю этот шаг после каждого раунда федеративного усреднения, и проблема остается. Все проверочные изображения относятся к одному классу. Я также сохраняю веса модели tf keras после каждого раунда и делаю прогнозы на тестовом наборе - без изменений.
Некоторые шаги, которые я предпринял для проверки источника проблемы:
- Проверено, обновляются ли веса модели tf keras при преобразовании модели FL после каждого раунда - они обновляются.
- Гарантировано, что размер буфера больше, чем размер обучающего набора данных для каждого клиента.
- Сравнил прогнозы с распределением классов в обучающих наборах данных. Существует дисбаланс классов, но тот класс, который предсказывает модель, не обязательно является классом большинства. Кроме того, это не всегда один и тот же класс. По большей части, он предсказывает только класс 0.
- Увеличено количество раундов до 5 и эпох за раунд до 10. Это требует больших вычислительных ресурсов, так как это довольно большая модель, обучаемая примерно с 1500 изображениями на каждый. client.
- Исследовал журналы TensorBoard после каждой попытки обучения. Потери при обучении уменьшаются по мере прохождения раунда.
- Пробовал гораздо более простую модель - 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