使用Keras實現(xiàn)Tensor的相乘和相加代碼
前言
最近在寫行為識別的代碼,涉及到兩個網(wǎng)絡的融合,這個融合是有加權的網(wǎng)絡結果的融合,所以需要對網(wǎng)絡的結果進行加權(相乘)和融合(相加)。
最初的想法
最初的想法是用Keras.layers.Add和Keras.layers.Multiply來做,后來發(fā)現(xiàn)這樣會報錯。
rate_rgb = k.variable(np.ones((1024,),dtype='float32')*0.8) rate_esti = k.variable(np.ones((1024,),dtype='float32')*0.2) weight_gru1 = Multiply()([rate_rgb,gru1]) weight_gru2 = Multiply()([rate_esti,gru2]) last = Add()([weight_gru1,weight_gru2])
這么寫會報錯,如下
AttributeError: 'Variable' object has no attribute '_keras_history'
正確做法
后來在網(wǎng)上參考大神的博客,改為如下
weight_1 = Lambda(lambda x:x*0.8) weight_2 = Lambda(lambda x:x*0.2) weight_gru1 = weight_1(gru1) weight_gru2 = weight_2(gru2) last = Add()([weight_gru1,weight_gru2])
這樣就沒問題了。
補充知識:Keras天坑:想當然的對層的直接運算帶來的問題
天坑
keras如何操作某一層的值(如讓某一層的值取反加1等)?keras如何將某一層的神經(jīng)元拆分以便進一步操作(如取輸入的向量的第一個元素乘別的層)?keras如何重用某一層的值(如輸入層和輸出層乘積作為最終輸出)?
這些問題都指向同一個答案,即使用Lambda層。
另外,如果想要更加靈活地操作層的話,推薦使用函數(shù)式模型寫法,而不是序列式。
Keras當中,任何的操作都是以網(wǎng)絡層為單位,操作的實現(xiàn)都是新添一層,不管是加減一個常數(shù)還是做乘法,或者是對兩層的簡單拼接。所以,將一層單獨劈一半出來,是一件難事。強調,Keras的最小操作單位是Layer,每次操作的是整個batch。自然,在keras中,每個層都是對象,可以通過dir(Layer對象)來查看具有哪些屬性。然而,Backend中Tensorflow的最小操作單位是Tensor,而你搞不清楚到底是Layer和Tensor時,盲目而想當然地進行層的操作,就會出問題。到底是什么?通過type和shape是看不出來的。
如果你只是想對流經(jīng)該層的數(shù)據(jù)做個變換,而這個變換本身沒有什么需要學習的參數(shù),那么直接用Lambda Layer是最合適的了。
也就是說,對每一層的加減乘除都得用keras的函數(shù),你不能簡單使用形如 ‘new_layer' =1−= 1-=1−'layer'這樣的表達方式來對層進行操作。
當遇到如下報錯信息:
AttributeError: 'NoneType' object has no attribute '_inbound_nodes'
或
TypeError: 'Tensor' object is not callable
等等
這是就要考慮一下將程序中層的操作改成Lambda的方式表達。
使用Lambda編寫自己的層
Lamda層怎么用?官方文檔給了這樣一個例子。
# add a x -> x^2 layer model.add(Lambda(lambda x: x ** 2)) # add a layer that returns the concatenation # of the positive part of the input and # the opposite of the negative part def antirectifier(x): x -= K.mean(x, axis=1, keepdims=True) x = K.l2_normalize(x, axis=1) pos = K.relu(x) neg = K.relu(-x) return K.concatenate([pos, neg], axis=1) def antirectifier_output_shape(input_shape): shape = list(input_shape) assert len(shape) == 2 # only valid for 2D tensors shape[-1] *= 2 return tuple(shape) model.add(Lambda(antirectifier, output_shape=antirectifier_output_shape))
乍一看,有點懵逼,什么亂七八糟的。事實上,很簡單,假設L0和L1是兩層,你只要將你形如下面這樣的表達:
L1 = F(L0);
改成
L1 = Lambda( lambda L0:F(L0) ) (L0)
即可。為了看得清楚,多加了幾個空格。
事實上,無非就是將原來的變換,通過Lambda(lambda 輸入:表達式)這樣的方式,改成了Lambda型函數(shù),再把輸入傳進去,放在尾巴上即可。
參考
https://keras-cn.readthedocs.io/en/latest/layers/core_layer/#lambda
(個人覺得這份文檔某些地方比官方中文要完整許多)
keras許多簡單操作,都需要新建一個層,使用Lambda可以很好完成需求。當你不知道有這個東西存在的時候,就會走不少彎路。
以上這篇使用Keras實現(xiàn)Tensor的相乘和相加代碼就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
python實現(xiàn)自動發(fā)送報警監(jiān)控郵件
這篇文章主要為大家詳細介紹了python實現(xiàn)自動發(fā)送報警監(jiān)控郵件,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-06-06使用Python實現(xiàn)在Word文檔中進行郵件合并
郵件合并是現(xiàn)代辦公中一項顯著提升效率的技術,它巧妙地將大量個體數(shù)據(jù)與預設的文檔模板相結合,實現(xiàn)了一次性批量生成定制化文檔,下面我們就來看看如何使用Python實現(xiàn)在Word文檔中進行郵件合并吧2024-04-04pandas實現(xiàn)to_sql將DataFrame保存到數(shù)據(jù)庫中
這篇文章主要介紹了pandas實現(xiàn)to_sql將DataFrame保存到數(shù)據(jù)庫中,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2019-07-07使用Python根據(jù)一個列表的順序對其他列表進行排序
這篇文章主要介紹了使用Python根據(jù)一個列表的順序對其他列表進行排序,根據(jù)列表B中每個元素的下標來獲取列表A中對應位置的元素,將其作為排序依據(jù)即可,需要的朋友可以參考下2023-10-10python的數(shù)據(jù)與matlab互通問題:SciPy
這篇文章主要介紹了python的數(shù)據(jù)與matlab互通問題SciPy,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-12-12