解決Keras的自定義lambda層去reshape張量時model保存出錯問題
前幾天忙著參加一個AI Challenger比賽,一直沒有更新博客,忙了將近一個月的時間,也沒有取得很好的成績,不過這這段時間內(nèi)的確學(xué)到了很多,就在決賽結(jié)束的前一天晚上,準(zhǔn)備復(fù)現(xiàn)使用一個新的網(wǎng)絡(luò)UPerNet的時候出現(xiàn)了一個很匪夷所思,莫名其妙的一個問題。谷歌很久都沒有解決,最后在一個日語網(wǎng)站上看到了解決方法。
事后想想,這個問題在后面搭建網(wǎng)絡(luò)的時候會很常見,但是網(wǎng)上卻沒有人提出解決辦法,So, I think that's very necessary for me to note this.
背景
分割網(wǎng)絡(luò)在進行上采樣的時候我用的是雙線性插值上采樣的,而Keras里面并沒有實現(xiàn)雙線性插值的函數(shù),所以要自己調(diào)用tensorflow里面的tf.image.resize_bilinear()函數(shù)來進行resize,如果直接用tf.image.resize_bilinear()函數(shù)對Keras張量進行resize的話,會報出異常,大概意思是tenorflow張量不能轉(zhuǎn)換為Keras張量,要想將Kears Tensor轉(zhuǎn)換為 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,我用的是根據(jù)張量(first_layer)的形狀來做為reshape后的形狀,保存模型用的是model.save().然后就會出現(xiàn)以下錯誤!
異常描述:
在一個epoch完成后保存model時出現(xiàn)下面錯誤,五個錯誤提示隨機出現(xiàn):
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不應(yīng)該用另一個張量的size去指定。
如果用了另一個張量去指定size,用model.save()來保存model是不能序列化的。那么保存model的時候只能保存權(quán)重——model.save_weights('mode_weights.hdf5')
解決辦法(兩種):
1.tf.image.resize_bilinear()的size用常數(shù)去指定
upsample_bilinear = Lambda(lambda x: tf.image.resize_bilinear(x,size=[64,32]))
2.如果用了另一個張量去指定size,那么就修改保存模型的函數(shù),變成只保存權(quán)重
model.save_weights('model_weights.hdf5')
總結(jié):
我想使用keras的Lambda層去reshape一個張量
如果為重塑形狀指定了張量,則保存模型(保存)將失敗
您可以使用save_weights而不是save進行保存
補充知識:Keras 添加一個自定義的loss層(output及compile中,輸出及l(fā)oss的表示方法)
例如:
計算兩個層之間的距離,作為一個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保存出錯問題就是小編分享給大家的全部內(nèi)容了,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
python中的property及屬性與特性之間的優(yōu)先權(quán)
這篇文章主要介紹了python中的property及屬性與特性之間的優(yōu)先權(quán),文章圍繞主題展開詳細的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下2022-07-07
pyspark創(chuàng)建DataFrame的幾種方法
為了便于操作,使用pyspark時我們通常將數(shù)據(jù)轉(zhuǎn)為DataFrame的形式來完成清洗和分析動作。那么你知道pyspark創(chuàng)建DataFrame有幾種方法嗎,下面就一起來了解一下2021-05-05
python logging設(shè)置level失敗的解決方法
今天小編就為大家分享一篇python logging設(shè)置level失敗的解決方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-02-02
淺談Python中threading join和setDaemon用法及區(qū)別說明
這篇文章主要介紹了淺談Python中threading join和setDaemon用法及區(qū)別說明,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-05-05
python+selenium爬取微博熱搜存入Mysql的實現(xiàn)方法
這篇文章主要介紹了python+selenium爬取微博熱搜存入Mysql的實現(xiàn)方法,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-01-01

