Repository: lishenghui/blades (language: python)

Issue:
From master



Discussion / hints:

Fix patch:
diff --git a/src/blades/aggregators/autogm.py b/src/blades/aggregators/autogm.py
index 4b6422e..1d7dea6 100644
--- a/src/blades/aggregators/autogm.py
+++ b/src/blades/aggregators/autogm.py
@@ -13,10 +13,10 @@ def _compute_euclidean_distance(v1, v2):
 
 
 class Autogm(_BaseAggregator):
-    r"""A robust aggregator from paper `"Byzantine-Robust Aggregation in
-    Federated Learning Empowered Industrial IoT".
+    r"""A robust aggregator from paper `Byzantine-Robust Aggregation in
+    Federated Learning Empowered Industrial IoT.
 
-    <https://ieeexplore.ieee.org/abstract/document/9614992>`_
+    <https://ieeexplore.ieee.org/abstract/document/9614992>`_.
 
     Args:
         maxiter: Maximum number of Weiszfeld iterations, default 2.0.
diff --git a/src/blades/aggregators/centeredclipping.py b/src/blades/aggregators/centeredclipping.py
index 6194a96..c84bf2c 100644
--- a/src/blades/aggregators/centeredclipping.py
+++ b/src/blades/aggregators/centeredclipping.py
@@ -13,13 +13,12 @@ class Centeredclipping(_BaseAggregator):
     r"""A robust aggregator from paper `Learning from History for Byzantine
     Robust Optimization.
 
-    <http://proceedings.mlr.press/v139/karimireddy21a.html>`_
+    <http://proceedings.mlr.press/v139/karimireddy21a.html>`_. It iteratively
+    clips the updates around the center while updating the center accordingly.
 
-    It iteratively clips the updates around the center while updating the center
-    accordingly.
-
-    :param tau: The threshold of clipping. Default 10.0
-    :param n_iter: The number of clipping iterations. Default 5
+    Args:
+        tau (float): The threshold of clipping. Default 10.0
+        n_iter (int): The number of clipping iterations. Default 5
     """
 
     def __init__(self, tau: Optional[float] = 10.0, n_iter: Optional[int] = 5):
diff --git a/src/blades/aggregators/clippedclustering.py b/src/blades/aggregators/clippedclustering.py
index d2589b3..0528da3 100644
--- a/src/blades/aggregators/clippedclustering.py
+++ b/src/blades/aggregators/clippedclustering.py
@@ -12,17 +12,18 @@
 
 
 class Clippedclustering(_BaseAggregator):
-    r"""A robust aggregator from paper `"An Experimental Study of Byzantine-
-    Robust sAggregation Schemes in Federated Learning" <https://www.techrxiv.or
-    g/articles/preprint/An_Experimental_Study_of_Byzantine.
+    r"""A robust aggregator from paper `An Experimental Study of Byzantine-
+    Robust Aggregation Schemes in Federated L earning.
 
-         -Robust_Aggregation_Schemes_in_Federated_Learning/19560325>`_ # noqa: E501
-
-         it separates the client population into two groups based on the cosine similarities
+    <https://doi.org/10.36227/techrxiv.19560325.v1>`_. It separates the client
+    population into two groups based on the cosine similarities.
 
     Args:
         tau (float): threshold of clipping norm.
-                    If it is not given, updates are clipped according the median of historical norm.
+                    If it is not \given, updates are clipped according the median of
+                    historical norm.
+
+    __
     """
 
     def __init__(
diff --git a/src/blades/aggregators/clustering.py b/src/blades/aggregators/clustering.py
index 29a3ca2..429ad39 100644
--- a/src/blades/aggregators/clustering.py
+++ b/src/blades/aggregators/clustering.py
@@ -10,12 +10,13 @@
 
 
 class Clustering(_BaseAggregator):
-    r"""A robust aggregator from paper `"On the byzantine robustness of
-    clustered federated learning".
+    r"""A robust aggregator from paper `On the byzantine robustness of clustered
+    federated learning.
 
