Keras Functional API и функция потерь с несколькими входами - PullRequest
0 голосов
/ 09 ноября 2018

Я пытаюсь использовать пользовательскую функцию потери Keras, которая помимо обычной подписи (y_true, y_pred) принимает другой параметр sigma (который также создается последним уровнем сети).Обучение работает нормально, но тогда я не уверен, как выполнить прямое распространение и вернуть sigma (в то время как mu является выводом метода model.predict).Это код, который я использую, который имеет собственный слой GaussianLayer, который возвращает список [mu, sigma].

import tensorflow as tf
from keras import backend as K
from keras.layers import Input, Dense, Layer, Dropout
from keras.models import Model
from keras.initializers import glorot_normal
import numpy as np

def custom_loss(sigma):
    def gaussian_loss(y_true, y_pred):
        return tf.reduce_mean(0.5*tf.log(sigma) + 0.5*tf.div(tf.square(y_true - y_pred), sigma)) + 10
    return gaussian_loss

class GaussianLayer(Layer):

    def __init__(self, output_dim, **kwargs):
        self.output_dim = output_dim
        super(GaussianLayer, self).__init__(**kwargs)

    def build(self, input_shape):
        self.kernel_1 = self.add_weight(name='kernel_1', 
                                      shape=(30, self.output_dim),
                                      initializer=glorot_normal(),
                                      trainable=True)
        self.kernel_2 = self.add_weight(name='kernel_2', 
                                      shape=(30, self.output_dim),
                                      initializer=glorot_normal(),
                                      trainable=True)
        self.bias_1 = self.add_weight(name='bias_1',
                                    shape=(self.output_dim, ),
                                    initializer=glorot_normal(),
                                    trainable=True)
        self.bias_2 = self.add_weight(name='bias_2',
                                    shape=(self.output_dim, ),
                                    initializer=glorot_normal(),
                                    trainable=True)
        super(GaussianLayer, self).build(input_shape) 

    def call(self, x):
        output_mu  = K.dot(x, self.kernel_1) + self.bias_1
        output_sig = K.dot(x, self.kernel_2) + self.bias_2
        output_sig_pos = K.log(1 + K.exp(output_sig)) + 1e-06  
        return [output_mu, output_sig_pos]

    def compute_output_shape(self, input_shape):
        return [(input_shape[0], self.output_dim), (input_shape[0], self.output_dim)]

# This returns a tensor
inputs = Input(shape=(1,))
x = Dense(30, activation='relu')(inputs)
x = Dropout(0.3)(x)
x = Dense(30, activation='relu')(x)
x = Dense(40, activation='relu')(x)
x = Dropout(0.3)(x)
x = Dense(30, activation='relu')(x)
mu, sigma = GaussianLayer(1)(x)

model = Model(inputs, mu)
model.compile(loss=custom_loss(sigma), optimizer='adam')
model.fit(train_x, train_y, epochs=150)

Ответы [ 2 ]

0 голосов
/ 11 ноября 2018

Возможно, я нашел ответ среди Keras FAQs . Я обнаружил, что можно получить выходные данные промежуточных шагов, используя фрагмент кода ниже:

layer_name = 'main_output'
intermediate_layer_model = Model(inputs=model.input,
                                 outputs=model.get_layer(layer_name).output)
intermediate_output = intermediate_layer_model.predict(train_x[0])
intermediate_output

В этом случае intermediate_output - это список из двух значений [mu, sigma] (просто необходимо указать имя выходного слоя main_output и получить его позже)

0 голосов
/ 09 ноября 2018

Поскольку ваша модель возвращает два тензора в качестве выходных данных, вам также нужно передать список из двух массивов в качестве выходных данных при вызове метода fit(). По сути, это то, что ошибка пытается передать:

Ошибка при проверке модели цели :

Таким образом, ошибка находится в целях (то есть метках). Что не так?

список массивов Numpy, передаваемых вашей модели - это не тот размер, который ожидала модель . Ожидается , чтобы увидеть 2 массива (ов) , но вместо этого получил следующий список 1 массивов :

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