TensorFlow相关教程(概念版)

一、参考资料

简单粗暴 TensorFlow 2
简单粗暴 TensorFlow 2 | A Concise Handbook of TensorFlow 2
TensorFlow 中文文档
TensorFlow 英文文档
tensorflow2.0的函数签名与图结构
Tensorflow - AI研习社

二、相关介绍

1. tensorflow命名空间

scope 命名方法
tensorflow中的scope命名方法:name_scope, variavle_scope

2. tag标签

tag 是用来区别不同的 MetaGraphDef,这是在加载模型所需要的参数。其默认值是 tag_constants.SERVING (“serve”)

from tensorflow.python.saved_model import tag_constants

tag_train = tag_constants.TRAINING
tag_serve = tag_constants.SERVING
tag_gpu = tag_constants.GPU
tag_tpu = tag_constants.TPU
import tensorflow.compat.v1 as tf
tf.disable_v2_behavior()

tag_train = tf.saved_model.tag_constants.TRAINING
tag_serve = tf.saved_model.tag_constants.SERVING
tag_gpu = tf.saved_model.tag_constants.GPU
tag_tpu = tf.saved_model.tag_constants.TPU

3. Eager模式

Eager模式在TensorFlow v1.5首次引入,它是一种交互模式(命令行模式),每进行一步输入就可以得出一步结果,而无需构建计算图。

引入的Eager Execution模式后, TensorFlow就拥有了类似于Pytorch一样动态图模型能力, 我们可以不必再等到see.run(*)才能看到执行结果,可以方便在IDE随时调试代码,查看OPs执行结果。Eager模式极大的方便TensorFlow的使用和模型调试,增加了网络调试的灵活程度和TensorFlow对于初学者友好性。

TensorFlow 1.X 版本可以通过 tf.enable_eager_execution() 方法来启用动态图机制,TensorFlow 2.X默认启用Eager模式

开启Eager模式

import tensorflow as tf
tf.enable_eager_execution

查看是否启用Eager模式

import tensorflow as tf
tf.executing_eagerly()

三、TensorFlow各种模型格式

tensorflow 模型导出总结
Tensorflow模型保存方式大汇总
辨析tensorflow模型存储形式:checkpoint、graphdef、savedmodel、frezzemodel
tensorflow模型保存(三)——tensorflow1.x版本的savedmodel格式的模型保存与加载
Tensorflow笔记:模型保存、加载和Fine-tune

0. 简介

针对不同场景,tensorflow 1.x 以及2.x 提供了多种不同的模型导出格式,例如有 checkpointSavedModelFrozen GraphDefKeras model(HDF5) 以及用于移动端、嵌入式的 TFLite

  • Checkpoint: 用于保存模型的权重,主要用于模型训练过程中参数的备份和模型训练热启动。
  • GraphDef:用于保存模型的Graph,不包含模型权重,加上checkpoint后就有模型上线的全部信息。
  • SavedModel:使用saved_model接口导出的模型文件,包含模型Graph和权限可直接用于上线,TensorFlow和Keras模型推荐使用这种模型格式。
  • FrozenGraph:使用 freeze_graph.py 对checkpoint和GraphDef进行整合和优化,可以直接部署到Android、iOS等移动设备上。
  • TFLite:基于flatbuf对模型进行优化,可以直接部署到Android、iOS等移动设备上,使用接口和FrozenGraph有些差异。

模型导出主要包含了:参数以及网络结构的导出,不同的导出格式可能是分别导出,或者是整合成一个独立的文件。

  • 权重参数和网络结构分开保存:checkpoint, SavedModel;
  • 只保存权重:HDF5(可选);
  • 权重参数和网络结构保存为一个文件:Frozen GraphDef,HDF5(可选)。

TensorFlow 1.x

在TensorFlow 1.x中,可以见下图,主要有三种主要的API,KerasEstimator,以及 Legacy 即最初的session模型,其中 tf.Keras 主要保存为 HDF5Estimator保存为SavedModel,而 Lagacy主要保存为 Checkpoint,并且可以通过 freeze_graph,将模型变量冻结,得到 Frozen GradhDef 文件。这三种格式的模型,都可以通过 TFLite Converter 导出为 .tflite 的模型文件,用于安卓/ios/嵌入式设备的serving。

在这里插入图片描述

TensorFlow 2.x

在TensorFlow 2.x中,推荐使用 SavedModel 进行模型的保存,所以keras默认导出格式是 SavedModel,也可以通过显性使用 .h5 后缀,使得保存的模型格式为HDF5 。 此外其他low level API,都支持导出为SavedModel 格式,以及 Concrete FunctionsConcrete Function 是一个签名函数,有固定格式的输入和输出。

1. Frozen GraphDef 格式(pb格式)

请参考另一篇博客:TensorFlow之pb模型保存和加载

2. SavedModel格式

请参考另一篇博客:TensorFlow之SavedModel模型保存和加载

3. checkpoint格式

checkpint 的导出是网络结构和权重参数分开保存的。一个checkpoint 由两个部分以及三个文件组成,其中网络结构部分(meta文件),以及权重参数部分(参数名:index,参数值:data)

checkpoint文件如下所示:

checkpoint # 列出该目录下,保存的所有的checkpoint列表,下面有具体的例子
events.out.tfevents.1583930869.prod-cloudserver-gpu169 # tensorboad可视化所需文件,可以直观展示模型的结构

# model.ckpt-13000表示前缀,代表第13000 global steps时的保存结果,当加载指定checkpoint时,只需要说明前缀即可
model.ckpt-13000.index # 表示参数名
model.ckpt-13000.data-00000-of-00001 # 表示参数值
model.ckpt-13000.meta # 表示网络结构

3.1 保存checkpoint模型

  • TensorFlow 1.x

    # in tensorflow 1.x
    saver = tf.train.Saver()
    saver.save(sess=session, save_path=args.save_path)
    
  • estimator

    # estimator
    """
    通过 RunConfig 配置多少时间或者多少个steps 保存一次模型,默认600s 保存一次。
    具体参考 https://zhuanlan.zhihu.com/p/112062303
    """
    run_config = tf.estimator.RunConfig(
        model_dir=FLAGS.output_dir, # 模型保存路径
        session_config=config,
        save_checkpoints_steps=FLAGS.save_checkpoints_steps, # 多少steps保存一次ckpt
        keep_checkpoint_max=1)
    estimator = tf.estimator.Estimator(
      model_fn=model_fn,
      config=run_config,
      params=None
    )
    

3.2 加载checkpoint模型

  • TensorFlow 1.x

    # tf1.0
    session = tf.Session()
    session.run(tf.global_variables_initializer())
    saver = tf.train.Saver()
    saver.restore(sess=session, save_path=args.save_path)  # 读取保存的模型
    

    对于estimator 会自动 load output_dir 中的最新的ckpt,通常用 model_file = tf.train.latest_checkpoint(FLAGS.output_dir) 获取最新的ckpt。

  • TensorFlow 2.x

    import os
    import tensorflow.compat.v1 as tf
    tf.disable_v2_behavior()
    
    
    def restore_model_ckpt(ckpt_file_path="./ckpt"):
        sess = tf.Session()
    
        saver = tf.train.import_meta_graph(os.path.join(ckpt_file_path, "model.ckpt.meta"))
    
        saver.restore(sess, tf.train.latest_checkpoint(ckpt_file_path))
    
        # 直接获取保存的变量
        print(sess.run('b:0'))
    
        # 获取placeholder变量
        input_x = sess.graph.get_tensor_by_name('x_input:0')
        input_y = sess.graph.get_tensor_by_name('y_input:0')
        # 获取需要进行计算的operator
        op = sess.graph.get_tensor_by_name('output:0')
    
        # 加入新的操作
        add_on_op = tf.multiply(op, 2)
    
        ret = sess.run(add_on_op, feed_dict={input_x: 10, input_y: 3})
        print(ret)
    
    

4. HDF5格式

4.1 保存/导出HDF5模型

  • 导出整个模型

    """TensorFlow 1.x 默认是HDF5,但是2.0中,默认是SavedModel,所以需要显性地指定`.h5`后缀"""
    model.save('my_model.h5') 
    # 或者
    model.save('my_model.h5', save_format="h5") 
    
  • 导出模型weights

    """keras 1.0"""
    model.save_weights('my_model_weights.h5')
    

4.2 加载/导入HDF5模型

  • 加载整个模型(无自定义部分)

    """keras 1.0"""
    from keras.models import load_model
    model = load_model(model_path)
    
    """keras 2.0"""
    new_model = tf.keras.models.load_model('my_model.h5')
    
  • 加载整个模型(含自定义部分)
    对于有自定义layers的或者实现的模型加载,需要增加dependencies 的映射字典,示例如下:

    dependencies = {'MyLayer': MyLayer(), 'auc': auc, 'log_loss': log_loss}
    model = load_model(model_path, custom_objects=dependencies, compile=False)
    

4.3 自定义Keras模型

使用继承 tf.keras.Model 类建立的 Keras 模型同样可以用 tf.saved_model.save(model, "xxx") 的方法导出,唯须注意 call 方法需要以 @tf.funtion 修饰,以转化为 SavedModel 支持的计算图。

5. TFLite格式

Frozen GraphDef 转 TFLite

tflite_convert --graph_def_file ./models/frozen_graph.pb \
               --input_arrays 'x_input,y_input' \
               --output_arrays 'output'\
               --input_shapes 1:1 \
               --output_file frozen_graph.tflite \
               --enable_v1_converter \
               --experimental_new_converter

