Agora que passamos pelos planos, nós iremos introduzir um novo objeto chamado Protocol (Protocolo). Um Protocol coordena uma sequência da Planos, implementa-os em workers distantes e executa-os em uma passada só.
O Protocolo é um objeto de alto nível que contém uma lógica de computações complexas distribuidas através de vários workers. A principal função de um Protocol é a habilidade de ser enviado / procurado/ buscado de volta entre workers e finalmente distribuído para workers identificados. Então um usuário pode planejar um protocolo, carregá-lo para uma rede de workers, e qualquer outro worker será capaz de procurá-lo, baixá-lo e aplicar o programa de computação que ele contém em workers ao qual ele está conectado.
Vamos ver como usá-lo!
Autores:
Tradutor:
Protocolos são criados fornecendo uma lista de pares (worker, plan)
. worker
pode ser tanto um worker real quanto um id do worker ou uma string que representa um worker fictício. Esse último caso pode ser usado na criação para especificar que dois planos devem ser pertencidos (ou não pertencidos) ao mesmo worker na implementação. plan
pode ser tanto um Plano como um PointerPlan.
In [ ]:
import torch as th
import syft as sy
hook = sy.TorchHook(th)
# IMPORTANTE: Worker local não deve ser um worker cliente
hook.local_worker.is_client_worker = False
Vamos definir 3 planos e alimentá-los para um protocolo. Todos eles implementam uma operação de incremento.
In [ ]:
@sy.func2plan(args_shape=[(1,)])
def inc1(x):
return x + 1
@sy.func2plan(args_shape=[(1,)])
def inc2(x):
return x + 1
@sy.func2plan(args_shape=[(1,)])
def inc3(x):
return x + 1
protocol = sy.Protocol([("worker1", inc1), ("worker2", inc2), ("worker3", inc3)])
Agora nós precisamos ligar o Protocolo aos workers, o que é feito chamando .deploy(*workers)
. Vamos criar alguns workers.
In [ ]:
bob = sy.VirtualWorker(hook, id="bob")
alice = sy.VirtualWorker(hook, id="alice")
charlie = sy.VirtualWorker(hook, id="charlie")
In [ ]:
workers = alice, bob, charlie
protocol.deploy(*workers)
Você pode ver que os planos já foram enviados para os workers apropriados: isso já foi implantado!
Esse processo tem sido feito em 2 fases: primeiramente, nós mapeamos os workers fictícios fornecidos na criação (nomeados por strings ) para os workers fornecidos e, em segundo lugar, nós enviamos os planos correspondentes para cada um deles.
Executar um protocolo significa executar todos os planos sequencialmente. Para isso, você fornece alguma dado de entrada que é enviado para a primeira localidade de um plano. Esse primeiro plano é executado e sua saída é redirecionada para a localização do segundo plano, e assim por diante. O resultado final é retornado depois que todos os planos foram executados, e é composto de apontadores para a última localização do plano.
In [ ]:
x = th.tensor([1.0])
ptr = protocol.run(x)
ptr
In [ ]:
ptr.get()
Essa entrada 1.0 passou por 3 planos e foi incrementada 3 vezes, por isso agora ela é igual 4.0!
Na verdade, voce também pode executar um protocolo remotamente em alguns apontadores dos dados:
In [ ]:
james = sy.VirtualWorker(hook, id="james")
In [ ]:
protocol.send(james)
In [ ]:
x = th.tensor([1.0]).send(james)
ptr = protocol.run(x)
ptr
Como você pode ver, o resultado é um apontador para james.
In [ ]:
ptr = ptr.get()
ptr
In [ ]:
ptr = ptr.get()
ptr
Vamos inicializar um protocolo que não é distribuído, e colocá-lo em um worker remoto.
In [ ]:
protocol = sy.Protocol([("worker1", inc1), ("worker2", inc2), ("worker3", inc3)])
protocol.tag('my_protocol')
protocol.send(james)
In [ ]:
me = sy.hook.local_worker # get access to me as a local worker
Agora nós fazemos uma busca para encontrar o protocolo.
In [ ]:
responses = me.request_search(['my_protocol'], location=james)
responses
Você tem acesso ao apontador para o Protocolo.
In [ ]:
ptr_protocol = responses[0]
Como um apontador normal, você pode pegar isso de volta:
In [ ]:
protocol_back = ptr_protocol.get()
protocol_back
E nós podemos fazer como fizemos nas partes 1. & 2.
In [ ]:
protocol_back.deploy(alice, bob, charlie)
x = th.tensor([1.0])
ptr = protocol_back.run(x)
ptr.get()
Mais exemplos do mundo real virão com Protocolos, mas você já pode observar todas as possibilidades que foram abertas por esse novo objeto!
A maneira mais fácil de ajudar nossa comunidade é adicionando uma estrela nos nossos repositórios! Isso ajuda a aumentar a conscientização sobre essas ferramentas legais que estamos construindo.
Fizemos tutoriais muito bons para entender melhor como deve ser a Aprendizagem Federada e a proteção de Privacidade, e como estamos construindo as coisas básicas que precisamos para fazer com que isso aconteça.
A melhor maneira de manter-se atualizado sobre os últimos avanços é se juntar à nossa comunidade!
A melhor maneira de contribuir para a nossa comunidade é se tornando um contribuidor do código! A qualquer momento, você pode acessar a página de Issues (problemas) do PySyft no GitHub e filtrar por "Projetos". Isso mostrará todas as etiquetas (tags) na parte superior, com uma visão geral de quais projetos você pode participar! Se você não deseja ingressar em um projeto, mas gostaria de codificar um pouco, também pode procurar mais mini-projetos "independentes" pesquisando problemas no GitHub marcados como "good first issue".
Se você não tem tempo para contribuir com nossa base de códigos, mas ainda deseja nos apoiar, também pode se tornar um Apoiador em nosso Open Collective. Todas as doações vão para hospedagem na web e outras despesas da comunidade, como hackathons e meetups!