If you want a simple, efficient and flexible way to integrate TensorFlow into your Flutter application, don’t miss the new plugin tflite_FLUTTER that we introduced today. The plugin was developed by Amish Garg, an intern at Google’s Summer of Code(GSoC), in his Medium article titled “Text Categorization using TensorFlow Lite in Flutter”.

The core features of the Tflite_FLUTTER plugin are:

  • It provides Dart APIS that are similar to TFLite Java and Swift apis, so the flexibility is exactly the same on those platforms
  • Dart: FFI is tied directly to the TensorFlow Lite C API, so it is more efficient than other platform integration approaches.
  • You don’t have to write platform-specific code.
  • Support for acceleration via NNAPI, using GPU Delegate on Android and Metal Delegate on iOS.

In this article, we will use Tflite_flutter to build a text classification Flutter application to take you through the Tflite_flutter plugin, starting with creating a new Flutter project, text_Classification_app.

Initial Configuration

Linux and Mac users

Copy install.sh to the root directory of your application, and then run sh install.sh in the root directory, in this case, text_Classification_app /.

Windows users

Copy the install.bat file to the application root directory and run the batch file install.bat in the root directory, which is text_Classification_app/in this example.

It automatically downloads the latest binary resource from Release Assets and places it in the specified directory.

Click on the README file for more information about the initial configuration.

To get the plugin

Add tflite_flutter to pubspec.yaml: ^

(details).

Download the model

To run the TensorFlow training model on mobile, we need to use the.tflite format. If you need to know how to convert TensorFlow trained models to.tflite format, please refer to the official guide.

Here we are going to use a pre-trained text classification model from the official TensorFlow site, which can be downloaded here.

The pre-trained model can predict whether the emotion of the current paragraph is positive or negative. It is trained based on the Large Movie Review Dataset V1.0 from Mass et al. The dataset consists of positive or negative labels based on IMDB movie reviews. Click here for more information.

Copy the text_classification. Tflite and text_Classification_vocab. TXT files to the text_Classification_app /assets/ directory.

Add assets/ to the pubspec.yaml file.

assets:    
  - assets/
Copy the code

Now we’re ready to start writing code. 🚀

Implementation classifier

pretreatment

As mentioned in the text classification model page. You can use the model to classify paragraphs by following these steps:

  1. The paragraph text is segmented and then converted into a set of term ids using a predefined word collection;
  2. Enter the generated set of term ids into the TensorFlow Lite model;
  3. Get the probability that the current paragraph is positive or negative from the output of the model.

We first write a method to partition the raw string using text_classification_vocab.txt as a word collection.

Create a new file classifier.dart under the lib/ folder.

So I’m going to load the text_classiFICation_vocab.txt into the dictionary.

import 'package:flutter/services.dart';

class Classifier {
  final _vocabFile = 'text_classification_vocab.txt';
  
  Map<String.int> _dict;

  Classifier() {
    _loadDictionary();
  }

  void _loadDictionary() async {
    final vocab = await rootBundle.loadString('assets/$_vocabFile');
    var dict = <String.int> {};final vocabList = vocab.split('\n');
    for (var i = 0; i < vocabList.length; i++) {
      var entry = vocabList[i].trim().split(' ');
      dict[entry[0]] = int.parse(entry[1]);
    }
    _dict = dict;
    print('Dictionary loaded successfully'); }}Copy the code

Loading the dictionary

Now let’s write a function to partition the raw string.

import 'package:flutter/services.dart';

class Classifier {
  final _vocabFile = 'text_classification_vocab.txt';

  // Maximum length of a single sentence
  final int _sentenceLen = 256;

  final String start = '<START>';
  final String pad = '<PAD>';
  final String unk = '<UNKNOWN>';

  Map<String.int> _dict;
  
  List<List<double>> tokenizeInputText(String text) {
    
    // Use Spaces for word segmentation
    final toks = text.split(' ');
    
    // Create a list whose length is equal to _sentenceLen and fill it with the corresponding dictionary value of 
      
    var vec = List<double>.filled(_sentenceLen, _dict[pad].toDouble());

    var index = 0;
    if (_dict.containsKey(start)) {
      vec[index++] = _dict[start].toDouble();
    }

    // For each word in the sentence, find the corresponding index value in the dict
    for (var tok in toks) {
      if (index > _sentenceLen) {
        break;
      }
      vec[index++] = _dict.containsKey(tok)
          ? _dict[tok].toDouble()
          : _dict[unk].toDouble();
    }

    // Use our interpreter to input the shape we need for our tensor.
    return[vec]; }}Copy the code

