簡體   English   中英

tensorflow 2 keras shuffle 每行梯度問題

[英]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也是一個阻塞反向傳播的操​​作,如果你這樣使用它肯定會導致這個錯誤。 (這甚至可能是您問題的“原因”,而不是解決方案)

下面為您的操作提供了更簡單的建議,但它們都不會修復此錯誤,因為此錯誤在其他地方。

建議操作 1

現在,為此使用tf.random.shuffle會更容易:

def shuffleColumns(x):
    x = tf.transpose(x)
    x = tf.random.shuffle(x)
    return tf.transpose(x)

在模型中使用Lambda(shuffleColumns)層。 確實,這將平等地洗牌所有列,但每個批次都會有不同的排列。 並且由於您將有許多 epoch,並且您將在每個 epoch 之間混洗(我假設)樣本(這在fit是自動的),因此您幾乎不會有重復的批次。 所以:

  • 每批將有不同的排列
  • 幾乎不可能兩次使用同一批次

這種方法可能比你的方法快得多。

建議操作 2

如果您希望它們排列不變,為什么不使用tf.sort而不是排列? 對列進行排序,而不是有無限的排列來訓練,您只需消除排列的任何可能性。 模型應該學習得更快,但不會考慮輸入中列的順序。

使用層Lambda(lambda x: tf.sort(x, axis=-1))

這個建議必須同時用於訓練和推理。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM