tensorflow_知识点


1. tensorflow动态图和静态图切换

  动态图是Tensorflow1.3版本之后出现的,到1.11版本时,已经比较完善。在2.0之后版本为默认工作方式。
        tensorflow2.X 关闭动态图的函数 

tf.compat.v1.disable_v2_behavior 

        启用动态图的函数:

tf.compat.v1.enable_v2_behavior 

2.tensor和numpy互转

  静态图中,tensor和numpy不能互转。动态图 可以转化

data_tensor= tf.convert_to_tensor(data_numpy) # numpy转tensor 显式转换。大多数情况tensor接收到numpy会自动转化

  data_numpy = data_tensor.numpy() # tensor转numpy

3.声明函数为静态图

  在函数前面加上 "@tf.function"  。函数将以张量运算图运行。自东土中,如果在被修饰的函数有多个返回分支,则必须确保所有的分支都返回相同类型的张量,否则会报错

4.在静态图中使用动态图

  tensorflow2.X提供 在静态图使用动态图操作方式的封装关键字"tf.py_function"

  

tf.compat.v1.disable_v2_behavior # 使用静态图方式

def my_py_func(X,Y):
    ……
    return z


z=tf.py_function(my_py_func,[X,Y] ,tf.float32)
#后续接静态图调用过程代码
……


#程序执行时,my_py_func内 的tensor都是 “EaderTensro”动态tensor类型,因此可以numpy等数据类型相互转换调用

 

5.静态图和动态图性能差异

  2021-9月份,数据集3万张,8个类。分别在批次=20,128下测试

  测试以下三种方式:tf.kreas静态图方式, 2.X全部动态图方式,2.X部分动态图方式(train_step 使用 @tf.function 修饰,其余动态图) 。取三次情况做平均。测试结果如下

      20批次(显卡6G显存): 以静态图为基准, 全动态图耗时是 140% , 部分动态图 100%

      128批次(显卡24显存): 以静态图为基准,全部动态图耗时100% , 部分动态图 115% 

  似乎动态图性能都能找到方式和静态图一样的执行效率

6.冻结网络层

  tensorflow只需要更改模型的"trainable" 属性即可完成更改。更改完,需要调用 模型的"compile"函数,完成关联项更改

  trainable 的优先级,高级覆盖低级

  

model.trainable = False
model.layers[0].trainable = False
model.layers[1].trainable = True
model.compile(……)

此时,整个模型都不可训练

model.trainable = True
model.layers[0].trainable = False
model.layers[1].trainable = True
model.compile(……)
此时, 模型的layers层中设置使能性能的,进行巡礼。 比如训练过程 层0将不会进行参数更新。 层1将进行参数。
如果要详细查看 可以设定动态图,然后调试过程中 查看“self.model.trainable_weights”的值

7.迁移学习中,只训练输出层

  参考“冻结网络层”, 将其余层的训练使能设为“False”,输出层的训练使能启用。

 

8. Loaded cuDNN version 8204 后程序退出

  模型能够加载, 但是执行如下语句

y = model(x, training=True)

 程序不报异常,直接结束执行。 

  原因: cuda,cudnn 和tensorflow版本不匹配。tensorflow官网 安装页面 “GPU支持”有cuda11.2字样, 最下面又有cuda11.1 。 并且安装的适合没有像 pytorch ,直接在安装语句指定 cuda版本。 误以为安装最新版本都支持。因此安装cuda11.4+cudnn8.2 。 

  解决办法:按照tensorflow官网-》源代码构建 -》Windows   

 

  版本对应关系,安装后解决。

       PS: 安装最新版本驱动,再安装cuda11.2 会报 已经安装更新版本,无法安装cuda11.2。此时需要手动卸掉 。 安装cuda后,再安装一次显卡驱动。 

9. 集成学习(ensemble learning)合并网络时,报错“ValueError: Graph disconnected: cannot obtain value for tensor KerasTensor(type_spec=TensorSpec(shape=(None, 224, 224, 3), dtype=tf.float32, name='input_2'), name='input_2', ……". The following previous layers were accessed without issue: []”

  #错误代码
for ……   inputs.append(models[index_model].input )   outputs.append( sub_models[index_model].get_layer(merge_layer_name).output)
  output_concat = tf.keras.layers.Concatenate()( outputs )
  tf.keras.models.Model(inputs,output_concat )

将多个模型合并成一个,重命名层名后,合并。 执行到Model()时,函数报找不到梯度图。 后面查找,发现原来的代码是取原来网络 第一层网络的input  和需要合并层的网络输出,进行合并。  

 #正确的代码   
#假定模型是俩层嵌套。 输入和 合并的网络层都在第二层嵌套中。
  for …… inputs.append(models[index_model].layers[0].input ) outputs.append(models[index_model].get_layer( "目标层父亲层名").get_layer("目标层名".output)   output_concat = tf.keras.layers.Concatenate()( outputs )   model = tf.keras.models.Model(inputs, output_concat )   #代码运行成功

  

 原因是:模型input和 “layers”层之间数据流方式不一样。可能改名之后,layers之间的数据流向跟着变,而模型的input等没有跟着更改。

解决办法:找到最开始的最底层的input , 找到具体要合并的层,返回output 。 

10. tensorflow2.X 读入 frozen graph 形式pb文件

tensorflow 的pb文件有俩种,一种是saved_model_dir ,文件形式是文件夹;一种是 frozen graph in text or binary format ,形式是单个文件夹。 对于前者读取,网上搜下,一句函数搞定,对于后者搜索非常多,总感觉少掉 Graph Def 转使用的模型。 后面终于在csdn的 vokxchh:Python3.7的Tensorflow2.0 图像分类的模型生成与读取  的代码找到加载方法。

#包裹冻结图
def wrap_frozen_graph(graph_def, inputs, outputs, print_graph=False):
     
    def _imports_graph_def():
        tf.compat.v1.import_graph_def(graph_def, name="")

    wrapped_import = tf.compat.v1.wrap_function(_imports_graph_def, [])
    import_graph = wrapped_import.graph
    print("-" * 50)
    print("Frozen model layers: ")
    layers = [op.name for op in import_graph.get_operations()]
    if print_graph == True:
        for layer in layers:
            print(layer)
    print("-" * 50)
    return wrapped_import.prune(
        tf.nest.map_structure(import_graph.as_graph_element, inputs),
 
        tf.nest.map_structure(import_graph.as_graph_element, outputs))

#读取pb文件 with tf.io.gfile.GFile(
"./frozen_models/frozen_graph.pb", "rb") as f: graph_def = tf.compat.v1.GraphDef() #默认是二进制的按这样读取。如果是text,需要网上找函数 loaded = graph_def.ParseFromString(f.read()) #转化为可以使用的模型 frozen_func = wrap_frozen_graph(graph_def=graph_def, inputs=["Input:0"], #输入层的节点名称 outputs=["Identity:0"], #输出层的节点名称 print_graph=True) #True打印所有层名 #后续的使用就是 outputs = frozen_func(batch_data) #注意outputs是 list的EagerTensor

测试冻结的PB比 未作处理的“saved_model_dir”,运行速度快3.5倍。因此建议需要用tensorflow模型时,使用变量冻结常量操作,保存为 frozen graph 形式pb文件。

后面又找到类似上述代码更早的地址“Lei Mao”的github博客:

Save, Load and Inference From TensorFlow 2.x Frozen Graph

冻结部分可以参考他的。

 

posted @ 2021-10-13 16:42  飘零_未知的坚持  阅读(245)  评论(0编辑  收藏  举报