Analysis was performed using TFLite_FLUTTER

This is the main part of this article, where we discuss the purpose of the tflite_FLUTTER plugin.

Analysis here refers to the process of using the TensorFlow Lite model on the device based on input data. To use the TensorFlow Lite model for analysis, you need to run it through the interpreter to learn more.

Create the interpreter and load the model

Tflite_flutter provides a way to create an interpreter directly from a resource.

static Future<Interpreter> fromAsset(String assetName, {InterpreterOptions options})
Copy the code

Since our model is in assets/, we need to use the above method to create the parser. For instructions for InterpreterOptions, please refer here.

import 'package:flutter/services.dart';

/ / introduce tflite_flutter
import 'package:tflite_flutter/tflite_flutter.dart';

class Classifier {
  // The model file name
  final _modelFile = 'text_classification.tflite';

  // TensorFlow Lite interpreter object
  Interpreter _interpreter;

  Classifier() {
    // Load the model after the classifier is initialized
    _loadModel();
  }

  void _loadModel() async {
    
    // Create the Interpreter using interpreter.fromasset
    _interpreter = await Interpreter.fromAsset(_modelFile);
    print('Interpreter loaded successfully'); }}Copy the code

Create the code for the interpreter

Tflite_flutter also provides factory constructors to create interpreters if you don’t want to put models in assets/.

Let’s start analyzing!

Now start the analysis with the following method:

void run(Object input, Object output);
Copy the code

Note that the methods here are the same as in the Java API.

Object Input and Object Output have to be lists that have the same dimension as input Tensor and output Tensor.

To view the dimensions of input tensors and output tensors, you can use the following code:

_interpreter.allocateTensors();
// Print the input tensor list
print(_interpreter.getInputTensors());
// Prints the output tensor list
print(_interpreter.getOutputTensors());
Copy the code

In this example, the output of the Text_classification model is as follows:

