From bf1d61a3800e06e0d4a1e3f8aa5016e1698905c9 Mon Sep 17 00:00:00 2001 From: jefersonf Date: Fri, 13 Dec 2019 00:03:02 -0300 Subject: [PATCH 01/17] add translation to Portuguese of the tutorial Part 02 --- ...47\303\243o a Aprendizagem Federada.ipynb" | 298 ++++++++++++++++++ 1 file changed, 298 insertions(+) create mode 100644 "examples/tutorials/translations/portugues/Parte 02 - Introdu\303\247\303\243o a Aprendizagem Federada.ipynb" diff --git "a/examples/tutorials/translations/portugues/Parte 02 - Introdu\303\247\303\243o a Aprendizagem Federada.ipynb" "b/examples/tutorials/translations/portugues/Parte 02 - Introdu\303\247\303\243o a Aprendizagem Federada.ipynb" new file mode 100644 index 00000000000..bcc53095a17 --- /dev/null +++ "b/examples/tutorials/translations/portugues/Parte 02 - Introdu\303\247\303\243o a Aprendizagem Federada.ipynb" @@ -0,0 +1,298 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Parte 2: Introdução ao Federated Learning\n", + "\n", + "Na última seção, nós aprendemos sobre PointerTensors, que criam a infraestrutura necessária que precisamos para proteção de privacidade em Deep Learning. Nessa seção, nós iremos ver como usar essas ferramentas básicas para implementar nosso primeiro algoritmo de proteção de privacidade em Deep Learning: Federated Learning. \n", + "\n", + "Autores:\n", + "- Andrew Trask - Twitter: [@iamtrask](https://twitter.com/iamtrask)\n", + "\n", + "Tradução:\n", + "- Jeferson Silva - Twitter: [@jefersonnpn](https://twitter.com/jefersonnpn)\n", + "\n", + "### O que é Federated Learning?\n", + "\n", + "\n", + "É uma simples, porém poderosa maneira de treinar modelos de Deep Learning. Pense em dados de treinamento, são sempre o resultado de algum processo de coleta. As pessoas (via dispositivos) geram dados ao gravar eventos no mundo real. Normalmente, esses dados são agregados em uma simples localização central em que você pode treinar um modelo de aprendizegam de máquina. O Federated Learning vira isso de ponta a cabeça!\n", + "\n", + "Ao invés de trazer dados de treinamento para o modelo (um servidor central), você trás o modelo para os dados de treinamento (onde quer que ele esteja).\n", + "\n", + "A ideia é que isso permita que quem estiver criando os dados possua a única cópia permanente e, assim, mantenha o controle sobre quem já teve acesso a eles. Muito legal, não acha?" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Seção 2.1 - Um exemplo de Federated Learning\n", + "\n", + "Vamos começar treinando um modelo de exemplo da maneira centralizada. Isso é tão simples quanto obter o modelo. Primeiro precisamos:\n", + "\n", + "- um conjunto de dados para brincarmos\n", + "- um modelo\n", + "- alguma lógica básica de treinamento para treinar um modelo que se ajusta aos dados\n", + "\n", + "Obs.: Se para você, a seguinte API ainda não é familar. Visite o [fast.ai](http://fast.ai) e faça os seus cursos antes de continuar esse tutorial." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import torch\n", + "from torch import nn\n", + "from torch import optim" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "# Dataset de exemplo\n", + "data = torch.tensor([[0,0],[0,1],[1,0],[1,1.]], requires_grad=True)\n", + "target = torch.tensor([[0],[0],[1],[1.]], requires_grad=True)\n", + "\n", + "# Modelo simples de exemplo\n", + "model = nn.Linear(2,1)\n", + "\n", + "def train():\n", + " # Lógica de treinamento\n", + " opt = optim.SGD(params=model.parameters(),lr=0.1)\n", + " for iter in range(20):\n", + "\n", + " # 1) apague os gradientes anteriores (caso eles existam)\n", + " opt.zero_grad()\n", + "\n", + " # 2) faça uma predição\n", + " pred = model(data)\n", + "\n", + " # 3) calcule o erro, isto é, o quanto perdemos\n", + " loss = ((pred - target)**2).sum()\n", + "\n", + " # 4) descubra quais pesos nos causaram essa perda\n", + " loss.backward()\n", + "\n", + " # 5) altere esses pesos\n", + " opt.step()\n", + "\n", + " # 6) mostre o progresso até então\n", + " print(loss.data)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "train()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "E aí está! Nós treinamos um modelo simples da maneira convencional. Todos os nossos dados estão agregados em nossa máquina local e podemos usá-los para fazer atualizações em nosso modelo. O aprendizado federado, no entanto, não funciona dessa maneira. Então, vamos modificar este exemplo para fazê-lo da maneira federada!\n", + "\n", + "Então, o que precisamos:\n", + "\n", + "- criar alguns *workers*, isto é, nós de computação\n", + "- obter apontadores para dados de treinamento de cada *worker*\n", + "- atualizadar a lógica de treinamento para fazer o aprendizado federado\n", + "\n", + " Novas etapas de treinamento:\n", + " - enviar modelo para um *worker* e fazer correções/atualizações\n", + " - treinar com os dados que lá estão localizados\n", + " - pegar o modelo de volta e repetir o processo com o próximo *worker* " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import syft as sy\n", + "hook = sy.TorchHook(torch)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# cria dois nós (ou duas entidades de computação)\n", + "\n", + "bob = sy.VirtualWorker(hook, id=\"bob\")\n", + "alice = sy.VirtualWorker(hook, id=\"alice\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Nosso dataset de exemplo\n", + "data = torch.tensor([[0,0],[0,1],[1,0],[1,1.]], requires_grad=True)\n", + "target = torch.tensor([[0],[0],[1],[1.]], requires_grad=True)\n", + "\n", + "# obtenha apontadores para os dados de treinamento de cada worker \n", + "# enviando alguns dados de treinamento para bob e alice\n", + "data_bob = data[0:2]\n", + "target_bob = target[0:2]\n", + "\n", + "data_alice = data[2:]\n", + "target_alice = target[2:]\n", + "\n", + "# Inicialize o modelo\n", + "model = nn.Linear(2,1)\n", + "\n", + "data_bob = data_bob.send(bob)\n", + "data_alice = data_alice.send(alice)\n", + "target_bob = target_bob.send(bob)\n", + "target_alice = target_alice.send(alice)\n", + "\n", + "# organize os apontadores numa lista\n", + "datasets = [(data_bob,target_bob),(data_alice,target_alice)]\n", + "\n", + "opt = optim.SGD(params=model.parameters(),lr=0.1)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def train():\n", + " # Lógica de treinamento\n", + " opt = optim.SGD(params=model.parameters(),lr=0.1)\n", + " for iter in range(10):\n", + " \n", + " # NOVO) itere através do dataset de cada worker\n", + " for data,target in datasets:\n", + " \n", + " # NOVO) envie o modelo para corrigir/atualizar o worker\n", + " model.send(data.location)\n", + "\n", + " # 1) apague os gradientes anteriores (caso eles existam)\n", + " opt.zero_grad()\n", + "\n", + " # 2) faça uma predição\n", + " pred = model(data)\n", + "\n", + " # 3) calcule o erro, isto é, o quanto perdemos\n", + " loss = ((pred - target)**2).sum()\n", + "\n", + " # 4) descubra quais pesos nos causaram essa perda\n", + " loss.backward()\n", + "\n", + " # 5) atualize os pesos\n", + " opt.step()\n", + " \n", + " # NOVO) pegue o modelo (com gradientes)\n", + " model.get()\n", + "\n", + " # 6) mostre o progresso até então\n", + " print(loss.get()) # NOVO) leve edição... precisa usar o .get() a partir do loss\\\n", + " \n", + "# média federada" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "train()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Pronto!\n", + "\n", + "E voilà! Agora estamos treinando um modelo muito simples de Deep Learning usando o Federated Learning! Enviamos o modelo para cada *worker*, geramos um novo gradiente e, em seguida, devolvemos o gradiente ao servidor local, onde atualizamos nosso modelo global. Nunca, neste processo, jamais vemos ou solicitamos acesso aos dados subjacentes ao treinamento! Preservamos a privacidade de Bob e Alice!!!\n", + "\n", + "## Problemas deste exemplo\n", + "\n", + "Embora este exemplo seja uma boa introdução ao Federated Learning, ele ainda apresenta algumas falhas importantes. A mais notável, é que quando chamamos `model.get()` e recebemos o modelo atualizado de Bob ou Alice, podemos aprender muito sobre os dados de treinamento de ambos apenas observando seus gradientes. Em alguns casos, podemos restaurar os dados de treinamento de forma completa!\n", + "\n", + "Então o que poderíamos fazer? Bem, a primeira estratégia empregada pelas pessoas é **calcular a média do gradiente em vários indivíduos antes de carregá-lo no servidor central**. Essa estratégia, no entanto, exigirá um uso mais sofisticado dos objetos _PointerTensor_. Portanto, na próxima seção, vamos passar um algum tempo aprendendo sobre funcionalidades mais avançada ao utilizar ponteiros e, em seguida, iremos atualizar este exemplo de Federated Learning.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Parabéns!!! - Hora de se juntar a comunidade!\n", + "\n", + "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!\n", + "\n", + "### Dê-nos uma estrela em nosso repo do PySyft no GitHub\n", + "\n", + "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.\n", + "\n", + "- [Star PySyft](https://github.com/OpenMined/PySyft)\n", + "\n", + "### Junte-se ao Slack!\n", + "\n", + "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](http://slack.openmined.org)\n", + "\n", + "### Contribua com o projeto!\n", + "\n", + "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 de nível 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\".\n", + "\n", + "- [Projetos do PySyft](https://github.com/OpenMined/PySyft/issues?q=is%3Aopen+is%3Aissue+label%3AProject)\n", + "- [Etiquetados como Good First Issue](https://github.com/OpenMined/PySyft/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22)\n", + "\n", + "### Doar\n", + "\n", + "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!\n", + "\n", + "[Página do Open Collective do OpenMined](https://opencollective.com/openmined)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.5.2" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From 20444ef981064c96791da375488ab0cf2b2ccf22 Mon Sep 17 00:00:00 2001 From: jefersonf Date: Fri, 13 Dec 2019 00:43:10 -0300 Subject: [PATCH 02/17] (enhance) translate example toy expression literally --- ...02 - Introdu\303\247\303\243o a Aprendizagem Federada.ipynb" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/examples/tutorials/translations/portugues/Parte 02 - Introdu\303\247\303\243o a Aprendizagem Federada.ipynb" "b/examples/tutorials/translations/portugues/Parte 02 - Introdu\303\247\303\243o a Aprendizagem Federada.ipynb" index bcc53095a17..27b21175ffc 100644 --- "a/examples/tutorials/translations/portugues/Parte 02 - Introdu\303\247\303\243o a Aprendizagem Federada.ipynb" +++ "b/examples/tutorials/translations/portugues/Parte 02 - Introdu\303\247\303\243o a Aprendizagem Federada.ipynb" @@ -28,7 +28,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Seção 2.1 - Um exemplo de Federated Learning\n", + "# Seção 2.1 - Um exemplo brinquedo de Federated Learning\n", "\n", "Vamos começar treinando um modelo de exemplo da maneira centralizada. Isso é tão simples quanto obter o modelo. Primeiro precisamos:\n", "\n", From a1154e54dc88ddd3b3ab057adefa5f695b87b875 Mon Sep 17 00:00:00 2001 From: jefersonf Date: Sun, 15 Dec 2019 13:32:53 -0300 Subject: [PATCH 03/17] =?UTF-8?q?(minor=20fixes)=20change=20'portugues'=20?= =?UTF-8?q?to=20'portugu=C3=AAs'=20and=20'n=C3=ADvel=20superior'=20to=20'p?= =?UTF-8?q?arte=20superior'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...47\303\243o a Aprendizagem Federada.ipynb" | 298 ++++++++++++++++++ 1 file changed, 298 insertions(+) create mode 100644 "examples/tutorials/translations/portugu\303\252s/Parte 02 - Introdu\303\247\303\243o a Aprendizagem Federada.ipynb" diff --git "a/examples/tutorials/translations/portugu\303\252s/Parte 02 - Introdu\303\247\303\243o a Aprendizagem Federada.ipynb" "b/examples/tutorials/translations/portugu\303\252s/Parte 02 - Introdu\303\247\303\243o a Aprendizagem Federada.ipynb" new file mode 100644 index 00000000000..c979e64a3a5 --- /dev/null +++ "b/examples/tutorials/translations/portugu\303\252s/Parte 02 - Introdu\303\247\303\243o a Aprendizagem Federada.ipynb" @@ -0,0 +1,298 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Parte 2: Introdução ao Federated Learning\n", + "\n", + "Na última seção, nós aprendemos sobre PointerTensors, que criam a infraestrutura necessária que precisamos para proteção de privacidade em Deep Learning. Nessa seção, nós iremos ver como usar essas ferramentas básicas para implementar nosso primeiro algoritmo de proteção de privacidade em Deep Learning: Federated Learning. \n", + "\n", + "Autores:\n", + "- Andrew Trask - Twitter: [@iamtrask](https://twitter.com/iamtrask)\n", + "\n", + "Tradução:\n", + "- Jeferson Silva - Twitter: [@jefersonnpn](https://twitter.com/jefersonnpn)\n", + "\n", + "### O que é Federated Learning?\n", + "\n", + "\n", + "É uma simples, porém poderosa maneira de treinar modelos de Deep Learning. Pense em dados de treinamento, são sempre o resultado de algum processo de coleta. As pessoas (via dispositivos) geram dados ao gravar eventos no mundo real. Normalmente, esses dados são agregados em uma simples localização central em que você pode treinar um modelo de aprendizegam de máquina. O Federated Learning vira isso de ponta a cabeça!\n", + "\n", + "Ao invés de trazer dados de treinamento para o modelo (um servidor central), você trás o modelo para os dados de treinamento (onde quer que ele esteja).\n", + "\n", + "A ideia é que isso permita que quem estiver criando os dados possua a única cópia permanente e, assim, mantenha o controle sobre quem já teve acesso a eles. Muito legal, não acha?" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Seção 2.1 - Um exemplo brinquedo de Federated Learning\n", + "\n", + "Vamos começar treinando um modelo de exemplo da maneira centralizada. Isso é tão simples quanto obter o modelo. Primeiro precisamos:\n", + "\n", + "- um conjunto de dados para brincarmos\n", + "- um modelo\n", + "- alguma lógica básica de treinamento para treinar um modelo que se ajusta aos dados\n", + "\n", + "Obs.: Se para você, a seguinte API ainda não é familar. Visite o [fast.ai](http://fast.ai) e faça os seus cursos antes de continuar esse tutorial." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import torch\n", + "from torch import nn\n", + "from torch import optim" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "# Dataset de exemplo\n", + "data = torch.tensor([[0,0],[0,1],[1,0],[1,1.]], requires_grad=True)\n", + "target = torch.tensor([[0],[0],[1],[1.]], requires_grad=True)\n", + "\n", + "# Modelo simples de exemplo\n", + "model = nn.Linear(2,1)\n", + "\n", + "def train():\n", + " # Lógica de treinamento\n", + " opt = optim.SGD(params=model.parameters(),lr=0.1)\n", + " for iter in range(20):\n", + "\n", + " # 1) apague os gradientes anteriores (caso eles existam)\n", + " opt.zero_grad()\n", + "\n", + " # 2) faça uma predição\n", + " pred = model(data)\n", + "\n", + " # 3) calcule o erro, isto é, o quanto perdemos\n", + " loss = ((pred - target)**2).sum()\n", + "\n", + " # 4) descubra quais pesos nos causaram essa perda\n", + " loss.backward()\n", + "\n", + " # 5) altere esses pesos\n", + " opt.step()\n", + "\n", + " # 6) mostre o progresso até então\n", + " print(loss.data)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "train()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "E aí está! Nós treinamos um modelo simples da maneira convencional. Todos os nossos dados estão agregados em nossa máquina local e podemos usá-los para fazer atualizações em nosso modelo. O aprendizado federado, no entanto, não funciona dessa maneira. Então, vamos modificar este exemplo para fazê-lo da maneira federada!\n", + "\n", + "Então, o que precisamos:\n", + "\n", + "- criar alguns *workers*, isto é, nós de computação\n", + "- obter apontadores para dados de treinamento de cada *worker*\n", + "- atualizadar a lógica de treinamento para fazer o aprendizado federado\n", + "\n", + " Novas etapas de treinamento:\n", + " - enviar modelo para um *worker* e fazer correções/atualizações\n", + " - treinar com os dados que lá estão localizados\n", + " - pegar o modelo de volta e repetir o processo com o próximo *worker* " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import syft as sy\n", + "hook = sy.TorchHook(torch)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# cria dois nós (ou duas entidades de computação)\n", + "\n", + "bob = sy.VirtualWorker(hook, id=\"bob\")\n", + "alice = sy.VirtualWorker(hook, id=\"alice\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Nosso dataset de exemplo\n", + "data = torch.tensor([[0,0],[0,1],[1,0],[1,1.]], requires_grad=True)\n", + "target = torch.tensor([[0],[0],[1],[1.]], requires_grad=True)\n", + "\n", + "# obtenha apontadores para os dados de treinamento de cada worker \n", + "# enviando alguns dados de treinamento para bob e alice\n", + "data_bob = data[0:2]\n", + "target_bob = target[0:2]\n", + "\n", + "data_alice = data[2:]\n", + "target_alice = target[2:]\n", + "\n", + "# Inicialize o modelo\n", + "model = nn.Linear(2,1)\n", + "\n", + "data_bob = data_bob.send(bob)\n", + "data_alice = data_alice.send(alice)\n", + "target_bob = target_bob.send(bob)\n", + "target_alice = target_alice.send(alice)\n", + "\n", + "# organize os apontadores numa lista\n", + "datasets = [(data_bob,target_bob),(data_alice,target_alice)]\n", + "\n", + "opt = optim.SGD(params=model.parameters(),lr=0.1)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def train():\n", + " # Lógica de treinamento\n", + " opt = optim.SGD(params=model.parameters(),lr=0.1)\n", + " for iter in range(10):\n", + " \n", + " # NOVO) itere através do dataset de cada worker\n", + " for data,target in datasets:\n", + " \n", + " # NOVO) envie o modelo para corrigir/atualizar o worker\n", + " model.send(data.location)\n", + "\n", + " # 1) apague os gradientes anteriores (caso eles existam)\n", + " opt.zero_grad()\n", + "\n", + " # 2) faça uma predição\n", + " pred = model(data)\n", + "\n", + " # 3) calcule o erro, isto é, o quanto perdemos\n", + " loss = ((pred - target)**2).sum()\n", + "\n", + " # 4) descubra quais pesos nos causaram essa perda\n", + " loss.backward()\n", + "\n", + " # 5) atualize os pesos\n", + " opt.step()\n", + " \n", + " # NOVO) pegue o modelo (com gradientes)\n", + " model.get()\n", + "\n", + " # 6) mostre o progresso até então\n", + " print(loss.get()) # NOVO) leve edição... precisa usar o .get() a partir do loss\\\n", + " \n", + "# média federada" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "train()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Pronto!\n", + "\n", + "E voilà! Agora estamos treinando um modelo muito simples de Deep Learning usando o Federated Learning! Enviamos o modelo para cada *worker*, geramos um novo gradiente e, em seguida, devolvemos o gradiente ao servidor local, onde atualizamos nosso modelo global. Nunca, neste processo, jamais vemos ou solicitamos acesso aos dados subjacentes ao treinamento! Preservamos a privacidade de Bob e Alice!!!\n", + "\n", + "## Problemas deste exemplo\n", + "\n", + "Embora este exemplo seja uma boa introdução ao Federated Learning, ele ainda apresenta algumas falhas importantes. A mais notável, é que quando chamamos `model.get()` e recebemos o modelo atualizado de Bob ou Alice, podemos aprender muito sobre os dados de treinamento de ambos apenas observando seus gradientes. Em alguns casos, podemos restaurar os dados de treinamento de forma completa!\n", + "\n", + "Então o que poderíamos fazer? Bem, a primeira estratégia empregada pelas pessoas é **calcular a média do gradiente em vários indivíduos antes de carregá-lo no servidor central**. Essa estratégia, no entanto, exigirá um uso mais sofisticado dos objetos _PointerTensor_. Portanto, na próxima seção, vamos passar um algum tempo aprendendo sobre funcionalidades mais avançada ao utilizar ponteiros e, em seguida, iremos atualizar este exemplo de Federated Learning.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Parabéns!!! - Hora de se juntar a comunidade!\n", + "\n", + "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!\n", + "\n", + "### Dê-nos uma estrela em nosso repo do PySyft no GitHub\n", + "\n", + "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.\n", + "\n", + "- [Star PySyft](https://github.com/OpenMined/PySyft)\n", + "\n", + "### Junte-se ao Slack!\n", + "\n", + "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](http://slack.openmined.org)\n", + "\n", + "### Contribua com o projeto!\n", + "\n", + "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\".\n", + "\n", + "- [Projetos do PySyft](https://github.com/OpenMined/PySyft/issues?q=is%3Aopen+is%3Aissue+label%3AProject)\n", + "- [Etiquetados como Good First Issue](https://github.com/OpenMined/PySyft/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22)\n", + "\n", + "### Doar\n", + "\n", + "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!\n", + "\n", + "[Página do Open Collective do OpenMined](https://opencollective.com/openmined)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From 452514da16e2cd3b36504704ebb6b314864c7579 Mon Sep 17 00:00:00 2001 From: jefersonf Date: Sun, 15 Dec 2019 13:35:11 -0300 Subject: [PATCH 04/17] add translation to Portuguese of the tutorial Part 03 --- ... para Execu\303\247\303\243o Remota.ipynb" | 386 ++++++++++++++++++ 1 file changed, 386 insertions(+) create mode 100644 "examples/tutorials/translations/portugu\303\252s/Parte 03 - Ferramentas Avan\303\247adas para Execu\303\247\303\243o Remota.ipynb" diff --git "a/examples/tutorials/translations/portugu\303\252s/Parte 03 - Ferramentas Avan\303\247adas para Execu\303\247\303\243o Remota.ipynb" "b/examples/tutorials/translations/portugu\303\252s/Parte 03 - Ferramentas Avan\303\247adas para Execu\303\247\303\243o Remota.ipynb" new file mode 100644 index 00000000000..eac9d670aa7 --- /dev/null +++ "b/examples/tutorials/translations/portugu\303\252s/Parte 03 - Ferramentas Avan\303\247adas para Execu\303\247\303\243o Remota.ipynb" @@ -0,0 +1,386 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Parte 3: Ferramentas Avançadas para Execução Remota\n", + "\n", + "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!!!) \n", + "\n", + "Mas, para fazer isso, precisamos de mais algumas coisas:\n", + "\n", + "- usar um ponteiro para enviar um Tensor diretamente para outro Worker\n", + "\n", + "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!\n", + "\n", + "Autores:\n", + "- Andrew Trask - Twitter: [@iamtrask](https://twitter.com/iamtrask)\n", + "\n", + "Tradução:\n", + "- Jeferson Silva - Twitter: [@jefersonnpn](https://twitter.com/jefersonnpn)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import torch\n", + "import syft as sy\n", + "hook = sy.TorchHook(torch)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Seção 3.1 - De ponteiros para ponteiros\n", + "\n", + "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!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "bob = sy.VirtualWorker(hook, id='bob')\n", + "alice = sy.VirtualWorker(hook, id='alice')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# este é um tensor local.\n", + "x = torch.tensor([1,2,3,4])\n", + "x" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# enviando o tensor local para Bob\n", + "x_ptr = x.send(bob)\n", + "\n", + "# agora temos um apontador/ponteiro\n", + "x_ptr" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# agora podemos ENVIAR O APONTADOR para alice!!!\n", + "pointer_to_x_ptr = x_ptr.send(alice)\n", + "\n", + "pointer_to_x_ptr" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Mas o que acabamos de fazer?\n", + "\n", + "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`).\n", + "\n", + "Em seguida, nós chamamos `x_ptr.send(alice)` que **envia o ponteiro** para Alice.\n", + "\n", + "Note, isso NÃO move os dados! Em vez disso, move o ponteiro, isto é, o apontador para os dados!! " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Como você pode ver acima, Bob ainda possui os dados reais (os dados sempre são armazenados com tipo LocalTensor).\n", + "bob._objects" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Alice, por outro lado, tem x_ptr!! (observe o ponteiro para Bob)\n", + "alice._objects" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# podemos usar .get() para recuperar x_ptr de Alice\n", + "\n", + "x_ptr = pointer_to_x_ptr.get()\n", + "x_ptr" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# e então podemos usar x_ptr para recuperar x de Bob!\n", + "\n", + "x = x_ptr.get()\n", + "x" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Aritmética em Pointero -> Pointero -> Objeto com Dados\n", + "\n", + "Assim como nos ponteiros normais, podemos executar quaisquer operações do PyTorch nesses tensores." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "bob._objects" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "alice._objects" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "p2p2x = torch.tensor([1,2,3,4,5]).send(bob).send(alice)\n", + "\n", + "y = p2p2x + p2p2x" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "bob._objects" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "alice._objects" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "y.get().get()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "bob._objects" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "alice._objects" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "p2p2x.get().get()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "bob._objects" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "alice._objects" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Seção 3.2 - Operações com tensores em cadeia\n", + "\n", + "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.\n", + "\n", + "Essas operações são:\n", + "\n", + "- `meuPonteiro_para_outroPonteiro.mover(outro_worker)`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# x agora é um ponteiro para um outro ponteiro para os dados que vivem na máquina de Bob\n", + "x = torch.tensor([1,2,3,4,5]).send(bob)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(' bob:', bob._objects)\n", + "print('alice:', alice._objects)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "x = x.move(alice)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(' bob:', bob._objects)\n", + "print('alice:', alice._objects)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "x" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Excelente! Agora estamos equipados com as ferramentas para executar a **média de gradientes** remota usando um agregador confiável!" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Parabéns!!! - Hora de se juntar a comunidade!\n", + "\n", + "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!\n", + "\n", + "### Dê-nos uma estrela em nosso repo do PySyft no GitHub\n", + "\n", + "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.\n", + "\n", + "- [Star PySyft](https://github.com/OpenMined/PySyft)\n", + "\n", + "### Junte-se ao Slack!\n", + "\n", + "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](http://slack.openmined.org)\n", + "\n", + "### Contribua com o projeto!\n", + "\n", + "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\".\n", + "\n", + "- [Projetos do PySyft](https://github.com/OpenMined/PySyft/issues?q=is%3Aopen+is%3Aissue+label%3AProject)\n", + "- [Etiquetados como Good First Issue](https://github.com/OpenMined/PySyft/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22)\n", + "\n", + "### Doar\n", + "\n", + "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!\n", + "\n", + "[Página do Open Collective do OpenMined](https://opencollective.com/openmined)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From b9fe1abc404cd0cc69421d8cb9d9ecd9baa1cf4d Mon Sep 17 00:00:00 2001 From: jefersonf Date: Sun, 15 Dec 2019 13:51:15 -0300 Subject: [PATCH 05/17] (fix) remove old folder name --- ...47\303\243o a Aprendizagem Federada.ipynb" | 298 ------------------ 1 file changed, 298 deletions(-) delete mode 100644 "examples/tutorials/translations/portugues/Parte 02 - Introdu\303\247\303\243o a Aprendizagem Federada.ipynb" diff --git "a/examples/tutorials/translations/portugues/Parte 02 - Introdu\303\247\303\243o a Aprendizagem Federada.ipynb" "b/examples/tutorials/translations/portugues/Parte 02 - Introdu\303\247\303\243o a Aprendizagem Federada.ipynb" deleted file mode 100644 index 27b21175ffc..00000000000 --- "a/examples/tutorials/translations/portugues/Parte 02 - Introdu\303\247\303\243o a Aprendizagem Federada.ipynb" +++ /dev/null @@ -1,298 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Parte 2: Introdução ao Federated Learning\n", - "\n", - "Na última seção, nós aprendemos sobre PointerTensors, que criam a infraestrutura necessária que precisamos para proteção de privacidade em Deep Learning. Nessa seção, nós iremos ver como usar essas ferramentas básicas para implementar nosso primeiro algoritmo de proteção de privacidade em Deep Learning: Federated Learning. \n", - "\n", - "Autores:\n", - "- Andrew Trask - Twitter: [@iamtrask](https://twitter.com/iamtrask)\n", - "\n", - "Tradução:\n", - "- Jeferson Silva - Twitter: [@jefersonnpn](https://twitter.com/jefersonnpn)\n", - "\n", - "### O que é Federated Learning?\n", - "\n", - "\n", - "É uma simples, porém poderosa maneira de treinar modelos de Deep Learning. Pense em dados de treinamento, são sempre o resultado de algum processo de coleta. As pessoas (via dispositivos) geram dados ao gravar eventos no mundo real. Normalmente, esses dados são agregados em uma simples localização central em que você pode treinar um modelo de aprendizegam de máquina. O Federated Learning vira isso de ponta a cabeça!\n", - "\n", - "Ao invés de trazer dados de treinamento para o modelo (um servidor central), você trás o modelo para os dados de treinamento (onde quer que ele esteja).\n", - "\n", - "A ideia é que isso permita que quem estiver criando os dados possua a única cópia permanente e, assim, mantenha o controle sobre quem já teve acesso a eles. Muito legal, não acha?" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Seção 2.1 - Um exemplo brinquedo de Federated Learning\n", - "\n", - "Vamos começar treinando um modelo de exemplo da maneira centralizada. Isso é tão simples quanto obter o modelo. Primeiro precisamos:\n", - "\n", - "- um conjunto de dados para brincarmos\n", - "- um modelo\n", - "- alguma lógica básica de treinamento para treinar um modelo que se ajusta aos dados\n", - "\n", - "Obs.: Se para você, a seguinte API ainda não é familar. Visite o [fast.ai](http://fast.ai) e faça os seus cursos antes de continuar esse tutorial." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import torch\n", - "from torch import nn\n", - "from torch import optim" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "\n", - "# Dataset de exemplo\n", - "data = torch.tensor([[0,0],[0,1],[1,0],[1,1.]], requires_grad=True)\n", - "target = torch.tensor([[0],[0],[1],[1.]], requires_grad=True)\n", - "\n", - "# Modelo simples de exemplo\n", - "model = nn.Linear(2,1)\n", - "\n", - "def train():\n", - " # Lógica de treinamento\n", - " opt = optim.SGD(params=model.parameters(),lr=0.1)\n", - " for iter in range(20):\n", - "\n", - " # 1) apague os gradientes anteriores (caso eles existam)\n", - " opt.zero_grad()\n", - "\n", - " # 2) faça uma predição\n", - " pred = model(data)\n", - "\n", - " # 3) calcule o erro, isto é, o quanto perdemos\n", - " loss = ((pred - target)**2).sum()\n", - "\n", - " # 4) descubra quais pesos nos causaram essa perda\n", - " loss.backward()\n", - "\n", - " # 5) altere esses pesos\n", - " opt.step()\n", - "\n", - " # 6) mostre o progresso até então\n", - " print(loss.data)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "train()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "E aí está! Nós treinamos um modelo simples da maneira convencional. Todos os nossos dados estão agregados em nossa máquina local e podemos usá-los para fazer atualizações em nosso modelo. O aprendizado federado, no entanto, não funciona dessa maneira. Então, vamos modificar este exemplo para fazê-lo da maneira federada!\n", - "\n", - "Então, o que precisamos:\n", - "\n", - "- criar alguns *workers*, isto é, nós de computação\n", - "- obter apontadores para dados de treinamento de cada *worker*\n", - "- atualizadar a lógica de treinamento para fazer o aprendizado federado\n", - "\n", - " Novas etapas de treinamento:\n", - " - enviar modelo para um *worker* e fazer correções/atualizações\n", - " - treinar com os dados que lá estão localizados\n", - " - pegar o modelo de volta e repetir o processo com o próximo *worker* " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import syft as sy\n", - "hook = sy.TorchHook(torch)\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# cria dois nós (ou duas entidades de computação)\n", - "\n", - "bob = sy.VirtualWorker(hook, id=\"bob\")\n", - "alice = sy.VirtualWorker(hook, id=\"alice\")\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Nosso dataset de exemplo\n", - "data = torch.tensor([[0,0],[0,1],[1,0],[1,1.]], requires_grad=True)\n", - "target = torch.tensor([[0],[0],[1],[1.]], requires_grad=True)\n", - "\n", - "# obtenha apontadores para os dados de treinamento de cada worker \n", - "# enviando alguns dados de treinamento para bob e alice\n", - "data_bob = data[0:2]\n", - "target_bob = target[0:2]\n", - "\n", - "data_alice = data[2:]\n", - "target_alice = target[2:]\n", - "\n", - "# Inicialize o modelo\n", - "model = nn.Linear(2,1)\n", - "\n", - "data_bob = data_bob.send(bob)\n", - "data_alice = data_alice.send(alice)\n", - "target_bob = target_bob.send(bob)\n", - "target_alice = target_alice.send(alice)\n", - "\n", - "# organize os apontadores numa lista\n", - "datasets = [(data_bob,target_bob),(data_alice,target_alice)]\n", - "\n", - "opt = optim.SGD(params=model.parameters(),lr=0.1)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "def train():\n", - " # Lógica de treinamento\n", - " opt = optim.SGD(params=model.parameters(),lr=0.1)\n", - " for iter in range(10):\n", - " \n", - " # NOVO) itere através do dataset de cada worker\n", - " for data,target in datasets:\n", - " \n", - " # NOVO) envie o modelo para corrigir/atualizar o worker\n", - " model.send(data.location)\n", - "\n", - " # 1) apague os gradientes anteriores (caso eles existam)\n", - " opt.zero_grad()\n", - "\n", - " # 2) faça uma predição\n", - " pred = model(data)\n", - "\n", - " # 3) calcule o erro, isto é, o quanto perdemos\n", - " loss = ((pred - target)**2).sum()\n", - "\n", - " # 4) descubra quais pesos nos causaram essa perda\n", - " loss.backward()\n", - "\n", - " # 5) atualize os pesos\n", - " opt.step()\n", - " \n", - " # NOVO) pegue o modelo (com gradientes)\n", - " model.get()\n", - "\n", - " # 6) mostre o progresso até então\n", - " print(loss.get()) # NOVO) leve edição... precisa usar o .get() a partir do loss\\\n", - " \n", - "# média federada" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "train()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Pronto!\n", - "\n", - "E voilà! Agora estamos treinando um modelo muito simples de Deep Learning usando o Federated Learning! Enviamos o modelo para cada *worker*, geramos um novo gradiente e, em seguida, devolvemos o gradiente ao servidor local, onde atualizamos nosso modelo global. Nunca, neste processo, jamais vemos ou solicitamos acesso aos dados subjacentes ao treinamento! Preservamos a privacidade de Bob e Alice!!!\n", - "\n", - "## Problemas deste exemplo\n", - "\n", - "Embora este exemplo seja uma boa introdução ao Federated Learning, ele ainda apresenta algumas falhas importantes. A mais notável, é que quando chamamos `model.get()` e recebemos o modelo atualizado de Bob ou Alice, podemos aprender muito sobre os dados de treinamento de ambos apenas observando seus gradientes. Em alguns casos, podemos restaurar os dados de treinamento de forma completa!\n", - "\n", - "Então o que poderíamos fazer? Bem, a primeira estratégia empregada pelas pessoas é **calcular a média do gradiente em vários indivíduos antes de carregá-lo no servidor central**. Essa estratégia, no entanto, exigirá um uso mais sofisticado dos objetos _PointerTensor_. Portanto, na próxima seção, vamos passar um algum tempo aprendendo sobre funcionalidades mais avançada ao utilizar ponteiros e, em seguida, iremos atualizar este exemplo de Federated Learning.\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Parabéns!!! - Hora de se juntar a comunidade!\n", - "\n", - "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!\n", - "\n", - "### Dê-nos uma estrela em nosso repo do PySyft no GitHub\n", - "\n", - "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.\n", - "\n", - "- [Star PySyft](https://github.com/OpenMined/PySyft)\n", - "\n", - "### Junte-se ao Slack!\n", - "\n", - "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](http://slack.openmined.org)\n", - "\n", - "### Contribua com o projeto!\n", - "\n", - "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 de nível 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\".\n", - "\n", - "- [Projetos do PySyft](https://github.com/OpenMined/PySyft/issues?q=is%3Aopen+is%3Aissue+label%3AProject)\n", - "- [Etiquetados como Good First Issue](https://github.com/OpenMined/PySyft/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22)\n", - "\n", - "### Doar\n", - "\n", - "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!\n", - "\n", - "[Página do Open Collective do OpenMined](https://opencollective.com/openmined)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.5.2" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} From 9983a85aaef2e341981d2e4dcbb46b6aa8dd8667 Mon Sep 17 00:00:00 2001 From: jefersonf Date: Sun, 15 Dec 2019 23:15:35 -0300 Subject: [PATCH 06/17] add translation to Portuguese of the tutorial Part 04 --- ... meio de Agregador Confi\303\241vel.ipynb" | 371 ++++++++++++++++++ 1 file changed, 371 insertions(+) create mode 100644 "examples/tutorials/translations/portugu\303\252s/Parte 04 - Aprendizado Federado por meio de Agregador Confi\303\241vel.ipynb" diff --git "a/examples/tutorials/translations/portugu\303\252s/Parte 04 - Aprendizado Federado por meio de Agregador Confi\303\241vel.ipynb" "b/examples/tutorials/translations/portugu\303\252s/Parte 04 - Aprendizado Federado por meio de Agregador Confi\303\241vel.ipynb" new file mode 100644 index 00000000000..ab864413b7a --- /dev/null +++ "b/examples/tutorials/translations/portugu\303\252s/Parte 04 - Aprendizado Federado por meio de Agregador Confi\303\241vel.ipynb" @@ -0,0 +1,371 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Parte 4: Aprendizado Federado usando Média de Modelos\n", + "\n", + "**Recapitulando:** Na Parte 2 deste tutorial, nós treinamos um modelo usando uma versão bem simples do Aprendizado Federado. Isso exigia que cada proprietário dos dados confiasse no proprietário do modelo para poder ver seus gradientes.\n", + "\n", + "**Descrição:** Neste tutorial, mostraremos como usar as ferramentas avançadas de agregação da Parte 3 para permitir que os pesos sejam agregados por um \\\"worker seguro\\\" confiável antes que o modelo resultante final seja enviado de volta ao proprietário do modelo (nesse caso, nós).\n", + "\n", + "Dessa maneira, somente o *worker* seguro pode ver de quem são os pesos. Talvez possamos saber quais partes do modelo foram alteradas, mas NÃO saberemos qual *worker* (bob ou alice) fez tal alteração, o que cria uma camada de privacidade.\n", + "\n", + "Autores:\n", + " - Andrew Trask - Twitter: [@iamtrask](https://twitter.com/iamtrask)\n", + " - Jason Mancuso - Twitter: [@jvmancuso](https://twitter.com/jvmancuso)\n", + " \n", + "Tradução:\n", + "- Jeferson Silva - Twitter: [@jefersonnpn](https://twitter.com/jefersonnpn)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import torch\n", + "import syft as sy\n", + "import copy\n", + "hook = sy.TorchHook(torch)\n", + "from torch import nn, optim" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Passo 1: Criar Proprietários de Dados\n", + "\n", + "Primeiro, vamos criar dois proprietários de dados (Bob e Alice), cada um com alguns dados. Também vamos inicializar uma máquina segura chamada \"secure_worker\". Na prática, pode ser um hardware seguro (como o SGX da Intel) ou simplesmente um intermediário confiável." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# criando alguns workers\n", + "\n", + "bob = sy.VirtualWorker(hook, id=\"bob\")\n", + "alice = sy.VirtualWorker(hook, id=\"alice\")\n", + "secure_worker = sy.VirtualWorker(hook, id=\"secure_worker\")\n", + "\n", + "\n", + "# Nosso Dataset de exemplo\n", + "data = torch.tensor([[0,0],[0,1],[1,0],[1,1.]], requires_grad=True)\n", + "target = torch.tensor([[0],[0],[1],[1.]], requires_grad=True)\n", + "\n", + "# obtenha apontadores para os dados de treinamento de cada worker \n", + "# enviando alguns dados de treinamento para bob e alice\n", + "bobs_data = data[0:2].send(bob)\n", + "bobs_target = target[0:2].send(bob)\n", + "\n", + "alices_data = data[2:].send(alice)\n", + "alices_target = target[2:].send(alice)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Passo 2: Criar Nosso Modelo\n", + "\n", + "Neste exemplo, vamos treinar com um modelo linear simples. Podemos inicializá-lo, normalmente, usando o construtor `nn.Linear` do PyTorch." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Inicialize o modelo\n", + "model = nn.Linear(2,1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Passo 3: Envie uma Cópia do Modelo para Alice e Bob\n", + "\n", + "Em seguida, precisamos enviar uma cópia do modelo atual para Alice e Bob para que eles possam executar as etapas de aprendizado em seus próprios conjuntos de dados." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "bobs_model = model.copy().send(bob)\n", + "alices_model = model.copy().send(alice)\n", + "\n", + "bobs_opt = optim.SGD(params=bobs_model.parameters(),lr=0.1)\n", + "alices_opt = optim.SGD(params=alices_model.parameters(),lr=0.1)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Passo 4: Treine os Modelos de Alice e Bob (em paralelo)\n", + "\n", + "De forma convencional, na aprendizagem federada via *Secure Averaging* (Média Segura), cada proprietário dos dados primeiro treina seu modelo em várias iterações localmente antes que seja feito o cálculo da média dos modelos." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "for i in range(10):\n", + "\n", + " # Treina o Modelo de Bob\n", + " bobs_opt.zero_grad()\n", + " bobs_pred = bobs_model(bobs_data)\n", + " bobs_loss = ((bobs_pred - bobs_target)**2).sum()\n", + " bobs_loss.backward()\n", + "\n", + " bobs_opt.step()\n", + " bobs_loss = bobs_loss.get().data\n", + "\n", + " # Treina o Modelo de Alice\n", + " alices_opt.zero_grad()\n", + " alices_pred = alices_model(alices_data)\n", + " alices_loss = ((alices_pred - alices_target)**2).sum()\n", + " alices_loss.backward()\n", + "\n", + " alices_opt.step()\n", + " alices_loss = alices_loss.get().data\n", + " \n", + " print(\"Bob:\" + str(bobs_loss) + \" Alice:\" + str(alices_loss))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Passo 5: Enviar Ambos os Modelos Atualizados para um Worker Seguro\n", + "\n", + "Agora que cada proprietário de dados possui um modelo parcialmente treinado, é hora de calcular a média entre eles de maneira segura. Conseguimos isso instruindo Alice e Bob a enviar seus modelos para o servidor seguro (confiável).\n", + "\n", + "Observe que esse uso de nossa API significa que cada modelo é enviado DIRETAMENTE ao `secure_worker`. Mas, nunca vemos isso." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "alices_model.move(secure_worker)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "bobs_model.move(secure_worker)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Passo 6: Calcular a Média dos Modelos" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Finalmente, o último passo é calcular a média dos modelos treinados por Bob e Alice e, em seguida, usá-lo para definir os valores dos pesos do nosso \"modelo\" global." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "with torch.no_grad():\n", + " model.weight.set_(((alices_model.weight.data + bobs_model.weight.data) / 2).get())\n", + " model.bias.set_(((alices_model.bias.data + bobs_model.bias.data) / 2).get())\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Apenas Repita!\n", + "\n", + "E agora só precisamos repetir esse processo várias vezes!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "iterations = 10\n", + "worker_iters = 5\n", + "\n", + "for a_iter in range(iterations):\n", + " \n", + " bobs_model = model.copy().send(bob)\n", + " alices_model = model.copy().send(alice)\n", + "\n", + " bobs_opt = optim.SGD(params=bobs_model.parameters(),lr=0.1)\n", + " alices_opt = optim.SGD(params=alices_model.parameters(),lr=0.1)\n", + "\n", + " for wi in range(worker_iters):\n", + "\n", + " # Treina o Modelo de Bob\n", + " bobs_opt.zero_grad()\n", + " bobs_pred = bobs_model(bobs_data)\n", + " bobs_loss = ((bobs_pred - bobs_target)**2).sum()\n", + " bobs_loss.backward()\n", + "\n", + " bobs_opt.step()\n", + " bobs_loss = bobs_loss.get().data\n", + "\n", + " # Treina o Modelo de Alice\n", + " alices_opt.zero_grad()\n", + " alices_pred = alices_model(alices_data)\n", + " alices_loss = ((alices_pred - alices_target)**2).sum()\n", + " alices_loss.backward()\n", + "\n", + " alices_opt.step()\n", + " alices_loss = alices_loss.get().data\n", + " \n", + " alices_model.move(secure_worker)\n", + " bobs_model.move(secure_worker)\n", + " with torch.no_grad():\n", + " model.weight.set_(((alices_model.weight.data + bobs_model.weight.data) / 2).get())\n", + " model.bias.set_(((alices_model.bias.data + bobs_model.bias.data) / 2).get())\n", + " \n", + " print(\"Bob:\" + str(bobs_loss) + \" Alice:\" + str(alices_loss))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Por fim, queremos garantir que nosso modelo resultante tenha aprendido corretamente, para que possamos avaliá-lo em um conjunto de dados de teste. Neste problema simples, usamos os dados originais, mas, na prática, queremos usar novos dados para entender o quão generalizado o modelo é para exemplos não vistos." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "preds = model(data)\n", + "loss = ((preds - target) ** 2).sum()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(preds)\n", + "print(target)\n", + "print(loss.data)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Neste exemplo, o modelo médio resultante está pouco ajustado em relação a como se comportaria um modelo individual treinado localmente, no entanto, pudemos treiná-lo sem expor os dados de treinamento de cada *worker*. Também fomos capazes de agregar os modelos atualizados de cada *worker* em um lugar confiável para evitar vazamento de dados do proprietário do modelo.\n", + "\n", + "Em um tutorial futuro, teremos como objetivo fazer nossa agregação segura e confiável diretamente com os gradientes, para que possamos atualizar o modelo com melhores estimativas de gradientes e chegar a um modelo mais forte." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Parabéns!!! - Hora de se juntar a comunidade!\n", + "\n", + "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!\n", + "\n", + "### Dê-nos uma estrela em nosso repo do PySyft no GitHub\n", + "\n", + "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.\n", + "\n", + "- [Star PySyft](https://github.com/OpenMined/PySyft)\n", + "\n", + "### Junte-se ao Slack!\n", + "\n", + "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](http://slack.openmined.org)\n", + "\n", + "### Contribua com o projeto!\n", + "\n", + "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\".\n", + "\n", + "- [Projetos do PySyft](https://github.com/OpenMined/PySyft/issues?q=is%3Aopen+is%3Aissue+label%3AProject)\n", + "- [Etiquetados como Good First Issue](https://github.com/OpenMined/PySyft/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22)\n", + "\n", + "### Doar\n", + "\n", + "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!\n", + "\n", + "[Página do Open Collective do OpenMined](https://opencollective.com/openmined)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From 2788496e00119a681c368a9f5a1423ef37b4de32 Mon Sep 17 00:00:00 2001 From: jefersonf Date: Sun, 15 Dec 2019 23:24:36 -0300 Subject: [PATCH 07/17] =?UTF-8?q?(update)=20rename=20'portugues'=20to=20'p?= =?UTF-8?q?ortugu=C3=AAs'=20and=20remove=20old=20folder?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...47\303\243o a Aprendizagem Federada.ipynb" | 298 ------------------ 1 file changed, 298 deletions(-) delete mode 100644 "examples/tutorials/translations/portugues/Parte 02 - Introdu\303\247\303\243o a Aprendizagem Federada.ipynb" diff --git "a/examples/tutorials/translations/portugues/Parte 02 - Introdu\303\247\303\243o a Aprendizagem Federada.ipynb" "b/examples/tutorials/translations/portugues/Parte 02 - Introdu\303\247\303\243o a Aprendizagem Federada.ipynb" deleted file mode 100644 index 27b21175ffc..00000000000 --- "a/examples/tutorials/translations/portugues/Parte 02 - Introdu\303\247\303\243o a Aprendizagem Federada.ipynb" +++ /dev/null @@ -1,298 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Parte 2: Introdução ao Federated Learning\n", - "\n", - "Na última seção, nós aprendemos sobre PointerTensors, que criam a infraestrutura necessária que precisamos para proteção de privacidade em Deep Learning. Nessa seção, nós iremos ver como usar essas ferramentas básicas para implementar nosso primeiro algoritmo de proteção de privacidade em Deep Learning: Federated Learning. \n", - "\n", - "Autores:\n", - "- Andrew Trask - Twitter: [@iamtrask](https://twitter.com/iamtrask)\n", - "\n", - "Tradução:\n", - "- Jeferson Silva - Twitter: [@jefersonnpn](https://twitter.com/jefersonnpn)\n", - "\n", - "### O que é Federated Learning?\n", - "\n", - "\n", - "É uma simples, porém poderosa maneira de treinar modelos de Deep Learning. Pense em dados de treinamento, são sempre o resultado de algum processo de coleta. As pessoas (via dispositivos) geram dados ao gravar eventos no mundo real. Normalmente, esses dados são agregados em uma simples localização central em que você pode treinar um modelo de aprendizegam de máquina. O Federated Learning vira isso de ponta a cabeça!\n", - "\n", - "Ao invés de trazer dados de treinamento para o modelo (um servidor central), você trás o modelo para os dados de treinamento (onde quer que ele esteja).\n", - "\n", - "A ideia é que isso permita que quem estiver criando os dados possua a única cópia permanente e, assim, mantenha o controle sobre quem já teve acesso a eles. Muito legal, não acha?" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Seção 2.1 - Um exemplo brinquedo de Federated Learning\n", - "\n", - "Vamos começar treinando um modelo de exemplo da maneira centralizada. Isso é tão simples quanto obter o modelo. Primeiro precisamos:\n", - "\n", - "- um conjunto de dados para brincarmos\n", - "- um modelo\n", - "- alguma lógica básica de treinamento para treinar um modelo que se ajusta aos dados\n", - "\n", - "Obs.: Se para você, a seguinte API ainda não é familar. Visite o [fast.ai](http://fast.ai) e faça os seus cursos antes de continuar esse tutorial." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import torch\n", - "from torch import nn\n", - "from torch import optim" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "\n", - "# Dataset de exemplo\n", - "data = torch.tensor([[0,0],[0,1],[1,0],[1,1.]], requires_grad=True)\n", - "target = torch.tensor([[0],[0],[1],[1.]], requires_grad=True)\n", - "\n", - "# Modelo simples de exemplo\n", - "model = nn.Linear(2,1)\n", - "\n", - "def train():\n", - " # Lógica de treinamento\n", - " opt = optim.SGD(params=model.parameters(),lr=0.1)\n", - " for iter in range(20):\n", - "\n", - " # 1) apague os gradientes anteriores (caso eles existam)\n", - " opt.zero_grad()\n", - "\n", - " # 2) faça uma predição\n", - " pred = model(data)\n", - "\n", - " # 3) calcule o erro, isto é, o quanto perdemos\n", - " loss = ((pred - target)**2).sum()\n", - "\n", - " # 4) descubra quais pesos nos causaram essa perda\n", - " loss.backward()\n", - "\n", - " # 5) altere esses pesos\n", - " opt.step()\n", - "\n", - " # 6) mostre o progresso até então\n", - " print(loss.data)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "train()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "E aí está! Nós treinamos um modelo simples da maneira convencional. Todos os nossos dados estão agregados em nossa máquina local e podemos usá-los para fazer atualizações em nosso modelo. O aprendizado federado, no entanto, não funciona dessa maneira. Então, vamos modificar este exemplo para fazê-lo da maneira federada!\n", - "\n", - "Então, o que precisamos:\n", - "\n", - "- criar alguns *workers*, isto é, nós de computação\n", - "- obter apontadores para dados de treinamento de cada *worker*\n", - "- atualizadar a lógica de treinamento para fazer o aprendizado federado\n", - "\n", - " Novas etapas de treinamento:\n", - " - enviar modelo para um *worker* e fazer correções/atualizações\n", - " - treinar com os dados que lá estão localizados\n", - " - pegar o modelo de volta e repetir o processo com o próximo *worker* " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import syft as sy\n", - "hook = sy.TorchHook(torch)\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# cria dois nós (ou duas entidades de computação)\n", - "\n", - "bob = sy.VirtualWorker(hook, id=\"bob\")\n", - "alice = sy.VirtualWorker(hook, id=\"alice\")\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Nosso dataset de exemplo\n", - "data = torch.tensor([[0,0],[0,1],[1,0],[1,1.]], requires_grad=True)\n", - "target = torch.tensor([[0],[0],[1],[1.]], requires_grad=True)\n", - "\n", - "# obtenha apontadores para os dados de treinamento de cada worker \n", - "# enviando alguns dados de treinamento para bob e alice\n", - "data_bob = data[0:2]\n", - "target_bob = target[0:2]\n", - "\n", - "data_alice = data[2:]\n", - "target_alice = target[2:]\n", - "\n", - "# Inicialize o modelo\n", - "model = nn.Linear(2,1)\n", - "\n", - "data_bob = data_bob.send(bob)\n", - "data_alice = data_alice.send(alice)\n", - "target_bob = target_bob.send(bob)\n", - "target_alice = target_alice.send(alice)\n", - "\n", - "# organize os apontadores numa lista\n", - "datasets = [(data_bob,target_bob),(data_alice,target_alice)]\n", - "\n", - "opt = optim.SGD(params=model.parameters(),lr=0.1)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "def train():\n", - " # Lógica de treinamento\n", - " opt = optim.SGD(params=model.parameters(),lr=0.1)\n", - " for iter in range(10):\n", - " \n", - " # NOVO) itere através do dataset de cada worker\n", - " for data,target in datasets:\n", - " \n", - " # NOVO) envie o modelo para corrigir/atualizar o worker\n", - " model.send(data.location)\n", - "\n", - " # 1) apague os gradientes anteriores (caso eles existam)\n", - " opt.zero_grad()\n", - "\n", - " # 2) faça uma predição\n", - " pred = model(data)\n", - "\n", - " # 3) calcule o erro, isto é, o quanto perdemos\n", - " loss = ((pred - target)**2).sum()\n", - "\n", - " # 4) descubra quais pesos nos causaram essa perda\n", - " loss.backward()\n", - "\n", - " # 5) atualize os pesos\n", - " opt.step()\n", - " \n", - " # NOVO) pegue o modelo (com gradientes)\n", - " model.get()\n", - "\n", - " # 6) mostre o progresso até então\n", - " print(loss.get()) # NOVO) leve edição... precisa usar o .get() a partir do loss\\\n", - " \n", - "# média federada" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "train()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Pronto!\n", - "\n", - "E voilà! Agora estamos treinando um modelo muito simples de Deep Learning usando o Federated Learning! Enviamos o modelo para cada *worker*, geramos um novo gradiente e, em seguida, devolvemos o gradiente ao servidor local, onde atualizamos nosso modelo global. Nunca, neste processo, jamais vemos ou solicitamos acesso aos dados subjacentes ao treinamento! Preservamos a privacidade de Bob e Alice!!!\n", - "\n", - "## Problemas deste exemplo\n", - "\n", - "Embora este exemplo seja uma boa introdução ao Federated Learning, ele ainda apresenta algumas falhas importantes. A mais notável, é que quando chamamos `model.get()` e recebemos o modelo atualizado de Bob ou Alice, podemos aprender muito sobre os dados de treinamento de ambos apenas observando seus gradientes. Em alguns casos, podemos restaurar os dados de treinamento de forma completa!\n", - "\n", - "Então o que poderíamos fazer? Bem, a primeira estratégia empregada pelas pessoas é **calcular a média do gradiente em vários indivíduos antes de carregá-lo no servidor central**. Essa estratégia, no entanto, exigirá um uso mais sofisticado dos objetos _PointerTensor_. Portanto, na próxima seção, vamos passar um algum tempo aprendendo sobre funcionalidades mais avançada ao utilizar ponteiros e, em seguida, iremos atualizar este exemplo de Federated Learning.\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Parabéns!!! - Hora de se juntar a comunidade!\n", - "\n", - "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!\n", - "\n", - "### Dê-nos uma estrela em nosso repo do PySyft no GitHub\n", - "\n", - "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.\n", - "\n", - "- [Star PySyft](https://github.com/OpenMined/PySyft)\n", - "\n", - "### Junte-se ao Slack!\n", - "\n", - "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](http://slack.openmined.org)\n", - "\n", - "### Contribua com o projeto!\n", - "\n", - "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 de nível 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\".\n", - "\n", - "- [Projetos do PySyft](https://github.com/OpenMined/PySyft/issues?q=is%3Aopen+is%3Aissue+label%3AProject)\n", - "- [Etiquetados como Good First Issue](https://github.com/OpenMined/PySyft/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22)\n", - "\n", - "### Doar\n", - "\n", - "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!\n", - "\n", - "[Página do Open Collective do OpenMined](https://opencollective.com/openmined)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.5.2" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} From 8e605befb0d1734905562014283dc6c32ce46162 Mon Sep 17 00:00:00 2001 From: jefersonf Date: Mon, 16 Dec 2019 23:29:59 -0300 Subject: [PATCH 08/17] add translation to Portuguese of the tutorial Part 05 --- .../Parte 05 - Bem-vindo ao Sandbox.ipynb" | 212 ++++++++++++++++++ 1 file changed, 212 insertions(+) create mode 100644 "examples/tutorials/translations/portugu\303\252s/Parte 05 - Bem-vindo ao Sandbox.ipynb" diff --git "a/examples/tutorials/translations/portugu\303\252s/Parte 05 - Bem-vindo ao Sandbox.ipynb" "b/examples/tutorials/translations/portugu\303\252s/Parte 05 - Bem-vindo ao Sandbox.ipynb" new file mode 100644 index 00000000000..da859ee0109 --- /dev/null +++ "b/examples/tutorials/translations/portugu\303\252s/Parte 05 - Bem-vindo ao Sandbox.ipynb" @@ -0,0 +1,212 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Parte 5 - Bem-vindo ao Sandbox\n", + "\n", + "Nos últimos tutoriais, sempre começamos nosso gancho das funções do PyTorch e todos os nossos *workers* de forma manual. Isso pode ser um pouco chato quando você está apenas brincando/aprendendo sobre as interfaces. Então, daqui em diante, criaremos todas essas mesmas variáveis usando uma função especial bastante conveniente." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import torch\n", + "import syft as sy\n", + "sy.create_sandbox(globals())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### O que o Sandbox nos fornece?\n", + "\n", + "Como você pode ver acima, criamos vários *workers* virtuais e carregamos vários conjuntos de dados de teste, distribuindo-os pelos vários *workers*, para que possamos praticar o uso das técnicas de proteção de privacidade, como a Aprendização Federada.\n", + "\n", + "Criamos seis *workers*...." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "workers" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Também foram criadas várias variáveis globais que, inclusive, já podemos utilizar de forma imediata." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "hook" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "bob" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Seção 5.1: Funcionalidade de pesquisa de Workers\n", + "\n", + "Um aspecto importante da ciência de dados remota é que queremos ser capazes de procurar por conjuntos de dados em uma máquina remota. Pense em um laboratório de pesquisa que deseja consultar, por exemplo, dados de radiografias e lesões de um hospital." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "torch.Tensor([1,2,3,4,5])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "x = torch.tensor([1,2,3,4,5]).tag(\"#fun\", \"#boston\", \"#housing\").describe(\"The input datapoints to the boston housing dataset.\")\n", + "y = torch.tensor([1,2,3,4,5]).tag(\"#fun\", \"#boston\", \"#housing\").describe(\"The input datapoints to the boston housing dataset.\")\n", + "z = torch.tensor([1,2,3,4,5]).tag(\"#fun\", \"#mnist\",).describe(\"The images in the MNIST training dataset.\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "x" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "x = x.send(bob)\n", + "y = y.send(bob)\n", + "z = z.send(bob)\n", + "\n", + "# Procura por conjunto de dados que possuem as seguintes chaves, seja na etiqueta ou na descrição\n", + "results = bob.search([\"#boston\", \"#housing\"])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "results" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(results[0].description)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Seção 5.2: Grade Virtual\n", + "\n", + "Uma Grade (Grid) é simplesmente uma coleção de *workers* capaz de fornecer algumas funções, muito convenientes, para quando você deseja montar conjunto de dados." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "grid = sy.VirtualGrid(*workers)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "results, tag_ctr = grid.search(\"#boston\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "boston_data, _ = grid.search(\"#boston\",\"#data\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "boston_target, _ = grid.search(\"#boston\",\"#target\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From 63b492e34d6262a7a188c364a489e2691cea7e78 Mon Sep 17 00:00:00 2001 From: Jeferson Date: Fri, 10 Jan 2020 18:23:16 -0300 Subject: [PATCH 09/17] add translation to Portuguese of the tutorial Part 06 --- ...o Federado com MNIST usando uma CNN.ipynb" | 369 ++++++++++++++++++ 1 file changed, 369 insertions(+) create mode 100644 "examples/tutorials/translations/portugu\303\252s/Parte 06 - Aprendizado Federado com MNIST usando uma CNN.ipynb" diff --git "a/examples/tutorials/translations/portugu\303\252s/Parte 06 - Aprendizado Federado com MNIST usando uma CNN.ipynb" "b/examples/tutorials/translations/portugu\303\252s/Parte 06 - Aprendizado Federado com MNIST usando uma CNN.ipynb" new file mode 100644 index 00000000000..38f6b27e34e --- /dev/null +++ "b/examples/tutorials/translations/portugu\303\252s/Parte 06 - Aprendizado Federado com MNIST usando uma CNN.ipynb" @@ -0,0 +1,369 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "parameters" + ] + }, + "outputs": [], + "source": [ + "epochs = 10" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Parte 6 - Aprendizado Federado com MNIST usando uma CNN\n", + "\n", + "## Melhore o Aprendizado Federado com 10 linhas de código PyTorch + PySyft\n", + "\n", + "\n", + "### Contexto \n", + "\n", + "Federated Learning é uma técnica de Machine Learning muito fascinante e inovadora que visa a construção de sistemas que aprendem a partir de dados descentralizados. A idéia é que os dados permaneçam nas mãos de quem os gerou, isto é, seu possuidor (também conhecido como o *Worker*), o que ajuda a melhorar a privacidade e o direito de propriedade, assim o modelo é compartilhado entre os *Workers*. Uma aplicação imediata é, por exemplo, prever a próxima palavra em seu telefone celular quando você escreve texto: você não deseja que os dados usados no treinamento - ou seja, suas mensagens de texto - sejam enviados para um servidor central.\n", + "\n", + "\n", + "A ascensão do Federated Learning está, portanto, fortemente ligada à disseminação da conscientização sobre privacidade de dados, e o GDPR na UE, que faz cumprir a proteção de dados desde maio de 2018, atuou como um catalisador. Para antecipar a regulamentação, grandes companias como Apple ou Google começaram a investir maciçamente nessa tecnologia, especialmente para proteger a privacidade dos usuários de dispositivos móveis, mas não disponibilizaram suas ferramentas. Na OpenMined, acreditamos que qualquer pessoa disposta a conduzir um projeto de Machine Learning deve ser capaz de implementar ferramentas de proteção de privacidade com muito pouco esforço. Criamos ferramentas para criptografar dados em uma única linha [conforme mencionado em nossa postagem no blog](https://blog.openmined.org/training-cnns-using-spdz/) e agora lançamos nosso framework de Aprendizado Federado, que utiliza o nova versão do PyTorch 1.0 para fornecer uma interface intuitiva para criar modelos seguros e escaláveis.\n", + "\n", + "Neste tutorial, usaremos diretamente o [exemplo mais básico de treinamento de uma CNN no MNIST usando PyTorch](https://github.com/pytorch/examples/blob/master/mnist/main.py) e mostraremos como é simples implementar o Aprendizado Federado com ele usando nossa biblioteca [PySyft](https://github.com/OpenMined/PySyft/). Analisaremos cada parte do exemplo e sublinharemos o código que foi alterado.\n", + "\n", + "Você também pode encontrar esse material em [nosso blog](https://blog.openmined.org/upgrade-to-federated-learning-in-10-lines).\n", + "\n", + "Autores:\n", + "- Théo Ryffel - GitHub: [@LaRiffle](https://github.com/LaRiffle)\n", + "\n", + "Tradução:\n", + "- Jeferson Silva - Github: [@jefersonf](https://github.com/jefersonf)\n", + "\n", + "**Ok, vamos começar!**" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Imports e especificações do modelo\n", + "\n", + "Primeiro fazemos os *imports* oficiais" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import torch\n", + "import torch.nn as nn\n", + "import torch.nn.functional as F\n", + "import torch.optim as optim\n", + "from torchvision import datasets, transforms" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "E então aqueles específicos para o PySyft. Em particular, definimos os workers remotos `alice` e` bob`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import syft as sy # <-- NOVO: importe a biblioteca do PySyft\n", + "hook = sy.TorchHook(torch) # <-- NOVO: gancho do PyTorch, ou seja, adicione funcionalidades extras para dar suporte ao Federated Learning\n", + "bob = sy.VirtualWorker(hook, id=\"bob\") # <-- NOVO: define os workers remotos bob\n", + "alice = sy.VirtualWorker(hook, id=\"alice\") # <-- NOVO: e alice" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Definimos a configuração da tarefa de aprendizagem" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "class Arguments():\n", + " def __init__(self):\n", + " self.batch_size = 64\n", + " self.test_batch_size = 1000\n", + " self.epochs = epochs\n", + " self.lr = 0.01\n", + " self.momentum = 0.5\n", + " self.no_cuda = False\n", + " self.seed = 1\n", + " self.log_interval = 30\n", + " self.save_model = False\n", + "\n", + "args = Arguments()\n", + "\n", + "use_cuda = not args.no_cuda and torch.cuda.is_available()\n", + "\n", + "torch.manual_seed(args.seed)\n", + "\n", + "device = torch.device(\"cuda\" if use_cuda else \"cpu\")\n", + "\n", + "kwargs = {'num_workers': 1, 'pin_memory': True} if use_cuda else {}" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Carregamento e envio de dados para os workers\n", + "Primeiro carregamos os dados e transformamos o conjunto de dados de treinamento em um conjunto de dados federado dividido entre os workers usando o método `.federate`. Este conjunto de dados federado agora é fornecido para um Federated DataLoader. O conjunto de dados de teste permanece inalterado." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "federated_train_loader = sy.FederatedDataLoader( # <-- agora é um FederatedDataLoader \n", + " datasets.MNIST('../data', train=True, download=True,\n", + " transform=transforms.Compose([\n", + " transforms.ToTensor(),\n", + " transforms.Normalize((0.1307,), (0.3081,))\n", + " ]))\n", + " .federate((bob, alice)), # <-- NOVO: distribuímos o dados entre todos os workers, agora é um FederatedDataset\n", + " batch_size=args.batch_size, shuffle=True, **kwargs)\n", + "\n", + "test_loader = torch.utils.data.DataLoader(\n", + " datasets.MNIST('../data', train=False, transform=transforms.Compose([\n", + " transforms.ToTensor(),\n", + " transforms.Normalize((0.1307,), (0.3081,))\n", + " ])),\n", + " batch_size=args.test_batch_size, shuffle=True, **kwargs)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Especificação da CNN\n", + "Aqui usamos exatamente a mesma CNN que do exemplo oficial." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "class Net(nn.Module):\n", + " def __init__(self):\n", + " super(Net, self).__init__()\n", + " self.conv1 = nn.Conv2d(1, 20, 5, 1)\n", + " self.conv2 = nn.Conv2d(20, 50, 5, 1)\n", + " self.fc1 = nn.Linear(4*4*50, 500)\n", + " self.fc2 = nn.Linear(500, 10)\n", + "\n", + " def forward(self, x):\n", + " x = F.relu(self.conv1(x))\n", + " x = F.max_pool2d(x, 2, 2)\n", + " x = F.relu(self.conv2(x))\n", + " x = F.max_pool2d(x, 2, 2)\n", + " x = x.view(-1, 4*4*50)\n", + " x = F.relu(self.fc1(x))\n", + " x = self.fc2(x)\n", + " return F.log_softmax(x, dim=1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Defina as funções de treino e teste\n", + "Para a função de treino, como os *batches* de dados são distribuídos entre `alice` e `bob`, você precisa enviar o modelo para o local certo para cada *batch*. Em seguida, você executa todas as operações remotamente com a mesma sintaxe que você está executando no PyTorch local. Quando terminar, você recupera o modelo atualizado e a perda (*loss*) para buscar melhorias." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def train(args, model, device, federated_train_loader, optimizer, epoch):\n", + " model.train()\n", + " for batch_idx, (data, target) in enumerate(federated_train_loader): # <-- agora é um dataset distribuído\n", + " model.send(data.location) # <-- NOVO: envie o modelo para o local certo\n", + " data, target = data.to(device), target.to(device)\n", + " optimizer.zero_grad()\n", + " output = model(data)\n", + " loss = F.nll_loss(output, target)\n", + " loss.backward()\n", + " optimizer.step()\n", + " model.get() # <-- NOVO: receba o modelo de volta\n", + " if batch_idx % args.log_interval == 0:\n", + " loss = loss.get() # <-- NOVO: recupere a perda\n", + " print('Train Epoch: {} [{}/{} ({:.0f}%)]\\tLoss: {:.6f}'.format(\n", + " epoch, batch_idx * args.batch_size, len(federated_train_loader) * args.batch_size,\n", + " 100. * batch_idx / len(federated_train_loader), loss.item()))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "A função de teste não muda!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def test(args, model, device, test_loader):\n", + " model.eval()\n", + " test_loss = 0\n", + " correct = 0\n", + " with torch.no_grad():\n", + " for data, target in test_loader:\n", + " data, target = data.to(device), target.to(device)\n", + " output = model(data)\n", + " test_loss += F.nll_loss(output, target, reduction='sum').item() # calcule a perda em cada batch\n", + " pred = output.argmax(1, keepdim=True) # obtenha o índice de maior probabilidade logarítmica\n", + " correct += pred.eq(target.view_as(pred)).sum().item()\n", + "\n", + " test_loss /= len(test_loader.dataset)\n", + "\n", + " print('\\nTest set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)\\n'.format(\n", + " test_loss, correct, len(test_loader.dataset),\n", + " 100. * correct / len(test_loader.dataset)))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Inicie o treinamento!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%%time\n", + "model = Net().to(device)\n", + "optimizer = optim.SGD(model.parameters(), lr=args.lr) # TODO momentum não é suportado no momento\n", + "\n", + "for epoch in range(1, args.epochs + 1):\n", + " train(args, model, device, federated_train_loader, optimizer, epoch)\n", + " test(args, model, device, test_loader)\n", + "\n", + "if (args.save_model):\n", + " torch.save(model.state_dict(), \"mnist_cnn.pt\")\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Et voilà! Aqui você treinou um modelo a partir de dados remotos usando o Federated Learning!" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Uma última coisa\n", + "Sei que há uma pergunta que você está ansioso para fazer: **quanto tempo leva o treinamento com Federated Learning comparado ao treinamento com PyTorch normal?**\n", + "\n", + "O tempo de computação é na verdade **menos do dobro do tempo** usado para a execução normal do PyTorch! Mais precisamente, leva 1.9 vezes mais tempo, o que é muito pouco se comparado aos recursos que pudemos adicionar." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Conclusão\n", + "\n", + "Como você observou, modificamos 10 linhas de código para atualizar o exemplo oficial do Pytorch no MNIST para uma configuração real de Aprendizado Federado!\n", + "\n", + "Obviamente, existem dezenas de melhorias em que poderíamos pensar. Gostaríamos que o cálculo operasse em paralelo com os *workers* e realizasse a média federada (i.e. federated averaging), atualizando o modelo central a cada `n` *batches* apenas, para reduzir o número de mensagens que usamos para nos comunicarmos entre os *workers*, etc. Essas são características em que estamos trabalhando para tornar o Federated Learning pronto para um ambiente de produção e escreverêmos sobre assim que forem lançadas!\n", + "\n", + "You should now be able to do Federated Learning by yourself! If you enjoyed this and would like to join the movement toward privacy preserving, decentralized ownership of AI and the AI supply chain (data), you can do so in the following ways! \n", + "\n", + "Agora você deve poder fazer Aprendizado Federado sozinho! Se você gostou disso e gostaria de se juntar ao movimento em direção à preservação da privacidade, propriedade descentralizada da IA e da cadeia de suprimentos da AI (dados), você pode fazê-lo das seguintes maneiras!\n", + "\n", + "\n", + "### Dê-nos uma estrela em nosso repo do PySyft no GitHub\n", + "\n", + "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.\n", + "\n", + "- [Star PySyft](https://github.com/OpenMined/PySyft)\n", + "\n", + "### Veja nossos tutoriais no GitHub!\n", + "\n", + "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.\n", + "\n", + "- [Tutoriais do PySyft](https://github.com/OpenMined/PySyft/tree/master/examples/tutorials)\n", + "\n", + "### Junte-se ao Slack!\n", + "\n", + "A melhor maneira de manter-se atualizado sobre os últimos avanços é se juntar à nossa comunidade! \n", + "\n", + "- [http://slack.openmined.org](http://slack.openmined.org)\n", + "\n", + "### Contribua com o projeto!\n", + "\n", + "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\".\n", + "\n", + "- [Etiquetados como Good First Issue](https://github.com/OpenMined/PySyft/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22)\n", + "\n", + "### Doar\n", + "\n", + "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!\n", + "\n", + "[Página do Open Collective do OpenMined](https://opencollective.com/openmined)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "celltoolbar": "Tags", + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From 88a0959917dc1dd9ca30c52f506c2a964972f164 Mon Sep 17 00:00:00 2001 From: Jeferson Date: Wed, 15 Jan 2020 19:39:12 -0300 Subject: [PATCH 10/17] (minor fixes) typo and verb correction --- .../portugu\303\252s/Parte 05 - Bem-vindo ao Sandbox.ipynb" | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git "a/examples/tutorials/translations/portugu\303\252s/Parte 05 - Bem-vindo ao Sandbox.ipynb" "b/examples/tutorials/translations/portugu\303\252s/Parte 05 - Bem-vindo ao Sandbox.ipynb" index da859ee0109..cbd4f11892a 100644 --- "a/examples/tutorials/translations/portugu\303\252s/Parte 05 - Bem-vindo ao Sandbox.ipynb" +++ "b/examples/tutorials/translations/portugu\303\252s/Parte 05 - Bem-vindo ao Sandbox.ipynb" @@ -26,7 +26,7 @@ "source": [ "### O que o Sandbox nos fornece?\n", "\n", - "Como você pode ver acima, criamos vários *workers* virtuais e carregamos vários conjuntos de dados de teste, distribuindo-os pelos vários *workers*, para que possamos praticar o uso das técnicas de proteção de privacidade, como a Aprendização Federada.\n", + "Como você pode ver acima, criamos vários *workers* virtuais e carregamos vários conjuntos de dados de teste, distribuindo-os pelos vários *workers*, para que possamos praticar o uso das técnicas de proteção de privacidade, como o Aprendizado Federado.\n", "\n", "Criamos seis *workers*...." ] @@ -71,7 +71,7 @@ "source": [ "# Seção 5.1: Funcionalidade de pesquisa de Workers\n", "\n", - "Um aspecto importante da ciência de dados remota é que queremos ser capazes de procurar por conjuntos de dados em uma máquina remota. Pense em um laboratório de pesquisa que deseja consultar, por exemplo, dados de radiografias e lesões de um hospital." + "Um aspecto importante da ciência de dados que não é feita localmente é que queremos ser capazes de procurar por conjuntos de dados em uma máquina remota. Pense em um laboratório de pesquisa que deseja consultar, por exemplo, dados de radiografias e lesões de um hospital." ] }, { @@ -204,7 +204,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.3" + "version": "3.7.5" } }, "nbformat": 4, From 4b83650f30805fc3470d80eee22f899de49c28f2 Mon Sep 17 00:00:00 2001 From: jeferson Date: Wed, 29 Jan 2020 13:07:41 -0300 Subject: [PATCH 11/17] add translation to Portuguese of the tutorial Part 09 --- ...o \303\240 Programas Criptografados.ipynb" | 857 ++++++++++++++++++ 1 file changed, 857 insertions(+) create mode 100644 "examples/tutorials/translations/portugu\303\252s/Parte 09 - Introdu\303\247\303\243o \303\240 Programas Criptografados.ipynb" diff --git "a/examples/tutorials/translations/portugu\303\252s/Parte 09 - Introdu\303\247\303\243o \303\240 Programas Criptografados.ipynb" "b/examples/tutorials/translations/portugu\303\252s/Parte 09 - Introdu\303\247\303\243o \303\240 Programas Criptografados.ipynb" new file mode 100644 index 00000000000..5bfcf4d865f --- /dev/null +++ "b/examples/tutorials/translations/portugu\303\252s/Parte 09 - Introdu\303\247\303\243o \303\240 Programas Criptografados.ipynb" @@ -0,0 +1,857 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Parte 09 - Introdução à Programas Criptografados\n", + "\n", + "\n", + "Acredite ou não, é possível realizar cálculos com dados criptografados. Em outras palavras, é possível executar um programa onde **TODAS as variáveis** estão **criptografadas**! \n", + "\n", + "Neste tutorial, nós vamos falar sobre as ferramentas básicas de computação criptografada. Em particular, nós vamos focar em uma abordagem popular chamada Computação Multiparte Segura (i.e **Secure Multi-Party Computation ou SMPC**). Nesta lição, você aprenderá como criar uma calculadora criptografada que pode executar cálculos com números criptografados.\n", + "\n", + "Autores:\n", + "- Andrew Trask - Twitter: [@iamtrask](https://twitter.com/iamtrask)\n", + "- Théo Ryffel - GitHub: [@LaRiffle](https://github.com/LaRiffle)\n", + "\n", + "Tradução:\n", + "- Jeferson Silva - Github: [@jefersonf](https://github.com/jefersonf)\n", + "\n", + "Referências: \n", + "- Morten Dahl - [Blog](https://mortendahl.github.io) - Twitter: [@mortendahlcs](https://twitter.com/mortendahlcs)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Passo 1: Criptografia Usando Computação Multiparte Segura\n", + "\n", + "SMPC é, à primeira vista, uma forma bastante estranha de \"criptografia\". Em vez de usar uma chave pública/privada para criptografar uma variável, cada valor é dividido em várias `partes`, cada uma das quais opera como uma chave privada. Normalmente, essas `partes` serão distribuídas entre 2 ou mais proprietários. Assim, para decifrar a variável, todos os proprietários devem concordar em permitir a sua descriptografia. Em essência, todos têm uma chave privada.\n", + "\n", + "### Encrypt()\n", + "\n", + "Então, digamos que queríamos \"encriptar\" uma variável `x`, podíamos fazê-lo da seguinte forma.\n", + "\n", + "> A criptografia não utiliza números reais ou de ponto flutuante mas um espaço matemático chamado de [integer quotient ring](http://mathworld.wolfram.com/QuotientRing.html) (anel quociente inteiro) que são basicamente os inteiros entre `0` e `Q-1`, onde `Q` é primo e \"grande o suficiente\" tal que o espaço contenha todos os números que nós usamos em nossos experimentos. Na prática, dado um valor `x` inteiro, fazemos `x % Q` (resto da divisão inteira) para que esteja contido no \"anel\". (É por isso que evitamos usar o número `x` > `Q`)" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "Q = 1234567891011" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "x = 25" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "import random\n", + "\n", + "def encrypt(x):\n", + " share_a = random.randint(-Q,Q) # Entenda share_a como parte A de x, idem para B, e C.\n", + " share_b = random.randint(-Q,Q)\n", + " share_c = (x - share_a - share_b) % Q\n", + " return (share_a, share_b, share_c)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(890804432397, -2305631655, 346069090294)" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "encrypt(x)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Como você pode ver aqui, nós dividimos nossa variável `x` em 3 partes diferentes, que poderiam ser enviadas para 3 diferentes proprietários de dados.\n", + "\n", + "### Decrypt()\n", + "\n", + "Se quiséssemos decifrar essas três partes, poderíamos simplesmente juntá-las e pegar o módulo do resultado (mod Q)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "def decrypt(*shares):\n", + " return sum(shares) % Q" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "a,b,c = encrypt(25)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "25" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "decrypt(a, b, c)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "É importante notar que se tentarmos decifrar com apenas duas partes, a descriptografia não funciona!" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "778460474681" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "decrypt(a, b)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Assim, precisamos que todos os proprietários participem para decifrar o valor. É desta forma que as partes agem como chaves privadas, todas as quais devem estar presentes para decifrar um valor." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Passo 2: Aritmética Básica Usando SMPC\n", + "\n", + "No entanto, a propriedade verdadeiramente extraordinária da Computação Multiparte Segura é a capacidade de realizar cálculos **enquanto as variáveis ainda estão criptografadas**. Vamos demonstrar uma simples adição abaixo." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [], + "source": [ + "x = encrypt(25)\n", + "y = encrypt(5)" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [], + "source": [ + "def add(x, y):\n", + " z = list()\n", + " # o primeiro worker adiciona as suas partes\n", + " z.append((x[0] + y[0]) % Q)\n", + " \n", + " # o segundo worker adiciona as suas partes\n", + " z.append((x[1] + y[1]) % Q)\n", + " \n", + " # o terceiro worker adiciona as suas partes\n", + " z.append((x[2] + y[2]) % Q)\n", + " \n", + " return z" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "30" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "decrypt(*add(x,y))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Sucesso!!!\n", + "\n", + "E aqui o temos! Se cada _worker_ (separadamente) somar suas partes, então as partes resultantes serão decifradas para o valor correto (25 + 5 === 30). \n", + "\n", + "Acontece que, existem protocolos SMPC que podem permitir este cálculo criptografado para as seguintes operações:\n", + "- Adição (que acabamos de ver)\n", + "- Multiplicação\n", + "- Comparação\n", + "\n", + "\n", + "e usando estas três operações básicas, podemos fazer cálculos arbitrários!!!\n", + "\n", + "Na próxima seção, vamos aprender como usar a biblioteca PySyft para realizar estas operações!" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Passo 3: SMPC Usando PySyft\n", + "\n", + "Nas seções anteriores, nós demostramos algumas intuições básicas em torno do SMPC e como o método deve funcionar. Contudo, na prática, não queremos ter de ser nós próprios a escrever à mão todas as operações primitivas ao escrever os nossos programas criptografados. Então, nesta seção vamos passar pelo básico de como fazer computação criptografada usando o PySyft. Em particular, vamos focar em como fazer as 3 operações básicas mencionados anteriormente: adição, multiplicação, e comparação.\n", + "\n", + "Primeiro, precisamos criar alguns _Workers Virtuais_ (esperamos que você já esteja familiarizado com os nossos tutoriais anteriores). " + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [], + "source": [ + "import torch\n", + "import syft as sy\n", + "hook = sy.TorchHook(torch)\n", + "\n", + "bob = sy.VirtualWorker(hook, id=\"bob\")\n", + "alice = sy.VirtualWorker(hook, id=\"alice\")\n", + "bill = sy.VirtualWorker(hook, id=\"bill\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Criptografia e Descriptografia Básica\n", + "\n", + "Criptografar é tão simples como tomar qualquer tensor PySyft e chamar `.share()`. Descriptografar é tão simples como chamar `.get()` na variável compartilhada." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [], + "source": [ + "x = torch.tensor([25])" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "tensor([25])" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "x" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [], + "source": [ + "encrypted_x = x.share(bob, alice, bill)" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "tensor([25])" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "encrypted_x.get()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Considerações sobre os Valores Criptografados\n", + "\n", + "Se olharmos mais de perto para os _workers_ Alice, Bob e Bill, podemos ver as partes que são criadas em cada um deles!" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{}" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "bob._objects" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [], + "source": [ + "x = torch.tensor([25]).share(bob, alice, bill)" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "tensor([3212861001891376707])" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Parte de Bob\n", + "bobs_share = list(bob._objects.values())[0]\n", + "bobs_share" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "tensor([61371170032936135])" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Parte de Alice\n", + "alices_share = list(alice._objects.values())[0]\n", + "alices_share" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "tensor([1337453846503075087])" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Parte de Bill\n", + "bills_share = list(bill._objects.values())[0]\n", + "bills_share" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "E se quiséssemos, poderíamos decifrar esses valores usando a mesma abordagem de que falamos anteriormente!!!" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "tensor([25])" + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "Q = x.child.field\n", + "\n", + "(bobs_share + alices_share + bills_share) % Q" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "As you can see, when we called `.share()` it simply split the value into 3 shares and sent one share to each of the parties!\n", + "\n", + "Como você pode ver, quando chamamos `.share()` simplesmente dividimos o valor em 3 partes e o enviamos para cada um dos _workers_ !" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Aritmética Criptografada\n", + "\n", + "E agora você vê que nós podemos fazer aritmética sobre os valores subjacentes! A API é construída para que possamos simplesmente executar a aritmética como faríamos com os tensores PyTorch normais." + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [], + "source": [ + "x = torch.tensor([25]).share(bob,alice)\n", + "y = torch.tensor([5]).share(bob,alice)" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "tensor([30])" + ] + }, + "execution_count": 24, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "z = x + y\n", + "z.get()" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "tensor([20])" + ] + }, + "execution_count": 25, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "z = x - y\n", + "z.get()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Multiplicação Criptografada\n", + "\n", + "Para a multiplicação, precisamos de uma parte adicional que seja responsável pela geração consistente de números aleatórios (e que não colida com nenhuma das outras partes). Nós chamamos essa terceira parte de \"provedor de criptografia\". Para todos os propósitos, o provedor de criptografia é apenas um \"VirtualWorker\" adicional, mas é importante reconhecer que o provedor de criptografia não é um \"dono/proprietário\", pois ele não possui partes, mas é alguém que precisa ser confiável para não entrar em conluio com nenhuma das partes existentes." + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [], + "source": [ + "crypto_provider = sy.VirtualWorker(hook, id=\"crypto_provider\")" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": {}, + "outputs": [], + "source": [ + "x = torch.tensor([25]).share(bob,alice, crypto_provider=crypto_provider)\n", + "y = torch.tensor([5]).share(bob,alice, crypto_provider=crypto_provider)" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "tensor([125])" + ] + }, + "execution_count": 28, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# multiplicação\n", + "\n", + "z = x * y\n", + "z.get()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Você também pode fazer multiplicação matricial" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": {}, + "outputs": [], + "source": [ + "x = torch.tensor([[1, 2],[3,4]]).share(bob,alice, crypto_provider=crypto_provider)\n", + "y = torch.tensor([[2, 0],[0,2]]).share(bob,alice, crypto_provider=crypto_provider)" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "tensor([[2, 4],\n", + " [6, 8]])" + ] + }, + "execution_count": 30, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# multiplicação de matrizes\n", + "\n", + "z = x.mm(y)\n", + "z.get()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Comparação Criptografada\n", + "\n", + "Também é possível fazer comparações privadas entre valores privados. Contamos aqui com o protocolo _SecureNN_ , cujos detalhes podem ser encontrados [aqui](https://eprint.iacr.org/2018/442.pdf). O resultado da comparação é também um tensor privado compartilhado." + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": {}, + "outputs": [], + "source": [ + "x = torch.tensor([25]).share(bob,alice, crypto_provider=crypto_provider)\n", + "y = torch.tensor([5]).share(bob,alice, crypto_provider=crypto_provider)" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "tensor([1])" + ] + }, + "execution_count": 32, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "z = x > y\n", + "z.get()" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "tensor([0])" + ] + }, + "execution_count": 33, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "z = x <= y\n", + "z.get()" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "tensor([0])" + ] + }, + "execution_count": 34, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "z = x == y\n", + "z.get()" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "tensor([1])" + ] + }, + "execution_count": 35, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "z = x == y + 20\n", + "z.get()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Você também pode realizar operações de _maximum._" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "tensor([4])" + ] + }, + "execution_count": 36, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "x = torch.tensor([2, 3, 4, 1]).share(bob,alice, crypto_provider=crypto_provider)\n", + "x.max().get()" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "tensor([4, 3])" + ] + }, + "execution_count": 37, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "x = torch.tensor([[2, 3], [4, 1]]).share(bob,alice, crypto_provider=crypto_provider)\n", + "max_values, max_ids = x.max(dim=0)\n", + "max_values.get()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Parabéns!!! - Hora de se juntar a comunidade!\n", + "\n", + "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!\n", + "\n", + "### Dê-nos uma estrela em nosso repo do PySyft no GitHub\n", + "\n", + "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.\n", + "\n", + "- [Star PySyft](https://github.com/OpenMined/PySyft)\n", + "\n", + "### Junte-se ao Slack!\n", + "\n", + "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](http://slack.openmined.org)\n", + "\n", + "### Contribua com o projeto!\n", + "\n", + "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\".\n", + "\n", + "- [Projetos do PySyft](https://github.com/OpenMined/PySyft/issues?q=is%3Aopen+is%3Aissue+label%3AProject)\n", + "- [Etiquetados como Good First Issue](https://github.com/OpenMined/PySyft/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22)\n", + "\n", + "### Doar\n", + "\n", + "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!\n", + "\n", + "[Página do Open Collective do OpenMined](https://opencollective.com/openmined)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From 7eddad6e2cd296cc2662a5f0016bd6994de5d913 Mon Sep 17 00:00:00 2001 From: jeferson Date: Thu, 30 Jan 2020 11:50:50 -0300 Subject: [PATCH 12/17] add translation to Portuguese of the tutorial Part 10 --- ... com Agrega\303\247\303\243o Segura.ipynb" | 543 ++++++++++++++++++ 1 file changed, 543 insertions(+) create mode 100644 "examples/tutorials/translations/portugu\303\252s/Parte 10 - Aprendizagem Federada com Agrega\303\247\303\243o Segura.ipynb" diff --git "a/examples/tutorials/translations/portugu\303\252s/Parte 10 - Aprendizagem Federada com Agrega\303\247\303\243o Segura.ipynb" "b/examples/tutorials/translations/portugu\303\252s/Parte 10 - Aprendizagem Federada com Agrega\303\247\303\243o Segura.ipynb" new file mode 100644 index 00000000000..52f3a07f02e --- /dev/null +++ "b/examples/tutorials/translations/portugu\303\252s/Parte 10 - Aprendizagem Federada com Agrega\303\247\303\243o Segura.ipynb" @@ -0,0 +1,543 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Parte 10: Aprendizagem Federada com Agregação de Gradientes Criptografada\n", + "\n", + "Nas últimas seções, temos aprendido sobre computação criptografada através da construção de vários programas simples. Nesta seção, vamos voltar à [demonstração de Aprendizagem Federada da Parte 4](https://github.com/OpenMined/PySyft/blob/master/examples/tutorials/translations/portugu%C3%AAs/Parte%2004%20-%20Aprendizado%20Federado%20por%20meio%20de%20Agregador%20Confi%C3%A1vel.ipynb), onde tivemos um \"agregador de confiança\" que foi responsável pela média das atualizações do modelo de vários _vorkers_.\n", + "\n", + "Vamos agora usar nossas novas ferramentas de computação criptografada para remover esse agregador confiável, pois ele é menos do que ideal, pois pressupõe que podemos encontrar alguém confiável o suficiente para ter acesso a essas informações confidenciais. Este nem sempre é o caso.\n", + "\n", + "Assim, nesta parte do tutorial, mostraremos como se pode usar o SMPC para realizar uma agregação segura, de modo a não precisarmos de um \"agregador de confiança\".\n", + "\n", + "Autores:\n", + "- Theo Ryffel - Twitter: [@theoryffel](https://twitter.com/theoryffel)\n", + "- Andrew Trask - Twitter: [@iamtrask](https://twitter.com/iamtrask)\n", + "\n", + "Tradução:\n", + "- Jeferson Silva - Github: [@jefersonf](https://github.com/jefersonf)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Seção 1: Aprendizagem Federada Usual\n", + "\n", + "Primeiro, aqui está um código que realiza o clássico aprendizado federado no _Boston Housing Dataset_. Esta seção do código é dividida em várias partes.\n", + "\n", + "### Configuração" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import pickle\n", + "\n", + "import torch\n", + "import torch.nn as nn\n", + "import torch.nn.functional as F\n", + "import torch.optim as optim\n", + "from torch.utils.data import TensorDataset, DataLoader\n", + "\n", + "class Parser:\n", + " \"\"\"Parameters for training\"\"\"\n", + " def __init__(self):\n", + " self.epochs = 10\n", + " self.lr = 0.001\n", + " self.test_batch_size = 8\n", + " self.batch_size = 8\n", + " self.log_interval = 10\n", + " self.seed = 1\n", + " \n", + "args = Parser()\n", + "\n", + "torch.manual_seed(args.seed)\n", + "kwargs = {}" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Carregando o Conjunto de Dados" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "with open('../data/BostonHousing/boston_housing.pickle','rb') as f:\n", + " ((X, y), (X_test, y_test)) = pickle.load(f)\n", + "\n", + "X = torch.from_numpy(X).float()\n", + "y = torch.from_numpy(y).float()\n", + "X_test = torch.from_numpy(X_test).float()\n", + "y_test = torch.from_numpy(y_test).float()\n", + "# preprocessing\n", + "mean = X.mean(0, keepdim=True)\n", + "dev = X.std(0, keepdim=True)\n", + "mean[:, 3] = 0. # a *feature* da coluna 3 é binária,\n", + "dev[:, 3] = 1. # então não o padronizarmos.\n", + "X = (X - mean) / dev\n", + "X_test = (X_test - mean) / dev\n", + "train = TensorDataset(X, y)\n", + "test = TensorDataset(X_test, y_test)\n", + "train_loader = DataLoader(train, batch_size=args.batch_size, shuffle=True, **kwargs)\n", + "test_loader = DataLoader(test, batch_size=args.test_batch_size, shuffle=True, **kwargs)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Estrutura da Rede Neural" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "class Net(nn.Module):\n", + " def __init__(self):\n", + " super(Net, self).__init__()\n", + " self.fc1 = nn.Linear(13, 32)\n", + " self.fc2 = nn.Linear(32, 24)\n", + " self.fc3 = nn.Linear(24, 1)\n", + "\n", + " def forward(self, x):\n", + " x = x.view(-1, 13)\n", + " x = F.relu(self.fc1(x))\n", + " x = F.relu(self.fc2(x))\n", + " x = self.fc3(x)\n", + " return x\n", + "\n", + "model = Net()\n", + "optimizer = optim.SGD(model.parameters(), lr=args.lr)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Criando Gancho do PyTorch" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import syft as sy\n", + "\n", + "hook = sy.TorchHook(torch)\n", + "bob = sy.VirtualWorker(hook, id=\"bob\")\n", + "alice = sy.VirtualWorker(hook, id=\"alice\")\n", + "james = sy.VirtualWorker(hook, id=\"james\")\n", + "\n", + "compute_nodes = [bob, alice]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Envie dados para os workers**
\n", + "Normalmente eles já o teriam, isto é apenas para fins de demonstração que nós o enviamos manualmente." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "train_distributed_dataset = []\n", + "\n", + "for batch_idx, (data,target) in enumerate(train_loader):\n", + " data = data.send(compute_nodes[batch_idx % len(compute_nodes)])\n", + " target = target.send(compute_nodes[batch_idx % len(compute_nodes)])\n", + " train_distributed_dataset.append((data, target))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Função de Treinamento" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def train(epoch):\n", + " model.train()\n", + " for batch_idx, (data,target) in enumerate(train_distributed_dataset):\n", + " worker = data.location\n", + " model.send(worker)\n", + "\n", + " optimizer.zero_grad()\n", + " # atualize o modelo\n", + " pred = model(data)\n", + " loss = F.mse_loss(pred.view(-1), target)\n", + " loss.backward()\n", + " optimizer.step()\n", + " model.get()\n", + " \n", + " if batch_idx % args.log_interval == 0:\n", + " loss = loss.get()\n", + " print('Train Epoch: {} [{}/{} ({:.0f}%)]\\tLoss: {:.6f}'.format(\n", + " epoch, batch_idx * data.shape[0], len(train_loader),\n", + " 100. * batch_idx / len(train_loader), loss.item()))\n", + " \n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Função de Teste" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def test():\n", + " model.eval()\n", + " test_loss = 0\n", + " for data, target in test_loader:\n", + " output = model(data)\n", + " test_loss += F.mse_loss(output.view(-1), target, reduction='sum').item() # soma as perdas dos *batches*\n", + " pred = output.data.max(1, keepdim=True)[1] # obtem o índice da probabilidade logarítima máxima\n", + " \n", + " test_loss /= len(test_loader.dataset)\n", + " print('\\nTest set: Average loss: {:.4f}\\n'.format(test_loss))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Treinando o Modelo" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import time" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "t = time.time()\n", + "\n", + "for epoch in range(1, args.epochs + 1):\n", + " train(epoch)\n", + "\n", + " \n", + "total_time = time.time() - t\n", + "print('Total', round(total_time, 2), 's')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Calculando a Performance" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "test()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Seção 2: Adicionando Agregação Criptografada\n", + "\n", + "Agora vamos modificar um pouco este exemplo para agregar gradientes usando criptografia. A diferença principal é uma ou duas linhas de código na função `train()`, que nós vamos destacar. Por enquanto, vamos reprocessar nossos dados e inicializar um modelo para bob e alice." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "remote_dataset = (list(),list())\n", + "\n", + "train_distributed_dataset = []\n", + "\n", + "for batch_idx, (data,target) in enumerate(train_loader):\n", + " data = data.send(compute_nodes[batch_idx % len(compute_nodes)])\n", + " target = target.send(compute_nodes[batch_idx % len(compute_nodes)])\n", + " remote_dataset[batch_idx % len(compute_nodes)].append((data, target))\n", + "\n", + "def update(data, target, model, optimizer):\n", + " model.send(data.location)\n", + " optimizer.zero_grad()\n", + " pred = model(data)\n", + " loss = F.mse_loss(pred.view(-1), target)\n", + " loss.backward()\n", + " optimizer.step()\n", + " return model\n", + "\n", + "bobs_model = Net()\n", + "alices_model = Net()\n", + "\n", + "bobs_optimizer = optim.SGD(bobs_model.parameters(), lr=args.lr)\n", + "alices_optimizer = optim.SGD(alices_model.parameters(), lr=args.lr)\n", + "\n", + "models = [bobs_model, alices_model]\n", + "params = [list(bobs_model.parameters()), list(alices_model.parameters())]\n", + "optimizers = [bobs_optimizer, alices_optimizer]\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Construindo nossa Lógica de Treinamento\n", + "\n", + "A única diferença **real** está dentro deste método de treino. Vamos vê-lo passo-a-passo.\n", + "\n", + "### Parte A: Treino:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# seleciona em qual parte do conjunto de dados (batch) treinar\n", + "data_index = 0\n", + "# atualiza os modelos remotos\n", + "# poderíamos iterar o trecho seguinte várias vezes antes de prosseguir, mas vamos iterar uma vez por worker.\n", + "for remote_index in range(len(compute_nodes)):\n", + " data, target = remote_dataset[remote_index][data_index]\n", + " models[remote_index] = update(data, target, models[remote_index], optimizers[remote_index])\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Parte B: Agregação Criptografada" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# cria uma lista onde vamos depositar a média do nosso modelo encriptado\n", + "new_params = list()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# iterar através de cada parâmetro\n", + "for param_i in range(len(params[0])):\n", + "\n", + " # para cada worker\n", + " spdz_params = list()\n", + " for remote_index in range(len(compute_nodes)):\n", + " \n", + " # selecione o parâmetro em comum de cada worker e copie-o\n", + " copy_of_parameter = params[remote_index][param_i].copy()\n", + " \n", + " # Como o SMPC só pode trabalhar com inteiros (não valores de ponto flutuante), \n", + " # precisamos usar inteiros para armazenar informações decimais. Em outras palavras, \n", + " # precisamos usar a codificação \"Fixed Precision\".\n", + " fixed_precision_param = copy_of_parameter.fix_precision()\n", + " \n", + " # agora o criptografamos na máquina remota. \n", + " # Note que o fixed_precision_param JÁ é um ponteiro. Assim, \n", + " # quando chamamos share(...), ele realmente criptografa os dados \n", + " # para os quais os dados estão apontando. Isto retorna um PONTEIRO para o objecto MPC secreto \n", + " # compartilhado, e que depois precisamos buscar.\n", + " encrypted_param = fixed_precision_param.share(bob, alice, crypto_provider=james)\n", + " \n", + " # agora vamos buscar o ponteiro para valor compartilhado pelo MPC\n", + " param = encrypted_param.get()\n", + " \n", + " # salva o parâmetro para que possamos calcular a média \n", + " # com o mesmo parâmetro dos outros workers\n", + " spdz_params.append(param)\n", + "\n", + " # calcule a média do parâmetros de vários workers, e traga-os para a máquina local.\n", + " # descriptografe e decodifique (a partir de precisão fixa) de volta para um número de ponto flutuante\n", + " new_param = (spdz_params[0] + spdz_params[1]).get().float_precision()/2\n", + " \n", + " # salve o novo parâmetro que representa a média\n", + " new_params.append(new_param)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Parte C: Limpeza" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "with torch.no_grad():\n", + " for model in params:\n", + " for param in model:\n", + " param *= 0\n", + "\n", + " for model in models:\n", + " model.get()\n", + "\n", + " for remote_index in range(len(compute_nodes)):\n", + " for param_index in range(len(params[remote_index])):\n", + " params[remote_index][param_index].set_(new_params[param_index])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Vamos Juntar Tudo!!\n", + "\n", + "E agora que conhecemos cada etapa, nós podemos colocar todas juntas em mesmo ciclo de treinamento." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def test():\n", + " models[0].eval()\n", + " test_loss = 0\n", + " for data, target in test_loader:\n", + " output = models[0](data)\n", + " test_loss += F.mse_loss(output.view(-1), target, reduction='sum').item() # soma as perdas dos *batches*\n", + " pred = output.data.max(1, keepdim=True)[1] # obtem o índice da probabilidade logarítima máxima\n", + " \n", + " test_loss /= len(test_loader.dataset)\n", + " print('Test set: Average loss: {:.4f}\\n'.format(test_loss))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "t = time.time()\n", + "\n", + "for epoch in range(args.epochs):\n", + " print(f\"Epoch {epoch + 1}\")\n", + " train(epoch)\n", + " test()\n", + "\n", + " \n", + "total_time = time.time() - t\n", + "print('Total', round(total_time, 2), 's')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Parabéns!!! - Hora de se juntar a comunidade!\n", + "\n", + "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!\n", + "\n", + "### Dê-nos uma estrela em nosso repo do PySyft no GitHub\n", + "\n", + "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.\n", + "\n", + "- [Star PySyft](https://github.com/OpenMined/PySyft)\n", + "\n", + "### Junte-se ao Slack!\n", + "\n", + "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](http://slack.openmined.org)\n", + "\n", + "### Contribua com o projeto!\n", + "\n", + "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\".\n", + "\n", + "- [Projetos do PySyft](https://github.com/OpenMined/PySyft/issues?q=is%3Aopen+is%3Aissue+label%3AProject)\n", + "- [Etiquetados como Good First Issue](https://github.com/OpenMined/PySyft/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22)\n", + "\n", + "### Doar\n", + "\n", + "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!\n", + "\n", + "[Página do Open Collective do OpenMined](https://opencollective.com/openmined)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From 4a9b8f57410699591ba0e36142306fd5a57455e0 Mon Sep 17 00:00:00 2001 From: jeferson Date: Thu, 30 Jan 2020 16:40:48 -0300 Subject: [PATCH 13/17] add translation to Portuguese of the tutorial Part 11 --- ...Segura Usando Aprendizagem Profunda.ipynb" | 445 ++++++++++++++++++ 1 file changed, 445 insertions(+) create mode 100644 "examples/tutorials/translations/portugu\303\252s/Parte 11 - Classifica\303\247\303\243o Segura Usando Aprendizagem Profunda.ipynb" diff --git "a/examples/tutorials/translations/portugu\303\252s/Parte 11 - Classifica\303\247\303\243o Segura Usando Aprendizagem Profunda.ipynb" "b/examples/tutorials/translations/portugu\303\252s/Parte 11 - Classifica\303\247\303\243o Segura Usando Aprendizagem Profunda.ipynb" new file mode 100644 index 00000000000..9d0915cdf46 --- /dev/null +++ "b/examples/tutorials/translations/portugu\303\252s/Parte 11 - Classifica\303\247\303\243o Segura Usando Aprendizagem Profunda.ipynb" @@ -0,0 +1,445 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "parameters" + ] + }, + "outputs": [], + "source": [ + "epochs = 10\n", + "n_test_batches = 200" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Parte 11 - Classificação Segura Usando Aprendizagem Profunda\n", + "\n", + "\n", + "## Os seus dados são importantes, o seu modelo também.\n", + "\n", + "Os dados são o carro-chefe por trás da Aprendizagem de Máquina (Machine Learning). As organizações que criam e coletam dados são capazes de construir e treinar seus próprios modelos de aprendizagem de máquina. Isto permite-lhes oferecer o uso de tais modelos como um serviço (MLaaS) a organizações externas. Isto é útil para organizações que podem não ser capazes de criar esses modelos por si próprias, mas que ainda gostariam de usar esses modelos para fazer predições sobre os seus próprios dados.\n", + "\n", + "No entanto, um modelo hospedado na nuvem ainda apresenta um problema de privacidade/IP. Para que organizações externas possam usá-lo - elas devem carregar seus dados de entrada (como imagens a serem classificadas) ou fazer o _download_ do modelo. O _upload_ dos dados de entrada pode ser problemático do ponto de vista da privacidade, mas o _download_ do modelo pode não ser uma opção se a organização que criou/possui o modelo estiver preocupada em preservar seu IP.\n", + "\n", + "\n", + "\n", + "## Computação sobre dados criptografados\n", + "\n", + "Neste contexto, uma possível solução seria criptografar tanto o modelo como os dados de uma forma que permita a uma organização utilizar um modelo de outra organização sem revelar o seu IP. Existem várias estratégias de criptografia que permitem o cálculo sobre dados criptografados, entre os quais _Secure Multi-Party Computation_ (SMPC), criptografia Homomórfica (FHE/SHE) e criptografia Funcional (FE) são os tipos mais conhecidos. Vamos focar aqui na Computação Multiparte Segura ([introduzida em detalhe aqui no tutorial 5](https://github.com/OpenMined/PySyft/blob/master/examples/tutorials/translations/portugu%C3%AAs/Parte%2005%20-%20Bem-vindo%20ao%20Sandbox.ipynb)) que consiste na soma de partes compartilhadas de forma privada. E que se baseia em protocolos de criptografia como o SecureNN e SPDZ, cujos detalhes são dados [nesta excelente publicação de de blog](https://mortendahl.github.io/2017/09/19/private-image-analysis-with-mpc/). \n", + "\n", + "Estes protocolos alcançam desempenhos notáveis sobre dados criptografados, e nos últimos meses temos trabalhado para tornar estes protocolos fáceis de usar. Em específico, estamos construindo ferramentas para permitir que você use esses protocolos sem ter que reimplementá-los novamente (ou se quer conhecer a criptografia por trás de seu funcionamento). Vamos direto ao assunto.\n", + "\n", + "## Cenário\n", + "\n", + "Neste tutorial considere o seguinte cenário: considere que você é o servidor e que você tem alguns dados. Primeiro, você define e treina um modelo com esses dados de treinamento privado. Depois, você entra em contato com um cliente que possui alguns dos seus próprios dados e que gostaria de acessar o seu modelo para fazer algumas previsões/predições. \n", + "\n", + "Você criptografa o seu modelo (uma rede neural). O cliente criptografa os seus dados. Ambos usam esses dois recursos criptografados para usar o modelo para classificar os dados. Finalmente, o resultado da predição é enviado de volta para o cliente de forma criptografada para que o servidor (ou seja, você) não aprenda nada sobre os dados do cliente (ou seja, você não aprende nem as entradas nem as predições).\n", + "\n", + "O ideal seria que, de maneira incremental, compartilhássemos as `entradas dos clientes` entre eles próprios e o `servidor` e vice-versa para o modelo. Por uma questão de simplicidade, as entradas (i.e dados de treino) serão mantidas por outros dois _workers_ , `alice` e `bob`. Se você considerar que alice é de propriedade do cliente e bob do servidor, é completamente equivalente.\n", + "\n", + "O cálculo é seguro no modelo HBC (i.e. Honest-But-Curious adversary), que é padrão em [muitas ferramentas MPC](https://arxiv.org/pdf/1801.03239.pdf) (Multi-Party Computation).\n", + "\n", + "**Agora temos tudo o que precisamos!**\n", + "\n", + "\n", + "Autor:\n", + "- Théo Ryffel - Twitter: [@theoryffel](https://twitter.com/theoryffel) · GitHub: [@LaRiffle](https://github.com/LaRiffle)\n", + "\n", + "Tradução:\n", + "- Jeferson Silva - Github: [@jefersonf](https://github.com/jefersonf)\n", + "\n", + "**Vamos começar!**" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Imports e especificações do modelo" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import torch\n", + "import torch.nn as nn\n", + "import torch.nn.functional as F\n", + "import torch.optim as optim\n", + "from torchvision import datasets, transforms" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " Nós também precisamos executar comandos específicos para importar/iniciar o PySyft. Nós criamos alguns _workers_ (chamados `client`, `bob` e `alice`). Por fim, nós definimos o provedor de criptografia (`cripto_provider`) que nos dá todos as ferramentas básicas de criptografia que podemos precisar ([Veja nosso tutorial sobre SMPC para mais detalhes](https://github.com/OpenMined/PySyft/blob/master/examples/tutorials/Part%2009%20-%20Intro%20to%20Encrypted%20Programs.ipynb))." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import syft as sy\n", + "hook = sy.TorchHook(torch) \n", + "client = sy.VirtualWorker(hook, id=\"client\")\n", + "bob = sy.VirtualWorker(hook, id=\"bob\")\n", + "alice = sy.VirtualWorker(hook, id=\"alice\")\n", + "crypto_provider = sy.VirtualWorker(hook, id=\"crypto_provider\") " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Nós definimos o cenário da tarefa de aprendizagem" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "class Arguments():\n", + " def __init__(self):\n", + " self.batch_size = 64\n", + " self.test_batch_size = 50\n", + " self.epochs = epochs\n", + " self.lr = 0.001\n", + " self.log_interval = 100\n", + "\n", + "args = Arguments()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Carregamento e envio de dados aos Workers\n", + "\n", + "Na nosso cenário, assumimos que o servidor tem acesso a alguns dados de treino para que possa treinar seu modelo. Aqui temos o conjunto de treinamento do MNIST." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "train_loader = torch.utils.data.DataLoader(\n", + " datasets.MNIST('../data', train=True, download=True,\n", + " transform=transforms.Compose([\n", + " transforms.ToTensor(),\n", + " transforms.Normalize((0.1307,), (0.3081,))\n", + " ])),\n", + " batch_size=args.batch_size, shuffle=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Em segundo lugar, o cliente tem alguns dados e gostaria de ter predições sobre eles usando o modelo do servidor. Este cliente criptografa seus dados, compartilhando-os entre os dois _workers_ , `alice` e `bob`.\n", + "> SMPC usa protocolos de criptografia que requerem o uso de inteiros. Nós aproveitamos aqui a abstração do tensor PySyft para converter os tensores de ponto flutuante do PyTorch em tensores de precisão fixa utilizando `.fix_precision()`. Por exemplo 0.123 com precisão 2 faz um arredondamento com o segundo dígito decimal para que o número armazenado seja o número inteiro 12.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "test_loader = torch.utils.data.DataLoader(\n", + " datasets.MNIST('../data', train=False,\n", + " transform=transforms.Compose([\n", + " transforms.ToTensor(),\n", + " transforms.Normalize((0.1307,), (0.3081,))\n", + " ])),\n", + " batch_size=args.test_batch_size, shuffle=True)\n", + "\n", + "private_test_loader = []\n", + "for data, target in test_loader:\n", + " private_test_loader.append((\n", + " data.fix_precision().share(alice, bob, crypto_provider=crypto_provider),\n", + " target.fix_precision().share(alice, bob, crypto_provider=crypto_provider)\n", + " ))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Especificação de uma Rede Neural (Feed Forward Neural Network)\n", + "\n", + "Aqui está a especificação da rede utilizada pelo servidor" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "class Net(nn.Module):\n", + " def __init__(self):\n", + " super(Net, self).__init__()\n", + " self.fc1 = nn.Linear(784, 500)\n", + " self.fc2 = nn.Linear(500, 10)\n", + "\n", + " def forward(self, x):\n", + " x = x.view(-1, 784)\n", + " x = self.fc1(x)\n", + " x = F.relu(x)\n", + " x = self.fc2(x)\n", + " return x" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Iniciar o treinamento\n", + "O treinamento é feito localmente, então este é um treinamento no PyTorch inteiramente local, nada de especial aqui!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def train(args, model, train_loader, optimizer, epoch):\n", + " model.train()\n", + " for batch_idx, (data, target) in enumerate(train_loader):\n", + " optimizer.zero_grad()\n", + " output = model(data)\n", + " output = F.log_softmax(output, dim=1)\n", + " loss = F.nll_loss(output, target)\n", + " loss.backward()\n", + " optimizer.step()\n", + " if batch_idx % args.log_interval == 0:\n", + " print('Train Epoch: {} [{}/{} ({:.0f}%)]\\tLoss: {:.6f}'.format(\n", + " epoch, batch_idx * args.batch_size, len(train_loader) * args.batch_size,\n", + " 100. * batch_idx / len(train_loader), loss.item()))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "model = Net()\n", + "optimizer = torch.optim.Adam(model.parameters(), lr=args.lr)\n", + "\n", + "for epoch in range(1, args.epochs + 1):\n", + " train(args, model, train_loader, optimizer, epoch)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def test(args, model, test_loader):\n", + " model.eval()\n", + " test_loss = 0\n", + " correct = 0\n", + " with torch.no_grad():\n", + " for data, target in test_loader:\n", + " output = model(data)\n", + " output = F.log_softmax(output, dim=1)\n", + " test_loss += F.nll_loss(output, target, reduction='sum').item() # sum up batch loss\n", + " pred = output.argmax(1, keepdim=True) # get the index of the max log-probability \n", + " correct += pred.eq(target.view_as(pred)).sum().item()\n", + "\n", + " test_loss /= len(test_loader.dataset)\n", + "\n", + " print('\\nTest set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)\\n'.format(\n", + " test_loss, correct, len(test_loader.dataset),\n", + " 100. * correct / len(test_loader.dataset)))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "test(args, model, test_loader)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "O nosso modelo está agora treinado e pronto para ser fornecido como um serviço!" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Avaliação segura" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Agora, como servidor, enviamos o modelo para os _workers_ que têm os dados. Como o modelo é informação sensível (você gastou tempo otimizando-o!), você não quer revelar seus pesos então você compartilha o modelo, de forma secreta/criptografada, como nós fizemos com o conjunto de dados anteriormente." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "model.fix_precision().share(alice, bob, crypto_provider=crypto_provider)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "A seguinte função de teste realiza uma avaliação criptografada. Os pesos do modelo, as entradas de dados, a predição e o alvo (target) utilizado para a pontuação são criptografados!\n", + "\n", + "No entanto, a sintaxe é muito semelhante ao teste de modelos usual do PyTorch, não é legal/Fixe?!\n", + "\n", + "A única coisa que deciframos/descriptografamos no lado do servidor é a pontuação final dos nossos 200 batches de itens (`n_test_batches`) para verificar se as previsões eram em média boas." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def test(args, model, test_loader):\n", + " model.eval()\n", + " n_correct_priv = 0\n", + " n_total = 0\n", + " with torch.no_grad():\n", + " for data, target in test_loader[:n_test_batches]:\n", + " output = model(data)\n", + " pred = output.argmax(dim=1) \n", + " n_correct_priv += pred.eq(target.view_as(pred)).sum()\n", + " n_total += args.test_batch_size\n", + "\n", + " n_correct = n_correct_priv.copy().get().float_precision().long().item()\n", + " \n", + " print('Test set: Accuracy: {}/{} ({:.0f}%)'.format(\n", + " n_correct, n_total,\n", + " 100. * n_correct / n_total))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "test(args, model, private_test_loader)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Et voilà! Aqui está, você aprendeu como fazer previsões/predições seguras de ponta a ponta: os pesos do modelo do servidor não vazaram para o cliente e o servidor não tem informações sobre os dados de entrada nem sobre a saída da classificação!\n", + "\n", + "Quanto ao desempenho, classificar uma imagem leva **menos de 0,1 segundo**, aproximadamente **33ms** no meu computador portátil (2,7 GHz Intel Core i7, 16GB RAM). Entretanto, utilizei uma comunicação muito rápida (todos os _workers_ estão na minha máquina local). O desempenho irá variar dependendo da rapidez com que os diferentes _workers_ podem se comunicar uns com os outros.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Conclusão\n", + "\n", + "Você já viu como é fácil usar o PyTorch e o PySyft para realizar Aprendizagem de Máquina segura (i.e Secure Machine Learning) na prática e proteger os dados dos usuários, sem ter que ser um especialista em criptografia!\n", + "\n", + "Mais informações sobre este tópico virão em breve, incluindo camadas convolucionais para avaliar adequadamente o desempenho do PySyft em relação a outros casos de uso, bem como o treinamento criptografado privado de redes neurais, que é necessário quando uma organização recorre a dados sensíveis externos para treinar seu próprio modelo. Fique atento!\n", + "\n", + "If you enjoyed this and would like to join the movement toward privacy preserving, decentralized ownership of AI and the AI supply chain (data), you can do so in the following ways! \n", + "\n", + "Se você gostou disso e gostaria de participar do movimento em prol da preservação da privacidade, da propriedade descentralizada da IA e da cadeia de fornecimento de IA (dados), você pode fazer isso das seguintes maneiras! \n", + "\n", + "Se você gostou disso e gostaria de se juntar ao movimento em direção à preservação da privacidade, propriedade descentralizada da IA e da cadeia de suprimentos da AI (dados), você pode fazê-lo das seguintes maneiras!\n", + "\n", + "\n", + "### Dê-nos uma estrela em nosso repo do PySyft no GitHub\n", + "\n", + "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.\n", + "\n", + "- [Star PySyft](https://github.com/OpenMined/PySyft)\n", + "\n", + "### Veja nossos tutoriais no GitHub!\n", + "\n", + "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.\n", + "\n", + "- [Tutoriais do PySyft](https://github.com/OpenMined/PySyft/tree/master/examples/tutorials)\n", + "\n", + "### Junte-se ao Slack!\n", + "\n", + "A melhor maneira de manter-se atualizado sobre os últimos avanços é se juntar à nossa comunidade! \n", + "\n", + "- [http://slack.openmined.org](http://slack.openmined.org)\n", + "\n", + "### Contribua com o projeto!\n", + "\n", + "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\".\n", + "\n", + "- [Etiquetados como Good First Issue](https://github.com/OpenMined/PySyft/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22)\n", + "\n", + "### Doar\n", + "\n", + "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!\n", + "\n", + "[Página do Open Collective do OpenMined](https://opencollective.com/openmined)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "celltoolbar": "Tags", + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From 5ddbc7cee647b81e3dbe49311b75b03243d6fa0c Mon Sep 17 00:00:00 2001 From: jeferson Date: Tue, 4 Feb 2020 09:43:33 -0300 Subject: [PATCH 14/17] (fix) a cell has been removed by mistake :expressionless: --- ... com Agrega\303\247\303\243o Segura.ipynb" | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git "a/examples/tutorials/translations/portugu\303\252s/Parte 10 - Aprendizagem Federada com Agrega\303\247\303\243o Segura.ipynb" "b/examples/tutorials/translations/portugu\303\252s/Parte 10 - Aprendizagem Federada com Agrega\303\247\303\243o Segura.ipynb" index 52f3a07f02e..afef0cc9a10 100644 --- "a/examples/tutorials/translations/portugu\303\252s/Parte 10 - Aprendizagem Federada com Agrega\303\247\303\243o Segura.ipynb" +++ "b/examples/tutorials/translations/portugu\303\252s/Parte 10 - Aprendizagem Federada com Agrega\303\247\303\243o Segura.ipynb" @@ -443,6 +443,43 @@ "E agora que conhecemos cada etapa, nós podemos colocar todas juntas em mesmo ciclo de treinamento." ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def train(epoch):\n", + " for data_index in range(len(remote_dataset[0])-1):\n", + " # atualiza os modelos remotos\n", + " for remote_index in range(len(compute_nodes)):\n", + " data, target = remote_dataset[remote_index][data_index]\n", + " models[remote_index] = update(data, target, models[remote_index], optimizers[remote_index])\n", + "\n", + " # agregação criptografada\n", + " new_params = list()\n", + " for param_i in range(len(params[0])):\n", + " spdz_params = list()\n", + " for remote_index in range(len(compute_nodes)):\n", + " spdz_params.append(params[remote_index][param_i].copy().fix_precision().share(bob, alice, crypto_provider=james).get())\n", + "\n", + " new_param = (spdz_params[0] + spdz_params[1]).get().float_precision()/2\n", + " new_params.append(new_param)\n", + "\n", + " # limpeza\n", + " with torch.no_grad():\n", + " for model in params:\n", + " for param in model:\n", + " param *= 0\n", + "\n", + " for model in models:\n", + " model.get()\n", + "\n", + " for remote_index in range(len(compute_nodes)):\n", + " for param_index in range(len(params[remote_index])):\n", + " params[remote_index][param_index].set_(new_params[param_index])" + ] + }, { "cell_type": "code", "execution_count": null, From 05e2455c654e4e547fc93cf0083786fe9b5870b7 Mon Sep 17 00:00:00 2001 From: jeferson Date: Tue, 4 Feb 2020 10:57:36 -0300 Subject: [PATCH 15/17] (minor fixes) :crossed_fingers: :crossed_fingers: :crossed_fingers: --- ... com Agrega\303\247\303\243o Segura.ipynb" | 64 +++++++++---------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git "a/examples/tutorials/translations/portugu\303\252s/Parte 10 - Aprendizagem Federada com Agrega\303\247\303\243o Segura.ipynb" "b/examples/tutorials/translations/portugu\303\252s/Parte 10 - Aprendizagem Federada com Agrega\303\247\303\243o Segura.ipynb" index afef0cc9a10..b879a050e62 100644 --- "a/examples/tutorials/translations/portugu\303\252s/Parte 10 - Aprendizagem Federada com Agrega\303\247\303\243o Segura.ipynb" +++ "b/examples/tutorials/translations/portugu\303\252s/Parte 10 - Aprendizagem Federada com Agrega\303\247\303\243o Segura.ipynb" @@ -84,8 +84,8 @@ "# preprocessing\n", "mean = X.mean(0, keepdim=True)\n", "dev = X.std(0, keepdim=True)\n", - "mean[:, 3] = 0. # a *feature* da coluna 3 é binária,\n", - "dev[:, 3] = 1. # então não o padronizarmos.\n", + "mean[:, 3] = 0. # the feature at column 3 is binary,\n", + "dev[:, 3] = 1. # so we don't standardize it\n", "X = (X - mean) / dev\n", "X_test = (X_test - mean) / dev\n", "train = TensorDataset(X, y)\n", @@ -98,7 +98,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Estrutura da Rede Neural" + "## Estrutura da Rede Neural## Neural Network Structure" ] }, { @@ -190,7 +190,7 @@ " model.send(worker)\n", "\n", " optimizer.zero_grad()\n", - " # atualize o modelo\n", + " # update the model\n", " pred = model(data)\n", " loss = F.mse_loss(pred.view(-1), target)\n", " loss.backward()\n", @@ -223,8 +223,8 @@ " test_loss = 0\n", " for data, target in test_loader:\n", " output = model(data)\n", - " test_loss += F.mse_loss(output.view(-1), target, reduction='sum').item() # soma as perdas dos *batches*\n", - " pred = output.data.max(1, keepdim=True)[1] # obtem o índice da probabilidade logarítima máxima\n", + " test_loss += F.mse_loss(output.view(-1), target, reduction='sum').item() # sum up batch loss\n", + " pred = output.data.max(1, keepdim=True)[1] # get the index of the max log-probability\n", " \n", " test_loss /= len(test_loader.dataset)\n", " print('\\nTest set: Average loss: {:.4f}\\n'.format(test_loss))" @@ -339,10 +339,10 @@ "metadata": {}, "outputs": [], "source": [ - "# seleciona em qual parte do conjunto de dados (batch) treinar\n", + "# this is selecting which batch to train on\n", "data_index = 0\n", - "# atualiza os modelos remotos\n", - "# poderíamos iterar o trecho seguinte várias vezes antes de prosseguir, mas vamos iterar uma vez por worker.\n", + "# update remote models\n", + "# we could iterate this multiple times before proceeding, but we're only iterating once per worker here\n", "for remote_index in range(len(compute_nodes)):\n", " data, target = remote_dataset[remote_index][data_index]\n", " models[remote_index] = update(data, target, models[remote_index], optimizers[remote_index])\n" @@ -361,7 +361,7 @@ "metadata": {}, "outputs": [], "source": [ - "# cria uma lista onde vamos depositar a média do nosso modelo encriptado\n", + "# create a list where we'll deposit our encrypted model average\n", "new_params = list()" ] }, @@ -371,40 +371,40 @@ "metadata": {}, "outputs": [], "source": [ - "# iterar através de cada parâmetro\n", + "# iterate through each parameter\n", "for param_i in range(len(params[0])):\n", "\n", - " # para cada worker\n", + " # for each worker\n", " spdz_params = list()\n", " for remote_index in range(len(compute_nodes)):\n", " \n", - " # selecione o parâmetro em comum de cada worker e copie-o\n", + " # select the identical parameter from each worker and copy it\n", " copy_of_parameter = params[remote_index][param_i].copy()\n", " \n", - " # Como o SMPC só pode trabalhar com inteiros (não valores de ponto flutuante), \n", - " # precisamos usar inteiros para armazenar informações decimais. Em outras palavras, \n", - " # precisamos usar a codificação \"Fixed Precision\".\n", + " # since SMPC can only work with integers (not floats), we need\n", + " # to use Integers to store decimal information. In other words,\n", + " # we need to use \"Fixed Precision\" encoding.\n", " fixed_precision_param = copy_of_parameter.fix_precision()\n", " \n", - " # agora o criptografamos na máquina remota. \n", - " # Note que o fixed_precision_param JÁ é um ponteiro. Assim, \n", - " # quando chamamos share(...), ele realmente criptografa os dados \n", - " # para os quais os dados estão apontando. Isto retorna um PONTEIRO para o objecto MPC secreto \n", - " # compartilhado, e que depois precisamos buscar.\n", + " # now we encrypt it on the remote machine. Note that \n", + " # fixed_precision_param is ALREADY a pointer. Thus, when\n", + " # we call share, it actually encrypts the data that the\n", + " # data is pointing TO. This returns a POINTER to the \n", + " # MPC secret shared object, which we need to fetch.\n", " encrypted_param = fixed_precision_param.share(bob, alice, crypto_provider=james)\n", " \n", - " # agora vamos buscar o ponteiro para valor compartilhado pelo MPC\n", + " # now we fetch the pointer to the MPC shared value\n", " param = encrypted_param.get()\n", " \n", - " # salva o parâmetro para que possamos calcular a média \n", - " # com o mesmo parâmetro dos outros workers\n", + " # save the parameter so we can average it with the same parameter\n", + " # from the other workers\n", " spdz_params.append(param)\n", "\n", - " # calcule a média do parâmetros de vários workers, e traga-os para a máquina local.\n", - " # descriptografe e decodifique (a partir de precisão fixa) de volta para um número de ponto flutuante\n", + " # average params from multiple workers, fetch them to the local machine\n", + " # decrypt and decode (from fixed precision) back into a floating point number\n", " new_param = (spdz_params[0] + spdz_params[1]).get().float_precision()/2\n", " \n", - " # salve o novo parâmetro que representa a média\n", + " # save the new averaged parameter\n", " new_params.append(new_param)" ] }, @@ -451,12 +451,12 @@ "source": [ "def train(epoch):\n", " for data_index in range(len(remote_dataset[0])-1):\n", - " # atualiza os modelos remotos\n", + " # update remote models\n", " for remote_index in range(len(compute_nodes)):\n", " data, target = remote_dataset[remote_index][data_index]\n", " models[remote_index] = update(data, target, models[remote_index], optimizers[remote_index])\n", "\n", - " # agregação criptografada\n", + " # encrypted aggregation\n", " new_params = list()\n", " for param_i in range(len(params[0])):\n", " spdz_params = list()\n", @@ -466,7 +466,7 @@ " new_param = (spdz_params[0] + spdz_params[1]).get().float_precision()/2\n", " new_params.append(new_param)\n", "\n", - " # limpeza\n", + " # cleanup\n", " with torch.no_grad():\n", " for model in params:\n", " for param in model:\n", @@ -491,8 +491,8 @@ " test_loss = 0\n", " for data, target in test_loader:\n", " output = models[0](data)\n", - " test_loss += F.mse_loss(output.view(-1), target, reduction='sum').item() # soma as perdas dos *batches*\n", - " pred = output.data.max(1, keepdim=True)[1] # obtem o índice da probabilidade logarítima máxima\n", + " test_loss += F.mse_loss(output.view(-1), target, reduction='sum').item() # sum up batch loss\n", + " pred = output.data.max(1, keepdim=True)[1] # get the index of the max log-probability\n", " \n", " test_loss /= len(test_loader.dataset)\n", " print('Test set: Average loss: {:.4f}\\n'.format(test_loss))" From 9ec618ca3c19cb97df6bf97bd6a1daa40ee2cb0f Mon Sep 17 00:00:00 2001 From: jeferson Date: Thu, 6 Feb 2020 10:53:22 -0300 Subject: [PATCH 16/17] (minor fix) full stop added --- ...du\303\247\303\243o \303\240 Programas Criptografados.ipynb" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/examples/tutorials/translations/portugu\303\252s/Parte 09 - Introdu\303\247\303\243o \303\240 Programas Criptografados.ipynb" "b/examples/tutorials/translations/portugu\303\252s/Parte 09 - Introdu\303\247\303\243o \303\240 Programas Criptografados.ipynb" index 5bfcf4d865f..d2a295a4201 100644 --- "a/examples/tutorials/translations/portugu\303\252s/Parte 09 - Introdu\303\247\303\243o \303\240 Programas Criptografados.ipynb" +++ "b/examples/tutorials/translations/portugu\303\252s/Parte 09 - Introdu\303\247\303\243o \303\240 Programas Criptografados.ipynb" @@ -9,7 +9,7 @@ "\n", "Acredite ou não, é possível realizar cálculos com dados criptografados. Em outras palavras, é possível executar um programa onde **TODAS as variáveis** estão **criptografadas**! \n", "\n", - "Neste tutorial, nós vamos falar sobre as ferramentas básicas de computação criptografada. Em particular, nós vamos focar em uma abordagem popular chamada Computação Multiparte Segura (i.e **Secure Multi-Party Computation ou SMPC**). Nesta lição, você aprenderá como criar uma calculadora criptografada que pode executar cálculos com números criptografados.\n", + "Neste tutorial, nós vamos falar sobre as ferramentas básicas de computação criptografada. Em particular, nós vamos focar em uma abordagem popular chamada Computação Multiparte Segura (i.e. **Secure Multi-Party Computation ou SMPC**). Nesta lição, você aprenderá como criar uma calculadora criptografada que pode executar cálculos com números criptografados.\n", "\n", "Autores:\n", "- Andrew Trask - Twitter: [@iamtrask](https://twitter.com/iamtrask)\n", From f85cac2408960d034959fed1b92ba912a73a991b Mon Sep 17 00:00:00 2001 From: jeferson Date: Fri, 7 Feb 2020 16:24:54 -0300 Subject: [PATCH 17/17] (fixes) remove repeated paragraphs left in tutorials part 06 and 11 --- ... 06 - Aprendizado Federado com MNIST usando uma CNN.ipynb" | 2 -- ...03\247\303\243o Segura Usando Aprendizagem Profunda.ipynb" | 4 ---- 2 files changed, 6 deletions(-) diff --git "a/examples/tutorials/translations/portugu\303\252s/Parte 06 - Aprendizado Federado com MNIST usando uma CNN.ipynb" "b/examples/tutorials/translations/portugu\303\252s/Parte 06 - Aprendizado Federado com MNIST usando uma CNN.ipynb" index 38f6b27e34e..c37b5f112e8 100644 --- "a/examples/tutorials/translations/portugu\303\252s/Parte 06 - Aprendizado Federado com MNIST usando uma CNN.ipynb" +++ "b/examples/tutorials/translations/portugu\303\252s/Parte 06 - Aprendizado Federado com MNIST usando uma CNN.ipynb" @@ -300,8 +300,6 @@ "\n", "Obviamente, existem dezenas de melhorias em que poderíamos pensar. Gostaríamos que o cálculo operasse em paralelo com os *workers* e realizasse a média federada (i.e. federated averaging), atualizando o modelo central a cada `n` *batches* apenas, para reduzir o número de mensagens que usamos para nos comunicarmos entre os *workers*, etc. Essas são características em que estamos trabalhando para tornar o Federated Learning pronto para um ambiente de produção e escreverêmos sobre assim que forem lançadas!\n", "\n", - "You should now be able to do Federated Learning by yourself! If you enjoyed this and would like to join the movement toward privacy preserving, decentralized ownership of AI and the AI supply chain (data), you can do so in the following ways! \n", - "\n", "Agora você deve poder fazer Aprendizado Federado sozinho! Se você gostou disso e gostaria de se juntar ao movimento em direção à preservação da privacidade, propriedade descentralizada da IA e da cadeia de suprimentos da AI (dados), você pode fazê-lo das seguintes maneiras!\n", "\n", "\n", diff --git "a/examples/tutorials/translations/portugu\303\252s/Parte 11 - Classifica\303\247\303\243o Segura Usando Aprendizagem Profunda.ipynb" "b/examples/tutorials/translations/portugu\303\252s/Parte 11 - Classifica\303\247\303\243o Segura Usando Aprendizagem Profunda.ipynb" index 9d0915cdf46..8830b00ecba 100644 --- "a/examples/tutorials/translations/portugu\303\252s/Parte 11 - Classifica\303\247\303\243o Segura Usando Aprendizagem Profunda.ipynb" +++ "b/examples/tutorials/translations/portugu\303\252s/Parte 11 - Classifica\303\247\303\243o Segura Usando Aprendizagem Profunda.ipynb" @@ -374,12 +374,8 @@ "\n", "Mais informações sobre este tópico virão em breve, incluindo camadas convolucionais para avaliar adequadamente o desempenho do PySyft em relação a outros casos de uso, bem como o treinamento criptografado privado de redes neurais, que é necessário quando uma organização recorre a dados sensíveis externos para treinar seu próprio modelo. Fique atento!\n", "\n", - "If you enjoyed this and would like to join the movement toward privacy preserving, decentralized ownership of AI and the AI supply chain (data), you can do so in the following ways! \n", - "\n", "Se você gostou disso e gostaria de participar do movimento em prol da preservação da privacidade, da propriedade descentralizada da IA e da cadeia de fornecimento de IA (dados), você pode fazer isso das seguintes maneiras! \n", "\n", - "Se você gostou disso e gostaria de se juntar ao movimento em direção à preservação da privacidade, propriedade descentralizada da IA e da cadeia de suprimentos da AI (dados), você pode fazê-lo das seguintes maneiras!\n", - "\n", "\n", "### Dê-nos uma estrela em nosso repo do PySyft no GitHub\n", "\n",