Различные функции потерь в разных сегментах DNN

Возможно ли определить разные функции потерь в разных сегментах глубокой сети (в следующем смысле):

Предположим, что у меня есть несколько пар ввода-вывода (x_n, y_n) и (x_n, z_n), и я хочу обучить глубокую сеть из f_k∘...∘f_1 (каждый f_i является уровнем прямой связи), так что

  • MSE(f_k∘...∘f_1(x_n) - y_n) минимизируется
  • MSE(f_k∘f_k-1(x_n) - z_n) также сводится к минимуму.

Аналогия/Пример/Интуиция/Мотивация:

Предположим, я хочу, чтобы выходные данные моей сети были примерно равны x^2, тогда f_k∘f_k-1(x_n)~~ x_n^2 и z_n:= x_n^2. Затем f_k∘...∘f_1(x_n) — сеть с прямой связью, выходной слой которой приблизительно равен функции x^2.


Как вы можете сделать это в TensorFlow/Keras?


comment
с f_n∘f_n-1(x_n) вы имеете в виду вывод сети/окончательные прогнозы?   -  person Marco Cerliani    schedule 27.07.2020
comment
@MarcoCerliani Точно. Я добавил пример, чтобы прояснить мою конечную цель   -  person BLBA    schedule 27.07.2020
comment
Представляет ли _n для x_n, y_n, z_n образец индекса? Также _n для f_n представляет номер слоя? Если это так, использование одной и той же буквы немного сбивает с толку.   -  person Kota Mori    schedule 27.07.2020
comment
@KotaMori Хорошо, я изменил обозначение, чтобы сделать его чище, но да, вы правы.   -  person BLBA    schedule 27.07.2020
comment
если вы используете одну и ту же функцию потерь (MSE) для обоих выходных данных, вам не нужно ничего делать. вы можете определить loss_weight только для вывода 2, если вы заинтересованы   -  person Marco Cerliani    schedule 27.07.2020


Ответы (1)


Вы можете добиться этого, определив модель с двумя выходами. Это по существу минимизирует средневзвешенное значение двух потерь.

Ограничение состоит в том, что входная форма первого и (n-1)-го слоев должна быть одинаковой, так как оба получают один и тот же вход x.

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

input_shape = (1,)
model1 = Sequential([
    Dense(5, activation="relu", input_shape=input_shape),
    Dense(8, activation="relu"),
    Dense(input_shape[0])
])

model2 = Sequential([
    Dense(15, activation="relu", input_shape=input_shape),
    Dense(1)
])

x = Input(input_shape)
y = model2(model1(x))
z = model2(x)
model = Model(inputs=x, outputs=[y, z])
model.compile("adam", "mean_squared_error", loss_weight=[0.5, 0.5])

import numpy as np
n = 1000
x = np.random.normal(size=n * input_shape[0]).reshape((n, input_shape[0]))
y = x**2
z = x**2

history = model.fit(x, [y, z], epochs=100)

Визуализация:

import matplotlib.pyplot as plt
plt.plot(history.history["loss"])

yhat, zhat = model.predict(x)
plt.scatter(x, yhat)
plt.scatter(x, zhat)

введите здесь описание изображения введите здесь описание изображения

person Kota Mori    schedule 27.07.2020
comment
Как я могу сделать так, чтобы сообщать об ошибке набора тестов только для данных y, а не для данных z? - person BLBA; 27.07.2020
comment
Сделайте тестовый набор и предоставьте model.fit. Затем в истории вы должны увидеть каждый убыток отдельно, а также общий убыток. Я не знаю, как подавить один из них. - person Kota Mori; 27.07.2020
comment
Все отлично работает, но кажется несовместимым с RandomizedSearchCV, это нормально? - person BLBA; 28.07.2020
comment
Если вы говорите о RandomSearchCV из библиотеки sklearn, она не должна становиться несовместимой, потому что ваша модель имеет несколько выходов. Если есть, это общая проблема того, как вы используете его с моделями тензорного потока. В любом случае, это отдельная проблема, и вы должны открыть новый вопрос, если не можете понять. - person Kota Mori; 28.07.2020