当前位置: 首页 > 科技观察

如何用TensorFlow在安卓设备上实现深度学习推断

时间:2023-03-22 12:29:28 科技观察

如何使用TensorFlow在Android设备上实现深度学习推理,或者在处理将数据传输到云服务的隐私和延迟问题时。边缘计算是一种在物理上靠近数据生成位置处理和分析数据的方法,为这些问题提供了解决方案。以“OkGoogle”的功能为例:用用户的语音训练“OkGoogle”,手机收到这个关键词就会唤醒。这种小型关键字识别(KWS)推理通常在设备本地运行,因此您不必担心服务提供商会一直监听您的声音。另一方面,云服务只会在您发出命令后启动。类似的概念可以扩展到智能家电或其他物联网设备上的应用程序,我们需要不依赖互联网的免提语音控制。更重要的是,边缘计算不仅为物联网世界带来了人工智能,还提供了许多其他的可能性和好处。例如,我们可以在本地设备上将图像或语音数据预处理为压缩表示形式,然后将其发送到云端。这种方法解决了隐私和延迟问题。在Insight任职期间,我使用TensorFlow在Android上部署了预训练的WaveNet模型。我的目标是探索将深度学习模型部署到设备并使其正常工作的工程挑战!这篇文章简要介绍了如何使用TensorFlow在Android上构建通用的语音到文本识别应用程序。图1.流程概览。将WaveNet安装到Android的三个步骤。开发环境信息:Pixel,cpu类型:ARM64Android7.1.1AndroidNDK15.2Androidgradleplugin2.3.0TensorFlow1.3.0bazel0.5.4-homebrew详细教程及实现:https://github.com/chiachunfu/speech*第1步:模型压缩为了将深度学习模型部署到移动/嵌入式设备,我们应该以减少模型的内存占用、减少推理时间和降低功耗为目标。有多种方法可以实现这些要求,例如量化、权重修剪或将大型模型提炼成较小的模型。在这个项目中,我使用了TensorFlow中的量化工具来进行模型压缩。目前我只使用权重量化来减小模型大小,因为根据Mac上的测试结果,完整的8位转换不会提供额外的好处,例如减少推理时间。(由于requant_range中的错误,无法在Pixel上运行完整的8位模型)。时间甚至翻倍,因为8位量化工具不适合CPU。如果您有兴趣了解有关量化的更多实用建议,可以阅读PeteWarden的这篇精彩文章(https://petewarden.com/2017/06/22/what-ive-learned-about-neural-network-quantization/).权重量化模型:将模型写入协议缓冲区文件。从源(https://www.tensorflow.org/install/install_sources)安装和配置TensorFlow。在TensorFlow目录下运行如下命令行:bazelbuildtensorflow/tools/graph_transforms:transform_graphbazel-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应用程序,我建议从TensorFlowAndroidDemo开始。在我的项目中,我使用TF语音示例作为模板。本示例中的gradle文件帮助我们构建和编译适用于Android的TF库。但是,这个预构建的TF库可能不包含模型的所有必要操作。我们需要弄清楚WaveNet中需要的所有ops,并将它们编译成适合Androidapk的.so文件。为了找到完整的操作列表,我首先使用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文件更小。现在,运行以下命令:bazelbuild-copt//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文件。运行:bazelbuild//tensorflow/contrib/android:android_tensorflow_inference_java您将在此处找到该文件:bazel-bin/tensorflow/contrib/android/libandroid_tensorflow_inference_java.jar现在,您可以将.so和.jar文件一起移动到您的Android项目中“libs”文件夹中。第三步:Android上的数据预处理***,让我们把输入的数据处理成模型训练需要的格式。对于音频系统,原始语音波被转换为梅尔频率倒谱系数(MFCC),以模仿人耳感知声音的方式。TensorFlow有一个音频操作来执行这个特征提取。然而,事实证明有一些变体可以实现这种转换。如图2所示,来自TensorFlow音频运算的MFCC与librosa提供的MFCC不同。librosa是预训练WaveNet作者用来转换训练数据的Python库。图2.来自不同规模的librosa和TensorFlow音频操作的MFCC。如果您正在训练自己的模型或重新训练预训练模型,请务必在处理训练数据时考虑设备上的数据通道。最终,我用Java重写了librosaMFCC来处理转换。生成的图3显示了应用程序的屏幕截图和示例。由于模型中没有语言模型,识别只是在字符层面,所以句子中存在一些拼写错误。虽然没有经过严格测试,但我确实发现量化后精度略有下降,整体系统对环境噪声的灵敏度也有所下降。图3.应用程序中两个示例的屏幕截图。下表所示的推理时间是对5秒音频进行10次测试的平均值。推理时间在两个平台上都略有增加,而不是减少,因为权重量化有助于减小文件大小,但对优化推理时间或功耗几乎没有作用。表1.权重量化前后的推理时间。测试环境是我的Pixel手机和Macbookair。接下来做什么?有两件重要的事情将使这个项目更进一步,并为社区提供额外的教程和演练,以在边缘设备上部署逼真的语音识别系统。改进的语音识别性能:添加了拼写校正语言模型和噪声下采样模型以减少环境噪声的影响。提高推理时间和功耗:使用NEON或其他架构进行低级优化,使用gemmlowp进行低精度矩阵计算。