InputTensorList:
[Tensor{_tensor: Pointer<TfLiteTensor>: address=0xbffcf280, name: embedding_input, type: TfLiteType.float32, shape: [1, 256], data:  1024]
OutputTensorList:
[Tensor{_tensor: Pointer<TfLiteTensor>: address=0xbffcf140, name: dense_1/Softmax, type: TfLiteType.float32, shape: [1, 2], data:  8]
Copy the code

Now, we implement a classification method that returns 1 for positive and 0 for negative.

int classify(String rawText) {
    
    // tokenizeInputText returns List
      
       > of shape [1, 256]
      
    List<List<double>> input = tokenizeInputText(rawText);
   
    // output of the [1,2] shape
    var output = List<double> (2).reshape([1.2]);
    
    // The run method runs the analysis and stores the output value
    _interpreter.run(input, output);

    var result = 0;
    // If the value of the first element in the output is greater than that of the second, the sentence is negative
    
    if ((output[0] [0] as double) > (output[0] [1] as double)) {
      result = 0;
    } else {
      result = 1;
    }
    return result;
  }

Copy the code

Code for analysis

The extension ListShape on List of tflite_FLUTTER defines some extensions to use:

// Matrix deform the supplied list, taking the total number of elements as the input parameter // keeping it equal
List(400).0
/ / return the List < dynamic >

List reshape(List<int> shape)
// Return the list shape
List<int> get shape
// Returns the number of elements of any shape in the list
int get computeNumElements

Copy the code

The final classifier.dart should look like this:

import 'package:flutter/services.dart';

/ / introduce tflite_flutter
import 'package:tflite_flutter/tflite_flutter.dart';

class Classifier {
  // The model file name
  final _modelFile = 'text_classification.tflite';
  final _vocabFile = 'text_classification_vocab.txt';

  // The maximum length of the statement
  final int _sentenceLen = 256;

  final String start = '<START>';
  final String pad = '<PAD>';
  final String unk = '<UNKNOWN>';

  Map<String.int> _dict;

  // TensorFlow Lite interpreter object
  Interpreter _interpreter;

  Classifier() {
    // Load the model when the classifier is initialized
    _loadModel();
    _loadDictionary();
  }

  void _loadModel() async {
    // Create a parser with intepreter.fromasset
    _interpreter = await Interpreter.fromAsset(_modelFile);
    print('Interpreter loaded successfully');
  }

  void _loadDictionary() async {
    final vocab = await rootBundle.loadString('assets/$_vocabFile');
    var dict = <String.int> {};final vocabList = vocab.split('\n');
    for (var i = 0; i < vocabList.length; i++) {
      var entry = vocabList[i].trim().split(' ');
      dict[entry[0]] = int.parse(entry[1]);
    }
    _dict = dict;
    print('Dictionary loaded successfully');
  }

  int classify(String rawText) {
    // tokenizeInputText returns List
      
       > of shape [1, 256]
      
    List<List<double>> input = tokenizeInputText(rawText);

    // Output the matrix of shape [1, 2]
    var output = List<double> (2).reshape([1.2]);

    // The run method runs the analysis and stores the results in output.
    _interpreter.run(input, output);

    var result = 0;
    If the output of the first element is larger than the output of the second, the current statement is negative

    if ((output[0] [0] as double) > (output[0] [1] as double)) {
      result = 0;
    } else {
      result = 1;
    }
    return result;
  }

  List<List<double>> tokenizeInputText(String text) {
    // use Spaces to break words
    final toks = text.split(' ');

    // Create a list whose length is equal to _sentenceLen and fill it with the dictionary value corresponding to 
      
    var vec = List<double>.filled(_sentenceLen, _dict[pad].toDouble());

    var index = 0;
    if (_dict.containsKey(start)) {
      vec[index++] = _dict[start].toDouble();
    }

    // For each word in the sentence, find the corresponding index value in the dict
    for (var tok in toks) {
      if (index > _sentenceLen) {
        break;
      }
      vec[index++] = _dict.containsKey(tok)
          ? _dict[tok].toDouble()
          : _dict[unk].toDouble();
    }

    // Use our interpreter to input the shape we need for our tensor.
    return[vec]; }}Copy the code

Now that you can code the UI to your liking, the classifier is simple to use.

// Create the Classifier object
Classifer _classifier = Classifier();
// Call the classify method with the target statement as an argument
_classifier.classify("I liked the movie");
// Return 1 (active)
_classifier.classify("I didn't liked the movie");
// Return 0 (negative)
Copy the code

See the full code here: Text Classification Example app with UI

Example application of text classification

For more information about the Tflite_flutter_plugin, visit GitHub repo: am15h/ tflite_Flutter_plugin.

Answering questions

Q:tflite_flutter 和 Tflite v1.0.5What are the differences?

Tflite V1.0.5 focuses on advanced features for application-specific scenarios, such as image classification, object detection, and so on. The new Tflite_FLUTTER offers the same features and flexibility as the Java API, and can be used in any TFlite model. It also supports delegates.

Because dart: FFI (DART ↔️ (FFI) ↔️ C) is used, tFLite_FLUTTER is very fast (with low latency). Tflite uses platform integration (Dart ↔️ platform-channel ↔️ (Java/Swift) ↔️ JNI ↔️ C).

Q: How do I create an image classification application using Tflite_FLUTTER? Is there anything likeTensorFlow Lite Android Support LibraryDependency packages?

Update (07/01/2020) : The TFLite Flutter Helper development library has been released.

The TensorFlow Lite Flutter Helper Library provides an easy-to-use architecture for handling and controlling the inputs and outputs of TFLite models. Its API design and documentation are the same as the TensorFlow Lite Android Support Library. See here for more information.

This is the end of this article. Your feedback on tflite_FLUTTER is welcome. Please report any bugs or feature requirements here.

Thank you for your attention.

Michael Thomsen.

Thank you

  • Translation: Yuan, Gu Chuang subtitle group
  • Review: Xinlei, Lynn Wang, Alex, CFUG Community.

This article is published on the TensorFlow online discussion forum, 101.dev and the Flutter Chinese documentation, as well as the Flutter community online.