[英]tensorflow 2 keras shuffle each row gradient problem
我需要一個 NN,它將為相同輸入的任何排列提供相同的輸出。 試圖尋找解決方案(“排列不變性”),找到了一些層,但未能使它們工作。
我選擇了不同的方法:我想創建一個層,作為我在模型中的第一個添加,它將隨機洗牌輸入(每行獨立) - 請讓我們遵循這種方法,我知道它可以在模型之外完成,但我想要它作為模型的一部分。 我試過:
class ShuffleLayer(tf.keras.layers.Layer):
def __init__(self, **kwargs):
super(ShuffleLayer, self).__init__(**kwargs)
def call(self, inputs):
batchSize = tf.shape(inputs)[0]
cols = tf.shape(inputs)[-1]
order0 = tf.tile(tf.expand_dims(tf.range(0, batchSize), -1), [1, cols])
order1 = tf.argsort(tf.random.uniform(shape=(batchSize, cols)))
indices = tf.stack([tf.reshape(order0, [-1]), tf.reshape(order1, [-1])], axis=-1)
outputs = tf.reshape(tf.gather_nd(inputs, indices), [batchSize, cols])
return outputs
我收到以下錯誤:
ValueError:變量
None
漸變。 請確保您的所有操作都定義了梯度(即可微分)。 沒有梯度的常見操作:K.argmax、K.round、K.eval。
怎么避免?? 我嘗試使用tf.stop_gradient
,但沒有成功。
Lambda
層: 首先,如果您的層沒有可訓練的權重,您應該使用Lambda
層,而不是自定義層。 它更簡單,更容易。
def shuffleColumns(inputs):
batchSize = tf.shape(inputs)[0]
cols = tf.shape(inputs)[-1]
order0 = tf.tile(tf.expand_dims(tf.range(0, batchSize), -1), [1, cols])
order1 = tf.argsort(tf.random.uniform(shape=(batchSize, cols)))
indices = tf.stack([tf.reshape(order0, [-1]), tf.reshape(order1, [-1])], axis=-1)
outputs = tf.reshape(tf.gather_nd(inputs, indices), [batchSize, cols])
return outputs
在模型中,使用Lambda(shuffleColumns)
層。
如果這是第一層,這個錯誤很可能不是由這一層引起的。 (除非 Tensorflow 的新版本要求自定義層具有權重和def build(self, input_shape):
定義,這似乎不太合乎邏輯)。
看來您正在另一個地方做其他事情。 錯誤是:您正在使用一些阻止反向傳播的操作,因為不可能有該操作的導數。
由於對模型的“權重”進行導數,這意味着操作必須在模型中的第一個權重張量之后(即:在包含可訓練權重的第一層之后)。
您需要在模型中搜索沒有導數的任何內容,如錯誤提示:round、argmax、返回常量的條件、返回排序的y_true
但不返回對y_pred
操作的y_pred
等。
當然, K.stop_gradients
也是一個阻塞反向傳播的操作,如果你這樣使用它肯定會導致這個錯誤。 (這甚至可能是您問題的“原因”,而不是解決方案)
下面為您的操作提供了更簡單的建議,但它們都不會修復此錯誤,因為此錯誤在其他地方。
現在,為此使用tf.random.shuffle
會更容易:
def shuffleColumns(x):
x = tf.transpose(x)
x = tf.random.shuffle(x)
return tf.transpose(x)
在模型中使用Lambda(shuffleColumns)
層。 確實,這將平等地洗牌所有列,但每個批次都會有不同的排列。 並且由於您將有許多 epoch,並且您將在每個 epoch 之間混洗(我假設)樣本(這在fit
是自動的),因此您幾乎不會有重復的批次。 所以:
這種方法可能比你的方法快得多。
如果您希望它們排列不變,為什么不使用tf.sort
而不是排列? 對列進行排序,而不是有無限的排列來訓練,您只需消除排列的任何可能性。 模型應該學習得更快,但不會考慮輸入中列的順序。
使用層Lambda(lambda x: tf.sort(x, axis=-1))
這個建議必須同時用於訓練和推理。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.