-    <https://ieeexplore.ieee.org/abstract/document/9054676>`_
+    <https://ieeexplore.ieee.org/abstract/document/9054676>`_.
 
-    it separates the client population into two groups based on the cosine similarities
+    It separates the client population into two groups based on the cosine
+    similarities.
     """
 
     def __init__(self):
diff --git a/src/blades/aggregators/dnc.py b/src/blades/aggregators/dnc.py
index 140d418..c9b5605 100644
--- a/src/blades/aggregators/dnc.py
+++ b/src/blades/aggregators/dnc.py
@@ -11,7 +11,7 @@ class Dnc(_BaseAggregator):
     r"""A robust aggregator from paper `Manipulating the Byzantine: Optimizing
     Model Poisoning Attacks and Defenses for Federated Learning.
 
-    <https://par.nsf.gov/servlets/purl/10286354>`_
+    <https://par.nsf.gov/servlets/purl/10286354>`_.
     """
 
     def __init__(
diff --git a/src/blades/aggregators/fltrust.py b/src/blades/aggregators/fltrust.py
index 41217f0..8cd7bb6 100644
--- a/src/blades/aggregators/fltrust.py
+++ b/src/blades/aggregators/fltrust.py
@@ -6,10 +6,10 @@
 
 
 class Fltrust(object):
-    r"""
-    ``Fltrust`` it a trusted-based aggregator from paper
-    `FLTrust: Byzantine-robust Federated Learning via Trust Bootstrapping
-     <https://arxiv.org/abs/2012.13995>`_
+    r"""``Fltrust`` it a trusted-based aggregator from paper `FLTrust:
+    Byzantine-robust Federated Learning via Trust Bootstrapping.
+
+    <https://arxiv.org/abs/2012.13995>`_.
     """
 
     def __call__(self, clients: List[BladesClient]):
diff --git a/src/blades/aggregators/geomed.py b/src/blades/aggregators/geomed.py
index e30d8cc..45aa430 100644
--- a/src/blades/aggregators/geomed.py
+++ b/src/blades/aggregators/geomed.py
@@ -33,8 +33,8 @@ def smoothed_weiszfeld(weights, alphas, z, eps=1e-6, T=5):
 
 
 class Geomed(_BaseAggregator):
-    r"""A robust aggregator from paper `"Distributed Statistical Machine
-    Learning in Adversarial Settings: Byzantine Gradient Descent".
+    r"""A robust aggregator from paper `Distributed Statistical Machine Learning
+    in Adversarial Settings: Byzantine Gradient Descent.
 
     <https://arxiv.org/abs/1705.05491>`_
 
diff --git a/src/blades/aggregators/median.py b/src/blades/aggregators/median.py
index cc49f5c..2d89913 100644
--- a/src/blades/aggregators/median.py
+++ b/src/blades/aggregators/median.py
@@ -10,7 +10,7 @@ class Median(_BaseAggregator):
     r"""A robust aggregator from paper `Byzantine-robust distributed learning:
     Towards optimal statistical rates.
 
-    <https://proceedings.mlr.press/v80/yin18a>`_
+    <https://proceedings.mlr.press/v80/yin18a>`_.
 
     It computes the coordinate-wise median of the given set of clients
     """
diff --git a/src/blades/aggregators/multikrum.py b/src/blades/aggregators/multikrum.py
index 2ef9bc7..36b8395 100644
--- a/src/blades/aggregators/multikrum.py
+++ b/src/blades/aggregators/multikrum.py
@@ -92,12 +92,10 @@ def _pairwise_euclidean_distances(vectors):
 
 
 class Multikrum(_BaseAggregator):
-    r"""A robust aggregator from paper `"Machine Learning with Adversaries:
-    Byzantine Tolerant Gradient Descent".
+    r"""A robust aggregator from paper `Machine Learning with Adversaries:
+    Byzantine Tolerant Gradient Descent.
 
-    <https://proceedings.neurips.cc/paper/2017/hash.
-
-    /f4b9ec30ad9f68f89b29639786cb62ef-Abstract.html>`_
+    <https://dl.acm.org/doi/abs/10.5555/3294771.3294783>`_.
 
     Given a collection of vectors, ``Krum`` strives to find one of the vector that is
     closest to another :math:`K-M-2` ones with respect to squared Euclidean distance,
diff --git a/src/blades/aggregators/signguard.py b/src/blades/aggregators/signguard.py
index edcc281..3a1ac5c 100644
--- a/src/blades/aggregators/signguard.py
+++ b/src/blades/aggregators/signguard.py
@@ -11,10 +11,11 @@
 
 
 class Signguard(_BaseAggregator):
-    r"""A robust aggregator from paper `Xu et al. SignGuard: Byzantine-robust
-    Federated Learning through Collaborative Malicious Gradient Filtering.
+    r"""A robust aggregator from paper `Xu et al.
 
-    <https://arxiv.org/abs/2109.05872>`_
+    SignGuard: Byzantine-robust Federated
+    Learning through Collaborative Malicious Gradient
+    Filtering <https://arxiv.org/abs/2109.05872>`_.
     """
 
     def __init__(self, agg="mean", max_tau=1e5, linkage="average") -> None:
diff --git a/src/blades/aggregators/signsgdmv.py b/src/blades/aggregators/signsgdmv.py
index 0ed1b37..a4af757 100644
--- a/src/blades/aggregators/signsgdmv.py
+++ b/src/blades/aggregators/signsgdmv.py
@@ -8,9 +8,9 @@
 
 class Signsgdmv(_BaseAggregator):
     r"""A robust aggregator from paper `signSGD with Majority Vote is
-    Communication Efficient And Fault Tolerant.
+    Communication Efficient And Fault Tolerant`__.
 
-    <https://arxiv.org/abs/1810.05291>`_
+    __ <https://arxiv.org/abs/1810.05291
     """
 
     def __int__(self):
diff --git a/src/blades/models/__init__.py b/src/blades/models/__init__.py
index 693ac0f..7768915 100644
--- a/src/blades/models/__init__.py
+++ b/src/blades/models/__init__.py
@@ -2,4 +2,4 @@
 from .cifar100.cct import CCTNet100
 from .mnist.mlp import MLP
 
-__all__ = [CCTNet10, CCTNet100, MLP]
+__all__ = ["CCTNet10", "CCTNet100", "MLP"]
diff --git a/src/blades/models/mnist/mlp.py b/src/blades/models/mnist/mlp.py
index d03a5cf..2442c02 100644
--- a/src/blades/models/mnist/mlp.py
+++ b/src/blades/models/mnist/mlp.py
@@ -33,7 +33,6 @@ def forward(self, x):
         x = self.fc3(x)
         x = F.log_softmax(x, dim=1)
         return x
-        # return x
 
 
 def create_model():


Test patch:
diff --git a/src/tests/test_clients/test_clients.py b/src/tests/test_clients/test_clients.py
index b6da295..84aaf43 100644
--- a/src/tests/test_clients/test_clients.py
+++ b/src/tests/test_clients/test_clients.py
@@ -33,3 +33,25 @@ def test_rsaclient():
         rsa_client._per_model.named_parameters(), net.named_parameters()
     ):
         assert torch.allclose(p_rsa, p_base)
+
+
+def test_client_momentum():
+    lr = 0.1
+    net = nn.Sequential(nn.Linear(2, 2))
+    opt = torch.optim.SGD(net.parameters(), lr=lr)
+
+    data = torch.rand(2, 2)
+    target = torch.randint(0, 1, (2,))
+
+    dataset_gen = (i for i in [(data, target)])
+    client = BladesClient(momentum=0.9, dampening=0.1)
+    client.set_loss()
+    client.set_global_model_ref(net)
+
+    client.train_global_model(dataset_gen, 1, opt)
+    dataset_gen = (i for i in [(data, target)])
+
+    client.set_global_model_ref(net)
+    client.train_global_model(dataset_gen, 1, opt)
+
+    print("OK")