2017-04-07 201 views
3

我使用Kera和tensorflow後端,我很好奇是否有可能在反向傳播期間跳過一層但在正向傳遞中執行它。因此,這裏是我的意思keras反向傳播中的跳過層

Lambda (lambda x: a(x)) 

我想在直傳申請ax,但我不想當backprop發生一個被列入的推導。

我試圖找到一個解決方案,我找不到任何東西。有人可以幫助我嗎?

+0

你想凍結它嗎(=不更新該特定層的權重)? –

+0

編號可以說a(x)= 1 /(1 + e^x)。然後在正向傳遞中,我想通過sigmoid函數推送x,但在後向傳播中,我不想包含sigmoid的衍生物 – DalekSupreme

+0

對不起沒有幫助你在那裏......我真的沒有看到派生另一個函數,而不是你想要最小化的函數? backprop失去它的目的 –

回答

2

UPDATE 2

除了tf.py_func,現在一個official guide on how to add a custom op


UPDATE

寫純粹在Python梯度自定義運算,而無需重建任何東西的例子見this question。請注意,該方法有一些限制(請參閱tf.py_func的文檔)。


不完全是一個解決問題的方法,但那種仍然回答太長征求意見。

這甚至不是Keras問題,而是一個TensorFlow問題。每個操作定義自己的反向傳播時使用的梯度計算。我想真的想要這樣的東西,你需要自己實現操作到TensorFlow(不容易的壯舉),並定義你想要的梯度 - 因爲你不能有「沒有梯度」,如果有的話它會是1或0(否則你不能繼續反向傳播)。在TensorFlow中有一個tf.NoGradient函數,它導致op傳播零,但我不認爲它可以用在TensorFlow自己的內部。

UPDATE

好了,所以多一點上下文。 TensorFlow圖是由ops構建的,其由內核實現;這基本上是1對1的映射,除了可能有例如CPU和GPU內核的操作,因此區分。 TensorFlow支持的操作集通常是靜態的,我的意思是它可以隨着更新的版本而改變,但原則上你不能添加你自己的操作,因爲圖的操作會進入Protobuf序列化格式,所以如果你自己做了操作那麼你將無法分享你的圖表。然後在C++級別用宏REGISTER_OP(參見例如here)和具有REGISTER_KERNEL_BUILDER的內核(參見例如here)定義Ops。

現在,漸變在哪裏發揮作用?那麼,有趣的是,一個op的漸變沒有在C++級別定義;有操作系統(和內核),實現其他操作的梯度(如果你看看以前的文件,你會發現操作系統/內核的名稱結尾Grad),但(據我所知)這些在這個層面上沒有明確地「聯繫」。似乎ops及其漸變之間的關聯在Python中定義,通常通過tf.RegisterGradient或前述的tf.NoGradient(例如參見here,Python模塊以gen_開頭,在C++宏的幫助下自動生成);這些註冊通知反向傳播算法如何計算圖的梯度。

那麼,如何真正解決這個問題呢?那麼,你需要在C++中至少創建一個操作,其中相應的內核實現你想要的正向傳遞的計算。然後,如果要使用的梯度計算可以用現有的TensorFlow操作(很有可能)來表示,則只需在Python中調用tf.RegisterGradient,然後在「標準」TensorFlow中進行計算。這是相當複雜的,但好消息是這是可能,甚至還有一個example它(雖然我覺得他們有點忘了那個梯度註冊部分)!正如你將會看到的,這個過程涉及到將新的操作代碼編譯到一個庫中(順便說一下,我不確定這是否可以在Windows上工作),然後從Python加載(顯然這涉及通過manual compilation of TensorFlow的痛苦過程Bazel)。一個可能更現實的例子可以在TensorFlow Fold中找到,TensorFlow是TensorFlow的擴展,用於通過調用REGISTER_OP的宏定義的here註冊(作爲一個)一個自定義操作here,然後在Python中加載庫並註冊其漸變here通過自己的註冊功能定義here簡單地調用tf.NotDifferentiable(別稱tf.NoGradient

tldr:這是相當困難的,但它可以來完成,甚至有一對夫婦的例子在那裏。

+0

感謝您的回答。如果你想用非微分函數來計算正向通過,然後用一個非常相似但可微的函數進行反向傳播,那麼這是有道理的,我們將會看到。你可以給我鏈接他們描述如何實現op並將其嵌入Keras層嗎? – DalekSupreme

+1

@DalekSupreme哦,我明白了,所以它不是「刪除」漸變,而是用「替代」計算取代它,好的,這是有道理的。我會看看我能否找到一個例子,但除非出錯(我可以),否則我認爲它會涉及到C++方面的改變和重新編譯......但至少應該是可能的。 – jdehesa

+0

嗯,我有點希望有一個更簡單的解決方案,但如果是這樣的話,我至少知道它很難實現。讓更容易的解決方案的人有希望。如果沒有這樣的事情,我會接受你的答案。感謝您的幫助:) – DalekSupreme