Créer une application iOS pour prédire des valeurs

1. Avant de commencer

Dans cet atelier de programmation, vous allez apprendre à exécuter une inférence de régression à partir d'une application iOS à l'aide de TensorFlow Serving avec REST et gRPC.

Prérequis

  • Connaissances de base en développement iOS avec Swift
  • Des connaissances de base en machine learning avec TensorFlow, telles que l'entraînement et le déploiement
  • Connaissances de base de Colaboratory
  • Connaissances de base des terminaux, de Python et de Docker

Points abordés

  • Entraînement d'un modèle de régression avec TensorFlow.
  • Créer une application iOS simple et effectuer des prédictions à l'aide du modèle entraîné avec TensorFlow Serving (REST et gRPC)
  • Comment afficher le résultat dans l'UI

Prérequis

2. Configuration

Pour télécharger le code de cet atelier de programmation:

  1. Accédez au dépôt GitHub de cet atelier de programmation.
  2. Cliquez sur Code > Télécharger le fichier ZIP pour télécharger l'ensemble du code de cet atelier de programmation.

A72f2bb4caa9a96.png

  1. Décompressez le fichier ZIP téléchargé pour décompresser un dossier racine codelabs contenant toutes les ressources dont vous avez besoin.

Pour cet atelier de programmation, vous n'avez besoin que des fichiers du sous-répertoire TFServing/RegressioniOS dans le dépôt, qui contient deux dossiers:

  • Le dossier starter contient le code de démarrage sur lequel s'appuie cet atelier de programmation.
  • Le dossier finished contient le code final de l'exemple d'application.

3. Télécharger les dépendances pour le projet

Télécharger les pods requis

  • Dans le dossier starter/iOS, exécutez la commande suivante:
pod install

CocoaPods installera toutes les bibliothèques nécessaires et générera un fichier regression.xcworkspace.

4. Exécuter l'application de démarrage

  • Double-cliquez sur le fichier regression.xcworkspace pour ouvrir Xcode.

Exécuter et explorer l'application

  1. Définissez la cible de l'appareil sur n'importe quel iPhone, par exemple iPhone 13.

A57198A4f21f970.png

  1. Cliquez sur Cacc15c5638260ed.png 'Run' (Exécuter), puis attendez que Xcode compile le projet et démarre l'application de départ du simulateur.

L'interface utilisateur est assez simple. Il existe une zone de texte dans laquelle vous pouvez saisir un nombre, qui est envoyé au backend de TensorFlow Serving avec REST ou gRPC. Le backend effectue une régression sur la valeur d'entrée et renvoie la valeur prédite à l'application cliente, qui affiche à nouveau le résultat dans l'interface utilisateur.

D2976072474ce0b1.png

Si vous saisissez un nombre et cliquez sur Déduire, rien ne se produit, car l'application ne peut pas encore communiquer avec le backend.

5. Entraîner un modèle de régression simple avec TensorFlow

La régression est l'une des tâches de ML les plus courantes. Son objectif est de prédire une quantité continue unique en fonction de l'entrée. Par exemple, en fonction de la météo, annoncez la température la plus élevée demain.

Entraîner un modèle de régression

  1. Ouvrez ce lien dans votre navigateur.

Colab charge le notebook Python.

  1. Dans le notebook Python, importez la commande suivante :TensorFlow etNumPy Ensuite, créez six paires de données d'entraînement avecxs en entrée etys en tant que libellés.

Si vous représentez ces points de données sur un graphique, ils se trouvent en fait sur une ligne droite, car ils sont générés à partir de l'équation y = 2x -1.

56d05252cfc9df9d.png

  1. Utilisez l'API Keras pour créer un réseau de neurones à deux couches simple afin de prédire la valeur y en fonction de l'entrée x, puis compiler et ajuster le modèle.
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]))

L'entraînement du modèle prend quelques secondes. Vous pouvez voir que la valeur prédite pour l'entrée 10 est 18.999996, ce qui est une bonne prédiction, car la vérité terrain est 2 * 10 -1 = 19.

  1. Exporter le modèle:
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}
  1. Compressez le modèle SavedModel exporté dans un seul fichier regression.zip:
!zip -r regression.zip ./regression
  1. Dans le menu de navigation, cliquez sur Runtime > Run all (Exécuter > Tout exécuter) pour exécuter le notebook, puis attendez que l'exécution se termine.
  2. Cliquez sur C55600D42359f901.png Fichiers, puis téléchargez le fichier regression.zip.

bceda15d86571583.png

6. Déployer un modèle de régression avec TensorFlow Serving

  • Pour déployer le modèle avec TensorFlow Serving, décompressez le fichier regression.zip téléchargé avec un outil de décompression comme 7-Zip.

La structure de dossiers doit se présenter comme suit:

7faeb4f03af39646.png

Vous pouvez désigner le dossier regression comme le dossier SavedModel. 123 est un exemple de numéro de version. Si vous le souhaitez, vous pouvez en choisir un autre.

Lancer TensorFlow Serving

  • Dans votre terminal, démarrez TensorFlow Serving avec Docker, mais remplacez l'espace réservé PATH/TO/SAVEDMODEL par le chemin absolu du dossier regression sur votre ordinateur.
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 télécharge d'abord l'image TensorFlow Serving, ce qui prend une minute. Ensuite, le service TensorFlow Serving doit commencer. Le journal doit ressembler à l'extrait de code suivant:

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. Connecter l'application iOS à TensorFlow Serving par REST

