adap / flower

Flower: A Friendly Federated AI Framework
https://flower.ai
Apache License 2.0
5.14k stars 882 forks source link

`Server.fit` method crash with `TypeError: 'int' object is not iterable` error #530

Closed altor closed 3 years ago

altor commented 3 years ago

Hello, since release 0.11.0 I'm not able to launch code that worked fine with release 0.10.0

I have the same problem with release 0.12.0

Here is the Error Stack :

File "/srv/code/utils/ml_server_flower.py", line 70, in run
    hist = server.fit(num_rounds=federated_config['ROUND_BEFORE_AGGREGATION'])
  File "/usr/local/lib/python3.7/dist-packages/flwr/server/server.py", line 110, in fit
    res_fed = self.evaluate(rnd=current_round)
  File "/usr/local/lib/python3.7/dist-packages/flwr/server/server.py", line 133, in evaluate
    rnd=rnd, weights=self.weights, client_manager=self._client_manager
  File "/usr/local/lib/python3.7/dist-packages/flwr/server/strategy/fedavg.py", line 121, in configure_evaluate
    parameters = weights_to_parameters(weights)
  File "/usr/local/lib/python3.7/dist-packages/flwr/common/parameter.py", line 28, in weights_to_parameters
    tensors = [ndarray_to_bytes(ndarray) for ndarray in weights]
TypeError: 'int' object is not iterable

The context where the issue appears

client_manager = SimpleClientManager()
strategy = FedAvg()
server = Server(client_manager=client_manager, strategy=strategy)

model = KerasModel(data[0].shape[1], data[0].shape[2], data[1].shape[1])

grpc_server = start_insecure_grpc_server(
    client_manager=server.client_manager(), server_address=params['grpc_host']
)
hist = server.fit(num_rounds=federated_config['ROUND_BEFORE_AGGREGATION'])
...

the model i use :

class KerasModel:
    def __init__(self, n_timesteps, n_features, n_outputs):
        """
        with : n_timesteps, n_features, n_outputs = trainX.shape[1], trainX.shape[2], trainy.shape[1]
        """
        #Personalization of the optimizer
        sgd = optimizers.SGD(lr=float(keras_config['LEARNING_RATE']), momentum=0.0, decay=0.0,
                             nesterov=False)
        adam = optimizers.Adam(lr=float(keras_config['LEARNING_RATE']))
        rmsProp = optimizers.RMSprop(lr=float(keras_config['LEARNING_RATE']), rho=0.9, epsilon=None, decay=0.0)
        adagrad = optimizers.Adagrad(lr=0.01, epsilon=None, decay=0.0)
        adadelta = optimizers.Adadelta(lr=1.0, rho=0.95, epsilon=None, decay=0.0)
        adamax = optimizers.Adamax(lr=0.002, beta_1=0.9, beta_2=0.999, epsilon=None, decay=0.0)

        #The network
        self.model = Sequential()
        self.model.add(Conv1D(filters=int(keras_config['FILTERS_CONV1D']),
                         kernel_size=int(keras_config['KERNEL_CONV1D']), activation=keras_config['ACTIVATION_CONV1D'],
                         input_shape=(n_timesteps,n_features)))
        #self.model.add(Conv1D(filters=8, kernel_size=5, activation='relu'))
        self.model.add(Dropout(float(keras_config['DROPOUT_RATIO'])))
        self.model.add(MaxPooling1D(pool_size=int(keras_config['POOL_SIZE_MAXPOOL'])))

        self.model.add(Conv1D(filters = int(keras_config['FILTERS_CONV1D']),
                              kernel_size=int(keras_config['KERNEL_CONV1D']), activation = keras_config['ACTIVATION_CONV1D']))
        self.model.add(Dropout(float(keras_config['DROPOUT_RATIO'])))
        self.model.add(MaxPooling1D(pool_size=int(keras_config['POOL_SIZE_MAXPOOL'])))

        self.model.add(Flatten())
        self.model.add(Dense(int(keras_config['DENSE1_NEURONS']), activation=keras_config['ACTIVATION_DENSE1']))
        self.model.add(Dense(n_outputs, activation=keras_config['ACTIVATION_DENSE2']))
        self.model.compile(loss=keras_config['LOSS'], optimizer=keras_config['OPTIMIZER'], metrics=['accuracy'])

    def set_weights(self, weights):
        self.model.set_weights(weights)

    def fit(self, x_train, y_train, epochs=None):
        self.model.fit(x_train, y_train, epochs=epochs, batch_size=common_config['BATCH_SIZE'])

    def get_weights(self):
        return self.model.get_weights()

    def evaluate(self, x_test, y_test):
        return self.model.evaluate(x_test, y_test)

configuration dictionary :


federated_config = {
    'ROUND_BEFORE_AGGREGATION': 3,
    'EPOCHS_PER_ROUND': 2,
}

common_config = {
    'TEST_BATCH_SIZE': 1000,
    'BATCH_SIZE': 64,
    'EPOCHS': 5,
}

keras_config = {
    'LEARNING_RATE': 0.0004,
    'FILTERS_CONV1D': 8,
    'KERNEL_CONV1D': 3,
    'ACTIVATION_CONV1D': 'relu',
    'DROPOUT_RATIO': 0.5,
    'POOL_SIZE_MAXPOOL': 3,
    'L2_REGU': False,
    'DENSE1_NEURONS': 20,
    'ACTIVATION_DENSE1': 'relu',
    'VALUE_L2_REGU': 0.001,
    'ACTIVATION_DENSE2': 'softmax',
    'LOSS': 'mean_squared_error',
    'OPTIMIZER': 'adam',
}
danieljanes commented 3 years ago

Thanks for the report @altor ! We went through your code and everything looks fine. The issues seems to be related to parameter serialization for distributed evaluation (i.e., on the clients). Does the initial round of training work before Flower tries to do the evaluation? IIRC there were no changes related to that part of the codebase during the 0.11.0 and 0.12.0 release. Would it be possible to open source your code (or alternatively invite @tanertopal and @danieljanes to a private repo) so that we can try to run it?

danieljanes commented 3 years ago

Closing this now because we couldn't reproduce. Feel free to reopen if this is still an issue for you @altor .