Parte 3: Ferramentas Avançadas para Execução Remota

Na última seção nós utilizamos o conceito de Federated Learning para treinarmos um modelo bem simples. Nós fizemos isto apenas chamando .send() e .get() em nosso modelo. Ou seja, enviando-o para o local onde se encontram os dados de treinamento, atualizando-o, e então trazendo-o de volta. No entando, ao final do exemplo nós percebemos que precisaríamos ir mais além para proteger a privacidade das pessoas. Isto é, queremos calcular a média dos gradientes antes de chamar .get(). Dessa forma, nunca veremos o gradiente exato de ninguém (protegendo melhor sua privacidade!!!)

Mas, para fazer isso, precisamos de mais algumas coisas:

  • usar um ponteiro para enviar um Tensor diretamente para outro Worker

Além disso, enquanto estivermos aqui, vamos aprender sobre algumas operações mais avançadas com tensores, o que nos ajudará tanto com este exemplo quanto com alguns outros no futuro!

Autores:

Tradução:


In [ ]:
import torch
import syft as sy
hook = sy.TorchHook(torch)

Seção 3.1 - De ponteiros para ponteiros

Como você sabe, os objetos do tipo PointerTensor se comportam da mesma forma que tensores normais. De fato, eles são tão parecidos com tensores que podemos até ter ponteiros que apontam para outros ponteiros. Confira!


In [ ]:
bob = sy.VirtualWorker(hook, id='bob')
alice = sy.VirtualWorker(hook, id='alice')

In [ ]:
# este é um tensor local.
x = torch.tensor([1,2,3,4])
x

In [ ]:
# enviando o tensor local para Bob
x_ptr = x.send(bob)

# agora temos um apontador/ponteiro
x_ptr

In [ ]:
# agora podemos ENVIAR O APONTADOR para alice!!!
pointer_to_x_ptr = x_ptr.send(alice)

pointer_to_x_ptr

Mas o que acabamos de fazer?

Bom, no exemplo anterior, nós criamos um tensor chamado x e o enviamos para Bob, criando um ponteiro em nossa máquina local (x_ptr).

Em seguida, nós chamamos x_ptr.send(alice) que envia o ponteiro para Alice.

Note, isso NÃO move os dados! Em vez disso, move o ponteiro, isto é, o apontador para os dados!!


In [ ]:
# Como você pode ver acima, Bob ainda possui os dados reais (os dados sempre são armazenados com tipo LocalTensor).
bob._objects

In [ ]:
# Alice, por outro lado, tem x_ptr!! (observe o ponteiro para Bob)
alice._objects

In [ ]:
# podemos usar .get() para recuperar x_ptr de Alice

x_ptr = pointer_to_x_ptr.get()
x_ptr

In [ ]:
# e então podemos usar x_ptr para recuperar x de Bob!

x = x_ptr.get()
x

Aritmética em Pointero -> Pointero -> Objeto com Dados

Assim como nos ponteiros normais, podemos executar quaisquer operações do PyTorch nesses tensores.


In [ ]:
bob._objects

In [ ]:
alice._objects

In [ ]:
p2p2x = torch.tensor([1,2,3,4,5]).send(bob).send(alice)

y = p2p2x + p2p2x

In [ ]:
bob._objects

In [ ]:
alice._objects

In [ ]:
y.get().get()

In [ ]:
bob._objects

In [ ]:
alice._objects

In [ ]:
p2p2x.get().get()

In [ ]:
bob._objects

In [ ]:
alice._objects

Seção 3.2 - Operações com tensores em cadeia

Na última seção, sempre que usávamos uma operação .send() ou .get(), chamávamos essas operações diretamente do tensor em nossa máquina local. No entanto, se você tiver uma cadeia de ponteiros, às vezes você deseja chamar essas operações como .get() ou .send() no último ponteiro da cadeia (como enviar dados diretamente de um worker* para outro). Para conseguirmos isso, você deseja usar funções especialmente projetadas para lidar com operações que devem preservar sua privacidade.

Essas operações são:

  • meuPonteiro_para_outroPonteiro.mover(outro_worker)

In [ ]:
# x agora é um ponteiro para um outro ponteiro para os dados que vivem na máquina de Bob
x = torch.tensor([1,2,3,4,5]).send(bob)

In [ ]:
print('  bob:', bob._objects)
print('alice:', alice._objects)

In [ ]:
x = x.move(alice)

In [ ]:
print('  bob:', bob._objects)
print('alice:', alice._objects)

In [ ]:
x

Excelente! Agora estamos equipados com as ferramentas para executar a média de gradientes remota usando um agregador confiável!

Parabéns!!! - Hora de se juntar a comunidade!

Parabéns por concluir esta etapa do tutorial! Se você gostou e gostaria de se juntar ao movimento em direção à proteção de privacidade, propriedade descentralizada e geração, demanda em cadeia, de dados em IA, você pode fazê-lo das seguintes maneiras!

Dê-nos uma estrela em nosso repo do PySyft no GitHub

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.

Junte-se ao Slack!

A melhor maneira de manter-se atualizado sobre os últimos avanços é se juntar à nossa comunidade! Você pode fazer isso preenchendo o formulário em http://slack.openmined.org

Contribua com o projeto!

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".

Doar

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!

Página do Open Collective do OpenMined


In [ ]: