Acerca de este codelab
1. Antes de comenzar
En este codelab, aprenderás a ejecutar una inferencia de regresión desde una app para iOS con TensorFlow Serving con REST y gRPC.
Requisitos previos
- Conocimientos básicos del desarrollo de iOS con Swift
- Conocimientos básicos del aprendizaje automático con TensorFlow, como la implementación y el entrenamiento
- Conocimientos básicos de Colaboratory
- Conocimientos básicos de terminales, Python y Docker
Qué aprenderás
- Cómo entrenar un modelo de regresión con TensorFlow
- Cómo compilar una app para iOS simple y realizar predicciones con el modelo entrenado mediante TensorFlow Serving (REST y gRPC).
- Cómo mostrar el resultado en la IU
Requisitos
- Acceso a Colab
- La versión más reciente de Xcode
- CocoaPods
- Docker
- Bash
- Compilador de búfer de protocolo (solo es necesario si quieres volver a generar el stub de gRPC por tu cuenta)
- Complemento generador de código rápido de gRPC (solo es necesario si deseas generar el stub de gRPC por tu cuenta)
2. Prepárate
Para descargar el código de este codelab, haz lo siguiente:
- Navega al repositorio de GitHub de este codelab.
- Haz clic en Código > Descargar ZIP para descargar todo el código de este codelab.
- Descomprime el archivo ZIP descargado para descomprimir una carpeta raíz
codelabs
con todos los recursos que necesitas.
Para este codelab, solo necesitas los archivos del subdirectorio TFServing/RegressioniOS
en el repositorio, que contiene dos carpetas:
- La carpeta
starter
contiene el código de inicio en el que se basa este codelab. - La carpeta
finished
contiene el código completo de la app de muestra finalizada.
3. Descarga las dependencias del proyecto
Descargue los Pods necesarios
- En la carpeta
starter/iOS
, ejecuta lo siguiente:
pod install
CocoaPods instalará todas las bibliotecas necesarias y generará un nuevo archivo regression.xcworkspace
.
4. Ejecuta la app de inicio
- Haz doble clic en el archivo
regression.xcworkspace
para abrir Xcode.
Ejecuta y explora la app
- Cambiar la orientación por dispositivo a cualquier iPhone, como iPhone 13
- Haz clic en
"Run", espera a que Xcode compile el proyecto e inicie la app de inicio en el simulador.
La IU es bastante simple. Hay un cuadro de texto en el que puedes escribir un número, que se envía al backend de TensorFlow Serving con REST o gRPC. El backend realiza una regresión sobre el valor de entrada y muestra el valor predicho a la app cliente, que muestra el resultado en la IU nuevamente.
Si ingresas un número y haces clic en Inferir, no sucede nada porque la app aún no puede comunicarse con el backend.
5. Entrena un modelo de regresión simple con TensorFlow
La regresión es una de las tareas de AA más comunes. Su objetivo es predecir una sola cantidad continua según la entrada. Por ejemplo, según el clima de hoy, predice la temperatura más alta para mañana.
Entrena un modelo de regresión
- Abra este vínculo en su navegador.
Colab carga el notebook de Python.
- En el notebook de Python, importa las bibliotecas
TensorFlow
yNumPy
y, luego, crea seis pares de datos de entrenamiento conxs
como entrada yys
como etiquetas.
Si trazas estos datos en un gráfico, en realidad se ubican en una línea recta porque se generan a partir de la ecuación y = 2x -1.
- Usa la API de Keras para crear una red neuronal simple de dos capas a fin de predecir el valor
y
según la entradax
. Luego, compila y ajusta el modelo.
xs = np.array([-1.0, 0.0, 1.0, 2.0, 3.0, 4.0], dtype=float)
ys = np.array([-3.0, -1.0, 1.0, 3.0, 5.0, 7.0], dtype=float)
model = tf.keras.Sequential([
tf.keras.layers.Dense(units=10, input_shape=[1]),
tf.keras.layers.Dense(units=1),
])
model.compile(optimizer='sgd',
loss='mean_squared_error')
history = model.fit(xs, ys, epochs=500, verbose=0)
print("Finished training the model")
print(model.predict([10.0]))
El modelo tarda unos segundos en entrenarse y puedes ver que el valor previsto para la entrada 10
es 18.999996
, que es una predicción bastante buena, ya que la verdad fundamental es 2 * 10 -1 = 19.
- Exporta el modelo:
model_dir = './regression/'
version = 123
export_path = os.path.join(model_dir, str(version))
model.save(export_path, save_format="tf")
print('\nexport_path = {}'.format(export_path))
!ls -l {export_path}
- Comprime el modelo guardado exportado en un solo archivo
regression.zip
:
!zip -r regression.zip ./regression
- Haga clic en Entorno de ejecución > Ejecutar todo en el menú de navegación para ejecutar el notebook y, luego, espere a que se complete la ejecución.
- Haz clic en
Archivos y, luego, descarga el archivo
regression.zip
.
6. Implementa un modelo de regresión con TensorFlow Serving
- Para implementar el modelo con TensorFlow Serving, descomprime el archivo
regression.zip
descargado con una herramienta de descompresión, como 7-Zip.
La estructura de carpetas debe verse de la siguiente manera:
Puedes hacer referencia a la carpeta regression
como la carpeta SavedModel
. 123
es un número de versión de ejemplo. Si quieres, puedes elegir otro número.
Inicia TensorFlow Serving
- En tu terminal, inicia TensorFlow Serving con Docker, pero reemplaza el marcador de posición
PATH/TO/SAVEDMODEL
por la ruta de acceso absoluta de la carpetaregression
en tu computadora.
docker pull tensorflow/serving docker run -it --rm -p 8500:8500 -p 8501:8501 -v "PATH/TO/SAVEDMODEL:/models/regression" -e MODEL_NAME=regression tensorflow/serving
Docker descarga automáticamente la imagen de TensorFlow Serving primero, lo cual tarda un minuto. Luego, TensorFlow Serving debería comenzar. El registro debería verse como este fragmento de código:
2022-02-25 06:01:12.513231: I external/org_tensorflow/tensorflow/cc/saved_model/loader.cc:206] Restoring SavedModel bundle. 2022-02-25 06:01:12.585012: I external/org_tensorflow/tensorflow/core/platform/profile_utils/cpu_utils.cc:114] CPU Frequency: 3000000000 Hz 2022-02-25 06:01:13.395083: I external/org_tensorflow/tensorflow/cc/saved_model/loader.cc:190] Running initialization op on SavedModel bundle at path: /models/ssd_mobilenet_v2_2/123 2022-02-25 06:01:13.837562: I external/org_tensorflow/tensorflow/cc/saved_model/loader.cc:277] SavedModel load for tags { serve }; Status: success: OK. Took 1928700 microseconds. 2022-02-25 06:01:13.877848: I tensorflow_serving/servables/tensorflow/saved_model_warmup_util.cc:59] No warmup data file found at /models/ssd_mobilenet_v2_2/123/assets.extra/tf_serving_warmup_requests 2022-02-25 06:01:13.929844: I tensorflow_serving/core/loader_harness.cc:87] Successfully loaded servable version {name: regression version: 123} 2022-02-25 06:01:13.985848: I tensorflow_serving/model_servers/server_core.cc:486] Finished adding/updating models 2022-02-25 06:01:13.985987: I tensorflow_serving/model_servers/server.cc:367] Profiler service is enabled 2022-02-25 06:01:13.988994: I tensorflow_serving/model_servers/server.cc:393] Running gRPC ModelServer at 0.0.0.0:8500 ... [warn] getaddrinfo: address family for nodename not supported 2022-02-25 06:01:14.033872: I tensorflow_serving/model_servers/server.cc:414] Exporting HTTP/REST API at:localhost:8501 ... [evhttp_server.cc : 245] NET_LOG: Entering the event loop ...
7. Conecta la app para iOS con TensorFlow Serving mediante REST
El backend está listo, por lo que puedes enviar solicitudes de clientes a TensorFlow Serving para hacer predicciones. Hay dos maneras de enviar solicitudes a TensorFlow Serving:
- REST
- gRPC
Envía solicitudes y recibe respuestas con REST.
Existen tres pasos sencillos:
- Crea la solicitud REST.
- Envía la solicitud de REST a TensorFlow Serving.
- Extrae el resultado previsto de la respuesta de REST y procesa la IU.
Debes seguir estos pasos en el archivo iOS/regression/ViewController.swift
.
Crea la solicitud de REST
- En este momento, la función
doInference()
no envía la solicitud de REST a TensorFlow Serving. Debes implementar esta rama de REST para crear una solicitud de REST:
if (connectionMode[picker.selectedRow(inComponent: 0)] == "REST") {
print("Using REST")
// TODO: Add code to send a REST request to TensorFlow Serving.
}
TensorFlow Serving espera una solicitud POST que contiene un solo valor, por lo que debes incorporar el valor de entrada en un JSON, que es la carga útil de la solicitud.
- Agrega este código a la rama de REST:
//Create the REST request.
let json: [String: Any] = ["signature_name" : "serving_default", "instances" : [[value]]]
let jsonData = try? JSONSerialization.data(withJSONObject: json)
let url = URL(string: "http://localhost:8501/v1/models/regression:predict")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
// Insert JSON data into the request.
request.httpBody = jsonData
Envía la solicitud de REST a TensorFlow Serving
- Agrega este código inmediatamente después del código en la rama de REST:
// Send the REST request.
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data, error == nil else {
print(error?.localizedDescription ?? "No data")
return
}
// TODO: Add code to process the response.
}
task.resume()
Cómo procesar la respuesta de REST de TensorFlow Serving
- Agrega este código al fragmento de código anterior inmediatamente después del comentario
TODO: Add code to process the response.
:
// Process the REST response.
let results: RESTResults = try! JSONDecoder().decode(RESTResults.self, from: data)
DispatchQueue.main.async{
self.txtOutput.text = String(results.predictions[0][0])
}
Ahora, la función de procesamiento posterior extrae los valores previstos de la respuesta y muestra el resultado en la IU.
Ejecuta la app
- Haz clic en
"Run" y, luego, espera a que Xcode inicie la app en el simulador.
- Ingresa un número en el cuadro de texto y haz clic en Inferir.
Ahora verá un valor previsto en la IU.
8. Conecta la app para iOS con TensorFlow Serving a través de gRPC
Además de REST, TensorFlow Serving también es compatible con gRPC.
gRPC es un framework moderno de código abierto, de alto rendimiento y llamada de procedimiento remoto (RPC), que se puede ejecutar en cualquier entorno. Puede conectar servicios en centros de datos, y entre ellos, con compatibilidad conectable para balanceo de cargas, seguimiento, verificación de estado y autenticación. Se observó que gRPC tiene un mejor rendimiento que REST en la práctica.
Envía solicitudes y recibe respuestas con gRPC
Hay cuatro pasos sencillos:
- Genera el código de stub del cliente de gRPC (opcional).
- Crea la solicitud de gRPC.
- Envía la solicitud gRPC a TensorFlow Serving.
- Extrae el resultado previsto de la respuesta de gRPC y procesa la IU.
Debes seguir estos pasos en el archivo iOS/regression/ViewController.swift
.
Genera el código de stub del cliente de gRPC (opcional)
Para usar gRPC con TensorFlow Serving, debes seguir el flujo de trabajo de gRPC. Para obtener más información, consulta la documentación de gRPC.
TensorFlow Serving y TensorFlow definen los archivos .proto
por ti. A partir de TensorFlow y TensorFlow Serving 2.8, estos archivos .proto
son los necesarios:
tensorflow/core/example/example.proto
tensorflow/core/example/feature.proto
tensorflow/core/protobuf/struct.proto
tensorflow/core/protobuf/saved_object_graph.proto
tensorflow/core/protobuf/saver.proto
tensorflow/core/protobuf/trackable_object_graph.proto
tensorflow/core/protobuf/meta_graph.proto
tensorflow/core/framework/node_def.proto
tensorflow/core/framework/attr_value.proto
tensorflow/core/framework/function.proto
tensorflow/core/framework/types.proto
tensorflow/core/framework/tensor_shape.proto
tensorflow/core/framework/full_type.proto
tensorflow/core/framework/versions.proto
tensorflow/core/framework/op_def.proto
tensorflow/core/framework/graph.proto
tensorflow/core/framework/tensor.proto
tensorflow/core/framework/resource_handle.proto
tensorflow/core/framework/variable.proto
tensorflow_serving/apis/inference.proto
tensorflow_serving/apis/classification.proto
tensorflow_serving/apis/predict.proto
tensorflow_serving/apis/regression.proto
tensorflow_serving/apis/get_model_metadata.proto
tensorflow_serving/apis/input.proto
tensorflow_serving/apis/prediction_service.proto
tensorflow_serving/apis/model.proto
Para generar el código auxiliar de cliente de gRPC:
- En tu terminal, navega a la carpeta
starter/src/proto/
y, luego, genera el stub:
bash generate_grpc_stub_swift.sh
Se generará una serie de archivos .swift
en la carpeta starter/src/proto/generated/import
.
- Si todavía no se copian en tu proyecto, arrastra todos los archivos
.swift
generados hasta tu proyecto en Xcode.
Crea la solicitud de gRPC
Al igual que con la solicitud de REST, debes crear la solicitud de gRPC en la rama de gRPC.
if (connectionMode[picker.selectedRow(inComponent: 0)] == "REST") {
}
else {
print("Using gRPC")
// TODO: add code to send a gRPC request to TF Serving
}
- Para crear la solicitud de gRPC, agrega este código a la rama de gRPC:
//Create the gRPC request.
let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)
let channel = ClientConnection.insecure(group: group).connect(host: "localhost", port: 8500)
let stub = Tensorflow_Serving_PredictionServiceClient(channel: channel)
var modelSpec = Tensorflow_Serving_ModelSpec()
modelSpec.name = "regression"
modelSpec.signatureName = "serving_default"
// Prepare the input tensor.
var batchDim = Tensorflow_TensorShapeProto.Dim()
batchDim.size = 1
var inputDim = Tensorflow_TensorShapeProto.Dim()
inputDim.size = 1
var inputTensorShape = Tensorflow_TensorShapeProto()
inputTensorShape.dim = [batchDim, inputDim]
var inputTensor = Tensorflow_TensorProto()
inputTensor.dtype = Tensorflow_DataType.dtFloat
inputTensor.tensorShape = inputTensorShape
inputTensor.floatVal = [Float(value)]
var request = Tensorflow_Serving_PredictRequest()
request.modelSpec = modelSpec
request.inputs = ["dense_input" : inputTensor]
let callOptions = CallOptions(timeLimit: .timeout(.seconds(15)))
Envía la solicitud de gRPC a TensorFlow Serving
- Agrega este código a la rama de gRPC inmediatamente después del código en el fragmento de código anterior:
// Send the gRPC request.
let call = stub.predict(request, callOptions: callOptions)
Cómo procesar la respuesta de gRPC de TensorFlow Serving
- Agrega este código inmediatamente después del código del fragmento de código anterior:
// Process the response.
call.response.whenSuccess { response in
let result = response.outputs["dense_1"]?.floatVal[0]
DispatchQueue.main.async{
self.txtOutput.text = String(describing: result!)
}
}
call.response.whenFailure { error in
print("Call failed with error\n\(error)")
}
Ahora, la función de procesamiento posterior extrae los valores previstos de la respuesta y muestra el resultado en la IU.
Ejecuta la app
- Haz clic en
"Run" en el menú de navegación y espera a que Xcode inicie la app en el simulador.
- Ingresa un número en el cuadro de texto y haz clic en Inferir.
Ahora verá un valor previsto en la IU.
9. Felicitaciones
Usaste TensorFlow Serving para agregar capacidades de regresión a tu app.