从零点一开始机器学习之TF1.0版本HDF5转换为saved_model

从零点一开始机器学习之TF1.0版本HDF5转换为saved_model

赶鸭子上架搞机器学习,此系列希望能够帮助新手入门,或者其他开发人员快速上手机器学习,并用在项目中(我们刚开始可能是“掉包侠”,但是对于后续理论的学习也是必不可少的喔)
为什么是0.1而不是0呢?应为我是从其他语言体系转到机器学习中,以前积累的一些其他经验可以快速帮助我们上手,所以是0.1。
如果本文对你有所帮助,欢迎评论点赞收藏,如有错误,欢迎指正。

系列文章目录

从零点一开始机器学习之晦涩难懂的各种概念
从零点一开始机器学习之Win10 64位下安装Cuda+Cudnn
从零点一开始机器学习之GPU运算性能和CPU性能对比(GPU算力表)
从零点一开始机器学习之TF1.0版本HDF5转换为saved_model
从零点一开始机器学习之HDF5模型发布到tensorflow/serving
Python中tensorflow Import使用错误集合2035298)

TF1.0版本HDF5转换为saved_model

  • 从零点一开始机器学习之TF1.0版本HDF5转换为saved_model
      • 系列文章目录
  • 前言
  • 一、hdf5转换为pb模型
  • 二、pb模型转saved_model形式
  • BUG解决
    • 1.keras_contrib.layers不存在
    • 2 tf2.0版本运行1.0版本代码报错module 'tensorflow._api.v2' has no 'builder'

前言

在tf1.0版本系列下我们应该如何转换hdf5到saved_model形式呢?如下所示,此代码未在1.0环境下运行验证。
环境说明 环境和版本很重要,大量的博客没有环境说明和版本介绍,对新人很不友好
tensorflow版本:tf2.0系列
vggmodel_22-0.15-0.95.hdf5:

一、hdf5转换为pb模型

h52pb_1.py代码

# -*- coding: utf-8 -*-
import os
import tensorflow as tf

from tensorflow.python.framework import graph_util
from tensorflow.python.framework import graph_io
from pathlib import Path
from absl import app
from absl import flags
from absl import logging
import keras
from keras import backend as K
from keras.models import model_from_json
from keras_contrib.layers import CRF
from keras_contrib.losses import crf_loss
from keras_contrib.metrics import crf_accuracy
from keras_bert import get_custom_objects


custom_objects = get_custom_objects()
for key, value in {'CRF': CRF, 'crf_loss': crf_loss, 'crf_accuracy': crf_accuracy}.items():
    custom_objects[key] = value

K.set_learning_phase(0)
FLAGS = flags.FLAGS

flags.DEFINE_string('input_model', "./h5_model/vggmodel_22-0.15-0.95.hdf5", 'Path to the input model.')
flags.DEFINE_string('input_model_json', None, 'Path to the input model '
                                              'architecture in json format.')
flags.DEFINE_string('output_model', "./pb_model/example_ner.pb", 'Path where the converted model will '
                                          'be stored.')
flags.DEFINE_boolean('save_graph_def', False,
                     'Whether to save the graphdef.pbtxt file which contains '
                     'the graph definition in ASCII format.')
flags.DEFINE_string('output_nodes_prefix', None,
                    'If set, the output nodes will be renamed to '
                    '`output_nodes_prefix`+i, where `i` will numerate the '
                    'number of of output nodes of the network.')
flags.DEFINE_boolean('quantize', False,
                     'If set, the resultant TensorFlow graph weights will be '
                     'converted from float into eight-bit equivalents. See '
                     'documentation here: '
                     'https://github.com/tensorflow/tensorflow/tree/master/tensorflow/tools/graph_transforms')
flags.DEFINE_boolean('channels_first', False,
                     'Whether channels are the first dimension of a tensor. '
                     'The default is TensorFlow behaviour where channels are '
                     'the last dimension.')
flags.DEFINE_boolean('output_meta_ckpt', False,
                     'If set to True, exports the model as .meta, .index, and '
                     '.data files, with a checkpoint file. These can be later '
                     'loaded in TensorFlow to continue training.')

flags.mark_flag_as_required('input_model')
flags.mark_flag_as_required('output_model')


def load_model(input_model_path, input_json_path):
    if not Path(input_model_path).exists():
        raise FileNotFoundError(
            'Model file `{}` does not exist.'.format(input_model_path))
    try:
        # 下面一行已经修改,在改回普通的Keras加载模型时,需要去掉custom_objects
        model = keras.models.load_model(input_model_path, custom_objects=custom_objects)
        return model
    except FileNotFoundError as err:
        logging.error('Input mode file (%s) does not exist.', FLAGS.input_model)
        raise err
    except ValueError as wrong_file_err:
        if input_json_path:
            if not Path(input_json_path).exists():
                raise FileNotFoundError(
                    'Model description json file `{}` does not exist.'.format(
                        input_json_path))
            try:
                model = model_from_json(open(str(input_json_path)).read())
                model.load_weights(input_model_path)
                return model
            except Exception as err:
                logging.error("Couldn't load model from json.")
                raise err
        else:
            logging.error(
                'Input file specified only holds the weights, and not '
                'the model definition. Save the model using '
                'model.save(filename.h5) which will contain the network '
                'architecture as well as its weights. If the model is '
                'saved using model.save_weights(filename), the flag '
                'input_model_json should also be set to the '
                'architecture which is exported separately in a '
                'json format. Check the keras documentation for more details '
                '(https://keras.io/getting-started/faq/)')
            raise wrong_file_err


