请关注我的微信公众号,谢谢啦
在TensorFlow 2中,@tf.function装饰器允许Python函数成为TensorFlow图(或多或少),并可以导致一些性能提升。但是,以这种方式装饰后,Python不再在每次运行时跟踪这些函数。这使得使用Python调试器调试功能更加困难。有没有一种方法可以@tf.function暂时禁用所有装饰器,以便于调试?
解决方案
使用tf.config.experimental_run_functions_eagerly(True)。
tf2+keras,在不使用model.fit的情况下,可以和torch达到同样的效果,就是动态图的效果,数据的流向可以不唯一,模型也可以用tensorboard可视化出来。实际上动态图中用到keras的就只是keras.layer里面的层,例如conv2d,但是动态图的构建方法和torch是一模一样的,你不能直接用model.add,或者keras的函数式来构建模型,而要和torch中类似,现在类的init方法中定义好所有层,然后在call方法中给定数据流动的方向,这里注意,call方法的默认参数是inputs,这个不能变,如果你有多个输入,那应该组合成list或者tuple,一并输入给inputs,然后再在里面解包。有一个非常好理解的例子在https://github.com/Baichenjia/Resnet/blob/master/resnet50.py 这个例子真的让我茅塞顿开。
除了fit和compile方法不能用,keras的summary也没法用,这个功能就是要先建立模型才能输出。否则会报错
File "D:\Anaconda3\envs\tf2\lib\site-packages\tensorflow_core\python\keras\engine\network.py", line 1302, in summary
raise ValueError('This model has not yet been built. '
ValueError: This model has not yet been built. Build the model first by calling `build()` or calling `fit()` with some data, or specify an `input_shape` argument in the first layer(s) for automatic build.
Process finished with exit code 1
原来基于Model对象的方法也都用不了,比如tf.keras.utils.plot_model,这个方法如果给的不是Model(input,output)产生的对象,那么可能输出的只是一张包含函数名的图。
本人对tensorboard是更喜爱的。虽然也写过和用过torch+tensorboardX,但是不大喜欢。唯一的问题是动态图方法的使用导致无法使用fit方法,那么keras用model.fit产生的可爱的进度条也就没了,但是我用tqdm重写了一个,是有效的。其中,bar已经是一个可以迭代的东西,但是附加信息不能动态显示,例如我想像keras一样显示每一个batch的精度,那就得在每次for循环中,通过bar.postfix每次算好了给他也就是了。
不过有一个问题需要注意,第一次前向计算没结束的时候,可还没有精度值呢!也就是说,这个精度显示的其实是上一次的精度,而不是当前这个batch的精度!而且当前这个batch,你还没算呢,怎么可能有精度呢(手动狗头),这不是个技术问题,是个鸡生蛋蛋生鸡的哲学问题。
steps_acc = 0
steps_loss = 0
mmd_loss = torch.tensor(0)
cri_loss = torch.tensor(0)
bar = tqdm(data, total=steps_per_epoch,
desc="a string")
for source_trueColor, source_falseColor, source_dem, \
target_trueColor, target_falseColor, target_dem, \
masks, labels in bar:
bar.postfix = {
'acc': round(steps_acc, 4),
'steps_loss': round(steps_loss, 4),
'mmd_loss': mmd_loss.item(),
'cri_loss': cri_loss.item()
}
下面的错误,原因在于model_final.load_weights(pre_model_path,by_name=True)中的by_name=True,但是如果把by_name=True去掉就会解决这个问题,很奇怪?
Traceback (most recent call last):
File "D:/abc/2-code/fianl_code/pretrain model6/2_预训练分类模型_padding.py", line 100, in <module>
model_final.load_weights(pre_model_path,by_name=True)
File "D:\Anaconda3\envs\tf1\lib\site-packages\tensorflow\python\keras\engine\network.py", line 1514, in load_weights
saving.load_weights_from_hdf5_group_by_name(f, self.layers)
File "D:\Anaconda3\envs\tf1\lib\site-packages\tensorflow\python\keras\engine\saving.py", line 881, in load_weights_from_hdf5_group_by_name
str(weight_values[i].shape) + '.')
ValueError: Layer #97 (named "dense_3"), weight <tf.Variable 'dense_3/kernel:0' shape=(1536, 20) dtype=float32> has shape (1536, 20), but the saved weight has shape (60, 20).
Process finished with exit code 1
keras是可以直接用eager模式构建模型的,简单来说就是可以和tensorflow还有pytorch一样,在调试模式下直接看到每一个tensor的值,这个在某些调试过程中非常重要。因为以往写的代码中,都是无法直接采用eager模式运行的,导致有一些问题无法定位,只能通过Keras稍显晦涩的报错来猜,很痛苦,下面这个是github上找到的一个代码,不复杂,但是作为eager的demo绰绰有余,非常完美。
https://github.com/Shathe/MNasNet-Keras-Tensorflow
想要找到用keras实现自己想法的最快方法,就是在github上查相关的关键词,比如本人最近在做半监督相关的网络,就是包括有标签数据和无标签数据,那我就会去查 keras Semi-Supervised 或者 keras Siamese(孪生网络)。因为不一定你想要的东西人家就一定在github上弄好了给你,但是有一些画龙点睛的东西,你看了就知道,原来模型可以这样构建,这就好办多了!
本人在写keras代码的时候,把调用部分,模型,数据生成,loss函数等都分成不同的文件从而减少耦合,也容易定位问题。
但是遇到如下问题:我在模型文件最后对模型进行了实例化(没有放在if main函数中),而模型又是自动命名的,导致在导入模型的时候实例化一遍,在调用模型的时候又调用一遍,而模型中还用了get_layer()函数,于是模型命名就不对了。
下面问题出现的原因是在Model(inputs=input, outputs=output)中,output给的不是tensor,而是由多个tensor组成的列表,这个是不允许的,只能拆开写
Traceback (most recent call last):
File "E:/GraduationThesis/2-code/fianl_code/unet_multilabel_弱监督/unet.py", line 315, in <module>
unet_new(15, 15, 20)
File "E:/GraduationThesis/2-code/fianl_code/unet_multilabel_弱监督/unet.py", line 264, in unet_new
outputs=[output, mid_feature_set])
File "D:\Anaconda3\envs\tf1\lib\site-packages\tensorflow\python\keras\engine\training.py", line 121, in __init__
super(Model, self).__init__(*args, **kwargs)