Sobre este codelab
1. Antes de começar
Neste codelab, você aprenderá a executar uma inferência de regressão a partir de um app iOS usando o TensorFlow Serving com REST e gRPC.
Prerequisites
- Conhecimento básico de desenvolvimento para iOS com Swift
- Conhecimento básico de machine learning com o TensorFlow, como treinamento e implantação
- Conhecimento básico do Colaboratory
- Noções básicas de terminais, Python e Docker
O que você aprenderá
- Como treinar um modelo de regressão com o TensorFlow
- Como criar um app iOS simples e fazer previsões com o modelo treinado pelo TensorFlow Serving (REST e gRPC).
- Como exibir o resultado na IU.
Pré-requisitos
- Acesso ao Colab
- A versão mais recente do Xcode
- CocoaPods
- Docker
- Bash
- Compilador de buffer de protocolo (somente necessário se você quiser gerar o stub do gRPC novamente)
- Plug-in gerador de código gRPC-swift (necessário somente se você quiser gerar o stub do gRPC por conta própria)
2. Começar a configuração
Para fazer o download do código para este codelab, faça o seguinte:
- Navegue até o repositório do GitHub deste codelab.
- Clique em Code > Download zip para fazer o download de todo o código para este codelab.
- Descompacte o arquivo ZIP baixado para descompactar uma pasta raiz
codelabs
com todos os recursos necessários.
Neste codelab, você só precisará dos arquivos no subdiretório TFServing/RegressioniOS
do repositório, que contém duas pastas:
- A pasta
starter
contém o código inicial que você usará como base para este codelab. - A pasta
finished
contém o código concluído do app de exemplo finalizado.
3. Fazer o download das dependências do projeto
Faça o download dos pods necessários
- Na pasta
starter/iOS
, execute:
pod install
O Cocoapods instalará todas as bibliotecas necessárias e gerará um novo arquivo regression.xcworkspace
.
4. Executar o app inicial
- Clique duas vezes no arquivo
regression.xcworkspace
para abrir o Xcode.
Executar e explorar o app
- Altere a segmentação por dispositivo para qualquer iPhone, como o iPhone 13.
- Clique em
'Run' e aguarde o Xcode compilar o projeto e iniciar o app inicial no Simulator.
A IU é bem direta. Há uma caixa de texto em que você pode digitar um número, que é enviado ao back-end do TensorFlow Serving com REST ou gRPC. O back-end realiza a regressão no valor de entrada e retorna o valor previsto para o app cliente, que exibe o resultado na IU novamente.
Se você inserir um número e clicar em Inferir, nada acontecerá porque o app ainda não poderá se comunicar com o back-end.
5. Treinar um modelo de regressão simples com o TensorFlow
A regressão é uma das tarefas mais comuns. O objetivo é prever uma única quantidade contínua com base na entrada. Por exemplo, com base na previsão do tempo para hoje, faça a previsão da temperatura mais alta amanhã.
Treinar um modelo de regressão
- Abra este link no navegador.
O Colab carrega o notebook Python.
- No notebook Python, importe as bibliotecas
TensorFlow
eNumPy
e crie seis pares de dados de treinamento comxs
como entrada eys
como rótulos.
Se você plotar esses pontos de dados em um gráfico, eles serão posicionados em uma linha reta porque são gerados pela equação y = 2x -1.
- Use a API Keras para criar uma rede neural de duas camadas simples e prever o valor de
y
com base na entrada dex
. Depois, compile e ajuste o 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]))
O treinamento do modelo pode levar alguns segundos, e o valor previsto para a entrada 10
é 18.999996
, o que é uma boa previsão, já que a verdade é 2 * 10 -1 = 19.
- Exporte o 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}
- Compacte o SavedModel exportado em um único arquivo
regression.zip
:
!zip -r regression.zip ./regression
- Clique em Runtime > Run all no menu de navegação para executar o notebook e depois esperar a execução ser concluída.
- Clique em
Arquivos e faça o download do
regression.zip
.
6. Implantar um modelo de regressão com o TensorFlow Serving
- Para implantar o modelo com o TensorFlow Serving, descompacte o arquivo
regression.zip
com uma ferramenta de descompactação, como o 7-Zip.
A estrutura de pasta será semelhante a esta imagem:
Você pode se referir à pasta regression
como a pasta SavedModel
. 123
é um exemplo de número da versão. Se quiser, você pode escolher outro número.
Iniciar o TensorFlow Serving
- No seu terminal, inicie o TensorFlow Serving com o Docker, mas substitua o marcador
PATH/TO/SAVEDMODEL
pelo caminho absoluto da pastaregression
no seu computador.
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
Primeiro, o Docker faz o download automático da imagem do TensorFlow Serving em um minuto. Depois disso, o TensorFlow Serving será iniciado. O registro será semelhante a este snippet 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. Conectar o app para iOS ao TensorFlow Serving por meio do REST
O back-end está pronto. Assim, você pode enviar solicitações de cliente ao TensorFlow Serving para fazer previsões. Há duas maneiras de enviar solicitações ao TensorFlow Serving:
- REST
- gRPC
Enviar solicitações e receber respostas com REST
Há três etapas simples:
- Crie a solicitação REST.
- Envie a solicitação REST para o TensorFlow Serving.
- Extraia o resultado previsto da resposta REST e renderize a IU.
Você realiza essas etapas no arquivo iOS/regression/ViewController.swift
.
Criar a solicitação REST
- No momento, a função
doInference()
não envia a solicitação REST para o TensorFlow Serving. Você precisa implementar essa ramificação de REST para criar uma solicitação REST:
if (connectionMode[picker.selectedRow(inComponent: 0)] == "REST") {
print("Using REST")
// TODO: Add code to send a REST request to TensorFlow Serving.
}
O TensorFlow Serving espera uma solicitação POST que contenha um valor único. Portanto, você precisa incorporar o valor de entrada em um JSON, que é o payload da solicitação.
- Adicione este código à ramificação 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
Enviar a solicitação REST para o TensorFlow Serving
- Adicione este código imediatamente após o código na ramificação 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()
Processar a resposta REST do TensorFlow Serving
- Adicione este código ao snippet de código anterior imediatamente após o comentário
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])
}
Agora, a função de pós-processamento extrai os valores previstos da resposta e exibe o resultado na IU.
Executar
- Clique em
Run e aguarde o Xcode iniciar o app no Simulator.
- Insira um número na caixa de texto e clique em Inferir.
Agora você verá um valor previsto na IU.
8. Conectar o app para iOS ao TensorFlow Serving por meio do gRPC
Além do REST, o TensorFlow Serving também é compatível com o gRPC.
O gRPC é um framework de chamada de procedimento remoto (RPC) moderno, de código aberto e de alta performance que pode ser executado em qualquer ambiente. Ele pode conectar serviços de forma eficiente em data centers e com compatibilidade conectável para balanceamento de carga, rastreamento, verificação de integridade e autenticação. Observamos que o gRPC tem uma performance melhor do que o REST na prática.
Enviar solicitações e receber respostas com o gRPC
Há quatro etapas simples:
- Opcional: gerar o código stub do cliente gRPC
- Criar a solicitação gRPC
- Enviar a solicitação gRPC para o TensorFlow Serving
- Extrair o resultado previsto da resposta gRPC e renderizar a IU
Você realiza essas etapas no arquivo iOS/regression/ViewController.swift
.
Opcional: gerar o código stub do cliente gRPC
Para usar o gRPC com o TensorFlow Serving, é necessário seguir o fluxo de trabalho do gRPC. Caso queira saber mais, consulte a documentação do gRPC.
O TensorFlow Serving e o TensorFlow definem os arquivos .proto
automaticamente. No TensorFlow e no TensorFlow Serving 2.8, os seguintes arquivos .proto
são necessários:
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 gerar o código de stub do cliente gRPC:
- No terminal, navegue até a pasta
starter/src/proto/
e gere o stub:
bash generate_grpc_stub_swift.sh
Vários arquivos .swift
são gerados na pasta starter/src/proto/generated/import
.
- Se eles ainda não foram copiados para o projeto, arraste todos os arquivos
.swift
gerados para o projeto no Xcode.
Criar a solicitação gRPC
Semelhante à solicitação REST, você cria a solicitação gRPC na ramificação gRPC.
if (connectionMode[picker.selectedRow(inComponent: 0)] == "REST") {
}
else {
print("Using gRPC")
// TODO: add code to send a gRPC request to TF Serving
}
- Para criar a solicitação gRPC, adicione este código à ramificação 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)))
Enviar a solicitação gRPC para o TensorFlow Serving
- Adicione este código à ramificação do gRPC imediatamente após o código no snippet de código anterior:
// Send the gRPC request.
let call = stub.predict(request, callOptions: callOptions)
Processar a resposta gRPC do TensorFlow Serving
- Adicione este código imediatamente após o no snippet 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)")
}
Agora, a função de pós-processamento extrai os valores previstos da resposta e exibe o resultado na IU.
Executar
- Clique em
Run no menu de navegação e aguarde o Xcode iniciar o app no Simulator.
- Insira um número na caixa de texto e clique em Inferir.
Agora você verá um valor previsto na IU.
9. Parabéns
Você usou o TensorFlow Serving para adicionar recursos de regressão ao seu app.