注意:該功能是實驗性的。
TensorFlow Lite 已經内置了很多運算符,并且還在不斷擴充,但是仍然還有一部分 TensorFlow 運算符沒有被 TensorFlow Lite 原生支援。這些不被支援的運算符會給 TensorFlow Lite 的模型轉換帶來一些阻力。為了減少模型轉換的阻力,TensorFlow Lite 開發團隊最近一直緻力于一個實驗性功能的開發。
這篇文檔簡單介紹了怎樣在 TensorFlow Lite 使用 TensorFlow 運算符。注意,這隻是一個實驗性的功能,并且還在開發中。 在使用該功能的時候,請記住這些已知的局限性,并且請将使用中遇到的問題回報至 [email protected]。
TensorFlow Lite 會繼續為移動裝置和嵌入式裝置優化内置的運算符。但是現在,當 TensorFlow Lite 内置的運算符不夠的時候,TensorFlow Lite 模型可以使用部分 TensorFlow 的運算符。
TensorFlow Lite 解釋器在處理轉換後的包含 TensorFlow 運算符的模型的時候,會比處理隻包含 TensorFlow Lite 内置運算符的模型占用更多的空間。并且,TensorFlow Lite 模型中包含的任何 TensorFlow 運算符,性能都不會被優化。
這篇文檔簡單介紹了怎樣針對不同的平台轉換和運作包含 TensorFlow 運算符的 TensorFlow Lite 模型。并且讨論了一些已知的局限性、為此功能制定的未來的計劃以及基本的性能和空間名額。
轉換模型
為了能夠轉換包含 TensorFlow 運算符的 TensorFlow Lite 模型,可使用位于 TensorFlow Lite 轉換器 中的 target_spec.supported_ops 參數。target_spec.supported_ops 的可選值如下:
TFLITE_BUILTINS - 使用 TensorFlow Lite 内置運算符轉換模型。
SELECT_TF_OPS - 使用 TensorFlow 運算符轉換模型。已經支援的 TensorFlow 運算符的完整清單可以在白名單
lite/delegates/flex/whitelisted_flex_ops.cc 中檢視。
注意:target_spec.supported_ops 是之前 Python API 中的 target_ops。
我們優先推薦使用 TFLITE_BUILTINS 轉換模型,然後是同時使用 TFLITE_BUILTINS,SELECT_TF_OPS ,最後是隻使用 SELECT_TF_OPS。同時使用兩個選項(也就是 TFLITE_BUILTINS,SELECT_TF_OPS)會用 TensorFlow Lite 内置的運算符去轉換支援的運算符。有些 TensorFlow 運算符 TensorFlow Lite 隻支援部分用法,這時可以使用 SELECT_TF_OPS 選項來避免這種局限性。
下面的示例展示了通過 Python API 中的 TFLiteConverter 來使用該功能。
import tensorflow as tf
converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS,
tf.lite.OpsSet.SELECT_TF_OPS]
tflite_model = converter.convert()
open("converted_model.tflite", "wb").write(tflite_model)
下面的示例展示了在指令行工具 tflite_convert 中通過 target_ops 标記來使用該功能。
tflite_convert \
--output_file=/tmp/foo.tflite \
--graph_def_file=/tmp/foo.pb \
--input_arrays=input \
--output_arrays=MobilenetV1/Predictions/Reshape_1 \
--target_ops=TFLITE_BUILTINS,SELECT_TF_OPS
如果直接使用 bazel 編譯和運作 tflite_convert,請傳入參數 --define=with_select_tf_ops=true。
bazel run --define=with_select_tf_ops=true tflite_convert -- \
--output_file=/tmp/foo.tflite \
--graph_def_file=/tmp/foo.pb \
--input_arrays=input \
--output_arrays=MobilenetV1/Predictions/Reshape_1 \
--target_ops=TFLITE_BUILTINS,SELECT_TF_OPS
運作模型
如果 TensorFlow Lite 模型在轉換的時候支援 TensorFlow select 運算符,那麼在使用的時候 Tensorflow Lite 運作時必須包含 TensorFlow 運算符的庫。
Android AAR
為了便于使用,新增了一個支援 TensorFlow select 運算符的Android AAR。如果已經有了可用的 TensorFlow Lite
編譯環境,可以按照下面的方式編譯支援使用 TensorFlow select 運算符的 Android AAR:
bazel build --cxxopt='--std=c++11' -c opt \
--config=android_arm --config=monolithic \
//tensorflow/lite/java:tensorflow-lite-with-select-tf-ops
上面的指令會在 bazel-genfiles/tensorflow/lite/java/ 目錄下生成一個 AAR 檔案。你可以直接将這個 AAR 檔案導入到項目中,也可以将其釋出到本地的 Maven 倉庫:
mvn install:install-file \
-Dfile=bazel-genfiles/tensorflow/lite/java/tensorflow-lite-with-select-tf-ops.aar \
-DgroupId=org.tensorflow \
-DartifactId=tensorflow-lite-with-select-tf-ops -Dversion=0.1.100 -Dpackaging=aar
最後,在應用的 build.gradle 檔案中需要保證有 mavenLocal() 依賴,并且需要用支援 TensorFlow select 運算符的 TensorFlow Lite 依賴去替換标準的 TensorFlow Lite 依賴:
allprojects {
repositories {
jcenter()
mavenLocal()
}
}
dependencies {
implementation 'org.tensorflow:tensorflow-lite-with-select-tf-ops:0.1.100'
}
iOS
如果安裝了 XCode 指令行工具,可以用下面的指令編譯支援 TensorFlow select 運算符的 TensorFlow Lite:
tensorflow/contrib/makefile/build_all_ios_with_tflite.sh
這條指令會在 tensorflow/contrib/makefile/gen/lib/ 目錄下生成所需要的靜态連結庫。
TensorFlow Lite 的相機示例應用可以用來進行測試。一個新的支援 TensorFlow select 運算符的 TensorFlow Lite XCode 項目已經添加在 tensorflow/lite/examples/ios/camera/tflite_camera_example_with_select_tf_ops.xcodeproj 中。
如果想要在自己的項目中使用這個功能,你可以克隆示例項目,也可以按照下面的方式對項目進行設定:
在 Build Phases -> Link Binary With Libraries 中,添加 tensorflow/contrib/makefile/gen/lib/ 目錄中的靜态庫:
libtensorflow-lite.a
libprotobuf.a
nsync.a
在 Build Settings -> Header Search Paths 中,添加下面的路徑:
tensorflow/lite/
tensorflow/contrib/makefile/downloads/flatbuffer/include
tensorflow/contrib/makefile/downloads/eigen
在 Build Settings -> Other Linker Flags 中,添加 -force_load
tensorflow/contrib/makefile/gen/lib/libtensorflow-lite.a。
未來還會釋出支援 TensorFlow select 運算符的 CocoaPod 。
C++
如果使用 bazel 編譯 TensorFlow Lite 庫,可以按照下面的方式添加和支援額外的 TensorFlow 運算符的庫。
如果需要單體編譯,可以添加 --config=monolithic 編譯标記。
從下面的方案中選擇一個:
在用 bazel build 指令編譯 TensorFlow Lite 時添加 --define=with_select_tf_ops=true 編譯标記。
在編譯依賴中添加 TensorFlow 運算符庫依賴 tensorflow/lite/delegates/flex:delegate。
注意,隻要委托連結到了用戶端庫,在運作時建立解釋器的時候就會自動安裝所需的 TfLiteDelegate,而不需要像其他委托類型去顯式安裝委托執行個體。
Python pip Package
對 Python 的支援還在開發當中。
性能和空間名額
性能
如果 TensorFlow Lite 模型是同時混合使用内置運算符和 TensorFlow select 運算符進行轉換的,那麼模型依然可以使用針對 TensorFlow Lite 的優化以及内置的優化核心。
下表列出了在 Pixel 2 上 MobileNet 的平均推斷時間。表中的時間是 100 次運作的平均時間。在對 Android 平台編譯的時候添加了 --config=android_arm64 -c opt 标記。
編譯
推斷時間 (milliseconds)
Only built-in ops (TFLITE_BUILTIN)
260.7
Using only TF ops (SELECT_TF_OPS)
264.5
二進制檔案大小
下表列出了不同編譯方式生成的 TensorFlow Lite 二進制檔案的大小。在對 Android 平台編譯的時候添加了 --config=android_arm -c opt 标記。
編譯
C++ 二進制檔案大小
Android APK 大小
Only built-in ops
796 KB
561 KB
Built-in ops + TF ops
23.0 MB
8.0 MB
已知的局限性
下面列出了一些已知的局限性:
目前還不支援控制流運算符。
目前還不支援 TensorFlow 運算符的 post_training_quantization 标記,是以不會對任何 TensorFlow 運算符進行權重量化。如果模型中既包含 TensorFlow Lite 運算符又包含 TensorFlow 運算符,那麼 TensorFlow Lite 内置的運算符的權重是可以被量化的。
目前還不支援像 HashTableV2 這種需要顯式用資源進行初始化的運算符。
某些 TensorFlow 操作可能不支援 TensorFlow 庫中整套正常可用輸入/輸出操作。
未來的計劃
下面列出了正在開發中的針對該功能的一些改進:
選擇性注冊 - 有一項正在完成的工作是,讓生成隻包含特定模型集合所需的 Tensorflow 運算符的 TensorFlow Lite 二進制檔案變得更簡單。
提升可用性 - 模型轉換的過程将被簡化,隻需要一次性完成轉換。 并且還會提供預編譯的 Android AAR 和 iOS CocoaPod 二進制檔案。
提升性能 - 有一項正在完成的工作是,讓使用 TensorFlow 運算符的 TensorFlow Lite 具有與 TensorFlow Mobile 同等的性能。