def main(args):
    logging.info("begin====================================================")
    # If output_model path is relative and in cwd, make it absolute from root
    output_model = FLAGS.output_model
    if str(Path(output_model).parent) == '.':
        output_model = str((Path.cwd() / output_model))

    output_fld = Path(output_model).parent
    output_model_name = Path(output_model).name
    output_model_stem = Path(output_model).stem
    output_model_pbtxt_name = output_model_stem + '.pbtxt'

    # Create output directory if it does not exist
    # print (Path(output_model).parent)
    if not os.path.exists(str(Path(output_model).parent)):
        Path(output_model).parent.mkdir(parents=True)

    if FLAGS.channels_first:
        K.set_image_data_format('channels_first')
    else:
        K.set_image_data_format('channels_last')

    model = load_model(FLAGS.input_model, FLAGS.input_model_json)

    input_node_names = [node.op.name for node in model.inputs]
    logging.info('Input nodes names are: %s', str(input_node_names))

    # TODO(amirabdi): Support networks with multiple inputs
    orig_output_node_names = [node.op.name for node in model.outputs]
    if FLAGS.output_nodes_prefix:  # 给模型节点编号
        num_output = len(orig_output_node_names)
        pred = [None] * num_output
        converted_output_node_names = [None] * num_output

        # Create dummy tf nodes to rename output
        for i in range(num_output):
            converted_output_node_names[i] = '{}{}'.format(
                FLAGS.output_nodes_prefix, i)
            pred[i] = tf.identity(model.outputs[i],
                                  name=converted_output_node_names[i])
    else:
        converted_output_node_names = orig_output_node_names
    logging.info('Converted output node names are: %s',
                 str(converted_output_node_names))

    sess = K.get_session()
    if FLAGS.output_meta_ckpt:  # 让转化的模型可以继续被训练
        saver = tf.train.Saver()
        saver.save(sess, str(output_fld / output_model_stem))

    if FLAGS.save_graph_def:  # 以ascii形式存储模型
        tf.train.write_graph(sess.graph.as_graph_def(), str(output_fld),
                             output_model_pbtxt_name, as_text=True)
        logging.info('Saved the graph definition in ascii format at %s',
                     str(Path(output_fld) / output_model_pbtxt_name))

    if FLAGS.quantize:  # 将权重从float转为八位比特
        from tensorflow.tools.graph_transforms import TransformGraph
        transforms = ["quantize_weights", "quantize_nodes"]
        transformed_graph_def = TransformGraph(sess.graph.as_graph_def(), [],
                                               converted_output_node_names,
                                               transforms)
        constant_graph = graph_util.convert_variables_to_constants(
            sess,
            transformed_graph_def,
            converted_output_node_names)
    else:  # float形式存储权重
        constant_graph = graph_util.convert_variables_to_constants(
            sess,
            sess.graph.as_graph_def(),
            converted_output_node_names)

    graph_io.write_graph(constant_graph, str(output_fld), output_model_name,
                         as_text=False)
    logging.info('Saved the freezed graph at %s',
                 str(Path(output_fld) / output_model_name))


if __name__ == "__main__":
    app.run(main)

二、pb模型转saved_model形式

pb2saved_1.py

# -*- coding: utf-8 -*-
import os
import tensorflow as tf
from tensorflow.python.saved_model import signature_constants
from tensorflow.python.saved_model import tag_constants
from keras_bert import get_custom_objects
from keras_contrib.layers import CRF
from keras_contrib.losses import crf_loss
from keras_contrib.metrics import crf_accuracy
from keras.models import load_model

custom_objects = get_custom_objects()
for key, value in {'CRF': CRF, 'crf_loss': crf_loss, 'crf_accuracy': crf_accuracy}.items():
    custom_objects[key] = value

export_dir = './pb_model/1'
graph_pb = './pb_model/vggmodel_22-0.15-0.95.pb'
model = load_model('./h5_model/vggmodel_22-0.15-0.95.hdf5', custom_objects=custom_objects)

builder = tf.compat.v1.saved_model.builder.SavedModelBuilder(export_dir)
with tf.gfile.GFile(graph_pb, "rb") as f:
    graph_def = tf.GraphDef()
graph_def.ParseFromString(f.read())


sigs = {}
with tf.Session(graph=tf.Graph()) as sess:
    tf.import_graph_def(graph_def, name="")

    g = tf.get_default_graph()

    sigs[signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY] = \
        tf.saved_model.signature_def_utils.predict_signature_def(
            inputs={"input_1": g.get_operation_by_name('input_1').outputs[0], "input_2": g.get_operation_by_name('input_2').outputs[0]},
            outputs={"output": g.get_operation_by_name('crf_1/one_hot').outputs[0]}
        )

    builder.add_meta_graph_and_variables(sess,
                                        [tag_constants.SERVING],
                                        signature_def_map = sigs)

    builder.save()

BUG解决

1.keras_contrib.layers不存在

from keras_contrib.layers import CRF报错,明显包不存在
pip安装一个

pip install git+https://www.github.com/keras-team/keras-contrib.git

很慢,而且可能报错timeout,切换github国内镜像
把 github.com 替换为 github.com.cnpmjs.org,其余保持不变,速度直接起飞,安装完成后可能需要重启VsCode,才能去掉波浪线。

2 tf2.0版本运行1.0版本代码报错module ‘tensorflow._api.v2’ has no ‘builder’

2.0版本不兼容1.0版本代码
将tf.saved_model.builder.SavedModelBuilder(export_dir)
修改为builder = tf.compat.v1.saved_model.builder.SavedModelBuilder(export_dir)
参考连接传送门https://tensorflow.google.cn/versions/r1.15/api_docs/python/tf/saved_model/Builder
在这里插入图片描述
博文参考:https://blog.csdn.net/jclian91/article/details/112712948

你可能感兴趣的:(机器学习,机器学习,人工智能,tensorflow)