56445


kerasで全結合ニューラルネットの回帰モデルを組んでいます(入力は10次元で出力が1次元)。  
また, 損失関数には平均二乗誤差を用いています。

誤差に対する入力の勾配(誤差をL, 入力をxとしたときの dL/dx)を知りたいのですが, kerasでそれを実現できるのでしょうか?


CC BY-SA 4.0
2019-06-27T06:42:25.727
56137
2020-06-10T06:44:08.357
34886
question
python keras
kerasで入力に対する勾配を得るにはどうすればよいですか?


同様の質問は以下かと思います。  
<https://stackoverflow.com/questions/53649837/how-to-compute-loss-gradient-w-
r-t-to-model-inputs-in-a-keras-model>

これによると backend functions を使えというようなことが記載されていました。  
backend functions については以下に記載がありました。

<https://keras.io/backend/#using-the-abstract-keras-backend-to-write-new-code>

これによると keras には abstract Keras backend API というものがありこれを通してバックエンドの関数を呼び出せるようです。  
tensorflow をバックエンドとしているならこのAPIを使用することにより、直接 tensorflow の関数を呼び出せるということだと思います。  
この API を Backend functions と呼ぶのだと思います。

Backend functions の一覧は以下に記載されています。  
<https://keras.io/backend/#backend-functions>

この中に

[code]

    gradients
    
    keras.backend.gradients(loss, variables)
    Returns the gradients of loss w.r.t. variables.
    
    Arguments
    
    loss: Scalar tensor to minimize.
    variables: List of variables.
    
    Returns
    
    A gradients tensor.
    
[/code]

というものがありますので、これを使用すればよいかと思います。  
解決いたしましたら、後学のためサンプルコードをあげていただくと幸いです。


CC BY-SA 4.0
2019-07-06T06:08:30.790
56445
2019-07-06T06:32:43.267
2019-07-06T06:32:43.267
45
45
56137
answer


頂いた回答を参考に解決できました.  
直接誤差に対する勾配は得られなかったのですが, 以下の様にして対処できます

  1. 入力の出力に対する勾配を得る
  2. 出力の誤差関数に対する勾配を得る  
今回は回帰モデルであり誤差関数にMSEを使用しています.  
したがってこの例では`2*(モデルの出力-真の出力)`となります

[code]

    import keras
    import keras.backend as K
        model = keras.models.load_model("model_path")
    
        get_grad = K.gradients(model.output, model.input)
        sess = K.get_session()
    
        grad_out = sess.run(get_grad[0], feed_dict={model.input: input_x})
        # d output / d input
    
        pred = model.predict(input_x)
        grad_loss = 2 * (pred - true_out).reshape(-1, 1) * grad_out
        # d loss / d input
    
[/code]


CC BY-SA 4.0
2019-07-08T06:37:33.007
56490
2019-07-08T06:37:33.007
34886
56137
answer


MNISTの分類モデル(CNN)に対して，入力データのGradientは，以下のようにして計算できます．

[code]

    import numpy as np
    import tensorflow as tf
    
    import keras
    import keras.backend as K
    import numpy as np
    from keras.datasets import mnist
    
    # Load MNIST dataset
    (x_train, y_train), (x_test, y_test) = mnist.load_data()
    del mnist
    
    # Min-Max Normalization
    x_train = x_train.astype('float32') / 255.
    x_test = x_test.astype('float32') / 255.
    x_train = x_train.reshape((len(x_train), np.prod(x_train.shape[1:])))
    x_test = x_test.reshape((len(x_test), np.prod(x_test.shape[1:])))
    # Ohe-Hot encoding
    y_train = keras.utils.np_utils.to_categorical(y_train) 
    y_test  = keras.utils.np_utils.to_categorical(y_test) 
    
    # ==================================
    
    model = keras.models.load_model('model_v0.h5', compile=False)
    
    idx = 0
    x_true = x_train[idx].reshape(1, 28, 28)
    y_true = y_train[idx].reshape(1, 10)
    y_pred = model.output
    
    loss = tf.keras.losses.categorical_crossentropy(y_true, y_pred)
    
    get_grad = K.gradients(loss, model.input)
    
    sess = K.get_session()
    grad = sess.run(get_grad[0], feed_dict={model.input: x_true})
    # grad: d loss / d input
    
    # ==================================
    
    
[/code]

また，取得したGradientの直積を計算すればHessian行列が取得できます．

[code]

    grad = grad.flatten()
    hessian = np.outer(grad, grad)
    
[/code]


CC BY-SA 4.0
2020-06-10T06:44:08.357
67495
2020-06-10T06:44:08.357
40569
56137
answer