Paso 2: Proveyendo modelos de manera segura con Syft Keras

Ahora que has entrenado un modelo con Keras, estás listo para proveer predicciones privadas. Podemos hacer eso usando Syft Keras.

Para asegurar y proveer este modelo, vamos a necesitar tres TFEWorkers (servidores). La razón es que TF Encrypted utiliza una técnica de encriptación llamada Computación Multi-Parte (CMP, o MPC en inglés). La idea es dividir los pesos del modelo y los datos de entrada en "acciones", para luego enviar una acción de cada valor a los servidores diferentes. La propiedad clave es que si observas a la acción de un servidor, no se revela nada sobre el valor original (sea de los datos de entrada o los pesos del modelo).

Vamos a definir un modelo Syft Keras como hicimos en el notebook anterior. Sin embargo, hay un truco: antes de instanciar este modelo, correremos hook = sy.KerasHook(tf.keras). Esto agregará tres nuevos métodos importantes a la clase de Keras Sequential:

  • share: Esto asegurará tu modelo usando 'secret sharing' (convirtiendo el modelo en un "secreto" para luego ser dividido); por defecto, usará el protocolo SecureNN de TF Encrupted para compartir el secreto entre los tres TFEWorkers. Esto agregará la capacidad de proveer predicciones en datos encriptados

  • serve: Esta función empezará una cola de provisiones, donde los TFEWorkers pueden aceptar pedidos de predicciones. Estas predicciones vendrán de un modelo que está protegido del exterior.

  • shutdown_workers: Una vez hayas terminado de proveer predicciones, puedes apagar tu modelo usando esta función. Te redirigirá a apagar los procesos del servidor manualmente si has optado por manejar cada trabajador manualmente.

Si quieres aprender más sobre CMP, visita este excelente blog (en inglés)


In [ ]:
import numpy as np
import tensorflow as tf
from tensorflow.keras import Sequential
from tensorflow.keras.layers import AveragePooling2D, Conv2D, Dense, Activation, Flatten, ReLU, Activation

import syft as sy
hook = sy.KerasHook(tf.keras)

Modelo

Como puedes ver, definimos casi el mismo modelo que antes, excepto que esta vez proveemos un batch_input_shape (tamaño del batch de los datos de entrada). Esto permite a TF Encrypted optimizar las computaciones seguras a través de tamaños predeterminados de tensores. Para este demo con MNIST, enviaremos datos de entrada con un tamaño de (1, 28, 28, 1). También obtendremos el logit en vez del resultado de softmax porque esta operación es complicada de hacer usando CMP, y no la necesitamos para responder a los pedidos de predicciones.


In [ ]:
num_classes = 10
input_shape = (1, 28, 28, 1)

In [ ]:
model = Sequential()

model.add(Conv2D(10, (3, 3), batch_input_shape=input_shape))
model.add(AveragePooling2D((2, 2)))
model.add(Activation('relu'))
model.add(Conv2D(32, (3, 3)))
model.add(AveragePooling2D((2, 2)))
model.add(Activation('relu'))
model.add(Conv2D(64, (3, 3)))
model.add(AveragePooling2D((2, 2)))
model.add(Activation('relu'))
model.add(Flatten())
model.add(Dense(num_classes, name="logit"))

Cargando pesos pre-entrenados

Con load_weights puedes cargar los pesos que has guardado anteriormente después de entrenar tu modelo.


In [ ]:
pre_trained_weights = 'short-conv-mnist.h5'
model.load_weights(pre_trained_weights)

Usando los trabajadores

Ahora crearemos TFEWorkers (alice, bob y carol) requeridos por TF Encrypted para calcular predicciones privadas. Por cada TFEWorker, necesitas especificar un host. Luego, combinamos estos trabajadores en un clúster.

Estos trabajadores corren en un servidor de TensorFlow, el cual puedes manejar manualmente (AUTO = False) o pedir a los trabajadores que lo manejen por ti (AUTO = True). Si escoges manejarlos manualmente, tendrás que ejecutar un comando en el terminal en cada dispositivo de host por cada trabajador después de llamar cluster.start() abajo. Si es que todos los trabajadores están bajo el mismo host en un solo dispositivo (e.g localhost), puedes escoger que Syft maneje el servidor Tensorflow de los trabajadores.


In [ ]:
AUTO = False

alice = sy.TFEWorker(host='localhost:4000', auto_managed=AUTO)
bob = sy.TFEWorker(host='localhost:4001', auto_managed=AUTO)
carol = sy.TFEWorker(host='localhost:4002', auto_managed=AUTO)

cluster = sy.TFECluster(alice, bob, carol)
cluster.start()

Asegurando el modelo, calculando los pesos

Gracias a sy.KerasHook(tf.keras), puedes llamar al método share para transformar tu modelo en un modelo de TF Encrypted.

Si has decidido manejar los servidores manualmente en el código de arriba, entonces este paso no completará hasta que todos los servidores hayan empezado a correr. Puede que tu firewall te pida permiso para que Python acepte la conexión.


In [ ]:
model.share(cluster)

Proveyendo el modelo

Perfecto! Ahora al llamar model.serve, tu modelo está listo para proveer predicciones privadas. Puedes ajustar num_requests para delimitar el número de predicciones que el modelo podrá proveer; Si no está especificado, entonces el modelo proveerá predicciones hasta que sea interrumpido.


In [ ]:
model.serve(num_requests=3)

Estamos listos para proseguir al notebook Parte 13c para pedir predicciones privadas.

Limpieza!

Una vez hayas topado el límite de pedidos, el modelo no podrá estar disponible para proveer predicciones, pero aun mantendrá el secreto entre los tres trabajadores. Puedes apagar a los trabajadores ejecutando el código siguiente.

Felicidades por terminar la parte 13b: Clasificación Segura con Syft Keras y TFE!


In [ ]:
model.stop()
cluster.stop()

if not AUTO:
    process_ids = !ps aux | grep '[p]ython -m tf_encrypted.player --config' | awk '{print $2}'
    for process_id in process_ids:
        !kill {process_id}
        print("Process ID {id} has been killed.".format(id=process_id))

In [ ]: