以resnet50为例,记录tensorflow和keras模型转ncnn的过程

resnet50 模型定义

def identity_block(input_tensor, kernel_size, filters, stage, block):nb_filter1, nb_filter2, nb_filter3 = filtersif K.image_dim_ordering() == 'tf':bn_axis = 3else:bn_axis = 1conv_name_base = 'res' + str(stage) + block + '_branch'bn_name_base = 'bn' + str(stage) + block + '_branch'x = Convolution2D(nb_filter1, 1, 1, name=conv_name_base + '2a')(input_tensor)x = BatchNormalization(axis=bn_axis, name=bn_name_base + '2a')(x)x = Activation('relu')(x)x = Convolution2D(nb_filter2, kernel_size, kernel_size,border_mode='same', name=conv_name_base + '2b')(x)x = BatchNormalization(axis=bn_axis, name=bn_name_base + '2b')(x)x = Activation('relu')(x)x = Convolution2D(nb_filter3, 1, 1, name=conv_name_base + '2c')(x)x = BatchNormalization(axis=bn_axis, name=bn_name_base + '2c')(x)x = merge([x, input_tensor], mode='sum')x = Activation('relu')(x)return xdef conv_block(input_tensor, kernel_size, filters, stage, block, strides=(2, 2)):nb_filter1, nb_filter2, nb_filter3 = filtersif K.image_dim_ordering() == 'tf':bn_axis = 3else:bn_axis = 1conv_name_base = 'res' + str(stage) + block + '_branch'bn_name_base = 'bn' + str(stage) + block + '_branch'x = Convolution2D(nb_filter1, 1, 1, subsample=strides,name=conv_name_base + '2a')(input_tensor)x = BatchNormalization(axis=bn_axis, name=bn_name_base + '2a')(x)x = Activation('relu')(x)x = Convolution2D(nb_filter2, kernel_size, kernel_size, border_mode='same',name=conv_name_base + '2b')(x)x = BatchNormalization(axis=bn_axis, name=bn_name_base + '2b')(x)x = Activation('relu')(x)x = Convolution2D(nb_filter3, 1, 1, name=conv_name_base + '2c')(x)x = BatchNormalization(axis=bn_axis, name=bn_name_base + '2c')(x)shortcut = Convolution2D(nb_filter3, 1, 1, subsample=strides,name=conv_name_base + '1')(input_tensor)shortcut = BatchNormalization(axis=bn_axis, name=bn_name_base + '1')(shortcut)x = merge([x, shortcut], mode='sum')x = Activation('relu')(x)return ximg_input = Input(shape=(image_width, image_height, 3))x = ZeroPadding2D((3, 3))(img_input)
x = Convolution2D(64, 7, 7, subsample=(2, 2), name='conv1')(x)
x = BatchNormalization(axis=3, name='bn_conv1')(x)
x = Activation('relu')(x)
x = MaxPooling2D((3, 3), strides=(2, 2))(x)x = conv_block(x, 3, [64, 64, 256], stage=2, block='a', strides=(1, 1))
x = identity_block(x, 3, [64, 64, 256], stage=2, block='b')
x = identity_block(x, 3, [64, 64, 256], stage=2, block='c')x = conv_block(x, 3, [128, 128, 512], stage=3, block='a')
x = identity_block(x, 3, [128, 128, 512], stage=3, block='b')
x = identity_block(x, 3, [128, 128, 512], stage=3, block='c')
x = identity_block(x, 3, [128, 128, 512], stage=3, block='d')x = conv_block(x, 3, [256, 256, 1024], stage=4, block='a')
x = identity_block(x, 3, [256, 256, 1024], stage=4, block='b')
x = identity_block(x, 3, [256, 256, 1024], stage=4, block='c')
x = identity_block(x, 3, [256, 256, 1024], stage=4, block='d')
x = identity_block(x, 3, [256, 256, 1024], stage=4, block='e')
x = identity_block(x, 3, [256, 256, 1024], stage=4, block='f')x = conv_block(x, 3, [512, 512, 2048], stage=5, block='a')
x = identity_block(x, 3, [512, 512, 2048], stage=5, block='b')
x = identity_block(x, 3, [512, 512, 2048], stage=5, block='c')x = AveragePooling2D((7, 13), name='avg_pool')(x)
x = Flatten()(x)
x = Dropout(0.5)(x)
x = Dense(1, activation='sigmoid', name='output')(x)model = Model(input=img_input, output=x)

