TensorFlow在iOS和Mac上的使用

一、环境

1、首先你得安装好Xcode 8,确定开发者目录指向你安装Xcode的位置并且已经被激活。(如果你在安装Xcode之前已经安装了Homebrew,这可能会指向错误的地址,导致TensorFlow安装失败):

sudo xcode-select -s /Applications/Xcode.app/Contents/Developer

2、安装Homebrew:https://brew.sh/index_zh-cn.html

3、Homebrew安装其他软件

brew install python3

brew cask install java

brew install bazel

brew install automake

brew install libtool

brew install wget

4、命令:brew list 查看已安装的软件

5、成功安装了python3,那pip3也随着被安装了,使用python3 的包管理器pip3来安装所需要的包。

pip3 install numpy

pip3 install scipy

pip3 install scikit-learn

pip3 install pandas

pip3 install tensorflow

6、命令:pip3 list 查看已安装的包

这些包会安装在/usr/local/lib/python3.6/site-packages目录下。

7、下载TensorFlow源码,需要使用源码文件编译模型,并且使用官方iOS的Demo。

克隆TensorFlow GitHub仓库。注意,一定要保存在没有空格的路径下,否则bazel会拒绝构建。我是克隆到我的主目录下:

cd /Users/javalong/Downloads/Tensorflow

git clone https://github.com/tensorflow/tensorflow

  

一旦GitHub仓库克隆完毕,你就需要运行配置脚本(configure script):

cd /Users/javalong/Downloads/Tensorflow/tensorflow-master

./configure

这里有些地方可能需要你自行配置,比如:

Please specify the location of python. [Default is /usr/bin/python]:

我写的是/usr/local/bin/python3,因为我使用的是Python 3.6。如果你选择默认选项,就会使用Python 2.7来创建TensorFlow。

Please specify optimization flags to use during compilation [Default is 

-march=native]:

这里只需要按Enter键。后面两个问题,只需要选择n(表示 no)。当询问使用哪个Python库时,按Enter键选择默认选项(应该是Python 3.6 库)。剩下的问题都选择n。随后,这个脚本将会下载大量的依赖项并准备构建TensorFlow所需的一切。

8、构建静态库

有两种方法构建TensorFlow:1.在Mac上使用bazel工具;2.在IOS上,使用Makefile。我们是在IOS上构建,所以选择第2种方式。不过因为会用到一些工具,也会用到第一种方式。

在TensorFlow的目录中执行以下脚本:

tensorflow/contrib/makefile/build_all_ios.sh

这个脚本首先会下载一些依赖项,然后开始构建。一切顺利的话,它会创建三个链入你的app的静态库:libtensorflow-core.a, libprotobuf.a, libprotobuf-lite.a。

还有另外两个工具需要构建,在终端运行如下两行命令:

bazel build tensorflow/python/tools:freeze_graph

bazel build tensorflow/python/tools:optimize_for_inference

Note: 这个过程至少需要20分钟,因为它会从头开始构建TensorFlow(本次使用的是bazel)。如果遇到问题,请参考官方指导

9、iOS工程配置引用参考:

9.1、Other Linker Flags : 

-force_load $(SRCROOT)/../../makefile/gen/lib/libtensorflow-core.a

如图:

9.2、Header Search Paths : 

$(SRCROOT)/../../makefile/gen/proto $(SRCROOT)/../../makefile/downloads/eigen $(SRCROOT)/../../makefile/downloads $(SRCROOT)/../../makefile/downloads/protobuf/src/ $(SRCROOT)/../../../..

9.3、Libaray Search Paths :

$(SRCROOT)/../../makefile/gen/lib $(SRCROOT)/../../makefile/gen/protobuf_ios/lib

如图:

9.4、Demo工程与makefile目录相对关系如图:

10、库的引用如图:

二、模型训练

1.下载数据

cd /Users/javalong/Desktop

mkdir Test

cd Test

curl -O http://download.tensorflow.org/example_images/flower_photos.tgz

tar xzf flower_photos.tgz

进入flower_photos,可以看到5个文件夹,daisy dandelion roses sunflowers tulips

2. 利用预训练模型训练数据

