Ошибка отключения графика из-за категориальной потери кроссентропии - PullRequest
1 голос
/ 28 апреля 2020

Я пытаюсь обучить вариационный автоэнкодер. Модель существует из двух частей: кодера и декодера. Кодер имеет 2 входа и 3 выхода. Декодер имеет 3 входа (первый - последний выход кодера, второй - потери, третий - маска.) И три выхода. Кодер и декодер объединяются для формирования модели автоматического кодера. Я попытался выполнить настройку, приведенную в примере с автоматическим кодировщиком: https://www.tensorflow.org/guide/keras/functional. Но, похоже, это не работает для меня.

Модель:

from tensorflow import keras
from tensorflow.keras.layers import Dense, Lambda, Reshape, Concatenate, Conv1D
from tensorflow.keras.models import Model
from tensorflow.keras.losses import mse, categorical_crossentropy
from tensorflow.keras import backend as K

import tensorflow.compat.v1 as tf

def sampling(args):
    z_mean, z_log_var = args
    batch = K.shape(z_mean)[0]
    dim = K.int_shape(z_mean)[1]
    epsilon = K.random_normal(shape=(batch, dim))
    return z_mean + K.exp(0.5 * z_log_var ) * epsilon

def mse_particles(inputs, outputs, particles):
    particles = K.reshape(particles, shape=(K.shape(particles)[0],))
    in_slice = K.cast(2 + particles*3, "int32")

    mask_fn = lambda n: K.concatenate((K.ones((n,), dtype="float32"), K.zeros((3*16+2-n,), dtype="float32")))
    mask = K.map_fn(mask_fn, in_slice, dtype='float32')

    se = (inputs - outputs)**2
    loss = K.sum(se * mask, axis=None)
    loss = loss / K.sum(mask, axis=None)
    return loss

def initialize_model(beta, n_particles, n_classes, latent_size, activation_func):
    'Network parameters'
    input_shape_class = (n_particles, )
    input_shape_regress = (3 * n_particles + 2, )
    hidden_layer_dim = 512
    latent_dim = latent_size * n_particles

    'Build encoder'
    encoder_inputs_class = keras.Input(shape=input_shape_class, name='inputs_class')
    inputs_class_t = Lambda(lambda x: K.one_hot(K.cast(x, 'int32'), n_classes))(encoder_inputs_class)
    inputs_class_t2 = Reshape((n_particles*n_classes,))(inputs_class_t)

    encoder_inputs_regress = keras.Input(shape=input_shape_regress, name='inputs_regress')

    inputs = Concatenate()([inputs_class_t2, encoder_inputs_regress])

    x_1 = Dense(hidden_layer_dim, activation=activation_func)(inputs)
    x_2 = Dense(int(hidden_layer_dim/2), activation=activation_func)(x_1)
    x_3 = Dense(int(hidden_layer_dim/4), activation=activation_func)(x_2)

    'Latent space'
    z_mean = Dense(latent_dim, activation='linear', name='z_mean')(x_3)
    z_log_var = Dense(latent_dim, activation='linear', name='z_log_var')(x_3)
    z = Lambda(sampling, output_shape=(latent_dim,), name='z')([z_mean, z_log_var])

    encoder = Model([encoder_inputs_class, encoder_inputs_regress], [z_mean, z_log_var, z], name='encoder')
    encoder.summary()

    'Build decoder'
    decoder_inputs_latent = keras.Input(shape=(latent_dim,), name='z_sampling')
    decoder_inputs_n_particles = keras.Input(shape=(1,), name='input_n_particles')
    decoder_inputs_n_particles_mask = keras.Input(shape=(latent_dim, ), name='inputs_n_particles_mask')

    # Implement mask
    masked_latent = Lambda(lambda x: x[0]*x[1])([decoder_inputs_latent, decoder_inputs_n_particles_mask])

    x_4 = Dense(int(hidden_layer_dim/4), activation=activation_func)(masked_latent)
    x_5 = Dense(int(hidden_layer_dim/2), activation=activation_func)(x_4)
    x_6 = Dense(hidden_layer_dim, activation=activation_func)(x_5)

    outputs_class_t = Dense(n_particles*n_classes, activation='elu')(x_6)
    outputs_class_t2 = Reshape((n_particles, n_classes))(outputs_class_t)
    decoder_outputs_class = Dense(n_classes, activation='softmax')(outputs_class_t2)

    decoder_outputs_regress = Dense(n_particles*3+2, activation='linear')(x_6)

    decoder_outputs_n_particles = Dense(1, activation='linear')(x_6)

    decoder = Model([decoder_inputs_latent, decoder_inputs_n_particles, decoder_inputs_n_particles_mask], [decoder_outputs_class, decoder_outputs_regress, decoder_outputs_n_particles], name='decoder')
    decoder.summary()

    'Build autoencoder'

    vae_input_1 = keras.Input(shape=input_shape_class, name = 'vae_input_1')
    vae_input_2 = keras.Input(shape=input_shape_regress, name = 'vae_input_2')
    vae_input_3 = keras.Input(shape=(1,), name = 'vae_input_3')
    vae_input_4 = keras.Input(shape=(latent_dim, ), name = 'vae_input_4')

    outputs = decoder([encoder([vae_input_1, vae_input_2])[2], vae_input_3, vae_input_4])

    vae = Model([vae_input_1, vae_input_2, vae_input_3, vae_input_4], outputs, name='bvae')
    vae.summary()

    'Calculate loss'
    n_particles_loss = mse(decoder_inputs_n_particles, outputs[2])
    classification_loss = categorical_crossentropy(inputs_class_t, outputs[0])
    regression_loss = mse(encoder_inputs_regress, outputs[1])

    reconstruction_loss = 100*K.mean(n_particles_loss) + 10*K.mean(classification_loss) + K.mean(regression_loss)

    kl_loss = -0.5 * K.sum((1+z_log_var-K.square(z_mean)-K.exp(z_log_var)), axis=-1)
    vae_loss = K.mean((1-beta) * reconstruction_loss + beta * kl_loss)
    vae.add_loss(vae_loss)

    vae.compile(optimizer = keras.optimizers.Adam(lr=1e-4, beta_1=0.9, beta_2=0.999))
    return vae, encoder, decoder

