Создайте приложение Flutter для классификации текстов

1. Прежде чем начать

В этой лаборатории кода вы узнаете, как выполнить вывод о классификации текста из приложения Flutter с помощью TensorFlow Serving через REST и gRPC.

Предпосылки

Что вы узнаете

  • Как создать простое приложение Flutter и классифицировать тексты с помощью TensorFlow Serving (REST и gRPC).
  • Как отобразить результаты в пользовательском интерфейсе.

Что вам понадобится

2. Настройте среду разработки Flutter

Для разработки Flutter вам потребуются две части программного обеспечения для выполнения этой лабораторной работы — Flutter SDK и редактор .

Вы можете запустить кодовую лабораторию, используя любое из этих устройств:

  • Симулятор iOS (требуется установка инструментов Xcode).
  • Эмулятор Android (требуется установка в Android Studio).
  • Браузер (для отладки требуется Chrome).
  • Как настольное приложение для Windows , Linux или macOS . Вы должны разрабатывать на той платформе, на которой планируете развертывание. Итак, если вы хотите разработать настольное приложение для Windows, вы должны разрабатывать в Windows, чтобы получить доступ к соответствующей цепочке сборки. Существуют требования к операционной системе, которые подробно описаны на docs.flutter.dev/desktop .

3. Настройте

Чтобы скачать код для этой кодлабы:

  1. Перейдите в репозиторий GitHub для этой лаборатории кода.
  2. Нажмите « Код» > «Загрузить zip» , чтобы загрузить весь код для этой лаборатории кода.

2cd45599f51fb8a2.png

  1. Разархивируйте загруженный zip-файл, чтобы распаковать codelabs-main со всеми необходимыми ресурсами.

Для этой лаборатории кода вам нужны только файлы в tfserving-flutter/codelab2 в репозитории, который содержит две папки:

  • starter папка содержит начальный код, на основе которого вы строите эту лабораторию кода.
  • finished папка содержит завершенный код для готового примера приложения.

4. Загрузите зависимости для проекта

  1. В VS Code нажмите « Файл» > «Открыть папку» , а затем выберите starter папку из загруженного ранее исходного кода.
  2. Если появится диалоговое окно с предложением загрузить необходимые пакеты для начального приложения, щелкните Получить пакеты .
  3. Если вы не видите это диалоговое окно, откройте терминал и запустите команду flutter pub get в starter папке.

7ada07c300f166a6.png

5. Запустите стартовое приложение

  1. В VS Code убедитесь, что эмулятор Android или iOS Simulator правильно настроены и отображаются в строке состояния.

Например, вот что вы видите, когда используете Pixel 5 с эмулятором Android:

9767649231898791.png

Вот что вы видите, когда используете iPhone 13 с симулятором iOS:

95529e3a682268b2.png

  1. Нажмите a19a0c68bc4046e6.png Начать отладку .

Запустите и исследуйте приложение

Приложение должно запуститься на эмуляторе Android или симуляторе iOS. Пользовательский интерфейс довольно прост. Есть текстовое поле, которое позволяет пользователю вводить текст. Пользователь может выбрать, отправлять ли данные на серверную часть с помощью REST или gRPC. Серверная часть использует модель TensorFlow для классификации текста на предварительно обработанном входе и возвращает результат классификации клиентскому приложению, которое, в свою очередь, обновляет пользовательский интерфейс.

b298f605d64dc132.pngd3ef3ccd3c338108.png

Если вы нажмете 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] . Конкретные числа могут варьироваться в зависимости от словаря.

  1. В файле 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]);
    }
  }
} 
  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:

  1. Создайте REST-запрос.
  2. Отправьте запрос REST в TensorFlow Serving.
  3. Извлеките прогнозируемый результат из ответа REST и визуализируйте пользовательский интерфейс.

Вы выполняете эти шаги в файле main.dart .

Создайте и отправьте запрос REST в TensorFlow Serving.

  1. Прямо сейчас функция predict() не отправляет запрос REST в TensorFlow Serving. Вам необходимо реализовать ветку REST для создания запроса REST:
if (_connectionMode == ConnectionModeType.rest) {
  // TODO: Create and send the REST request.

}
  1. Добавьте этот код в ветку 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');
}

Код постобработки извлекает вероятность того, что входное предложение является спам-сообщением, из ответа и отображает результат классификации в пользовательском интерфейсе.

Запустить его

  1. Нажмите a19a0c68bc4046e6.png Запустите отладку и дождитесь загрузки приложения.
  2. Введите текст, а затем выберите REST > Classify .

8e21d795af36d07a.pnge79a0367a03c2169.png

9. Подключите приложение Flutter к TensorFlow Serving через gRPC.

Помимо REST, TensorFlow Serving также поддерживает gRPC .

b6f4449c2c850b0e.png

gRPC — это современная высокопроизводительная платформа удаленного вызова процедур (RPC) с открытым исходным кодом, которая может работать в любой среде. Он может эффективно подключать службы в центрах обработки данных и между ними с подключаемой поддержкой балансировки нагрузки, трассировки, проверки работоспособности и аутентификации. Было замечено, что на практике gRPC более эффективен, чем REST.

Отправляйте запросы и получайте ответы с помощью gRPC

Есть четыре простых шага для отправки запросов и получения ответов с помощью gRPC:

  1. Необязательно: сгенерируйте код-заглушку клиента gRPC.
  2. Создайте запрос gRPC.
  3. Отправьте запрос gRPC в TensorFlow Serving.
  4. Извлеките прогнозируемый результат из ответа gRPC и визуализируйте пользовательский интерфейс.

Вы выполняете эти шаги в файле main.dart .

Необязательно: сгенерируйте код-заглушку клиента gRPC.

Чтобы использовать gRPC с TensorFlow Serving, вам необходимо следовать рабочему процессу gRPC. Чтобы узнать больше о деталях, см. документацию по gRPC .

a9d0e5cb543467b4.png

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');
}

Теперь код постобработки извлекает результат классификации из ответа и отображает его в пользовательском интерфейсе.

Запустить его

  1. Нажмите a19a0c68bc4046e6.png Запустите отладку и дождитесь загрузки приложения.
  2. Введите текст, а затем выберите gRPC > Classify .

e44e6e9a5bde2188.png92644d723f61968c.png

10. Поздравления

Вы использовали TensorFlow Serving, чтобы добавить в свое приложение возможности классификации текста!

В следующей лаборатории кода вы улучшите модель, чтобы можно было обнаруживать определенные спам-сообщения, которые не могут быть обнаружены текущим приложением.

Учить больше