Android TensorFlow
用TensorFlow在Android使用WaveNet,重写成Java,Python模块,从音频中提取特征。
根据用户口音训练”ok Google”,当听到“ok Google”时,激活用户手机。这可以应用于智能家居上,而不连接互联网。
使用训练好的WaveNet model在Android上使用TensorFlow。
在Android上使用WaveNet,整个过程分为3步。
开发环境
- 手机:Pixel, CPU: ARM64
- Android 7.1
- Android NDK 15.2
- Android gradle plugin 2.3.0
- TensorFlow 1.3.0
- bazel 0.5.4 - homebrew
TensorFlow on mobile with speech-to-text DL models
第一步:模型压缩
为了在手机/嵌入式设备上使用深度学习模型,我们必须减少模型对内存的占用,减小推理时间和尽量减少耗电。有好几种方法可以处理这些问题,比如量化,权重裁剪、将大模型变成小模型。
在这里使用TensorFlow量化工具对模型进行压缩。只用权重量化减小模型,Eight-bit Calculations并没有办法减少推理时间。Eight-bit Calculations 并没有针对CPU进行优化。如果你对这个话题感兴趣,可以参考这里。
为了对模型量化权重:
- 将模型改成protocol buffer文件
- 从源文件安装,构建tensorflow
- 在tensorflow目录下执行如下命令
bazel build tensorflow/tools/graph_transforms:transform_graph
bazel-bin/tensorflow/tools/graph_transforms/transform_graph \
–in_graph=/your/.pb/file \
–outputs=”output_node_name” \
–out_graph=/the/quantized/.pb/file \
–transforms=’quantize_weights’
量化后,预训练的WaveNet模型从15.5MB降到4.0MB。把模型文件放到Android项目的assets文件夹下。
第二步:给Android添加TensorFlow 库
用tensorflow构建Android应用程序,可以先学习TensorFlow Android Demo。这个例子中使用 TF speech example作为模板。例子中的gradle file可以用来构建和编译Android TF库。但这个预编译的TF库并不包括我们模型所有必要的操作,需要列出WaveNet需要的操作,编译成.so文件,做成Android APK。
为了找到这些操作,先用tf.train.write_graph输出图细节,再在命令行下运行以下命令:
grep “op: ” PATH/TO/mygraph.txt | sort | uniq | sed -E ‘s/^.+”(.+)”.?$/\1/g’
接下来,编辑/tensorflow/tensorflow/core/kernels/下的BUILD文件,添加操作到Android库的 ‘android_extended_ops_group1’ 或 ‘android_extended_ops_group2’ 中。删掉不需要的操作,可以使.so文件更小。
然后,运行:
bazel build -c opt //tensorflow/contrib/android:libtensorflow_inference.so \
–crosstool_top=//external:android/crosstool \
–host_crosstool_top=@bazel_tools//tools/cpp:toolchain \
–cpu=armeabi-v7a
这样就可以找到 libtensorflow_inference.so 文件:
bazel-bin/tensorflow/contrib/android/libtensorflow_inference.so
除了.so文件,还需要一个JAR 文件。
运行:
bazel build
//tensorflow/contrib/android:android_tensorflow_inference_java
就可以找到文件:
bazel-bin/tensorflow/contrib/android/libandroid_tensorflow_inference_java.jar
把.so和.jar文件放到Android项目的libs文件夹里。
第三步: Android 数据预处理
最后,要降输入数据处理成训练好的模型的格式。对音频系统,原始语音转换成 Mel Frequency Cepstral Coefficients (MFCC),这样人耳才能听到。TensorFlow可以对音频处理,提取特征。在执行这个会话的时候,有几个变量,如图2,TensorFlow 音频处理的MFCC和librosa处理不一样,预训练WaveNet的python库可以做这种训练格式的转换。
MFCC from librosa and TensorFlow audio ops are at different scales.
如果要训练自己的模型或是使用一个训练好的模型,预处理训练数据的时候,要考虑设备上的数据流程。这里把librosa MFCC用Java进行了重写。
效果
下图是最后APP的效果,这里模型没有语言模型,识别是用文字,可以看到有的字是写错了。尽管没有严谨的测试,还是可以看到权重量化后,精度有些降低,系统对周围噪声比较敏感。
推理时间如下:
权重量化可以帮助减小文件大小,但对推理时间和功耗没有太大影响。
Inference time before and after weights quantization. Tested with my Pixel phone and Macbook air.