数据

目录树如下:
datasets
– mytrain
---- cls1
---- cls2
– myvalid
---- cls1
---- cls2
– mytest
---- cls1
---- cls2

from keras.preprocessing.image import ImageDataGenerator
image_width = 224
image_height = 398 #224
image_size = (image_width, image_height)train_datagen = ImageDataGenerator(rescale=1.0/255)train_generator = train_datagen.flow_from_directory('datasets/mytrain',  # this is the target directorytarget_size=image_size,  # all images will be resized to 224x224batch_size=16,class_mode='binary')validation_datagen = ImageDataGenerator(rescale=1.0/255)
validation_generator = validation_datagen.flow_from_directory('datasets/myvalid',  # this is the target directorytarget_size=image_size,  # all images will be resized to 224x224batch_size=16,class_mode='binary')test_datagen = ImageDataGenerator(rescale=1.0/255)
test_datagen = validation_datagen.flow_from_directory('datasets/mytest/',  # this is the target directorytarget_size=image_size,  # all images will be resized to 224x224batch_size=1,class_mode='binary')

模型训练和保存

  • case1:模型保存为.h5文件(keras)
model.compile(loss='binary_crossentropy', optimizer=Adam(lr=1e-3), metrics=['accuracy'])
from keras.callbacks import ModelCheckpoint, TensorBoard
best_model = ModelCheckpoint("resnet_best.h5", monitor='val_acc', verbose=0, save_best_only=True)
model.fit_generator(train_generator,samples_per_epoch=2145,nb_epoch=40,validation_data=validation_generator,nb_val_samples=270,callbacks=[best_model, TensorBoard(log_dir='./logs', histogram_freq=0)])
  • case2: 保存为ckpt文件(tensorflow)(ckpt.index, ckpt.data, ckpt.meta)
    (略)

模型文件转为.pb文件

  • case 1: .h5文件
import sys
from keras.models import load_model
import tensorflow as tf
import os
import os.path as osp
from keras import backend as K
from tensorflow.python.framework.graph_util import convert_variables_to_constantsdef freeze_session(session, keep_var_names=None, output_names=None, clear_devices=True):# 将会话状态冻结为已删除的计算图,创建一个新的计算图,其中变量节点由在会话中获取其当前值的常量替换.# session要冻结的TensorFlow会话,keep_var_names不应冻结的变量名列表,或者无冻结图中的所有变量# output_names相关图输出的名称,clear_devices从图中删除设备以获得更好的可移植性graph = session.graphwith graph.as_default():freeze_var_names = list(set(v.op.name for v in tf.global_variables()).difference(keep_var_names or []))output_names = output_names or []output_names += [v.op.name for v in tf.global_variables()]input_graph_def = graph.as_graph_def()# 从图中删除设备以获得更好的可移植性if clear_devices:for node in input_graph_def.node:node.device = ""# 用相同值的常量替换图中的所有变量frozen_graph = convert_variables_to_constants(session, input_graph_def, output_names, freeze_var_names)return frozen_graphoutput_fld = 'tmp/'
if not os.path.isdir(output_fld):os.mkdir(output_fld)
weight_file_path = 'resnet50_best.h5'
K.set_learning_phase(0)
net_model = load_model(weight_file_path)print('input is :', net_model.input.name)
print ('output is:', net_model.output.name)# 获得当前图
sess = K.get_session()
# 冻结图
frozen_graph = freeze_session(sess, output_names=[net_model.output.op.name])from tensorflow.python.framework import graph_io
graph_io.write_graph(frozen_graph, output_fld, 'resnet50_best.pb', as_text=False)
  • case2: .ckpt文件
#encoding: utf-8
import tensorflow as tf
import argparse
from tensorflow.python.tools import freeze_graphdef load_model(model):# Check if the model is a model directory (containing a metagraph and a checkpoint file)#  or if it is a protobuf file with a frozen graph# load pretrained modelif model:print('Restoring pretrained model: %s' % model)saver = tf.train.import_meta_graph(model + '.meta')saver.restore(tf.get_default_session(), model)else:raise ValueError("Pretrained_model not found: ", model)if __name__ == '__main__':with tf.Graph().as_default():with tf.Session() as sess:# os.environ["CUDA_VISIBLE_DEVICES"] = "0"model_path = '/path/to/xxx.ckpt'load_model(model_path)#保存图graph_pb_name = 'model_graph.pb'model_pb_name = 'model_frozen.pb'tf.train.write_graph(sess.graph_def, './model_files', graph_pb_name)#把图和参数结构一起# 1、input_graph:(必选)模型文件,可以是二进制的pb文件,或文本的meta文件,用input_binary来指定区分(见下面说明)# 2、input_saver:(可选)Saver解析器。保存模型和权限时,Saver也可以自身序列化保存,以便在加载时应用合适的版本。主要用于版本不兼容时使用。可以为空,为空时用当前版本的Saver。# 3、input_binary:(可选)配合input_graph用,为true时,input_graph为二进制,为false时,input_graph为文件。默认False# 4、input_checkpoint:(必选)检查点数据文件。训练时,给Saver用于保存权重、偏置等变量值。这时用于模型恢复变量值。# 5、output_node_names:(必选)输出节点的名字,有多个时用逗号分开。用于指定输出节点,将没有在输出线上的其它节点剔除。# 6、restore_op_name:(可选)从模型恢复节点的名字。升级版中已弃用。默认:save/restore_all# 7、filename_tensor_name:(可选)已弃用。默认:save/Const:0# 8、output_graph:(必选)用来保存整合后的模型输出文件。# 9、clear_devices:(可选),默认True。指定是否清除训练时节点指定的运算设备(如cpu、gpu、tpu。cpu是默认)# 10、initializer_nodes:(可选)默认空。权限加载后,可通过此参数来指定需要初始化的节点,用逗号分隔多个节点名字。# 11、variable_names_blacklist:(可先)默认空。变量黑名单,用于指定不用恢复值的变量,用逗号分隔多个变量名字。freeze_graph.freeze_graph(input_graph='./model_files/' + graph_pb_name, input_saver='',input_binary=False, input_checkpoint=args.model, output_node_names='embeddings', restore_op_name='save/restore_all',filename_tensor_name='save/Const:0',output_graph='./model_files/' + model_pb_name,clear_devices=True,initializer_nodes="")print("done")

测试.pb文件(可忽略)

#!/usr/bin/python
# coding:utf8
import tensorflow as tf
import numpy as np
import os
import cv2predictions = np.zeros((test_datagen.samples), dtype=np.float32)
labels = np.zeros((test_datagen.samples), dtype=np.float32)pb_path = 'tmp/resnet50_best.pb'
with tf.Graph().as_default():output_graph_def = tf.GraphDef()with open(pb_path, "rb") as f:output_graph_def.ParseFromString(f.read())tensors = tf.import_graph_def(output_graph_def, name="")with tf.Session() as sess:init = tf.global_variables_initializer()sess.run(init)sess.graph.get_operations()input_x = sess.graph.get_tensor_by_name("input_1_1:0")  # 具体名称看上一段代码的input.nameout_softmax = sess.graph.get_tensor_by_name("output_2/Sigmoid:0")  # 具体名称看上一段代码的output.namefor i in range(test_datagen.samples):x, y = test_datagen.next()predictions[i] = sess.run(out_softmax,feed_dict={input_x: x})label_matrix[i] = ypred_bool = predictions > 0.5
num_tp = np.sum(pred_bool * label_matrix + (1.0 - pred_bool) * (1.0 - label_matrix))
acc = num_tp / test_datagen.samples
print(acc)

.pb文件转ncnn模型(.param,.bin)

tensorflow2ncnn项目地址:https://github.com/jiangxiluning/ncnn-tensorflow,编译得到可执行文件tensorflow2ncnn

./tensorflow2ncnn tmp/resnet50_best.pb tmp/resnet50_best.param tmp/resnet50_best.bin

测试ncnn模型

todo

tensorflow/keras 2 ncnn相关推荐

  1. TensorFlow Keras API用法

    TensorFlow Keras API用法 Keras 是与 TensorFlow 一起使用的更高级别的作为后端的 API.添加层就像添加一行代码一样简单.在模型架构之后,使用一行代码,可以编译和拟 ...

  2. 常用深度学习框——Caffe/TensorFlow / Keras/ PyTorch/MXNet

    常用深度学习框--Caffe/TensorFlow / Keras/ PyTorch/MXNet 一.概述 近几年来,深度学习的研究和应用的热潮持续高涨,各种开源深度学习框架层出不穷,包括Tensor ...

  3. 解决tensorflow报错:AttributeError: module ‘tensorflow.keras.backend‘ has no attribute ‘get_session‘ 问题

    欢迎大家关注笔者,你的关注是我持续更博的最大动力 原创文章,转载告知,盗版必究 解决tensorflow报错:AttributeError: module 'tensorflow.keras.back ...

  4. How HBO’s Silicon Valley built “Not Hotdog” with mobile TensorFlow, Keras React Native

    The HBO show Silicon Valley released a real AI app that identifies hotdogs - and not hotdogs - like ...

  5. 成功解决tensorflow.keras: AttributeError: ‘str‘ object has no attribute ‘decode‘

    tensorflow.keras: AttributeError: 'str' object has no attribute 'decode' 出现该问题,解决分两步首先检测自身的版本是否对应, 然 ...

  6. tensorflow环境下的识别食物_在TensorFlow+Keras环境下使用RoI池化一步步实现注意力机制...

    在本文中,作者解释了感兴趣区域池化(RoI 池化)的基本概念和一般用法,以及如何使用它来实现注意力机制.他一步步给出了在 Keras 和 TensorFlow 环境下使用 RoI 池化的实现. 选自 ...

  7. 【Python学习】 - TensorFlow.keras 不显示epochs进度条的方法

    一.概述 在我们使用TensorFlow进行神经网络的搭建时,难免遇到需要训练很多次来拟合数据的情况,假设需要拟合1000次数据,那么可能前800次的拟合效果都不是很好,所以显示进度条就会使得输出面板 ...

  8. [深度学习-实践]GAN入门例子-利用Tensorflow Keras与数据集CIFAR10生成新图片

    系列文章目录 深度学习GAN(一)之简单介绍 深度学习GAN(二)之基于CIFAR10数据集的例子; 深度学习GAN(三)之基于手写体Mnist数据集的例子; 深度学习GAN(四)之PIX2PIX G ...

  9. 【Keras】Win10系统 + Anaconda+TensorFlow+Keras 环境搭建教程

    1. 安装 Anaconda 打开 Anaconda 的官方下载地址:https://www.anaconda.com/download/ 选择 Python 对应的version 下载.下载完成后直 ...

最新文章

  1. HTTP_响应消息_响应行_状态码
  2. redis集群的三种模式
  3. 计算机组成原理实验串行口,计算机组成原理实验2.ppt
  4. 线程、多线程和线程池,看完这些你就能全部搞懂了
  5. onnx 测试_YOLOv5来了!Pytorch实现,支持ONNX和CoreML
  6. Git中的“起源”是什么?
  7. 一文让你读懂Macbook的使用技巧及命令
  8. 我从可用性测试中学到的五件事
  9. 排序算法专题-归并排序
  10. unity天空盒渐变_在Unity3D中使用天空盒
  11. 如何将Vue中表格数据,以Excel格式导出?报saveAs错误如何解决?
  12. paddlepaddle(六)模型保存与载入
  13. LeetCode 0417「太平洋大西洋水流问题」
  14. 找不到com.sun.beans.introspect.PropertyInfo的类文件问题
  15. 把路由器变成音乐播放器和网络收音机,支持摇控
  16. 世界顶级思维(必须收藏)
  17. 股票交易日(动态规划)----美团2016研发工程师编程题(二)
  18. 计算机管理找不到文件怎么办,Windows找不到文件怎么办
  19. linux不能强制显卡分辨率,Linux系统装显卡驱动及分辨率不正常的解决方法
  20. mysql中的gpl是什么意思_GPL是什么意思?急

热门文章

  1. 换一个灯泡需要多少程序员?
  2. Linux虚拟机安装gcc(解决依赖)
  3. 【Gis】Alpha Shapes提取离散点凹边轮廓线(java实现)
  4. 求助帖;RxtxFAX怎样通过调用传真服务器的串口COM1,COM2,通过电话线座机号发送传真?
  5. Java 继承底层实现原理
  6. 微信小程序导出Excel文件
  7. 微信小程序——利用java后台解析Excel文件的数据
  8. 8月末推荐伤感语录大全_我的世界太过安静
  9. 打游戏用什么耳机比较好?性价比高的游戏蓝牙耳机推荐
  10. Java基础算法50题(一)