参数解释

  • input_arrays:输入节点的名称,多个用逗号隔开;
  • output_arrays:输出节点的名称,多个用逗号隔开;
  • input_shapes:输入节点的尺寸,多个用冒号隔开;

SavedModel 转 TFLite

//TODO

“Only support at least one signature key.” when trying converting a tensorflow model to tensorflow lite model
Tflite converter signature error

四、常用TensorFlow库

1. TensorBoard

使用 tensorboard --logdir PATH_TO_CHECKPOINT: tensorboard 会调用 events.out.tfevents.*
文件,并生成tensorboard,如下图所示:

在这里插入图片描述

1.1 生成log日志

def print_pb_info_v1(pb_path):
    """
    打印pb模型可视化结构
    :param pb_path: pb模型文件的路径
    :return:
    """
    tf.reset_default_graph()  # 重置计算图
    output_graph_path = pb_path
    with tf.Session() as sess:
        tf.global_variables_initializer().run()
        output_graph_def = tf.GraphDef()
        # 获得默认的图
        graph = tf.get_default_graph()
        with open(output_graph_path, "rb") as f:
            output_graph_def.ParseFromString(f.read())
            _ = tf.import_graph_def(output_graph_def, name="")
            # 在log_graph文件夹下生产日志文件,可以在tensorboard中可视化模型
            _ = tf.summary.FileWriter('log_pb/', graph)

1.2 生成 TensorBoard

tensorboard --logdir="/PATH/TO/log_pb"

1.3 查看 TensorBoard

http://localhost:6006/

2. TensorFlow Serving

tf.saved_model.save模型导出、TensorFlowServing模型部署。。。

2.1 引言

当我们将模型训练完毕后,往往需要将模型在生产环境中部署。最常见的方式,是在服务器上提供一个 API,即客户机向服务器的某个 API 发送特定格式的请求,服务器收到请求数据后通过模型进行计算,并返回结果。如果仅仅是做一个 Demo,不考虑高并发和性能问题,其实配合 Flask 等 Python 下的 Web 框架就能非常轻松地实现服务器 API。

如果是在真的实际生产环境中部署,这样的方式就显得力不从心了。这时,TensorFlow 为我们提供了 TensorFlow Serving 这一组件,能够帮助我们在实际生产环境中灵活且高性能地部署机器学习模型。

2.2 简介

TensorFlow Serving是一种灵活的高性能服务系统,适用于机器学习模型,专为生产环境而设计。TensorFlow Serving可以进行算法和实验,同事保持相同的服务器架构和API。TensorFlow Serving提供与TensorFlow模型的开箱即用集成,可以轻松部署其他类型的模型和数据。

2.3 特点

TensorFlow Serving支持热更新模型,其典型的模型文件结构如下:

Saved_Model_files
├── 1  # 版本号为1的模型文件
│   ├── assets
│   ├── variables
│   ├── saved_model.pb
...
├── N # 版本号为N的模型文件
│   ├── assets
│   ├── variables
│   ├── saved_model.pb

从上面结构中,1-N的子文件夹代表不同版本号的模型。当指定 --model_base_path 时,只需要指定根目录的绝对路径(不是相对路径),例如 /PATH/TO/Saved_Model_filesTensorFlow Serving会自动选择版本号最大的模型进行载入

五、常用API

input_signature

@tf.function 可以给普通的python函数签名,再给它加上 input_signature, 可以让这个python函数变成一个可以保存的tensorflow 图结构(SavedModel)。

input_signature 可以限定函数的输入类型,以防止调用函数时调错。比如,定义函数的输入类型为 tf.int32,调用时的输入类型为 float32,导致函数调用失败。

@tf.function(input_signature=[tf.TensorSpec([None], tf.int32, name='x')])
def cube(z): #实现输入的立方
    return tf.pow(z, 3)
try:
    print(cube(tf.constant([1., 2., 3.])))
except ValueError as ex:
    print(ex)
# 输出
Python inputs incompatible with input_signature:
  inputs: (
    tf.Tensor([1. 2. 3.], shape=(3,), dtype=float32))
  input_signature: (
    TensorSpec(shape=(None,), dtype=tf.int32, name='x'))

正确调用方式:

print(cube(tf.constant([1, 2, 3])))

# 输出
tf.Tensor([ 1  8 27], shape=(3,), dtype=int32)

get_concrete_function()

调用 get_concrete_function 函数后,输出的是一个 ConcreteFunction 对象。

# @tf.function py func -> tf graph
# get_concrete_function -> add input signature -> SavedModel
 
cube_func_int32 = cube.get_concrete_function(
    tf.TensorSpec([None], tf.int32)) #tensorflow的类型
print(cube_func_int32)
# 输出
ConcreteFunction cube(z)
  Args:
    z: int32 Tensor, shape=(None,)
  Returns:
    int32 Tensor, shape=(None,)
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

花花少年

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值