Как использовать входные градиенты в качестве переменных в пользовательской функции потерь в Keras? - PullRequest
0 голосов
/ 15 октября 2019

Я использую входной градиент в качестве важного признака и хочу сравнить важность признака узла данных поезда с важностью аннотированного человеком. Я хотел бы сделать это сравнение дифференцируемым, чтобы его можно было изучить с помощью обратного распространения. Для этого я пишу пользовательскую функцию потерь, которая в дополнение к обычной потере (например, mse на прогнозе против истинных меток) также проверяет, является ли входной градиент правильным (например, mm входного градиента по сравнению с важностью аннотированных функций человека).

С помощью следующего кода я могу получить входной градиент:

from keras import backend as K
import numpy as np

from keras.models import Model
from keras.layers import Input, Dense

def normalize(x):
    # utility function to normalize a tensor by its L2 norm
    return x / (K.sqrt(K.mean(K.square(x))) + 1e-5)

# Amount of training samples
N = 1000
input_dim = 10

# Generate training set make the 1st and 2nd feature same as the target feature
X = np.random.standard_normal(size=(N, input_dim))
y = np.random.randint(low=0, high=2, size=(N, 1))
X[:, 1] = y[:, 0]
X[:, 2] = y[:, 0]

# Create simple model
inputs = Input(shape=(input_dim,))
x = Dense(10, name="dense1")(inputs)
output = Dense(1, activation='sigmoid')(x)
model = Model(input=[inputs], output=output)

# Compile and fit model
model.compile(optimizer='adam', loss="mse", metrics=['accuracy'])
model.fit([X], y, epochs=100, batch_size=64)

# Get function to get input gradients
gradients = K.gradients(model.output, model.input)[0]
gradient_function = K.function([model.input], [normalize(gradients)])

# Get input gradient values of the training-set
grads_val = gradient_function([X])[0]
print(grads_val[:2])

Это напечатает следующее (вы можете видеть, что 1-я и 2-я функции имеют наибольшую важность):

[[ 1.2629046e-02  2.2765596e+00  2.1479919e+00  2.1558853e-02
   4.5277486e-03  2.9851785e-03  9.5279224e-04 -1.0903150e-02
  -1.2230731e-02  2.1960819e-02]
 [ 1.1318034e-02  2.0402350e+00  1.9250139e+00  1.9320872e-02
   4.0577268e-03  2.6752844e-03  8.5390132e-04 -9.7713526e-03
  -1.0961102e-02  1.9681118e-02]]

Как я могу написать собственную функцию потерь, в которой входные градиенты дифференцируемы? Я начал со следующей функции потерь.

from keras.losses import mean_squared_error
def custom_loss():
    # human annotated feature importance
    # Let's say that it says to only look at the second feature
    human_feature_importance = []
    for i in range(N):
        human_feature_importance.append([0,0,1,0,0,0,0,0,0,0])


    def loss(y_true, y_pred):

        # Get regular loss
        regular_loss_value = mean_squared_error(y_true, y_pred)

        # Somehow get the input gradient of each training sample as a tensor
        # It should be differential w.r.t. all of the weights
        gradients = ??
        feature_importance_loss_value = mean_squared_error(gradients, human_feature_importance)

        # Combine the both losses
        return regular_loss_value + feature_importance_loss_value
    return loss

Я также нашел реализацию в тензорном потоке, чтобы сделать входной градиент дифференцируемым: https://github.com/dtak/rrr/blob/master/rrr/tensorflow_perceptron.py#L18

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...