И я пытаюсь загрузить его, чтобы обучить, но у меня появляется следующая ошибка:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-7-93e72a9318eb> in <module>
     21 
     22         'Load model'
---> 23         vae = model_v2.initialize_model(beta, max_particles, n_classes, latent_size, activation_function)
     24 
     25 

~/Stage/bvae_cut/Functions/model_v2.py in initialize_model(beta, n_particles, n_classes, latent_size, activation_func)
     99     kl_loss = -0.5 * K.sum((1+z_log_var-K.square(z_mean)-K.exp(z_log_var)), axis=-1)
    100     vae_loss = K.mean((1-beta) * reconstruction_loss + beta * kl_loss)
--> 101     vae.add_loss(vae_loss)
    102 
    103     vae.compile(optimizer = keras.optimizers.Adam(lr=1e-4, beta_1=0.9, beta_2=0.999))

~/Stage/venv/lib/python3.6/site-packages/tensorflow_core/python/keras/engine/base_layer.py in add_loss(self, losses, inputs)
   1130       for symbolic_loss in symbolic_losses:
   1131         if getattr(self, '_is_graph_network', False):
-> 1132           self._graph_network_add_loss(symbolic_loss)
   1133         else:
   1134           # Possible a loss was added in a Layer's `build`.

~/Stage/venv/lib/python3.6/site-packages/tensorflow_core/python/keras/engine/network.py in _graph_network_add_loss(self, symbolic_loss)
   1424 
   1425   def _graph_network_add_loss(self, symbolic_loss):
-> 1426     new_nodes, new_layers = _map_subgraph_network(self.inputs, [symbolic_loss])
   1427     # Losses must be keyed on inputs no matter what in order to be supported in
   1428     # DistributionStrategy.

~/Stage/venv/lib/python3.6/site-packages/tensorflow_core/python/keras/engine/network.py in _map_subgraph_network(inputs, outputs)
   1651   base_layer_utils.create_keras_history(outputs)
   1652   # Keep only nodes and layers in the topology betweeen inputs and outputs.
-> 1653   _, nodes_by_depth, layers, _ = _map_graph_network(inputs, outputs)
   1654   return nest.flatten([nodes for nodes in nodes_by_depth.values()]), layers
   1655 

~/Stage/venv/lib/python3.6/site-packages/tensorflow_core/python/keras/engine/network.py in _map_graph_network(inputs, outputs)
   1623                              'The following previous layers '
   1624                              'were accessed without issue: ' +
-> 1625                              str(layers_with_complete_input))
   1626         for x in nest.flatten(node.output_tensors):
   1627           computable_tensors.add(x)

ValueError: Graph disconnected: cannot obtain value for tensor Tensor("inputs_class:0", shape=(None, 15), dtype=float32) at layer "inputs_class". The following previous layers were accessed without issue: ['vae_input_1', 'vae_input_2', 'encoder', 'vae_input_3', 'vae_input_4', 'decoder']

Может ли кто-нибудь помочь мне с этой ошибкой?

Редактировать: Я попытался изменить потери, чтобы посмотреть, решит ли это проблему. Кажется, что проблема происходит от classification_loss. Если я изменяю vae.add_loss(vae_loss) на vae.add_loss(regression_loss) или vae.add_loss(n_particle_loss), он тренируется, но если я изменяю его на vae.add_loss(classification_loss), модель больше не работает. Без учета этой потери на самом деле не вариант исправить модель, так как у нее не будет желаемого результата.

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