# Early Stopping Implementation

**URL:** <https://discuss.flower.ai/t/early-stopping-implementation/426>\
**Category:** Flower Help - Intermediate\
**Created:** [November 18, 2024, 3:22pm UTC](https://discuss.flower.ai/t/early-stopping-implementation/426 "2024-11-18T15:22:11Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![azulu](https://dub1.discourse-cdn.com/flex013/user_avatar/discuss.flower.ai/azulu/32/140_2.png) [@azulu](https://discuss.flower.ai/u/azulu)\
**Post date:** [November 18, 2024, 3:22pm UTC](https://discuss.flower.ai/t/early-stopping-implementation/426/1 "2024-11-18T15:22:12Z")

</div>

Hello everyone!

I am doing a custom strategy with FedAVG as base strategy.

I was wondering, if there is any way to implement an Early stopping for the strategy, making use of the Flower framework methods, I haven’t seen in the documentation anything related to this, neither how to stop the federated training process manually.

Thank you in advance!

---

<div class="post-metadata">

**Author:** ![matt08](https://avatars.discourse-cdn.com/v4/letter/m/a4c791/32.png) [@matt08](https://discuss.flower.ai/u/matt08)\
**Post date:** [November 18, 2024, 5:20pm UTC](https://discuss.flower.ai/t/early-stopping-implementation/426/2 "2024-11-18T17:20:02Z")

</div>

Hello

a option could be to implement a new class e.g.

```auto
class EarlyStoppingStrategy(fl.server.strategy.FedAvg):                                                          
    def __init__ (self, patience, target_metric):
        super(). __init__ ()
        self.patience = patience
        self.target_metric = target_metric # mainly the loss or someting else e.g. accuracy, f1score...                                                                                
        self.beset_metric = 0  
        self.counter = 0                                                                                                                   

    def aggregate_evaluate(self, server_round, results, failures):
        aggregated_metrics = super().aggregate_evaluate(server_round, results, failures)
        if server_round == 1:
            if self.target_metric in aggregated_metrics:
                self.best_metric = aggregated_metrics[self.target_metric]                                           
        else:
            if self.target_metric in aggregated_metrics:
                current_metric = aggregated_metrics[self.target_metric]                                                                        
                if current_metric > self.best_metric:
                    self.best_metric = current_metric
                    self.counter = 0
                else:
                    self.counter += 1  
                if self.counter >= self.patience: 
                    return aggregated_metrics
            return aggregated_metrics

```

The question remains how to stop training. Maybe if you set your server\_round to your selected server\_round. There is certainly an optimal solution

---

<div class="post-metadata">

**Author:** ![matt08](https://avatars.discourse-cdn.com/v4/letter/m/a4c791/32.png) [@matt08](https://discuss.flower.ai/u/matt08)\
**Post date:** [November 18, 2024, 5:25pm UTC](https://discuss.flower.ai/t/early-stopping-implementation/426/3 "2024-11-18T17:25:10Z")

</div>

```auto
strategy = EarlyStoppingStrategy(
              fraction_fit= .....
                  patience=3,
                  target_metric = "loss", 
                  evaluate_metrics_aggregation_fn=weighted_average, )

```

There is definitely a more efficient one. So i am also excited which suggestions comes next 😃

---

<div class="post-metadata">

**Author:** ![azulu](https://dub1.discourse-cdn.com/flex013/user_avatar/discuss.flower.ai/azulu/32/140_2.png) [@azulu](https://discuss.flower.ai/u/azulu)\
**Post date:** [November 19, 2024, 10:24am UTC](https://discuss.flower.ai/t/early-stopping-implementation/426/4 "2024-11-19T10:24:14Z")

</div>

Exactly! I was trying to do something like this, a FedAvg strategy but with early stopping (with patience, best\_metric, counter, min\_delta…), but then I couldn’t find any way to stop the federated training! 😅

Let’s see if a Flower developer sees this, and recommends us a way to stop the process even if it is in a rudimentary way (closing gRPC communications e.g.) in the meanwhile.

---

<div class="post-metadata">

**Author:** ![adam-narozniak](https://dub1.discourse-cdn.com/flex013/user_avatar/discuss.flower.ai/adam-narozniak/32/33_2.png) [@adam-narozniak](https://discuss.flower.ai/u/adam-narozniak)\
**Post date:** [November 20, 2024, 9:51am UTC](https://discuss.flower.ai/t/early-stopping-implementation/426/5 "2024-11-20T09:51:20Z")

</div>

Hi,  
Unfortunately, I don’t think it’s currently possible to terminate the simulation earlier based on some external condition like early stopping (the server is started as a separate thread, and I don’t see a way to influence its behavior from the strategy level), but note that I haven’t been involved in the development. Maybe we’ll get a different response from @javier but we’ll have to wait a bit for his response (he’s currently not available).

---

<div class="post-metadata">

**Author:** ![azulu](https://dub1.discourse-cdn.com/flex013/user_avatar/discuss.flower.ai/azulu/32/140_2.png) [@azulu](https://discuss.flower.ai/u/azulu)\
**Post date:** [November 20, 2024, 10:44am UTC](https://discuss.flower.ai/t/early-stopping-implementation/426/6 "2024-11-20T10:44:04Z")

</div>

Hi Adam,

Thank you for letting me know about that issue, maybe we should think of another kind of solution…

It seems we’ll have to wait for Javier’s opinion on the matter.

Kind regards! 😄

---

<div class="post-metadata">

**Author:** ![javier](https://dub1.discourse-cdn.com/flex013/user_avatar/discuss.flower.ai/javier/32/116_2.png) [@javier](https://discuss.flower.ai/u/javier)\
**Post date:** [November 22, 2024, 7:59am UTC](https://discuss.flower.ai/t/early-stopping-implementation/426/7 "2024-11-22T07:59:24Z")

</div>

Hi @azulu, @adam-narozniak ,

What some people have done in the past is to modify slightly how the base [Server](https://github.com/adap/flower/blob/67688c6708b3cf23829c872999c0f9887b9ed558/src/py/flwr/server/server.py#L58) works. Of particular interset is the [fit](https://github.com/adap/flower/blob/67688c6708b3cf23829c872999c0f9887b9ed558/src/py/flwr/server/server.py#L111) for loop, which runs for the specified number of rounds. What you could do is to add a couple of lines that, given some logic in a custom strategy that you implement, it does the `break` from the for loop. Does it make sense?

Note you can pass a custom `Server` object when you write your `server_fn` that returns an instance of [ServerAppComponents](https://github.com/adap/flower/blob/67688c6708b3cf23829c872999c0f9887b9ed558/src/py/flwr/server/serverapp_components.py#L33).

This is currently the best way to achieve early stopping. It will be easier with upcoming versions of flower.

There is another way: implement a custom strategy and, once your early stopping condition is reached, effectively disable the sampling on clients In this way the remaining rounds will go through but will do no work (which will make your experiment finish very fast).

---

<div class="post-metadata">

**Author:** ![system](https://europe1.discourse-cdn.com/flex013/uploads/flower/original/1X/bc7fe36843c391cbd0b4e8b6f48275961d356abc.png) [@system](https://discuss.flower.ai/u/system)\
**Post date:** [November 29, 2024, 8:43am UTC](https://discuss.flower.ai/t/early-stopping-implementation/426/8 "2024-11-29T08:43:49Z")

</div>

Closed on November 29, 2024, 8:43am UTC

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.