模型是谷歌的Inceptionv3(http://arxiv.org/abs/1512.00567)。在2012年的imageNet上进行训练,并在2012ImageNet上取得了3.4%的top-5准确率(人类的只有5%)。

这么一个复杂的网络若是直接自己训练,起码需要几天甚至十几天的时间。所以这里我采用复用深度学习的方法。即模型前面的层的参数都不变,而只训练最后一层的方法。最后一层是一个softmax分类器,这个分类器在原来的网络上是1000个输出节点(ImageNet有1000个类),所以需要删除网络的最后的一层,变为所需要的输出节点数量,然后再进行训练。

tensorflow/examples/image_retraining/retrain.py 中采用的方法是这样的:将自己的训练集中的每张图像输入网络,最后在瓶颈层(bottleneck),就是倒数第二层,会生成一个2048维度的特征向量,将这个特征保存在一个txt文件中,再用这个特征来训练softmax分类器。

进入tensorflow源代码目录

2.1、

cd /Users/javalong/Downloads/Tensorflow/tensorflow-master

2.2、

python3 tensorflow/examples/image_retraining/retrain.py \

--bottleneck_dir=/Users/javalong/Desktop/Test/ \

--how_many_training_steps 100000 \

--model_dir=/Users/javalong/Desktop/Test/inception2 \

--output_graph=/Users/javalong/Desktop/Test/retrained_graph2.pb \

--output_labels=/Users/javalong/Desktop/Test/retrained_labels.txt \

--image_dir=/Users/javalong/Desktop/Test/flower_photos

脚本会下载Inceptionv3模型,80多兆,可以提前下载好放到Test的inception2目录下

模型路径:http://download.tensorflow.org/models/image/imagenet/inception-2015-12-05.tgz

训练完成后,在Test目录下看到模型文件retrained_graph.pb和标签retrained_labels.txt。

3. 模型验证

新建文件label_image.py,注意格式,代码缩进使用tab

#-*- coding:utf-8 -*-

import os

import numpy as np

import tensorflow as tf

from sklearn import metrics

# 随便一张玫瑰花图片

image_path = "test1.jpg"

# read in the image_data

image_data = tf.gfile.FastGFile(image_path, "rb").read()

# Loads label file, strips off carriage return

label_lines = [line.strip() for line in tf.gfile.GFile("retrained_labels.txt")]

# Unpersists graph from file

with tf.gfile.FastGFile("retrained_graph2.pb", "rb") as f:

    graph_def = tf.GraphDef()

    graph_def.ParseFromString(f.read())

    _ = tf.import_graph_def(graph_def, name="")

with tf.Session() as sess:

# Feed the image_data as input to the graph and get first prediction

    softmax_tensor = sess.graph.get_tensor_by_name("final_result:0")

    preditions = sess.run(softmax_tensor, {"DecodeJpeg/contents:0":image_data})

# sort to show labels of first prediction in order of confidence

    top_k = preditions[0].argsort()[-len(preditions[0]):][::-1]

    for node_id in top_k:

        human_string = label_lines[node_id]

        score = preditions[0][node_id]

        print('%s (score = %.5f' %(human_string, score))

执行文件

python label_image.py 

得到类似下图结果

三 、编译模型

将模型文件转化成ios可以上可以运行的文件

1、首先编译tensorflow源码示例中的label_image来测试retrained_graph2.pb模型

1.1、

cd /Users/javalong/Downloads/Tensorflow/tensorflow-master

1.2、

bazel build tensorflow/examples/label_image:label_image

1.3、

bazel-bin/tensorflow/examples/label_image/label_image \

--output_layer=final_result \

--labels=/Users/javalong/Desktop/Test/retrained_labels.txt \

--image=/Users/javalong/Desktop/Test/flower_photos/daisy/5547758_eea9edfd54_n.jpg \

--graph=/Users/javalong/Desktop/Test/retrained_graph2.pb

如图所示:

2、优化模型并去掉ios不支持的算子

翻译文章中说明如下:

“由于移动设备内存有限,并且app需要下载,因此TensorFlow的iOS版本只支持那些推理中常见的算子(ops,提供英文原文以防翻译错误),没有大量支持扩展的依赖项。你可以在tensorflow/contrib/makefile/tf_op_files.txt这个文件中找到可以使用的算子列表。”

文章中提到,DecodeJpeg是不能使用的算子之一,因为其实现方法依赖于libjpeg,而它在iOS上运行非常麻烦(painful to support),并且增加binary footprint(不懂。。。)。尽管可以用iOS原生的图像库实现,大部分应用其实直接图像buffer而不需要对jpeg进行编码。

问题麻烦的地方在于,我们使用的Inception模型包括了DecodeJpeg算子。我们通过直接将图片数据传给Mul结点绕过DecodeJpeg操作。尽管如此,图被加载的时候,如果平台不支持,即使算子没有被调用,还是会报错,因此我们利用optimize_for_inference去掉所有没有被输入和输出结点用到的结点。这个脚本同时会完成一些优化来加速,例如将batch normalization转换成卷积权重(the convolutional weights)来减少计算次数。

2.1、

bazel build tensorflow/python/tools:optimize_for_inference

2.2、

bazel-bin/tensorflow/python/tools/optimize_for_inference \

--input=/Users/javalong/Desktop/Test/retrained_graph2.pb \

--output=/Users/javalong/Desktop/Test/optimized_graph.pb \

--input_names=Mul \

--output_names=final_result

如图所示:

同样可以通过label_image验证optimized_graph.pb模型的有效性。

3、将模型的权重变成256之内的常数

优化前模型87.5M,优化后的模型还是有87.2M,可以损失一定的精确度,将模型的权重从浮点型转化成整数。

3.1、 

bazel build tensorflow/tools/quantization:quantize_graph

3.2、

bazel-bin/tensorflow/tools/quantization/quantize_graph --input=/Users/javalong/Desktop/Test/optimized_graph.pb \

--output=/Users/javalong/Desktop/Test/rounded_graph.pb \

--output_node_names=final_result \

--mode=weights_rounded

如图所示:

4、验证rounded_graph.pb模型

4.1、

bazel-bin/tensorflow/examples/label_image/label_image \

--output_layer=final_result \

--labels=/Users/javalong/Desktop/Test/retrained_labels.txt \

--image=/Users/javalong/Desktop/Test/flower_photos/daisy/5547758_eea9edfd54_n.jpg \

--graph=/Users/javalong/Desktop/Test/rounded_graph.pb

如图所示:

5、内存映射(memory mapping)

由于app将87M的模型权值加载到内存中,会对RAM带来压力导致稳定性问题,因为OS可能会杀死占用内存太多的应用。幸运的是,这些缓冲区的内容是只读的,能以os在内存遇到压力的时候很容易释放的方式将模型映射到内存中。为此,我们将模型转换成可以从GraphDef分别加载到形式。

5.1、

bazel build tensorflow/contrib/util:convert_graphdef_memmapped_format

5.2、

bazel-bin/tensorflow/contrib/util/convert_graphdef_memmapped_format \

--in_graph=/Users/javalong/Desktop/Test/rounded_graph.pb \

--out_graph=/Users/javalong/Desktop/Test/mmapped_graph.pb

需要注意的是,此时模型文件已经不是一般的GraphDef protobuf,所以如果还按照以前的方法加载会遇到错误。

5.3、

bazel-bin/tensorflow/examples/label_image/label_image \

--output_layer=final_result \

--labels=/Users/javalong/Desktop/Test/retrained_labels.txt \

--image=/Users/javalong/Desktop/Test/flower_photos/daisy/5547758_eea9edfd54_n.jpg \

--graph=/Users/javalong/Desktop/Test/mmapped_graph.pb

如图所示:

四、使用iOS Demo工程

1、demo是在tensorflow官方提供的ios示例代码camera的基础上进行的修改,工程路径:tensorflow/contrib/ios_examples/camera。

2、将rounded_graph.pb和retrained_labels.txt导入到data目录下。

3、修改CameraExampleViewController.mm中要加载到文件,图片等尺寸,结点的名字和如何缩放像素值。

4、最后程序运行的结果如下:

时间: 2024-11-03 22:18:25

TensorFlow在iOS和Mac上的使用的相关文章

Mac上录制iOS屏幕使用教程

  1.要开始对 iOS 8 设备屏幕的录制,你需要首先在运行 OS X Yosemite 的 Mac 上运行 QuickTime Player 应用.我们可以在应用程序里面找到它. 2.然后在右上角点击"文件">新影片录制(New Movie Recording). 3.点击后,QuickTime Player 将会打开并且试图通过 FaceTime 摄像头对你进行录制.接下来你需要移动到录制按钮旁边的下拉式箭头,并从源列表中选择你的 iOS 设备,如下图. 你可以选择视频输入

如何在Mac上用AirDrop共享文件和发送文件到IOS设备上

  在Mac中AirDrop功能便于您以无线方式将Mac 中的文件发送到周边使用IOS设备的人共享照片.视频.位置等信息 .那么苹果设备之间如何通过AirDrop共享文件和发送文件呢? 而且你无需为了传输文件而连接到同一网络,您的设备会针对 AirDrop 自动设置直接的无线连接 .AirDrop 可从 Finder."共享"菜单找到,也可在"打开"和"存储"窗口中找到.当您在 Yosemite 中选取 AirDrop 时,您的 Mac 会寻找附

[译]假如 Mac 上也有 iOS 应用?

本文讲的是[译]假如 Mac 上也有 iOS 应用?, 假如 Mac 上也有 iOS 应用,世界将会怎样? 没有人专门为 Mac 开发应用,Slack 有专门的 iOS 版本,放在 iPad 上的体验非常好,接上 smart keyboard 以后,你会发现还可以方便的使用快捷键.而且,在应用上无限下滑的体验甚至超过了他们本身的网页端,甚至于我从来没有看到过一个"加载中"的页面.这体验如果能够放到桌面端那是再好不过了,但是他们没有这么做,他们仅仅只是把他们的网页放到了一个 app-la

《深入浅出iPhone/iPad开发(第2版)》——iOS模拟器让你可以在Mac上测试你的应用程序

iOS模拟器让你可以在Mac上测试你的应用程序深入浅出iPhone/iPad开发(第2版)模拟器是一款伟大的测试工具,它可以让你快速并且免费测试应用程序.它不能兼容所有真正的设备,但是对于大多数设备而言,它表现得很好.当你第一次打开模拟器时,你会看到一个安装了iDecide(默认图标你可以在之后修改)的面板(就像一部真正的iPhone,它的初始屏幕会显示你的所有应用程序图标).Xcode会打开这个应用程序并运行你的代码. 使用模拟器与使用iPhone会有一些不同之处.首先,摇动和旋转你的Mac不

Appium+python自动化16-appium1.6在mac上环境搭建启动ios模拟器上Safari浏览器

前言 在mac上搭建appium踩了不少坑,先是版本低了,启动后无限重启模拟器.后来全部升级最新版本,就稳稳的了. 环境准备: 1.OS版本号10.12 2.xcode版本号8.3.2 3.appium版本号1.6.4(appium-desktop1.1.0) 4.ios模拟器版本号10.3   一.OS10.12 1.这里Mac上的OS系统一定要升级到10.12,低于10.12是无法安装8.3.2的xcode版本的 2.下载地址:https://www.apple.com/macos/sier

mac上的取色器怎么选择

问题描述 mac上的取色器怎么选择 平时做iOS开发的选择使用哪个方式,模拟器上得出来的颜色失真程度最小,(我用"一普通RGB显示"要比 "以sRGB显示"在模拟器上颜色显示准确度差,想问问大神哪个是相比较最准确的) 解决方案 用美工给的RGB最后实现没给就用吸色器.

Mac上最好的RSS阅读器

长期没有更新的 Mac 版本 RSS 阅读器 Reeder 终于要迎来更新了,这款由 Silvio Rizzi 打造的软件被认为是 Mac 上最好的 RSS 阅读器.注:RSS,简易信息聚合,也叫聚合内容,是一种描述和同步网站内容的格式.这款 Google RSS 阅读器,可以直接跟 Google Reader 进行数据对接.同时 Reeder 也拥有 iPhone 版和 Mac 版. Rizzi,并不是那种沉迷客户端和经常放出更新版本的作者,他在 6 个多月前发布了 iOS 版本的 Reede

Mac上的iCloud Drive怎么用?

  Mac上的iCloud Drive怎么用?苹果在 2014 年发布的 iOS8 和 Mac OS 10.10 中增加了新功能 iCloud Drive .以前我们在苹果设备上都会使用 iCloud 来整合自己的文稿数据,可以在 iOS 设备上使用,也可以在 Mac OS 系统上使用 iCloud 文稿数据.不过以后,这些都将会被整合到 iCloud Drive 中,让我们可以更加方便地共享讲文稿和数据. 1.当在 iOS8 中打开 iCloud 以后,可以在选项中找到 iCloud Driv

在Mac上接收iPhone/iPad推送信息

  pushNotify教程:在Mac上接收iPhone/iPad推送信息.pushNotify可以让您轻松在Mac设备上接收来自iOS设备的任何推送信息并使用Mac原生推送窗口再次推送给您,让您高效专注电脑工作的同时不错过任何iOS设备(iPhone/iPad/iPod touch)发来的推送消息.只需要在 Mac 和 iOS 端完成配置后,Mac 上就可以推送信息了. 补充:该插件仅支持Mac,如果你是Windows用户,可使用GrowlNotifier来实现电脑接收iOS设备推送信息. 一