Le backend est prêt. Vous pouvez donc envoyer des requêtes client à TensorFlow Serving pour effectuer des prédictions. Il existe deux façons d'envoyer des requêtes à TensorFlow Serving:

  • REST
  • gRPC

Envoyer des requêtes et recevoir des réponses avec REST

Il vous suffit de suivre ces trois étapes simples:

  1. Créez la requête REST.
  2. Envoyez la requête REST à TensorFlow Serving.
  3. Extrayez le résultat prédit de la réponse REST et affichez l'interface utilisateur.

Vous devez suivre ces étapes dans le fichier iOS/regression/ViewController.swift.

Créer la requête REST

  1. Pour le moment, la fonction doInference() n'envoie pas la requête REST à TensorFlow Serving. Vous devez implémenter cette branche REST pour créer une requête REST:
if (connectionMode[picker.selectedRow(inComponent: 0)] == "REST") {
    print("Using REST")
    // TODO: Add code to send a REST request to TensorFlow Serving.

}

TensorFlow Serving attend une requête POST contenant une seule valeur. Vous devez donc intégrer la valeur d'entrée dans un fichier JSON, qui est la charge utile de la requête.

  1. Ajoutez ce code à la branche 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

Envoyer la requête REST à TensorFlow Serving

  • Ajoutez ce code juste après le code de la branche 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()

Traitez la réponse REST à partir de TensorFlow Serving.

  • Ajoutez ce code à l'extrait de code précédent juste après le commentaire 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])
}

La fonction de post-traitement extrait les valeurs prédites de la réponse et affiche le résultat dans l'interface utilisateur.

Exécuter le code

  1. Cliquez sur Cacc15c5638260ed.png Run (Exécuter), puis attendez que Xcode lance l'application dans le simulateur.
  2. Saisissez un nombre dans la zone de texte, puis cliquez sur Décaler.

Une valeur prédite s'affiche dans l'UI.

df9bcb9aa21bb30e.png

8. Connecter l'application iOS à TensorFlow Serving via gRPC

Outre REST, TensorFlow Serving est également compatible avec gRPC.

B6F4449C2C850b0e.png

gRPC est un framework d'appel de procédure à distance (RPC) moderne et Open Source qui peut être exécuté dans n'importe quel environnement. Grâce à cette solution, les services peuvent être connectés efficacement aux services de centres de données, et ils sont compatibles avec l'équilibrage de charge, le traçage, la vérification de l'état et l'authentification. En pratique, gRPC a été plus performant que REST en pratique.

Envoyer des requêtes et recevoir des réponses avec gRPC

Il existe quatre étapes simples:

  1. Facultatif: Générez le code du bouchon pour le client gRPC.
  2. Créez la requête gRPC.
  3. Envoyez la requête gRPC à TensorFlow Serving.
  4. Extrayez le résultat prédit de la réponse gRPC, puis affichez l'interface utilisateur.

Vous devez suivre ces étapes dans le fichier iOS/regression/ViewController.swift.

Facultatif: Générer le code du bouchon pour le client gRPC

Pour utiliser gRPC avec TensorFlow Serving, vous devez suivre le workflow gRPC. Pour en savoir plus, consultez la documentation gRPC.

A9d0e5cb543467b4.png

TensorFlow Serving et TensorFlow définissent les fichiers .proto pour vous. À partir de TensorFlow et de TensorFlow Serving 2.8, ces fichiers .proto sont nécessaires:

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

Pour générer le code du bouchon, procédez comme suit:

  1. Dans votre terminal, accédez au dossier starter/src/proto/, puis générez la simulation:
bash generate_grpc_stub_swift.sh

Un certain nombre de fichiers .swift sont générés dans le dossier starter/src/proto/generated/import.

  1. S'ils ne sont pas encore copiés dans votre projet, faites glisser tous les fichiers .swift générés dans votre projet dans Xcode.

9e65705cf6be7aac.png

Créer la requête gRPC

Comme pour la requête REST, vous créez la requête gRPC dans la branche gRPC.

if (connectionMode[picker.selectedRow(inComponent: 0)] == "REST") {

}
else {
    print("Using gRPC")
    // TODO: add code to send a gRPC request to TF Serving

}
  • Pour créer la requête gRPC, ajoutez ce code à la branche 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)))

Envoyer la requête gRPC à TensorFlow Serving

  • Ajoutez ce code à la branche gRPC immédiatement après le code de l'extrait de code précédent:
// Send the gRPC request.
let call = stub.predict(request, callOptions: callOptions)

Traiter la réponse gRPC de TensorFlow Serving

  • Ajoutez ce code juste après le code dans l'extrait de code précédent:
// 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)")
}

La fonction de post-traitement extrait les valeurs prédites de la réponse et affiche le résultat dans l'interface utilisateur.

Exécuter le code

  1. Dans le menu de navigation, cliquez sur Cacc15c5638260ed.png Run (Exécuter), puis attendez que Xcode lance l'application dans le simulateur.
  2. Saisissez un nombre dans la zone de texte, puis cliquez sur Décaler.

Une valeur prédite s'affiche dans l'UI.

9. Félicitations

Vous avez utilisé TensorFlow Serving pour ajouter des fonctionnalités de régression à votre application.

Learn more