Как создать свою собственную функцию потерь для tf.keras, которая использует дополнительный параметр? - PullRequest
2 голосов
/ 19 февраля 2020

Моя потребность:

Я хотел бы изменить свою функцию потерь в нейронной сети, добавив выборочные веса. (Мне известно, что метод .fit имеет параметр sample_weight).

Моя идея состояла в том, чтобы создать дополнительный ввод в мою нейронную сеть с предварительно вычисленными весами для каждой строки данных поезда, как показано ниже:

# Generating mock data
train_X = np.random.randn(100, 5)
train_Y = np.random.randn(100, 1)
train_sample_weights = np.random.randn(*train_Y.shape)

# Designing loss function that uses my pre-computed weights
def example_loss(y_true, y_pred, sample_weights_):
    return K.mean(K.sqrt(K.sum(K.pow(y_pred - y_true, 2), axis=-1)), axis=0) * sample_weights_

# Two inputs for neural network, one for data, one for weights
input_tensor = Input(shape=(train_X.shape[1],))
weights_tensor = Input(shape=(train_sample_weights.shape[1],))

# Model uses only 'input_tensor'
x = Dense(100, activation="relu")(input_tensor)
out = Dense(1)(x)

# The 'weight_tensor' is inserted into example_loss() functon
loss_function = partial(example_loss, sample_weights_=weights_tensor)

# Model takes as an input both data and weights
model = Model([input_tensor, weights_tensor], out)
model.compile("Adam", loss_function)
model.fit(x=[train_X, train_sample_weights], y=train_Y, epochs=10)

Моя проблема:

Следующий код работает при использовании импорта Keras 2.2.4 для его запуска:

import numpy as np
from functools import partial

import keras.backend as K
from keras.layers import Input, Dense
from keras.models import Model

Следующий код аварийно завершает работу , когда я использую импорт tf.keras 2.2.4-tf для его запуска:

import numpy as np
from functools import partial

import tensorflow.keras.backend as K
from tensorflow.keras.layers import Input, Dense
from tensorflow.keras.models import Model

Со следующей ошибкой:

TypeError: example_loss () получил неожиданный аргумент ключевого слова 'sample_weight'

Мои вопросы:

  1. Почему это происходит?
  2. Как я мог переписать код, чтобы такая архитектура могла также работать на 2.2.4-tf?
  3. Предложение, которое работает на обеих платформах Keras / tf.keras, также является приемлемым ответом для меня.

Ошибка легко воспроизводится. Просто нужно скопировать код и запустить.

Ответы [ 2 ]

3 голосов
/ 19 февраля 2020

Вам необходимо определить свой убыток таким образом, чтобы передать ему новые параметры:

def custom_loss(sample_weights_):

    def example_loss(y_true, y_pred):
        return K.mean(K.sqrt(K.sum(K.pow(y_pred - y_true, 2), axis=-1)), axis=0) * sample_weights_

    return example_loss

и назвать его так:

model.compile("Adam", custom_loss(weights_tensor))
1 голос
/ 19 февраля 2020

Вы можете переписать свою потерю следующим образом:

# Designing loss function that uses my pre-computed weights
def example_loss(sample_weights_):
    def loss(y_true, y_pred):
        return K.mean(K.sqrt(K.sum(K.pow(y_pred - y_true, 2), axis=-1)), axis=0) * sample_weights_

Как видите, здесь у нас есть функция, которая берет весовые коэффициенты выборки и возвращает другую функцию (фактическую потерю), в которую встроены весовые коэффициенты выборки. внутрь. Вы можете использовать его как:

model.compile(optimizer="adam", loss=example_loss(weights_tensor))
...