前几天忙着参加一个AI Challenger比赛,一直没有更新博客,忙了将近一个月的时间,也没有取得很好的成绩,不过这这段时间内的确学到了很多,就在决赛结束的前一天晚上,准备复现使用一个新的网络UPerNet的时候出现了一个很匪夷所思,莫名其妙的一个问题。谷歌很久都没有解决,最后在一个日语网站上看到了解决方法。
事后想想,这个问题在后面搭建网络的时候会很常见,但是网上却没有人提出解决办法,So, I think that's very necessary for me to note this.
背景
分割网络在进行上采样的时候我用的是双线性插值上采样的,而Keras里面并没有实现双线性插值的函数,所以要自己调用tensorflow里面的tf.image.resize_bilinear()函数来进行resize,如果直接用tf.image.resize_bilinear()函数对Keras张量进行resize的话,会报出异常,大概意思是tenorflow张量不能转换为Keras张量,要想将Kears Tensor转换为 Tensorflow Tensor需要进行自定义层,Keras自定义层的时候需要用到Lambda层来包装。
大概源码(只是大概意思)如下:
from keras.layers import Lambda import tensorflow as tf first_layer=Input(batch_shape=(None, 64, 32, 3)) f=Conv2D(filters, 3, activation = None, padding = 'same', kernel_initializer = 'glorot_normal',name='last_conv_3')(x) upsample_bilinear = Lambda(lambda x: tf.image.resize_bilinear(x,size=first_layer.get_shape().as_list()[1:3])) f=upsample_bilinear(f)
然后编译 这个源码:
optimizer = SGD(lr=0.01, momentum=0.9) model.compile(optimizer = optimizer, loss = model_dice, metrics = ['accuracy']) model.save('model.hdf5')
其中要注意到这个tf.image.resize_bilinear()里面的size,我用的是根据张量(first_layer)的形状来做为reshape后的形状,保存模型用的是model.save().然后就会出现以下错误!
异常描述:
在一个epoch完成后保存model时出现下面错误,五个错误提示随机出现:
TypeError: cannot serialize ‘_io.TextIOWrapper' object
TypeError: object.new(PyCapsule) is not safe, use PyCapsule.new()
AttributeError: ‘NoneType' object has no attribute ‘update'
TypeError: cannot deepcopy this pattern object
TypeError: can't pickle module objects
问题分析:
这个有两方面原因:
tf.image.resize_bilinear()中的size不应该用另一个张量的size去指定。
如果用了另一个张量去指定size,用model.save()来保存model是不能序列化的。那么保存model的时候只能保存权重——model.save_weights('mode_weights.hdf5')
解决办法(两种):
1.tf.image.resize_bilinear()的size用常数去指定
upsample_bilinear = Lambda(lambda x: tf.image.resize_bilinear(x,size=[64,32]))
2.如果用了另一个张量去指定size,那么就修改保存模型的函数,变成只保存权重
model.save_weights('model_weights.hdf5')
总结:
我想使用keras的Lambda层去reshape一个张量
如果为重塑形状指定了张量,则保存模型(保存)将失败
您可以使用save_weights而不是save进行保存
补充知识:Keras 添加一个自定义的loss层(output及compile中,输出及loss的表示方法)
例如:
计算两个层之间的距离,作为一个loss
distance=keras.layers.Lambda(lambda x: tf.norm(x, axis=0))(keras.layers.Subtract(Dense1-Dense2))
这是添加的一个loss层,这个distance就直接作为loss
model=Model(input=[,,,], output=[distance])
model.compile(....., loss=lambda y_true, y_pred: ypred)
以上这篇解决Keras的自定义lambda层去reshape张量时model保存出错问题就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持小牛知识库。
本文向大家介绍django model去掉unique_together报错的解决方案,包括了django model去掉unique_together报错的解决方案的使用技巧和注意事项,需要的朋友参考一下 事情是这样的,我有一个存储考试的表 category 表示考试的类型, date 表示考试的日期。建表的时候考虑到一个类型的考试在同一个应该只有一个考试,所以就加了一个 unique_toge
根据keras文件(https://keras.io/layers/convolutional/)Conv1D输出张量的形状为(batch\u size,new\u steps,filters),而输入张量的形状为(batch\u size,steps,input\u dim)。我不明白这是怎么回事,因为这意味着如果你传递一个长度为8000的1d输入,其中batch\u size=1,steps=
本文向大家介绍Django 解决开发自定义抛出异常的问题,包括了Django 解决开发自定义抛出异常的问题的使用技巧和注意事项,需要的朋友参考一下 在开发过程中,针对用户输入的不合法信息,我们应该在后端进行数据验证,并抛出相关的异常传递到前端来提示用户。 可是如何进行自定义抛出异常信息呢?通常处理方法有三种,我将依次介绍这三种方法。 第一种方法: 这种方法最为简单,只需要创建一个字典对象,通过re
我想提供以下形状的神经网络输入:每个训练条目都是一个维度为700x10的2D数组。总共有204个训练条目。标签只是204大小的一维数组(二进制输出) 我试图只使用密集层: 但是我得到了以下错误(与第一层上的input\u形状无关,但在输出验证期间): 204-训练数据量。 堆栈跟踪: 调试Keras代码时发现: 培训前验证失败。它验证输出数组。 根据神经网络的结构,第一个密集层以某种方式产生700
本文向大家介绍解决element UI 自定义传参的问题,包括了解决element UI 自定义传参的问题的使用技巧和注意事项,需要的朋友参考一下 如下所示: 这里的 hanleSelect 默认绑定的参数是选中的那条数据。 但是如果一个页面有好几个相同的组件,要想知道选中的是第几个。 解决方法: 基于element-UI 事件添加额外自定义参数的方法 要想在element的 event事件中增加
本文向大家介绍在keras里实现自定义上采样层,包括了在keras里实现自定义上采样层的使用技巧和注意事项,需要的朋友参考一下 Keras里的UpSampling2D层不是中的双线性内插,而是简单的重复图像。这点和pytorch不一样,pytorch默认使用的是双线性内插。 同样:这里仍然使用的是keras而不是tf.keras. keras里UpSampling2D的部分定义说明如下: 可以看出
对于简单的定制操作,我们或许可以通过使用 layers.core.Lambda 层来完成。但对于任何具有可训练权重的定制层,你应该自己来实现。 from keras import backend as K from keras.engine.topology import Layer import numpy as np class MyLayer(Layer): def __init
深度学习的一个魅力在于神经网络中各式各样的层,例如全连接层和后面章节中将要介绍的卷积层、池化层与循环层。虽然Gluon提供了大量常用的层,但有时候我们依然希望自定义层。本节将介绍如何使用NDArray来自定义一个Gluon的层,从而可以被重复调用。 不含模型参数的自定义层 我们先介绍如何定义一个不含模型参数的自定义层。事实上,这和“模型构造”一节中介绍的使用Block类构造模型类似。下面的Cent