TensorFlow为什么能成为最出色的机器学习库呢?
主要有三个原因:
1. 机器学习专业知识:Google是机器学习中的主导力量。它在搜索中的突出地位很大程度上归功于它在机器学习中取得的长足进步。
2. 可扩展性:该公告指出TensorFlow最初是为内部使用而设计的,并且已经针对某些实时产品功能投入生产。
3. 能够在Mobile上运行。
这最后一个原因也是这篇文章的运行原因,因为我们将重点关注Android。
如果您在GitHub上检查tensorflow回购,您会发现一个小的 tensorflow / examples / android目录。
接下来将介绍Android TensorFlow示例以及一些正在进行的事情。
手机上的应用程序通过您的相机瞥了一眼,并试图识别它看到的对象。有时它做得很好,有时它不能完全固定住对象,有时甚至会引发令人发指的猜测!
下图就是一个说明,总的来说,这感觉很神奇!
App通过在设备上的TensorFlow中运行的捆绑式机器学习模型来完成这一壮举(无需网络调用后端服务)。
该模型针对数百万张图像进行了训练,因此它可以查看相机为其提供的照片,并将对象分类为最佳猜测(根据已知的1000个对象分类)。
连同其最佳猜测一起,它会显示置信度得分,以表明其对猜测的确信程度。
Android示例页面为您提供了有关如何构建应用程序的想法,最终达到了生成此APK(Android Package缩写)的目的。
作者构建并上传了APK,因为构建过程需要安装Android NDK和Google的构建工具Bazel 。
注意:由于该示例使用了Android 5.0中引入的Camera2软件包,因此需要Android 5.0或更高版本。
注意:如果您的设备运行的是Android 6.0或更高版本,则必须使用以下命令安装应用程序(它为应用程序提供了运行所需的适当权限):
adb install -r -g /path/to/apk.apk
App的结构是什么样的呢?
核心TensorFlow引擎是使用C ++构建的,但是程序员可以使用C ++或Python编写其TensorFlow软件。
Android TensorFlow示例以以下方式使用C ++接口:
在启动时,该应用程序启动一个Android活动(CameraActivity.java),然后启动一个片段(CameraConnectionFragment.java)
该片段进行了一些设置,以基本上启动相机并将传入的图像流馈送到其实例化的对象(TensorflowImageListener.java)
侦听器会查询分类器(TensorflowClassifier.java)关于它获取的每个图像,并接收每个图像的分类和置信度得分。
这样的好处是,大多数逻辑都在正常的Android Java SDK领域内-因此大多数Android开发人员应该熟悉这一逻辑。那么C ++在哪里?
如果仔细观察TensorflowClassifier,您可能会注意到以下方法:
public native int initializeTensorflow( );
private native String classifyImageBmp(Bitmap bitmap);
native这些方法签名中的关键字指示这些方法是用本机C ++代码实现的。在“ android / jni”目录下查找它们,并且足够真实,您将找到tensorflow_jni.cc
JNIEXPORT jint JNICALL
TENSORFLOW_METHOD(initializeTensorflow)(...)
{
...
}
JNIEXPORT jstring JNICALL
TENSORFLOW_METHOD(classifyImageBmp)(...)
{
...
}
JNI (Java本机接口的缩写)是一种方式,Android应用程序的Java部分可以与本机C ++部分进行通信。
因此,当我们调用classifyImageBmp(bitmap)Java代码时,它实际上将调用tensorflow_jni.cc中导出的C ++函数并返回其返回的值。
无法将位图文件直接发送给TensorFlow作为输入。
它已转换为输入张量,我们将在上面的流程的步骤2中发送该张量。张量是值的n维数组,是TensorFlow用于在其所有不同部分/操作之间发送数据的主题。
该模型需要一个3维数组,该数组提供图像中每个像素的红色/绿色/蓝色值。尺寸为:
1. 像素的X索引
2. 像素的Y索引
3. 指示此单元格保持哪个值(0表示红色,1表示绿色,2表示蓝色)
像元的值将是该像素的R或G或B通道的实际值。
这怎么解释呢?首先是将Android摄像机导出的YUV格式转换为模型期望的RGB格式。其次是模型采用了4维张量。
更具体的模型介绍来啦!
阅读示例的README.md时,您会注意到它指示您下载包含TensorFlow模型的zip文件并将其添加到assets目录中。
该zip文件包含两个对我们很重要的文件:
tensorflow_inception_graph.pb-解压缩后为54 MB,该文件构成了APK大小的大部分(58 MB)。
这是训练有素的机器学习模型,也可以说是一个魔术的来历。
这是一个预先构建的TensorFlow图,描述了根据输入图像数据计算分类所需的确切操作。
该图已序列化并使用Google的协议缓冲区编码为二进制,因此可以在不同平台上反序列化(可以将其视为二进制编码的JSON文件)。
imagenet_comp_graph_label_strings.txt-包含模型输出对应的1000个分类(例如“自动售货机”,“水壶”,“咖啡杯”)。
这些分类是由ImageNet大型视觉识别挑战赛定义的,该模型旨在竞争该模型。
这里的模型就是所谓的深度卷积神经网络。
它是建立在“用卷积更深入”中描述的Inception体系结构中的。
卷积神经网络是深度学习中最受欢迎的一些模型。
他们在图像识别方面非常成功(以至于比赛中排名最高的团队都使用了它们)。
从应用程序启动时,从文件中读取模型并将其嵌入TensorFlow。
这段代码实际上非常有趣,可以阅读并了解如何与tensorflow进行通信(如果在将设备连接到计算机的情况下运行该应用程序,则可以看到这些有用的日志消息打印在logcat中)。
接下来就是建立系统。
因为Android应用示例并非以传统的Gradle方式构建。
由于该应用程序必须包含NDK元素以及TensorFlow本身,因此使用了更为复杂的构建系统。
该示例配置为使用从TensorFlow根目录运行的Google Bazel构建系统构建。
根目录中的WORKSPACE文件指定项目的主要参数。
Android目录中的BUILD文件指示构建系统构建应用程序的Java和C ++文件。
那有什么可能性呢?
目前,在您的应用程序中使用经过训练的模型似乎是移动TensorFlow应用程序中最难获得的成果。
尽管您可能可以在Android上训练模型,但移动设备并不十分适合具有较大训练集的复杂模型所需的密集处理。
最后的彩蛋!这么厉害的作者是谁呢?
他叫杰伊阿拉玛(Jay Alammar), 毕业于斯坦福大学,他的博客和github非常有名,具体可以查看参考资料,大家都叫他"Transformer decoder"!