一个在ios中使用tensorflow的demo

0 篇文章 0 订阅
参考文献:

前言:采用参考文献的demo,在iphone上识别图片中花的种类
环境:macOS Sierra, python2.7, tensorflow 0.12(需要下载源码,后面需要编译模型文件,并且用到官方ios的demo)

一、模型训练
1.下载数据
cd ~
mkdir tf_files
cd tf_files
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. 训练模型
进入tensorflow源代码文件
cd tensorflow
python tensorflow/examples/image_retraining/retrain.py \
--bottleneck_dir=/User/***/tf_files/bottlenecks/ \
--how_many_training_steps 100000 \
--model_dir=/User/***/tf_files/inception2 \
--output_graph=/User/***/tf_files/retrained_graph2.pb \
--output_labels=/User/***/tf_files/retrained_labels.txt \
--image_dir /User/***/tf_files/flower_photos
脚本会下载inception v3模型,80多兆,可以提前下载好放到tf_files的inception目录下
训练完成后,在tf_files目录下看到模型文件retrained_graph.pb和标签retrained_labels.txt
3. 模型验证
新建文件label_image.py
#-*- coding:utf-8 -*-
import tensorflow as tf

# change this as you see fit
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_graph.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 \ /User/***/tf_files/flower_photos/roses/2414954629_3708a1a04d.jpg
得到类似下图结果


二 编译模型
将模型文件转化成ios可以上可以运行的文件
0. 首先编译tensorflow源码示例中的label_image来测试模型
tensorflow apple$ cd tensorflow
tensorflow apple$ bazel build tensorflow/examples/label_image:label_image
appledeMacBook-Pro:tensorflow apple$ bazel-bin/tensorflow/examples/label_image/label_image \
--output_layer=final_result \
--labels=/Users/apple/tf_files/retrained_labels.txt \
--image=/Users/apple/tf_files/flower_photos/daisy/5547758_eea9edfd54_n.jpg \
--graph=/Users/apple/tf_files/retrained_graph.pb

1. 优化模型并去掉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)来减少计算次数。
bazel build tensorflow/python/tools:optimize_for_inference
tensorflow apple$ bazel-bin/tensorflow/python/tools/optimize_for_inference \
--input=/Users/apple/tf_files/retrained_graph.pb \
--output=/Users/apple/tf_files/optimized_graph.pb \
--input_names=Mul \
--output_names=final_result
同样通过label_image验证模型的有效性

2. 将模型的权重变成256之内的常数
优化前模型87.5M,优化后的模型还是有87.2M,可以损失一定的精确度,将模型的权重从浮点型转化成整数
appledeMacBook-Pro:tensorflow apple$ bazel build tensorflow/tools/quantization:quantize_graph
appledeMacBook-Pro:tensorflow apple$ bazel-bin/tensorflow/tools/quantization/quantize_graph --input=/Users/apple/tf_files/optimized_graph.pb \
--output=/Users/apple/tf_files/rounded_graph.pb \
--output_node_names=final_result \
--mode=weights_rounded
尽管此时文件大小还是87.2M,压缩后只有24M
验证
appledeMacBook-Pro:tensorflow apple$ bazel-bin/tensorflow/examples/label_image/label_image \
--output_layer=final_result \
--labels=/Users/apple/tf_files/retrained_labels.txt \
--image=/Users/apple/tf_files/flower_photos/daisy/5547758_eea9edfd54_n.jpg \
--graph=/Users/apple/tf_files/rounded_graph.pb
结果


3. 内存映射(memory mapping)
由于app将87M的模型权值加载到内存中,会对RAM带来压力导致稳定性问题,因为OS可能会杀死占用内存太多的应用。幸运的是,这些缓冲区的内容是只读的,能以os在内存遇到压力的时候很容易释放的方式将模型映射到内存中。为此,我们将模型转换成可以从GraphDef分别加载到形式
appledeMacBook-Pro:tensorflow apple$ bazel build tensorflow/contrib/util:convert_graphdef_memmapped_format
appledeMacBook-Pro:tensorflow apple$ bazel-bin/tensorflow/contrib/util/convert_graphdef_memmapped_format --in_graph=/Users/apple/tf_files/rounded_graph.pb --out_graph=/Users/apple/tf_files/mmapped_graph.pb

需要注意的是,此时模型文件已经不是一般的GraphDef protobuf,所以如果还按照以前的方法加载会遇到错误。
appledeMacBook-Pro:tensorflow apple$ bazel-bin/tensorflow/examples/label_image/label_image --output_layer=final_result --labels=/Users/apple/tf_files/retrained_labels.txt --image=/Users/apple/tf_files/flower_photos/daisy/5547758_eea9edfd54_n.jpg --graph=/Users/apple/tf_files/mmapped_graph.pb


三、生成iOS工程文件
demo是在tensorflow官方提供的ios示例代码camera的基础上进行的修改,工程路径:tensorflow/contrib/ios_examples/camera
要求:
Xcode >= 7.3
brew
automake (brew install automake)
准备:
cd tensorflow
tensorflow/contrib/makefile/build_all_ios.sh
cp ~/tf_files/mmapped_graph.pb ~/tf_files/retrained_labels.txt \ tensorflow/contrib/ios_examples/camera/data
open tensorflow/contrib/ios_examples/camera/camera_example.xcodeproj

xcode打开工程文件后,将mmapped.ph和retrained_labels.txt导入到data目录下
修改CameraExampleViewController.mm中要加载到文件,图片等尺寸,结点的名字和如何缩放像素值。



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



  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值