【问题标题】:Need help in compiling custom loss在编译自定义损失时需要帮助
【发布时间】:2021-10-28 06:11:11
【问题描述】:

我正在向 VAE 添加自定义损失,如下所示:https://www.linkedin.com/pulse/supervised-variational-autoencoder-code-included-ibrahim-sobh-phd/

它没有定义损失函数,而是使用dense 网络并将其输出作为损失(如果我理解正确的话)。

# New: add a classifier
clf_latent_inputs = Input(shape=(latent_dim,), name='z_sampling_clf')
clf_outputs = Dense(10, activation='softmax', name='class_output')(clf_latent_inputs)
clf_supervised = Model(clf_latent_inputs, clf_outputs, name='clf')
clf_supervised.summary()


# instantiate VAE model
# New: Add another output
outputs = [decoder(encoder(inputs)[2]), clf_supervised(encoder(inputs)[2])]
vae = Model(inputs, outputs, name='vae_mlp')
vae.summary()

reconstruction_loss = binary_crossentropy(inputs, outputs[0])
reconstruction_loss *= original_dim

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

# New: add the clf loss
vae.compile(optimizer='adam', loss={'clf': 'categorical_crossentropy'})    ===> this line <===
vae.summary()

# reconstruction_loss = binary_crossentropy(inputs, outputs)
svae_history = vae.fit(x_train, {'clf': y_train},
        epochs=epochs,
        batch_size=batch_size)

我在编译步骤卡住了(注释为===>这一行

TypeError: Expected float32, got init..vae_loss at 0x7ff53051dd08> 类型 'function' 代替。

如果您有任何建议,我需要您的帮助。

【问题讨论】:

    标签: tensorflow keras


    【解决方案1】:

    在 Tensorflow 中有多种实现 VAE 的方法。我提出了一个替代实现,可以在 Tensorflow 指南页面的custom_layers_and_models 中找到:

    让我们将所有这些东西放在一个端到端的示例中:我们将实现一个变分自动编码器 (VAE)。我们将在 MNIST 数字上对其进行训练。

    它使用自定义模型类和渐变胶带。这样,很容易将分类器加入到VAE模型中,并在优化过程中将分类交叉熵加入到总损失中。

    你只需要修改:

    class VariationalAutoEncoder(Model):
    """Combines the encoder and decoder into an end-to-end model for training."""
    
    def __init__(
        self,
        original_dim,
        intermediate_dim=64,
        latent_dim=32,
        name="autoencoder",
        **kwargs
    ):
        super(VariationalAutoEncoder, self).__init__(name=name, **kwargs)
        self.original_dim = original_dim
        self.encoder = Encoder(latent_dim=latent_dim, intermediate_dim=intermediate_dim)
        self.decoder = Decoder(original_dim, intermediate_dim=intermediate_dim)
        self.clf_supervised = Dense(10, activation='softmax', name='class_output')
    
    def call(self, inputs):
        z_mean, z_log_var, z = self.encoder(inputs)
        reconstructed = self.decoder(z)
    
        # Add KL divergence regularization loss.
        kl_loss = -0.5 * tf.reduce_mean(
            z_log_var - tf.square(z_mean) - tf.exp(z_log_var) + 1
        )
        self.add_loss(kl_loss)
    
        # classifier
        y_pred = self.clf_supervised(z)
    
        return reconstructed, y_pred
    

    通过添加行 self.clf_supervised = Dense(10, activation='softmax', name='class_output')y_pred = self.clf_supervised(z)

    优化是这样完成的:

    vae = VariationalAutoEncoder(original_dim, intermediate_dim, latent_dim)
    
    optimizer = tf.keras.optimizers.Adam(learning_rate=1e-3)
    mse_loss_fn = tf.keras.losses.MeanSquaredError()
    loss_metric = tf.keras.metrics.Mean()
    
    epochs = 2
    train_dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train))
    train_dataset = train_dataset.shuffle(buffer_size=500).batch(4)
    
    # Iterate over epochs.
    for epoch in range(epochs):
        print("Start of epoch %d" % (epoch,))
    
        # Iterate over the batches of the dataset.
        for step, (x_batch_train, y_batch_train) in enumerate(train_dataset):
            with tf.GradientTape() as tape:
                reconstructed, y_pred = vae(x_batch_train)
                clf_loss = tf.keras.losses.SparseCategoricalCrossentropy()(y_batch_train, y_pred)
                # Compute reconstruction loss
                loss = mse_loss_fn(x_batch_train, reconstructed)
                loss += sum(vae.losses)  # Add KLD regularization loss
                loss += clf_loss
    
            grads = tape.gradient(loss, vae.trainable_weights)
            optimizer.apply_gradients(zip(grads, vae.trainable_weights))
    
            loss_metric(loss)
    
            if step % 100 == 0:
                print("step %d: mean loss = %.4f" % (step, loss_metric.result()))
    

    其余代码在上面的链接中。主要变化是使用 tf.GradientTape() 完成的优化。它比 fit 方法要复杂一些,但它仍然非常简单且非常强大。

    【讨论】:

    • 谢谢易北河!我正在详细研究你的代码。
    猜你喜欢
    • 2010-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-23
    • 2018-07-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多