En la sección previa, aprendimos sobre punteros de tensores (PointerTensors), que crean la infraestructura subyacente que necesitamos para preservar la privacidad con aprendizaje profundo. En esta sección, veremos cómo utilizar estas herramientas básicas para implementar nuestro primer algoritmo de aprendizaje profundo con preservación de privacidad, el aprendizaje federado.
Autores:
Traductores:
Es una manera simple y poderosa para entrenar modelos de aprendizaje profundo. Si piensas sobre datos de entrenamiento, siempre son el resultado de algún tipo de proceso de recolección. La gente (por medio de dispositivos) generan datos al registrar eventos del mundo real. Normalmente, estos datos son agregados a una ubicación central y única de tal manera que uno pueda entrenar un modelo de aprendizaje de máquina. El aprendizaje federado le da la vuelta a esto.
En lugar de llevar los datos de entrenamiento al modelo (o servidor central), uno lleva el modelo a los datos de entraniento (donde sea que que esté).
La idea es que esto la única copia permanente de los datos pertenece a quien los está creando, y así mantiene el control de su acceso. Cool, no?
Comencemos entrenando un modelo de juguete con el método centralizado. Este modelo es de lo más simple. Primero necesitamos:
Nota: Si esta API no te es familiar visita fast.ai y toma el curso antes de continuar con este tutorial.
In [ ]:
import torch
from torch import nn
from torch import optim
In [ ]:
# Un conjunto de datos de juguete
data = torch.tensor([[0,0],[0,1],[1,0],[1,1.]], requires_grad=True)
target = torch.tensor([[0],[0],[1],[1.]], requires_grad=True)
# Un modelo de juguete.
model = nn.Linear(2,1)
def train():
# Lógica de entrenamiento
opt = optim.SGD(params=model.parameters(),lr=0.1)
for iter in range(20):
# 1) borra los gradientes previos (si existen)
opt.zero_grad()
# 2) haz una predicción
pred = model(data)
# 3) calcula cuál fue la pérdida
loss = ((pred - target)**2).sum()
# 4) encuentra los pesos que causaron la pérdida
loss.backward()
# 5) cambia esos pesos
opt.step()
# 6) imprime nuesto progreso
print(loss.data)
In [ ]:
train()
¡Y ahí lo tienes! Hemos entrenado un modelo básico con un método convencional. Todos nuestros datos están agregados en nuestra máquina local y podemos usarlos para hacerle actualizaciones al modelo. El aprendizaje federado, sin embargo, no funciona así. Así que modifiquemos este ejemplo para hacerlo con aprendizaje federado.
Lo que necesitamos:
Actualizar la lógica de entrenamiento para que haga aprendizaje federado.
Nuevos Pasos de Entrenamiento:
In [ ]:
import syft as sy
hook = sy.TorchHook(torch)
In [ ]:
# Crear un par de trabajadores
bob = sy.VirtualWorker(hook, id="bob")
alice = sy.VirtualWorker(hook, id="alice")
In [ ]:
# Un conjunto de datos de juguete
data = torch.tensor([[0,0],[0,1],[1,0],[1,1.]], requires_grad=True)
target = torch.tensor([[0],[0],[1],[1.]], requires_grad=True)
# Hacer que los punteros entrenen los datos en
# cada trabajador mandando datos a bob y alice
data_bob = data[0:2]
target_bob = target[0:2]
data_alice = data[2:]
target_alice = target[2:]
# Inicializar un modelo de juguete
model = nn.Linear(2,1)
data_bob = data_bob.send(bob)
data_alice = data_alice.send(alice)
target_bob = target_bob.send(bob)
target_alice = target_alice.send(alice)
# Organizar los punteros en una lista
datasets = [(data_bob,target_bob),(data_alice,target_alice)]
opt = optim.SGD(params=model.parameters(),lr=0.1)
In [ ]:
def train():
# Lógica de entrenamiento
opt = optim.SGD(params=model.parameters(),lr=0.1)
for iter in range(10):
# NUEVO) Itera sobre el conjunto de datos de cada trabajador
for data,target in datasets:
# NUEVO) Manda el modelo a el trabajador correcto
model.send(data.location)
# 1) borra los gradientes previos (si existen)
opt.zero_grad()
# 2) haz una predicción
pred = model(data)
# 3) calcula cuál fue la pérdida
loss = ((pred - target)**2).sum()
# 4) encuentra los pesos que causaron la pérdida
loss.backward()
# 5) cambia esos pesos
opt.step()
# NUEVO recupera el modelo (con gradientes)
model.get()
# 6) imprime nuestro progreso
print(loss.get()) # NUEVO) Necesitamos llamar a .get()
# federated averaging
In [ ]:
train()
¡Y voilà! Ahora estamos entrenando un modelo de aprendizaje profundo muy simple utilizando aprendizaje federado. Mandamos el modelo a cada trabajador, generamos un nuevo gradiente, y luego recuperamos el gradiente en nuestro servidor local donde actualizamos nuestro modelo global. En ningún punto de este proceso vemos o requerimos acceso al conjunto de datos de entrenamiento subyacente. ¡Preservamos la privacidad de Bob y Alice!
Aunque este ejemplo es una buena introducción al aprendizaje federado, aún tiene algunos defectos importantes. Notablemente, cuando llamamos model.get()
y recibimos el modelo actualizado de Bob o Alice de hecho podemos aprender mucho sobre el conjunto de entrenamiento de Bob/Alice sólo con la información de sus gradientes. ¡En algunos casos, podemos restaurar el conjunto de entrenamiento a la perfección!
Así que, ¿qué podemos hacer? Bueno, la primera estrategia que utiliza la gente es promediar el gradiente sobre múltiples individuos antes de actulizarlo en el servidor central. Esta estrategia, sin embargo, requiere el uso de objetos PointerTensor más sofisticados. Entonces, en la siguiente sección nos tomaremos un tiempo para aprender un poco de la funcionalidad avanzada de los punteros y actualizaremos este ejemplo de aprendizaje federado.
¡Felicitaciones por completar esta parte del tutorial! Si te gustó y quieres unirte al movimiento para preservar la privacidad, propiedad descentralizada de IA y la cadena de suministro de IA (datos), puedes hacerlo de las ¡siguientes formas!
La forma más fácil de ayudar a nuestra comunidad es por darle estrellas a ¡los repositorios de Github! Esto ayuda a crear consciencia de las interesantes herramientas que estamos construyendo.
La mejor manera de mantenerte actualizado con los últimos avances es ¡unirte a la comunidad! Tú lo puedes hacer llenando el formulario en http://slack.openmined.org
La mejor manera de contribuir a nuestra comunidad es convertirte en un ¡contribuidor de código! En cualquier momento puedes ir al Github Issues de PySyft y filtrar por "Proyectos". Esto mostrará todos los tiquetes de nivel superior dando un resumen de los proyectos a los que ¡te puedes unir! Si no te quieres unir a un proyecto, pero quieres hacer un poco de código, también puedes mirar más mini-proyectos "de una persona" buscando por Github Issues con la etiqueta "good first issue".
Si no tienes tiempo para contribuir a nuestra base de código, pero quieres ofrecer tu ayuda, también puedes aportar a nuestro Open Collective". Todas las donaciones van a nuestro web hosting y otros gastos de nuestra comunidad como ¡hackathons y meetups!
In [ ]:
In [ ]: