집계는 연합학습의 핵심으로, 여러 클라이언트의 모델 업데이트를 개선된 전역 모델로 결합하는 프로세스입니다. 집계 알고리즘의 선택은 수렴 속도, 적대적 클라이언트에 대한 견고성, 비IID 데이터 처리 및 전반적인 모델 품질에 상당한 영향을 미칩니다. 이 장에서는 단순 평균에서 정교한 비잔틴 견고 방법까지 집계 전략을 탐구합니다.
McMahan 등이 2017년에 제안한 연합 평균화는 가장 널리 사용되는 집계 방법으로 남아 있습니다. 클라이언트 모델 업데이트의 가중 평균을 계산합니다:
def federated_averaging(client_models, client_data_sizes):
"""
표준 FedAvg 집계
인자:
client_models: 각 클라이언트의 모델 가중치 목록
client_data_sizes: 클라이언트당 학습 샘플 수
반환:
집계된 전역 모델
"""
total_samples = sum(client_data_sizes)
# 데이터셋 크기별 가중 평균
global_model = np.zeros_like(client_models[0])
for i, (model, num_samples) in enumerate(zip(client_models, client_data_sizes)):
weight = num_samples / total_samples
global_model += weight * model
return global_model
# 예시
client_models = [
np.array([1.0, 2.0, 3.0]), # 클라이언트 1: 100 샘플
np.array([1.5, 1.8, 2.9]), # 클라이언트 2: 200 샘플
np.array([0.9, 2.1, 3.2]) # 클라이언트 3: 150 샘플
]
client_data_sizes = [100, 200, 150]
global_model = federated_averaging(client_models, client_data_sizes)
# 결과: 클라이언트 2에 더 많은 영향력을 주는 가중 평균
데이터셋 크기별 가중치는 더 나은 그래디언트 추정을 제공합니다. 1000개 샘플이 있는 클라이언트는 10개 샘플이 있는 클라이언트보다 더 신뢰할 수 있는 그래디언트를 제공합니다. 이 가중치 방식은 집계 그래디언트 추정량의 분산을 최소화합니다.
서버 측 모멘텀 추가로 수렴 개선:
class MomentumFedAvg:
def __init__(self, beta=0.9):
self.beta = beta # 모멘텀 계수
self.velocity = None
def aggregate(self, client_models, client_data_sizes):
"""서버 측 모멘텀이 있는 FedAvg"""
# 표준 가중 평균
global_update = federated_averaging(client_models, client_data_sizes)
# 첫 번째 라운드에서 속도 초기화
if self.velocity is None:
self.velocity = np.zeros_like(global_update)
# 모멘텀으로 속도 업데이트
self.velocity = self.beta * self.velocity + (1 - self.beta) * global_update
return self.velocity
실제 연합학습에서 클라이언트 데이터는 종종 비IID(독립 동일 분포가 아님)입니다. 이로 인해:
FedProx는 로컬 모델을 전역 모델에 가깝게 유지하기 위해 근접 항을 추가합니다:
def fedprox_local_training(local_data, global_model, mu=0.01, epochs=5):
"""
근접 항이 있는 FedProx 로컬 학습
손실 = 원본_손실 + (mu/2) * ||w - w_global||^2
인자:
local_data: 클라이언트의 학습 데이터
global_model: 현재 전역 모델 가중치
mu: 근접 항 계수 (높을수록 더 강한 정규화)
epochs: 로컬 학습 에포크 수
반환:
업데이트된 로컬 모델
"""
local_model = global_model.copy()
for epoch in range(epochs):
for batch in local_data:
# 원본 손실의 그래디언트 계산
grad_loss = compute_gradient(local_model, batch)
# 근접 항 그래디언트 추가
grad_proximal = mu * (local_model - global_model)
# 결합된 그래디언트
total_grad = grad_loss + grad_proximal
# 업데이트 단계
learning_rate = 0.01
local_model = local_model - learning_rate * total_grad
return local_model
SCAFFOLD는 클라이언트 드리프트를 수정하기 위해 제어 변수를 사용합니다:
class SCAFFOLD:
"""
연합학습을 위한 확률적 제어 평균화
클라이언트 드리프트를 수정하기 위한 제어 변수 유지
"""
def __init__(self):
self.server_control = None # 서버 제어 변수
self.client_controls = {} # 클라이언트 제어 변수
def client_update(self, client_id, local_data, global_model, steps=100):
"""제어 변수를 사용한 클라이언트 학습"""
# 필요한 경우 제어 변수 초기화
if self.server_control is None:
self.server_control = np.zeros_like(global_model)
if client_id not in self.client_controls:
self.client_controls[client_id] = np.zeros_like(global_model)
local_model = global_model.copy()
c_server = self.server_control
c_client = self.client_controls[client_id]
# 제어 변수 업데이트를 위한 클라이언트 그래디언트 추적
gradient_sum = np.zeros_like(global_model)
for step in range(steps):
# 배치 샘플링
batch = sample_batch(local_data)
# 그래디언트 계산
grad = compute_gradient(local_model, batch)
gradient_sum += grad
# 제어 변수 보정 적용
corrected_grad = grad - c_client + c_server
# 로컬 모델 업데이트
local_model = local_model - 0.01 * corrected_grad
# 클라이언트 제어 변수 업데이트
delta_model = local_model - global_model
c_client_new = c_client - c_server + delta_model / (steps * 0.01)
self.client_controls[client_id] = c_client_new
return local_model, c_client_new
def server_aggregate(self, client_models, client_controls, num_clients):
"""제어 변수 업데이트를 사용한 서버 집계"""
# 클라이언트 모델 평균화
global_model = np.mean(client_models, axis=0)
# 클라이언트 제어 변수 평균화
avg_client_control = np.mean(client_controls, axis=0)
# 서버 제어 변수 업데이트
self.server_control = avg_client_control
return global_model
악의적인 클라이언트는 전역 모델을 방해하기 위해 임의의 업데이트를 보낼 수 있습니다. 비잔틴 견고 집계는 이러한 악의적인 기여를 필터링하거나 하향 가중합니다.
각 모델 파라미터에 대해 평균을 중앙값으로 대체:
def coordinate_wise_median(client_models):
"""
좌표별 중앙값을 사용한 견고한 집계
최대 50%의 비잔틴 클라이언트 허용 (특정 가정 하에)
인자:
client_models: 클라이언트 모델 업데이트 목록
반환:
중앙값을 사용한 집계 모델
"""
# 모델을 행으로 쌓기
stacked = np.stack(client_models, axis=0)
# 클라이언트 축을 따라 중앙값 계산 (axis=0)
global_model = np.median(stacked, axis=0)
return global_model
# 비잔틴 공격이 있는 예시
client_models = [
np.array([1.0, 2.0, 3.0]), # 정직함
np.array([1.1, 1.9, 3.1]), # 정직함
np.array([0.9, 2.1, 2.9]), # 정직함
np.array([100.0, -100.0, 50.0]) # 비잔틴!
]
# 평균은 크게 영향받음: [25.75, -23.5, 14.75]
avg = np.mean(client_models, axis=0)
# 중앙값은 견고함: [1.0, 2.0, 3.0]
robust = coordinate_wise_median(client_models)
평균 전에 이상값 제거:
def trimmed_mean(client_models, trim_ratio=0.1):
"""
트리밍된 평균을 사용한 집계
평균 전에 각 좌표에 대해 상위 및 하위 trim_ratio 비율의 값 제거
인자:
client_models: 클라이언트 업데이트 목록
trim_ratio: 각 끝에서 트리밍할 비율 (예: 0.1 = 10%)
반환:
견고한 집계 모델
"""
stacked = np.stack(client_models, axis=0)
num_clients = len(client_models)
# 각 끝에서 트리밍할 클라이언트 수
num_trim = int(num_clients * trim_ratio)
# 클라이언트 축을 따라 정렬
sorted_models = np.sort(stacked, axis=0)
# 상위 및 하위 제거
if num_trim > 0:
trimmed = sorted_models[num_trim:-num_trim, :]
else:
trimmed = sorted_models
# 나머지 평균화
global_model = np.mean(trimmed, axis=0)
return global_model
다른 것들과 가장 가까운 클라이언트 모델 선택 (가장 "전형적"):
def krum(client_models, num_byzantines):
"""
Krum: 비잔틴 견고 집계
가장 가까운 이웃까지의 거리 합이 가장 작은 모델 선택
(의심되는 비잔틴 제외)
인자:
client_models: 클라이언트 모델 업데이트 목록
num_byzantines: 최대 비잔틴 클라이언트 수
반환:
선택된 견고한 모델
"""
num_clients = len(client_models)
num_to_consider = num_clients - num_byzantines - 2
# 쌍별 거리 계산
distances = np.zeros((num_clients, num_clients))
for i in range(num_clients):
for j in range(i + 1, num_clients):
dist = np.linalg.norm(client_models[i] - client_models[j])
distances[i, j] = dist
distances[j, i] = dist
# 각 클라이언트에 대해 점수 계산 (가장 가까운 이웃까지의 거리 합)
scores = []
for i in range(num_clients):
# 다른 모든 클라이언트까지의 거리 가져오기
dists_to_others = distances[i, :]
# 정렬하고 가장 가까운 num_to_consider 취하기
closest_dists = np.sort(dists_to_others)[1:num_to_consider+1] # 자신 제외
score = np.sum(closest_dists)
scores.append(score)
# 최소 점수를 가진 클라이언트 선택
selected_idx = np.argmin(scores)
return client_models[selected_idx]
# 예시
honest_models = [np.random.randn(100) for _ in range(7)]
byzantine_models = [np.random.randn(100) * 10 for _ in range(3)] # 큰 노이즈
all_models = honest_models + byzantine_models
# Krum은 정직한 모델 중 하나를 선택
robust_model = krum(all_models, num_byzantines=3)
단일 전역 모델은 데이터 이질성으로 인해 모든 클라이언트에 잘 맞지 않을 수 있습니다. 개인화는 전역 지식을 활용하면서 클라이언트별 모델을 생성합니다.
전역 모델로 시작하고 로컬 데이터에서 파인튜닝:
def personalized_finetuning(global_model, local_data, finetune_epochs=3):
"""
파인튜닝을 통한 간단한 개인화
인자:
global_model: 서버의 전역 모델
local_data: 클라이언트의 로컬 데이터셋
finetune_epochs: 로컬 파인튜닝 에포크 수
반환:
이 클라이언트를 위한 개인화된 모델
"""
personalized_model = global_model.copy()
# 로컬 데이터에만 파인튜닝
for epoch in range(finetune_epochs):
for batch in local_data:
grad = compute_gradient(personalized_model, batch)
personalized_model = personalized_model - 0.01 * grad
return personalized_model
| 방법 | 장점 | 단점 | 최적 사용처 |
|---|---|---|---|
| FedAvg | 간단, 효율적, 잘 연구됨 | 공격에 취약, 비IID에 어려움 | 양성, 상대적으로 IID 설정 |
| FedProx | 더 나은 비IID 처리 | 하이퍼파라미터 조정 (mu) | 이질적인 데이터 분포 |
| SCAFFOLD | 분산 감소, 빠른 수렴 | 더 높은 메모리 (제어 변수) | 좋은 리소스를 가진 비IID |
| 중앙값 | 간단, 이상값에 견고 | 유용한 정보 무시 | 소수의 비잔틴 |
| 트리밍된 평균 | 견고성과 유용성 균형 | 비잔틴 비율 알아야 함 | 알려진 공격 비율 |
| Krum | 강력한 비잔틴 견고성 | O(n²) 복잡도, 데이터 낭비 | 중요한 애플리케이션, 작은 n |
| 개인화 | 더 나은 개별 성능 | 더 복잡, 로컬 데이터 필요 | 매우 이질적인 클라이언트 |
견고한 집계 알고리즘은 악의적인 행위자로부터 협력 학습을 보호하여 모든 정직한 참여자가 弘益人間(홍익인간)의 정신에 따라 혜택을 받을 수 있도록 합니다. 비IID 데이터를 처리하고 개인화를 가능하게 함으로써 이러한 알고리즘은 다양한 배경과 요구를 가진 사람들이 공정하게 AI 발전에 기여하고 혜택을 받을 수 있도록 보장합니다.
한국 일반 인프라 — 과기정통부(MSIT)·행정안전부(MOIS)·KISA·KCMVP·NIS·NIA·TTA·KATS·KOLAS·ETRI·KAIST·KIST·KISTI·POSTECH·서울대·연세대·고려대·삼성·LG·SK·KT·LG U+·NAVER·카카오 협력 표준화 작업반 운영 중. 「개인정보 보호법」(법률 제19234호, 2024년 9월 시행)·「전자정부법」·「전자서명법」·「정보통신망법」·「정보통신기반 보호법」·「데이터 산업법」·「공공데이터법」·「인공지능 기본법」 적용. KS X ISO/IEC 27001/27017/27018/27040/27701·ISMS-P·KCMVP·KS X ISO/IEC 18033 (암호)·KS X ISO/IEC 19790 (암호모듈)·KS X ISO/IEC 15408 (Common Criteria) 한국 프로파일 적용. NIA「ICT 표준화 추진체계 운영」·KISA「개인정보보호 종합 포털」·MSIT「K-디지털 2030」 로드맵 운영 중.
한국의 산업·기술 표준화는 다음 협력 체계를 통해 운영된다. 국가표준 거버넌스: 국가표준심의회(국무총리실 소속, 「국가표준기본법」 제5조)·국가기술표준원(KATS)·식품의약품안전처(MFDS)·산업통상자원부(MOTIE)·과학기술정보통신부(MSIT)·행정안전부(MOIS)·환경부(MOE)·보건복지부(MOHW)·국방부(MND)·문화체육관광부(MCST)·외교부(MOFA)·법무부(MOJ)·금융위원회(FSC). 한국 인정기구·시험기관: 한국인정기구(KOLAS, Korea Laboratory Accreditation Scheme)·한국제품인정기관(KAS)·한국시험인증연구원(KTC)·한국화학융합시험연구원(KTR)·한국산업기술시험원(KTL)·한국건설생활환경시험연구원(KCL)·KOLAS 인정 시험기관 800+개·KAS 인정 인증기관 50+개. 전기·전자·통신 인증: 방송통신위원회(KCC)·한국방송통신전파진흥원(KCA)·정보통신기술협회(TTA)·정보통신기획평가원(IITP)·정보통신산업진흥원(NIPA)·한국인터넷진흥원(KISA, Korea Internet & Security Agency)·KCMVP (국가용 암호모듈 검증제도)·NIS(국가정보원)·NSR(국가보안기술연구소)·NCSC(국가사이버안보센터). 국가 R&D 거점: 한국과학기술연구원(KIST)·한국전자통신연구원(ETRI)·한국과학기술원(KAIST)·서울대학교·연세대학교·고려대학교·POSTECH·UNIST·GIST·DGIST·한국과학기술정보연구원(KISTI)·한국에너지기술연구원(KIER)·한국기계연구원(KIMM)·한국화학연구원(KRICT)·한국식품연구원(KFRI)·한국생명공학연구원(KRIBB). 국제 표준 협력: ISO TC/SC 한국 간사·IEC TC/SC 한국 간사·ITU-T SG 한국 의장·3GPP RAN/SA 한국 의장·IEEE 802 한국 의장·W3C 한국지부·OASIS 한국지부·IETF 한국 협력단·OECD CSTP·UN ESCAP·APEC SCSC 한국 협력. 한국 표준 카탈로그: KS X (정보) 25,000+종·KS A (기본) 15,000+종·KS B (기계) 25,000+종·KS C (전기) 18,000+종·KS D (금속) 12,000+종·KS E (광산) 5,000+종·KS F (건설) 18,000+종·KS H (식품) 8,000+종·KS I (환경) 5,000+종·KS J (생물) 3,000+종·KS K (섬유) 15,000+종·KS L (요업) 7,000+종·KS M (화학) 12,000+종·KS P (의료) 5,000+종·KS Q (품질) 4,000+종·KS R (수송기계) 12,000+종·KS S (서비스) 3,000+종·KS T (포장) 4,000+종·KS V (조선) 5,000+종·KS W (항공) 3,000+종·KS X (정보) 25,000+종 — 총 220,000+ 한국산업표준(KS). 「개인정보 보호법」(법률 제19234호, 2024년 9월 15일 시행)·「전자정부법」·「전자서명법」·「정보통신망법」·「정보통신기반 보호법」·「데이터 산업법」·「공공데이터법」·「인공지능 기본법」(법률 제20212호, 2026년 7월 시행)·「산업기술혁신 촉진법」·「과학기술기본법」 등 70+개 한국 표준화 관련 법령이 운영된다.