如需转载请向本人确认~谢谢!
本系列文章中前几篇介绍了
tensorflow提供的android demo工程的结构;https://blog.csdn.net/c20081052/article/details/83145836
其目标检测的运行(工程默认的ssd-mobilenet v1),https://blog.csdn.net/c20081052/article/details/82865830
以及将yolo v2模型运行;https://blog.csdn.net/c20081052/article/details/83659476
所有的相似点就是该工程目前似乎只支持用户提供pb文件。(其实后来发现weights貌似可以直接读,后面会写文章阐述)
其中网上提供了yolo转为pb格式的权重文件可在链接中下载:https://drive.google.com/drive/folders/1GfS1Yle7Xari1tRUEi2EDYedFteAOaoN
(比如将yolo训练的.weights转为.pb;将keras训练的.h5转为.pb文件)
网上有较为成熟的第三方工具:darkflow (链接:darkflow)该链接提供了详细的安装方式,你需要编译生成一个可执行文件“flow”,最后你在转换时需要使用如下指令即可:
## Saving graph and weights to protobuf file
flow --model cfg/yolo.cfg --load bin/yolo.weights --savepb
When saving the .pb
file, a .meta
file will also be generated alongside it. This .meta
file is a JSON dump of everything in the meta
dictionary that contains information nessecary for post-processing such as anchors
and labels
. This way, everything you need to make predictions from the graph and do post processing is contained in those two files - no need to have the .cfg
or any labels file tagging along.
The created .pb
file can be used to migrate the graph to mobile devices (JAVA / C++ / Objective-C++). The name of input tensor and output tensor are respectively 'input'
and 'output'
. For further usage of this protobuf file, please refer to the official documentation of Tensorflow
on C++ API here. To run it on, say, iOS application, simply add the file to Bundle Resources and update the path to this file inside source code.
会在master文件夹的built_graph下生成两个模型文件:
*****但上诉第三方工具目前只支持yolo v1和 yolo v2以及他们的tiny版本;对于yolo v3本人尝试了,并没有成功(或是成功了,没啥印象了……)~
由于目前有tensorflow-keras方式训练yolo v3的方法,而且有现成的脚本将yolo的weights转为h5文件;
keras训练yolo的的仓库链接为:A Keras implementation of YOLOv3 (Tensorflow backend)
具体有如下使用方法:
Quick Start
wget https://pjreddie.com/media/files/yolov3.weights
python convert.py yolov3.cfg yolov3.weights model_data/yolo.h5
python yolo_video.py [OPTIONS...] --image, for image detection mode, OR
python yolo_video.py [video_path] [output_path (optional)]
使用其中的convert.py可将weights转为.h5文件,而且也可以用该仓库直接训练yolo v3生成h5文件;
有一点需要注意的是:用convert.py文件转h5时,需要传入yolo的weights和cfg文件,导出的h5文件格式有两种情况!!
convert.py文件中有如下内容:
上图划线处表示导出的h5文件是只保存了模型的权重信息,那么其结构信息是不在里面的。
如何保存 Keras 模型?
保存/加载整个模型(结构 + 权重 + 优化器状态)
不建议使用 pickle 或 cPickle 来保存 Keras 模型。
你可以使用 model.save(filepath)
将 Keras 模型保存到单个 HDF5 文件中,该文件将包含:
你可以使用 keras.models.load_model(filepath)
重新实例化模型。load_model
还将负责使用保存的训练配置项来编译模型(除非模型从未编译过)。
例子:
from keras.models import load_model
model.save('my_model.h5') # 创建 HDF5 文件 'my_model.h5'
del model # 删除现有模型
# 返回一个编译好的模型
# 与之前那个相同
model = load_model('my_model.h5')
查阅了Keras的官方文档(Keras官方文档)发现,对于模型的保存有如下两种方式:
如果您只需要保存模型的结构,而非其权重或训练配置项,则可以执行以下操作:
# 保存为 JSON
json_string = model.to_json()
# 保存为 YAML
yaml_string = model.to_yaml()
生成的 JSON/YAML 文件是人类可读的,如果需要还可以手动编辑。
你可以从这些数据建立一个新的模型:
# 从 JSON 重建模型:
from keras.models import model_from_json
model = model_from_json(json_string)
# 从 YAML 重建模型:
from keras.models import model_from_yaml
model = model_from_yaml(yaml_string)
如果您只需要 模型的权重,可以使用下面的代码以 HDF5 格式进行保存。
请注意,我们首先需要安装 HDF5 和 Python 库 h5py,它们不包含在 Keras 中。
model.save_weights('my_model_weights.h5')
假设你有用于实例化模型的代码,则可以将保存的权重加载到具有相同结构的模型中:
model.load_weights('my_model_weights.h5')
如果你需要将权重加载到不同的结构(有一些共同层)的模型中,例如微调或迁移学习,则可以按层的名字来加载权重:
model.load_weights('my_model_weights.h5', by_name=True)
例如:
"""
假设原始模型如下所示:
model = Sequential()
model.add(Dense(2, input_dim=3, name='dense_1'))
model.add(Dense(3, name='dense_2'))
...
model.save_weights(fname)
"""
# 新模型
model = Sequential()
model.add(Dense(2, input_dim=3, name='dense_1')) # 将被加载
model.add(Dense(10, name='new_dense')) # 将不被加载
# 从第一个模型加载权重;只会影响第一层,dense_1
model.load_weights(fname, by_name=True)
综上所述需要将convert.py中的model.save_weights更改成model.save生成的h5文件包含了结构信息~这点很重要,因为下一步将h5转为pb调用的文件中需要读取h5的结构信息,否则会报缺少cfg信息的错误!!
上述内容实现了将weights转为h5文件了,接下来就需要将h5转为pb了;
github上有这么个仓库可实现keras to tensorflow(keras to tensorflow)看了相关资料,发现有的人运行成功了有些还有问题;不过建议尝试!
How to use
Keras models can be saved as a single [.hdf5
or h5
] file, which stores both the architecture and weights, using the model.save()
function. 如果这种方式生成的h5文件用下面指令转换:
python keras_to_tensorflow.py
--input_model="path/to/keras/model.h5"
--output_model="path/to/save/model.pb"
Keras models can also be saved in two separate files where a [.hdf5
or h5
] file stores the weights, using the model.save_weights()
function, and another .json
file stores the network architecture using the model.to_json()
function. 如果用这种方式生成的h5文件和json文件用下面指令转换:
python keras_to_tensorflow.py
--input_model="path/to/keras/model.h5"
--input_model_json="path/to/keras/model.json"
--output_model="path/to/save/model.pb"
转换成功后就可以将pb文件导入到tensorflow的android tensorflow的安卓demo工程(四个功能)工程下做目标检测啦~
在拿上面的仓库做h5转pb时可能遇到的错误有:
错误:如果你用keras训练了mobilenet v2得到的h5,且你的keras版本2.2.0以上,tensorflow1.9.0,可能会提示你无法找到relu6;
解析:由于mobilenet有许多自定义的层,包括relu6,为了转换方便,可在load_model之前添加如下内容:
#model = keras.models.load_model(input_model_path)
from keras.utils.generic_utils import CustomObjectScope
with CustomObjectScope({'relu6': keras.applications.mobilenet.relu6,'DepthwiseConv2D': keras.applications.mobilenet.DepthwiseConv2D}):
model = load_model('yourmodelname.hdf5')
return model
如果上面的操作仍解决不了问题,可能是你keras的版本的问题了;网上有如下几种可尝试方式(参考链接:keras训练的mobilenet的h5文件转pb的解决方法):
If your keras is at "from tensorflow.python import keras" instead of at "import keras" then here is what worked for me:
from tensorflow.python.keras._impl.keras.utils.generic_utils import CustomObjectScope
from tensorflow.python.keras._impl.keras.applications import mobilenet
from tensorflow.python.keras._impl.keras.models import load_model
with CustomObjectScope({'relu6': mobilenet.relu6,'DepthwiseConv2D': mobilenet.DepthwiseConv2D}):
model = load_model('weights.hdf5')
或者
有反馈在keras-applications/keras_applications/mobilenet_v2.py找到relu6的;
或者
i downgraded to 2.1.4, it works fine. noticed pr on removing relu6 in 2.2, but the pretrained model still has it.
(将keras换成低版本的2.1.4怀疑2.2之后位置挪了)
或者
from keras_applications import mobilenet as mn 尝试了在keras_applications的mobilenet下找到了relu6;
或者
from keras.layers import DepthwiseConv2D
from keras_applications.mobilenet import relu6
Just for information, before they were imported as
from keras.applications.mobilenet import DepthwiseConv2D, relu6
或者
In Keras2.2, modified to(在keras2.2下更改为)
from keras.utils.generic_utils import CustomObjectScope
with CustomObjectScope({'relu6': keras.layers.ReLU(6.),'DepthwiseConv2D': keras.layers.DepthwiseConv2D}):
model = load_model('weights.hdf5')
或者
convert MobileNet from Keras 2.1.3 to CoreML
或者
此案例可参考案例一方法二中部分~
如果你尝试成功了,请留言告知哈~列出你的库的版本以便大家参考~