복습 본 튜토리얼의 2장에서는 매우 간단한 버전의 연합 학습을 사용하여 모델을 학습했습니다. 이를 위해 모델 소유자는 각 데이터 소유자의 그래디언트(gradient)에 대한 정보를 알 수 있었고, 데이터 소유자들은 모델 소유자를 신뢰해야 했습니다.
설명: 본 튜토리얼에서는 3장에서 소개했던 고급 집계 방법들을 응용해서, 최종 모델이 모델 소유자 (우리)에게 보내지기 전에 신뢰할 수 있는 "보안 작업자"가 모델의 가중치들을 집계하는 방법을 소개할 것입니다.
이렇게 해서, 어느 가중치가 누구의 것인지 오직 보안 작업자만이 알 수 있습니다. 우리는 모델의 어느 부분이 바뀌었는지는 알 수 있어도, 어떤 작업자(Bob 또는 Alice)가 무엇을 바꿨는지는 알 수 없고, 이렇게 추가적인 사생활 보호가 가능합니다.
저자:
역자:
In [ ]:
import torch
import syft as sy
import copy
hook = sy.TorchHook(torch)
from torch import nn, optim
In [ ]:
# create a couple workers
bob = sy.VirtualWorker(hook, id="bob")
alice = sy.VirtualWorker(hook, id="alice")
secure_worker = sy.VirtualWorker(hook, id="secure_worker")
# A Toy Dataset
data = torch.tensor([[0,0],[0,1],[1,0],[1,1.]], requires_grad=True)
target = torch.tensor([[0],[0],[1],[1.]], requires_grad=True)
# get pointers to training data on each worker by
# sending some training data to bob and alice
bobs_data = data[0:2].send(bob)
bobs_target = target[0:2].send(bob)
alices_data = data[2:].send(alice)
alices_target = target[2:].send(alice)
In [ ]:
# Iniitalize A Toy Model
model = nn.Linear(2,1)
In [ ]:
bobs_model = model.copy().send(bob)
alices_model = model.copy().send(alice)
bobs_opt = optim.SGD(params=bobs_model.parameters(),lr=0.1)
alices_opt = optim.SGD(params=alices_model.parameters(),lr=0.1)
In [ ]:
for i in range(10):
# Train Bob's Model
bobs_opt.zero_grad()
bobs_pred = bobs_model(bobs_data)
bobs_loss = ((bobs_pred - bobs_target)**2).sum()
bobs_loss.backward()
bobs_opt.step()
bobs_loss = bobs_loss.get().data
# Train Alice's Model
alices_opt.zero_grad()
alices_pred = alices_model(alices_data)
alices_loss = ((alices_pred - alices_target)**2).sum()
alices_loss.backward()
alices_opt.step()
alices_loss = alices_loss.get().data
print("Bob:" + str(bobs_loss) + " Alice:" + str(alices_loss))
In [ ]:
alices_model.move(secure_worker)
In [ ]:
bobs_model.move(secure_worker)
이 학습 epoch의 마지막 단계는 Bob과 Alice가 훈련한 모델들을 평균화한 것을 이용해서 글로벌 "모델"의 값들을 설정하는 것입니다.
In [ ]:
with torch.no_grad():
model.weight.set_(((alices_model.weight.data + bobs_model.weight.data) / 2).get())
model.bias.set_(((alices_model.bias.data + bobs_model.bias.data) / 2).get())
In [ ]:
iterations = 10
worker_iters = 5
for a_iter in range(iterations):
bobs_model = model.copy().send(bob)
alices_model = model.copy().send(alice)
bobs_opt = optim.SGD(params=bobs_model.parameters(),lr=0.1)
alices_opt = optim.SGD(params=alices_model.parameters(),lr=0.1)
for wi in range(worker_iters):
# Train Bob's Model
bobs_opt.zero_grad()
bobs_pred = bobs_model(bobs_data)
bobs_loss = ((bobs_pred - bobs_target)**2).sum()
bobs_loss.backward()
bobs_opt.step()
bobs_loss = bobs_loss.get().data
# Train Alice's Model
alices_opt.zero_grad()
alices_pred = alices_model(alices_data)
alices_loss = ((alices_pred - alices_target)**2).sum()
alices_loss.backward()
alices_opt.step()
alices_loss = alices_loss.get().data
alices_model.move(secure_worker)
bobs_model.move(secure_worker)
with torch.no_grad():
model.weight.set_(((alices_model.weight.data + bobs_model.weight.data) / 2).get())
model.bias.set_(((alices_model.bias.data + bobs_model.bias.data) / 2).get())
print("Bob:" + str(bobs_loss) + " Alice:" + str(alices_loss))
마지막으로, 우리의 모델이 올바르게 학습되었는지 확인하기 위해, 테스트 데이터셋 (test dataset)으로 이 모델을 평가할 것입니다. 이 간단한 예제에서는 기존 데이터를 사용하지만, 실제로는 새로운 데이터를 사용하여 이 모델이 본 적 없는 데이터에도 얼마나 잘 일반화하는지 확인합니다.
In [ ]:
preds = model(data)
loss = ((preds - target) ** 2).sum()
In [ ]:
print(preds)
print(target)
print(loss.data)
이 간단한 예제에서, 평균화된 모델은 데이터 소유자가 학습시킨 모델에 비해서 underfit 합니다. 대신 우리는 각 데이터 소유자의 학습 데이터를 노출시키지 않고 이 모델을 훈련시킬 수 있었습니다. 또한 우리는 모델 소유자에게 데이터가 유출되는 것을 방지하기 위해 각 데이터 소유자의 업데이트된 모델을 신뢰할 수 있는 집계기에서 통합했습니다.
향후의 튜토리얼에서는, 이러한 신뢰할 수 있는 집계 방식을 그래디언트에 사용하는 법을 배울 것입니다. 이렇게 함으로써 더 나은 그래디언트로 모델을 업데이트 함으로써 더 강력한 모델을 얻을 수 있습니다.
이 파이썬 노트북 튜토리얼을 완료한 것을 축하합니다! 이 튜토리얼에 만족하셨다면, 그리고 사생활을 보호하는 분산소유 형태의 AI와 AI 공급망(데이터)을 위한 움직임에 동참하고 싶다면 다음과 같은 방법이 있습니다!
커뮤니티를 돕는 가장 쉬운 방법은 GitHub 리포지토리를 널리 알리는 것입니다! 이를 통해 우리가 만드는 멋진 도구에 대한 인식을 높일 수 있습니다.
최신 소식을 받는 가장 좋은 방법은 커뮤니티에 가입하는 것입니다! http://slack.openmined.org에서 양식을 작성하면 됩니다.
커뮤니티에 기여하는 가장 좋은 방법은 코드에 기여하는 것입니다! 언제든지 PySyft GitHub 이슈 페이지로 이동하여 "Projects"를 필터링 할 수 있습니다. 그러면 참여할 수 있는 프로젝트에 대한 개요를 제공하는 모든 최상위 이슈 티켓이 표시됩니다. 프로젝트에 참여하고 싶지는 않지만 약간의 코딩을 원한다면 "good first issue"로 표시된 GitHub 이슈를 검색하여 더 많은 "일회용" 미니 프로젝트를 찾을 수도 있습니다.
코드에 기여할 시간이 없지만 지원을 하고 싶다면 Open Collective의 후원자가 될 수도 있습니다. 모든 기부금은 웹 호스팅 및 해커톤 및 밋업과 같은 기타 커뮤니티 비용으로 들어갑니다!