web-dev-qa-db-ja.com

KerasバックエンドのK.sumでaxis = [1,2,3]はどういう意味ですか?

CNNモデルにカスタム損失関数を実装しようとしています。次のように、Diceというカスタム損失関数を実装した IPython notebook を見つけました。

from keras import backend as K
smooth = 1.

def dice_coef(y_true, y_pred, smooth=1):
    intersection = K.sum(y_true * y_pred, axis=[1,2,3])
    union = K.sum(y_true, axis=[1,2,3]) + K.sum(y_pred, axis=[1,2,3])
    return K.mean( (2. * intersection + smooth) / (union + smooth), axis=0)

def bce_dice(y_true, y_pred):
    return binary_crossentropy(y_true, y_pred)-K.log(dice_coef(y_true, y_pred))

def true_positive_rate(y_true, y_pred):
    return K.sum(K.flatten(y_true)*K.flatten(K.round(y_pred)))/K.sum(y_true)

seg_model.compile(optimizer = 'adam', 
              loss = bce_dice, 
              metrics = ['binary_accuracy', dice_coef, true_positive_rate])

私はこれまでkerasバックエンドを使用したことがなく、kerasバックエンドの行列計算と本当に混乱しました。そこで、コードで何が起こっているのかを確認するために、いくつかのテンソルを作成しました。

val1 = np.arange(24).reshape((4, 6))
y_true = K.variable(value=val1)

val2 = np.arange(10,34).reshape((4, 6))
y_pred = K.variable(value=val2)

次に、dice_coef関数を実行します。

result = K.eval(dice_coef(y_true=y_true, y_pred=y_pred))
print('result is:', result)

しかし、それは私にこのエラーを与えます:

ValueError: Invalid reduction dimension 2 for input with 2 dimensions. for 'Sum_32' (op: 'Sum') with input shapes: [4,6], [3] and with computed input tensors: input[1] = <1 2 3>.

次に、以下のように[1,2,3]をすべて-1に変更しました。

def dice_coef(y_true, y_pred, smooth=1):
    intersection = K.sum(y_true * y_pred, axis=-1)
    # intersection = K.sum(y_true * y_pred, axis=[1,2,3])
    # union = K.sum(y_true, axis=[1,2,3]) + K.sum(y_pred, axis=[1,2,3])
    union = K.sum(y_true, axis=-1) + K.sum(y_pred, axis=-1)
    return K.mean( (2. * intersection + smooth) / (union + smooth), axis=0)

今それは私に価値を与えます。

result is: 14.7911625

質問:

  1. [1,2,3]とは何ですか?
  2. [1,2,3]-1に変更するとコードが機能するのはなぜですか?
  3. このdice_coef関数は何をしますか?
3
Muser

Numpyと同様に、特定の操作を実行する軸を定義できます。たとえば、4D配列の場合、次のように特定の軸に沿って合計できます

_>>> a = np.arange(150).reshape((2, 3, 5, 5))
>>> a.sum(axis=0).shape
(3, 5, 5)
>>> a.sum(axis=0, keepdims=True).shape
(1, 3, 5, 5)
>>> a.sum(axis=1, keepdims=True).shape
(2, 1, 5, 5)
_

タプルをフィードすると、この操作を複数の軸に沿って実行できます。

_>>> a.sum(axis=(1, 2, 3), keepdims=True).shape
(2, 1, 1, 1)
_

引数が_-1_の場合、その数に関係なく、デフォルトで最後の軸に対して操作を実行します。

_>>> a.sum(axis=-1, keepdims=True).shape
(2, 3, 5, 1)
_

これにより、ポイント1と2が明確になります。軸の引数は_(1, 2, 3)_であるため、操作を有効にするには、少なくとも4つの軸が必要です。変数をval1 = np.arange(24).reshape((2, 2, 2, 3))のようなものに変更してみてください。すべてが機能します。

モデルはバイナリクロスエントロピーダイス損失を計算しているようで、名前が示すようにdice_coeff()ダイス係数 を計算します。 smoothの目的が何であるかはわかりませんが、それが0による除算を回避する目的である場合は、1e-6のような小さい数を期待します。

2
Reti43

[1,2,3]とは何ですか?

これらの数値は、合計する次元を指定します。最小の数は外側の次元を示し、最大の数は内側の次元を示します。例を参照してください。

import tensorflow as tf

tf.enable_eager_execution()

    a = tf.constant([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])

    print(tf.reduce_sum(a, axis=2).numpy())
    #[[ 3  7]
    # [11 15]]
    print(tf.reduce_sum(a, axis=1).numpy())
    #[[ 4  6]
    # [12 14]]
    print(tf.reduce_sum(a, axis=0).numpy())
    #[[ 6  8]
    # [10 12]]

上記の例では、axis = 2は、[1,2]、[3,4]、[5,6]、および[7,8]の内部エントリを意味します。結果として、合計後、テンソル[[3, 7], [11, 15]]が得られます。同じ考え方が他の軸にも当てはまります。

[1,2,3]を-1に変更するとコードが機能する理由

軸を指定しなかった場合、またはすべての軸を指定した場合は、すべてのテンソル要素を合計することを意味します。この結果、テンソルが単一のスカラーに変換されます。例を参照してください:

a = tf.constant([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
print(tf.reduce_sum(a).numpy()) # 36
print(tf.reduce_sum(a, axis=[0,1,2])) # 36

3つの次元[0、1、2]がある場合、axis = -1axis = 2と等しくなります。 pythonインデックス付けの完全なチュートリアルについては こちら を参照してください。

このdice_coef関数は何をしますか?

enter image description here

Dice_coefについての完全な説明は here を参照してください。

1
Amir