전략 구현#
전략 추상화를 통해 완전한 맞춤형 전략을 구현할 수 있습니다. 전략은 기본적으로 서버에서 실행되는 연합 학습 알고리즘입니다. 전략은 클라이언트를 샘플링하는 방법, 학습을 위해 클라이언트를 구성하는 방법, 업데이트를 집계하는 방법, 모델을 평가하는 방법을 결정합니다. Flower는 아래에 설명된 것과 동일한 API를 기반으로 하는 몇 가지 기본 제공 전략을 제공합니다.
Strategy
추상화#
모든 전략 구현은 기본 제공 구현과 타사 구현 모두 추상 기본 클래스인 :code:`flwr.server.strategy.Strategy`에서 파생됩니다. 즉, 사용자 정의 전략 구현은 기본 제공 구현과 완전히 동일한 기능을 사용할 수 있습니다.
전략 추상화에서는 구현해야 하는 몇 가지 추상적인 메서드를 정의합니다:
class Strategy(ABC):
"""Abstract base class for server strategy implementations."""
@abstractmethod
def initialize_parameters(
self, client_manager: ClientManager
) -> Optional[Parameters]:
"""Initialize the (global) model parameters."""
@abstractmethod
def configure_fit(
self,
server_round: int,
parameters: Parameters,
client_manager: ClientManager
) -> List[Tuple[ClientProxy, FitIns]]:
"""Configure the next round of training."""
@abstractmethod
def aggregate_fit(
self,
server_round: int,
results: List[Tuple[ClientProxy, FitRes]],
failures: List[Union[Tuple[ClientProxy, FitRes], BaseException]],
) -> Tuple[Optional[Parameters], Dict[str, Scalar]]:
"""Aggregate training results."""
@abstractmethod
def configure_evaluate(
self,
server_round: int,
parameters: Parameters,
client_manager: ClientManager
) -> List[Tuple[ClientProxy, EvaluateIns]]:
"""Configure the next round of evaluation."""
@abstractmethod
def aggregate_evaluate(
self,
server_round: int,
results: List[Tuple[ClientProxy, EvaluateRes]],
failures: List[Union[Tuple[ClientProxy, FitRes], BaseException]],
) -> Tuple[Optional[float], Dict[str, Scalar]]:
"""Aggregate evaluation results."""
@abstractmethod
def evaluate(
self, parameters: Parameters
) -> Optional[Tuple[float, Dict[str, Scalar]]]:
"""Evaluate the current model parameters."""
새 전략을 생성한다는 것은 이전에 표시된 추상 메서드에 대해 구현하는 새로운 :code:`class`(추상 기본 클래스 :code:`Strategy`에서 파생됨)를 구현하는 것을 의미합니다:
class SotaStrategy(Strategy):
def initialize_parameters(self, client_manager):
# Your implementation here
def configure_fit(self, server_round, parameters, client_manager):
# Your implementation here
def aggregate_fit(self, server_round, results, failures):
# Your implementation here
def configure_evaluate(self, server_round, parameters, client_manager):
# Your implementation here
def aggregate_evaluate(self, server_round, results, failures):
# Your implementation here
def evaluate(self, parameters):
# Your implementation here
Flower 서버는 다음 순서로 이러한 메서드를 호출합니다:
다음 섹션에서는 이러한 각 방법에 대해 자세히 설명합니다.
initialize_parameters
메서드#
code:initialize_parameters`는 실행을 처음 시작할 때 한 번만 호출됩니다. 이 함수는 초기 전역 모델 파라미터를 직렬화된 형식(즉, :code:`Parameters 객체)으로 제공하는 역할을 합니다.
기본 제공 전략은 사용자가 제공한 초기 매개 변수를 반환합니다. 다음 예는 초기 매개 변수를 :code:`FedAvg`에 전달하는 방법을 보여줍니다:
import flwr as fl
import tensorflow as tf
# Load model for server-side parameter initialization
model = tf.keras.applications.EfficientNetB0(
input_shape=(32, 32, 3), weights=None, classes=10
)
model.compile("adam", "sparse_categorical_crossentropy", metrics=["accuracy"])
# Get model weights as a list of NumPy ndarray's
weights = model.get_weights()
# Serialize ndarrays to `Parameters`
parameters = fl.common.ndarrays_to_parameters(weights)
# Use the serialized parameters as the initial global parameters
strategy = fl.server.strategy.FedAvg(
initial_parameters=parameters,
)
fl.server.start_server(config=fl.server.ServerConfig(num_rounds=3), strategy=strategy)
Flower 서버는 initialize_parameters`를 호출하여 :code:`initial_parameters`에 전달된 파라미터를 반환하거나 :code:`None`을 반환합니다. :code:`initial_parameters`에서 반환되는 매개변수가 없는 경우(즉, :code:`None
) 서버는 무작위로 클라이언트 하나를 선택하여 해당 클라이언트에 매개변수를 제공하도록 요청합니다. 이는 편의 기능이며 실제로는 권장하지 않지만 프로토타이핑에는 유용할 수 있습니다. 실제로는 항상 서버 측 매개변수 초기화를 사용하는 것이 좋습니다.
참고
서버 측 파라미터 초기화는 강력한 메커니즘입니다. 예를 들어 이전에 저장한 체크포인트에서 학습을 재개하는 데 사용할 수 있습니다. 또한 연합 학습을 사용하여 사전 학습된 모델을 미세 조정하는 등 하이브리드 접근 방식을 구현하는 데 필요한 기본 기능입니다.
configure_fit
메서드#
:code:`configure_fit`은 다가오는 학 라운드를 구성하는 역할을 합니다. 이 문맥에서 *구성*은 무엇을 의미하나요? 라운드를 구성한다는 것은 클라이언트를 선택하고 이 클라이언트에게 어떤 지침을 보낼지 결정하는 것을 의미합니다. code:`configure_fit`의 시그니처를 보면 이를 명확히 알 수 있습니다:
@abstractmethod
def configure_fit(
self,
server_round: int,
parameters: Parameters,
client_manager: ClientManager
) -> List[Tuple[ClientProxy, FitIns]]:
"""Configure the next round of training."""
반환 값은 튜플 목록으로, 각 튜플은 특정 클라이언트로 전송될 명령어를 나타냅니다. 전략 구현은 일반적으로 :code:`configure_fit`에서 다음 단계를 수행합니다:
client_manager`를 사용하여 사용 가능한 모든 클라이언트(또는 그 하위 집합)를 무작위로 샘플링합니다(각각 :code:`ClientProxy
개체로 표시됨)각
ClientProxy`를 현재 글로벌 모델 :code:`parameters
및config
dict를 보유한 동일한 :code:`FitIns`와 쌍을 이룹니다
보다 정교한 구현은 :code:`configure_fit`을 사용하여 사용자 지정 클라이언트 선택 로직을 구현할 수 있습니다. 클라이언트는 :code:`configure_fit`에서 반환된 목록에 해당 :code:`ClientProxy`가 포함된 경우에만 라운드에 참여합니다.
참고
이 반환 값의 구조는 사용자에게 많은 유연성을 제공합니다. instructions은 클라이언트별로 정의되므로 각 클라이언트에 서로 다른 명령어를 전송할 수 있습니다. 이를 통해 예를 들어 클라이언트마다 다른 모델을 학습시키거나 클라이언트마다 다른 하이퍼파라미터를 사용하는 사용자 지정 전략을 사용할 수 있습니다(config
dict를 통해).
aggregate_fit
메서드#
code:`aggregate_fit`은 :code:`configure_fit`에서 훈련하도록 선택되고 요청된 클라이언트가 반환한 결과를 집계하는 역할을 담당합니다.
@abstractmethod
def aggregate_fit(
self,
server_round: int,
results: List[Tuple[ClientProxy, FitRes]],
failures: List[Union[Tuple[ClientProxy, FitRes], BaseException]],
) -> Tuple[Optional[Parameters], Dict[str, Scalar]]:
"""Aggregate training results."""
물론 실패가 발생할 수 있으므로 서버가 명령을 보낸 모든 클라이언트로부터 결과를 얻을 수 있다는 보장은 없습니다(configure_fit`을 통해). 따라서 :code:`aggregate_fit`은 :code:`results
목록뿐만 아니라 failures
목록도 받습니다.
code:aggregate_fit`은 선택적 :code:`Parameters 개체와 집계된 메트릭의 dictionary를 반환합니다. Parameters
반환 값은 :code:`aggregate_fit`이 제공된 결과가 집계에 충분하지 않다고 판단할 수 있으므로(예: 실패 수가 너무 많음) 선택 사항입니다.
configure_evaluate
메서드#
:code:`configure_evaluate`는 다가오는 평가 라운드를 구성하는 역할을 합니다. 이 문맥에서 *구성*은 무엇을 의미하나요? 라운드를 구성한다는 것은 클라이언트를 선택하고 이러한 클라이언트에 전송할 지침을 결정하는 것을 의미합니다. :code:`configure_evaluate`의 시그니처를 보면 이를 명확히 알 수 있습니다:
@abstractmethod
def configure_evaluate(
self,
server_round: int,
parameters: Parameters,
client_manager: ClientManager
) -> List[Tuple[ClientProxy, EvaluateIns]]:
"""Configure the next round of evaluation."""
반환 값은 튜플 목록으로, 각 튜플은 특정 클라이언트로 전송될 명령어를 나타냅니다. 전략 구현은 일반적으로 :code:`configure_evaluate`에서 다음 단계를 수행합니다:
client_manager`를 사용하여 사용 가능한 모든 클라이언트(또는 그 하위 집합)를 무작위로 샘플링합니다(각각 :code:`ClientProxy
개체로 표시됨)각
ClientProxy`를 현재 글로벌 모델 :code:`parameters
및config
dict를 보유한 동일한 :code:`EvaluateIns`와 쌍을 이룹니다
보다 정교한 구현은 :code:`configure_evaluate`를 사용하여 사용자 지정 클라이언트 선택 로직을 구현할 수 있습니다. 클라이언트는 :code:`configure_evaluate`에서 반환된 목록에 해당 :code:`ClientProxy`가 포함된 경우에만 라운드에 참여합니다.
참고
이 반환 값의 구조는 사용자에게 많은 유연성을 제공합니다. 명령어는 클라이언트별로 정의되므로 각 클라이언트에 서로 다른 명령어를 전송할 수 있습니다. 이를 통해 사용자 지정 전략을 통해 예를 들어 클라이언트마다 다른 모델을 평가하거나 클라이언트마다 다른 하이퍼파라미터를 사용할 수 있습니다(config
dict를 통해).
aggregate_evaluate
메서드#
code:`aggregate_evaluate`는 :code:`configure_evaluate`에서 선택되어 평가를 요청한 클라이언트가 반환한 결과를 집계하는 역할을 담당합니다.
@abstractmethod
def aggregate_evaluate(
self,
server_round: int,
results: List[Tuple[ClientProxy, EvaluateRes]],
failures: List[Union[Tuple[ClientProxy, FitRes], BaseException]],
) -> Tuple[Optional[float], Dict[str, Scalar]]:
"""Aggregate evaluation results."""
물론 실패가 발생할 수 있으므로 서버가 명령을 보낸 모든 클라이언트로부터 결과를 얻을 수 있다는 보장은 없습니다(configure_evaluate`를 통해). 따라서 :code:`aggregate_evaluate`는 :code:`results
목록뿐만 아니라 failures
목록도 받습니다.
code:aggregate_evaluate`는 선택적 :code:`float`(손실)와 집계된 메트릭의 dictionary를 반환합니다. code:`float 반환 값은 :code:`aggregate_evaluate`가 제공된 결과가 집계에 충분하지 않다고 판단할 수 있으므로(예: 실패 수가 너무 많음) 선택 사항입니다.
evaluate
메서드#
evaluate`는 서버 측에서 모델 매개변수를 평가하는 역할을 담당합니다. code:`configure_evaluate
/:code:`aggregate_evaluate`와 함께 :code:`evaluate`를 사용하면 서버 측과 클라이언트 측(federated) 평가를 모두 수행할 수 있는 전략을 사용할 수 있습니다.
@abstractmethod
def evaluate(
self, parameters: Parameters
) -> Optional[Tuple[float, Dict[str, Scalar]]]:
"""Evaluate the current model parameters."""
반환 값은 전략에서 서버 측 평가를 구현할 필요가 없거나 사용자 정의 evaluate
메서드가 성공적으로 완료되지 않을 수 있기 때문에(예: 서버 측 평가 데이터를 로드하지 못할 수 있음) 다시 선택 사항으로 설정할 수 있습니다.