1. Прежде чем начать
В этой лаборатории кода вы узнаете, как выполнить вывод о классификации текста из приложения Flutter с помощью TensorFlow Serving через REST и gRPC.
Предпосылки
- Базовые знания разработки Flutter с Dart
- Базовые знания о машинном обучении с TensorFlow, такие как обучение или развертывание
- Базовые знания терминалов и Docker
- Обучение модели обнаружения спама в комментариях с помощью кодовой лаборатории TensorFlow Lite Model Maker
Что вы узнаете
- Как создать простое приложение Flutter и классифицировать тексты с помощью TensorFlow Serving (REST и gRPC).
- Как отобразить результаты в пользовательском интерфейсе.
Что вам понадобится
- Флаттер SDK
- Настройка Android или iOS для Flutter
- Настройка Visual Studio Code (VS Code) для Flutter и Dart
- Докер
- Баш
- Компилятор буфера протокола и подключаемый модуль gRPC Dart для компилятора протокола (необходимы только в том случае, если вы хотите повторно сгенерировать заглушку gRPC самостоятельно)
2. Настройте среду разработки Flutter
Для разработки Flutter вам потребуются две части программного обеспечения для выполнения этой лабораторной работы — Flutter SDK и редактор .
Вы можете запустить кодовую лабораторию, используя любое из этих устройств:
- Симулятор iOS (требуется установка инструментов Xcode).
- Эмулятор Android (требуется установка в Android Studio).
- Браузер (для отладки требуется Chrome).
- Как настольное приложение для Windows , Linux или macOS . Вы должны разрабатывать на той платформе, на которой планируете развертывание. Итак, если вы хотите разработать настольное приложение для Windows, вы должны разрабатывать в Windows, чтобы получить доступ к соответствующей цепочке сборки. Существуют требования к операционной системе, которые подробно описаны на docs.flutter.dev/desktop .
3. Настройте
Чтобы скачать код для этой кодлабы:
- Перейдите в репозиторий GitHub для этой лаборатории кода.
- Нажмите « Код» > «Загрузить zip» , чтобы загрузить весь код для этой лаборатории кода.
- Разархивируйте загруженный zip-файл, чтобы распаковать
codelabs-main
со всеми необходимыми ресурсами.
Для этой лаборатории кода вам нужны только файлы в tfserving-flutter/codelab2
в репозитории, который содержит две папки:
-
starter
папка содержит начальный код, на основе которого вы строите эту лабораторию кода. -
finished
папка содержит завершенный код для готового примера приложения.
4. Загрузите зависимости для проекта
- В VS Code нажмите « Файл» > «Открыть папку» , а затем выберите
starter
папку из загруженного ранее исходного кода. - Если появится диалоговое окно с предложением загрузить необходимые пакеты для начального приложения, щелкните Получить пакеты .
- Если вы не видите это диалоговое окно, откройте терминал и запустите команду
flutter pub get
вstarter
папке.
5. Запустите стартовое приложение
- В VS Code убедитесь, что эмулятор Android или iOS Simulator правильно настроены и отображаются в строке состояния.
Например, вот что вы видите, когда используете Pixel 5 с эмулятором Android:
Вот что вы видите, когда используете iPhone 13 с симулятором iOS:
- Нажмите Начать отладку .
Запустите и исследуйте приложение
Приложение должно запуститься на эмуляторе Android или симуляторе iOS. Пользовательский интерфейс довольно прост. Есть текстовое поле, которое позволяет пользователю вводить текст. Пользователь может выбрать, отправлять ли данные на серверную часть с помощью REST или gRPC. Серверная часть использует модель TensorFlow для классификации текста на предварительно обработанном входе и возвращает результат классификации клиентскому приложению, которое, в свою очередь, обновляет пользовательский интерфейс.
Если вы нажмете Classify , ничего не произойдет, потому что он еще не может взаимодействовать с серверной частью.
6. Разверните модель классификации текста с помощью TensorFlow Serving.
Классификация текста — очень распространенная задача машинного обучения, которая классифицирует тексты по предопределенным категориям. В этой кодовой лаборатории вы развертываете предварительно обученную модель из кодовой лаборатории Обучение модели обнаружения спама в комментариях с помощью TensorFlow Lite Model Maker с TensorFlow Serving и вызываете серверную часть из своего внешнего интерфейса Flutter, чтобы классифицировать входной текст как спам или не спам .
Запустить обслуживание TensorFlow
- В терминале запустите TensorFlow Serving с Docker, но замените заполнитель
PATH/TO/SAVEDMODEL
на абсолютный путь к папкеmm_spam_savedmodel
на вашем компьютере.
docker pull tensorflow/serving docker run -it --rm -p 8500:8500 -p 8501:8501 -v "PATH/TO/SAVEDMODEL:/models/spam-detection" -e MODEL_NAME=spam-detection tensorflow/serving
Docker сначала автоматически загружает образ TensorFlow Serving, что занимает минуту. После этого должен запуститься TensorFlow Serving. Журнал должен выглядеть как этот фрагмент кода:
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: spam-detection 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. Токенизировать входное предложение
Теперь серверная часть готова, поэтому вы почти готовы отправлять клиентские запросы в TensorFlow Serving, но сначала вам нужно разметить входное предложение. Если вы проверите входной тензор модели, вы увидите, что он ожидает список из 20 целых чисел вместо необработанных строк. Токенизация — это когда вы сопоставляете отдельные слова, которые вы вводите в приложении, со списком целых чисел на основе словаря, прежде чем отправлять их на серверную часть для классификации. Например, если вы введете buy book online to learn more
, процесс токенизации сопоставит его с [32, 79, 183, 10, 224, 631, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
. Конкретные числа могут варьироваться в зависимости от словаря.
- В файле
lib/main.dart
добавьте этот код к методуpredict()
для создания словаря_vocabMap
.
// Build _vocabMap if empty.
if (_vocabMap.isEmpty) {
final vocabFileString = await rootBundle.loadString(vocabFile);
final lines = vocabFileString.split('\n');
for (final l in lines) {
if (l != "") {
var wordAndIndex = l.split(' ');
(_vocabMap)[wordAndIndex[0]] = int.parse(wordAndIndex[1]);
}
}
}
- Сразу после предыдущего фрагмента кода добавьте этот код для реализации токенизации:
// Tokenize the input sentence.
final inputWords = _inputSentenceController.text
.toLowerCase()
.replaceAll(RegExp('[^a-z ]'), '')
.split(' ');
// Initialize with padding token.
_tokenIndices = List.filled(maxSentenceLength, 0);
var i = 0;
for (final w in inputWords) {
if ((_vocabMap).containsKey(w)) {
_tokenIndices[i] = (_vocabMap)[w]!;
i++;
}
// Truncate the string if longer than maxSentenceLength.
if (i >= maxSentenceLength - 1) {
break;
}
}
Этот код преобразует строку предложения в нижний регистр, удаляет неалфавитные символы и сопоставляет слова с 20 целочисленными индексами на основе словарной таблицы.
8. Подключите приложение Flutter к TensorFlow Serving через REST.
Есть два способа отправки запросов в TensorFlow Serving:
- ОТДЫХАТЬ
- gRPC
Отправляйте запросы и получайте ответы через REST
Есть три простых шага для отправки запросов и получения ответов через REST:
- Создайте REST-запрос.
- Отправьте запрос REST в TensorFlow Serving.
- Извлеките прогнозируемый результат из ответа REST и визуализируйте пользовательский интерфейс.
Вы выполняете эти шаги в файле main.dart
.
Создайте и отправьте запрос REST в TensorFlow Serving.
- Прямо сейчас функция
predict()
не отправляет запрос REST в TensorFlow Serving. Вам необходимо реализовать ветку REST для создания запроса REST:
if (_connectionMode == ConnectionModeType.rest) {
// TODO: Create and send the REST request.
}
- Добавьте этот код в ветку REST:
//Create the REST request.
final response = await http.post(
Uri.parse('http://' +
_server +
':' +
restPort.toString() +
'/v1/models/' +
modelName +
':predict'),
body: jsonEncode(<String, List<List<int>>>{
'instances': [_tokenIndices],
}),
);
Обработка ответа REST от TensorFlow Serving
- Добавьте этот код сразу после предыдущего фрагмента кода для обработки ответа REST:
// Process the REST response.
if (response.statusCode == 200) {
Map<String, dynamic> result = jsonDecode(response.body);
if (result['predictions']![0][1] >= classificationThreshold) {
return 'This sentence is spam. Spam score is ' +
result['predictions']![0][1].toString();
}
return 'This sentence is not spam. Spam score is ' +
result['predictions']![0][1].toString();
} else {
throw Exception('Error response');
}
Код постобработки извлекает вероятность того, что входное предложение является спам-сообщением, из ответа и отображает результат классификации в пользовательском интерфейсе.
Запустить его
- Нажмите Запустите отладку и дождитесь загрузки приложения.
- Введите текст, а затем выберите REST > Classify .
9. Подключите приложение Flutter к TensorFlow Serving через gRPC.
Помимо REST, TensorFlow Serving также поддерживает gRPC .
gRPC — это современная высокопроизводительная платформа удаленного вызова процедур (RPC) с открытым исходным кодом, которая может работать в любой среде. Он может эффективно подключать службы в центрах обработки данных и между ними с подключаемой поддержкой балансировки нагрузки, трассировки, проверки работоспособности и аутентификации. Было замечено, что на практике gRPC более эффективен, чем REST.
Отправляйте запросы и получайте ответы с помощью gRPC
Есть четыре простых шага для отправки запросов и получения ответов с помощью gRPC:
- Необязательно: сгенерируйте код-заглушку клиента gRPC.
- Создайте запрос gRPC.
- Отправьте запрос gRPC в TensorFlow Serving.
- Извлеките прогнозируемый результат из ответа gRPC и визуализируйте пользовательский интерфейс.
Вы выполняете эти шаги в файле main.dart
.
Необязательно: сгенерируйте код-заглушку клиента gRPC.
Чтобы использовать gRPC с TensorFlow Serving, вам необходимо следовать рабочему процессу gRPC. Чтобы узнать больше о деталях, см. документацию по gRPC .
TensorFlow Serving и TensorFlow определяют для вас файлы .proto
. Начиная с TensorFlow и TensorFlow Serving 2.8, необходимы эти файлы .proto
:
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
google/protobuf/any.proto
google/protobuf/wrappers.proto
- В терминале перейдите в папку
starter/lib/proto/
и сгенерируйте заглушку:
bash generate_grpc_stub_dart.sh
Создайте запрос gRPC
Подобно запросу REST, вы создаете запрос gRPC в ветке gRPC.
if (_connectionMode == ConnectionModeType.rest) {
} else {
// TODO: Create and send the gRPC request.
}
- Добавьте этот код, чтобы создать запрос gRPC:
//Create the gRPC request.
final channel = ClientChannel(_server,
port: grpcPort,
options:
const ChannelOptions(credentials: ChannelCredentials.insecure()));
_stub = PredictionServiceClient(channel,
options: CallOptions(timeout: const Duration(seconds: 10)));
ModelSpec modelSpec = ModelSpec(
name: 'spam-detection',
signatureName: 'serving_default',
);
TensorShapeProto_Dim batchDim = TensorShapeProto_Dim(size: Int64(1));
TensorShapeProto_Dim inputDim =
TensorShapeProto_Dim(size: Int64(maxSentenceLength));
TensorShapeProto inputTensorShape =
TensorShapeProto(dim: [batchDim, inputDim]);
TensorProto inputTensor = TensorProto(
dtype: DataType.DT_INT32,
tensorShape: inputTensorShape,
intVal: _tokenIndices);
// If you train your own model, update the input and output tensor names.
const inputTensorName = 'input_3';
const outputTensorName = 'dense_5';
PredictRequest request = PredictRequest(
modelSpec: modelSpec, inputs: {inputTensorName: inputTensor});
Примечание. Имена входных и выходных тензоров могут отличаться от модели к модели, даже если архитектуры моделей одинаковы. Обязательно обновите их, если вы обучаете свою собственную модель.
Отправьте запрос gRPC в TensorFlow Serving.
- Добавьте этот код после предыдущего фрагмента кода, чтобы отправить запрос gRPC в TensorFlow Serving:
// Send the gRPC request.
PredictResponse response = await _stub.predict(request);
Обработка ответа gRPC от TensorFlow Serving
- Добавьте этот код после предыдущего фрагмента кода, чтобы реализовать функции обратного вызова для обработки ответа:
// Process the response.
if (response.outputs.containsKey(outputTensorName)) {
if (response.outputs[outputTensorName]!.floatVal[1] >
classificationThreshold) {
return 'This sentence is spam. Spam score is ' +
response.outputs[outputTensorName]!.floatVal[1].toString();
} else {
return 'This sentence is not spam. Spam score is ' +
response.outputs[outputTensorName]!.floatVal[1].toString();
}
} else {
throw Exception('Error response');
}
Теперь код постобработки извлекает результат классификации из ответа и отображает его в пользовательском интерфейсе.
Запустить его
- Нажмите Запустите отладку и дождитесь загрузки приложения.
- Введите текст, а затем выберите gRPC > Classify .
10. Поздравления
Вы использовали TensorFlow Serving, чтобы добавить в свое приложение возможности классификации текста!
В следующей лаборатории кода вы улучшите модель, чтобы можно было обнаруживать определенные спам-сообщения, которые не могут быть обнаружены текущим приложением.