【问题标题】:Tensorflow 2.0 ValueError while Loading weights from .h5 file从.h5文件加载权重时出现Tensorflow 2.0 ValueError
【发布时间】:2020-08-30 13:46:16
【问题描述】:

我有一个 VAE 架构脚本如下:

import numpy as np

import tensorflow as tf

from tensorflow.keras.layers import Input, Conv2D, Flatten, Dense, Conv2DTranspose, Lambda, Reshape, Layer
from tensorflow.keras.models import Model
from tensorflow.keras.optimizers import Adam
from tensorflow.keras import backend as K

INPUT_DIM = (64,64,3)

CONV_FILTERS = [32,64,64, 128]
CONV_KERNEL_SIZES = [4,4,4,4]
CONV_STRIDES = [2,2,2,2]
CONV_ACTIVATIONS = ['relu','relu','relu','relu']

DENSE_SIZE = 1024

CONV_T_FILTERS = [64,64,32,3]
CONV_T_KERNEL_SIZES = [5,5,6,6]
CONV_T_STRIDES = [2,2,2,2]
CONV_T_ACTIVATIONS = ['relu','relu','relu','sigmoid']

Z_DIM = 32

BATCH_SIZE = 100
LEARNING_RATE = 0.0001
KL_TOLERANCE = 0.5




class Sampling(Layer):
    def call(self, inputs):
        mu, log_var = inputs
        epsilon = K.random_normal(shape=K.shape(mu), mean=0., stddev=1.)
        return mu + K.exp(log_var / 2) * epsilon


class VAEModel(Model):


    def __init__(self, encoder, decoder, r_loss_factor, **kwargs):
        super(VAEModel, self).__init__(**kwargs)
        self.encoder = encoder
        self.decoder = decoder
        self.r_loss_factor = r_loss_factor

    def train_step(self, data):
        if isinstance(data, tuple):
            data = data[0]
        def compute_kernel(x, y):
            x_size = tf.shape(x)[0]
            y_size = tf.shape(y)[0]
            dim = tf.shape(x)[1]
            tiled_x = tf.tile(tf.reshape(x, tf.stack([x_size, 1, dim])), tf.stack([1, y_size, 1]))
            tiled_y = tf.tile(tf.reshape(y, tf.stack([1, y_size, dim])), tf.stack([x_size, 1, 1]))
            return tf.exp(-tf.reduce_mean(tf.square(tiled_x - tiled_y), axis=2) / tf.cast(dim, tf.float32))

        def compute_mmd(x, y):
            x_kernel = compute_kernel(x, x)
            y_kernel = compute_kernel(y, y)
            xy_kernel = compute_kernel(x, y)
            return tf.reduce_mean(x_kernel) + tf.reduce_mean(y_kernel) - 2 * tf.reduce_mean(xy_kernel)

        with tf.GradientTape() as tape:
            z_mean, z_log_var, z = self.encoder(data)
            reconstruction = self.decoder(z)
            reconstruction_loss = tf.reduce_mean(
                tf.square(data - reconstruction), axis = [1,2,3]
            )
            reconstruction_loss *= self.r_loss_factor
            kl_loss = 1 + z_log_var - tf.square(z_mean) - tf.exp(z_log_var)
            kl_loss = tf.reduce_sum(kl_loss, axis = 1)
            kl_loss *= -0.5

            true_samples = tf.random.normal(tf.stack([BATCH_SIZE, Z_DIM]))
            loss_mmd = compute_mmd(true_samples, z)
            

            total_loss = reconstruction_loss + loss_mmd
        grads = tape.gradient(total_loss, self.trainable_weights)
        self.optimizer.apply_gradients(zip(grads, self.trainable_weights))
        return {
            "loss": total_loss,
            "reconstruction_loss": reconstruction_loss,
            "kl_loss": kl_loss,
            "mmd_loss": loss_mmd
        }
    
    def call(self,inputs):
        latent = self.encoder(inputs)
        return self.decoder(latent)



class VAE():
    def __init__(self):
        self.models = self._build()
        self.full_model = self.models[0]
        self.encoder = self.models[1]
        self.decoder = self.models[2]

        self.input_dim = INPUT_DIM
        self.z_dim = Z_DIM
        self.learning_rate = LEARNING_RATE
        self.kl_tolerance = KL_TOLERANCE

    def _build(self):
        vae_x = Input(shape=INPUT_DIM, name='observation_input')
        vae_c1 = Conv2D(filters = CONV_FILTERS[0], kernel_size = CONV_KERNEL_SIZES[0], strides = CONV_STRIDES[0], activation=CONV_ACTIVATIONS[0], name='conv_layer_1')(vae_x)
        vae_c2 = Conv2D(filters = CONV_FILTERS[1], kernel_size = CONV_KERNEL_SIZES[1], strides = CONV_STRIDES[1], activation=CONV_ACTIVATIONS[0], name='conv_layer_2')(vae_c1)
        vae_c3= Conv2D(filters = CONV_FILTERS[2], kernel_size = CONV_KERNEL_SIZES[2], strides = CONV_STRIDES[2], activation=CONV_ACTIVATIONS[0], name='conv_layer_3')(vae_c2)
        vae_c4= Conv2D(filters = CONV_FILTERS[3], kernel_size = CONV_KERNEL_SIZES[3], strides = CONV_STRIDES[3], activation=CONV_ACTIVATIONS[0], name='conv_layer_4')(vae_c3)

        vae_z_in = Flatten()(vae_c4)

        vae_z_mean = Dense(Z_DIM, name='mu')(vae_z_in)
        vae_z_log_var = Dense(Z_DIM, name='log_var')(vae_z_in)

        vae_z = Sampling(name='z')([vae_z_mean, vae_z_log_var])
        

        #### DECODER: 
        vae_z_input = Input(shape=(Z_DIM,), name='z_input')

        vae_dense = Dense(1024, name='dense_layer')(vae_z_input)
        vae_unflatten = Reshape((1,1,DENSE_SIZE), name='unflatten')(vae_dense)
        vae_d1 = Conv2DTranspose(filters = CONV_T_FILTERS[0], kernel_size = CONV_T_KERNEL_SIZES[0] , strides = CONV_T_STRIDES[0], activation=CONV_T_ACTIVATIONS[0], name='deconv_layer_1')(vae_unflatten)
        vae_d2 = Conv2DTranspose(filters = CONV_T_FILTERS[1], kernel_size = CONV_T_KERNEL_SIZES[1] , strides = CONV_T_STRIDES[1], activation=CONV_T_ACTIVATIONS[1], name='deconv_layer_2')(vae_d1)
        vae_d3 = Conv2DTranspose(filters = CONV_T_FILTERS[2], kernel_size = CONV_T_KERNEL_SIZES[2] , strides = CONV_T_STRIDES[2], activation=CONV_T_ACTIVATIONS[2], name='deconv_layer_3')(vae_d2)
        vae_d4 = Conv2DTranspose(filters = CONV_T_FILTERS[3], kernel_size = CONV_T_KERNEL_SIZES[3] , strides = CONV_T_STRIDES[3], activation=CONV_T_ACTIVATIONS[3], name='deconv_layer_4')(vae_d3)
        

        #### MODELS

    
        vae_encoder = Model(vae_x, [vae_z_mean, vae_z_log_var, vae_z], name = 'encoder')
        vae_decoder = Model(vae_z_input, vae_d4, name = 'decoder')

        vae_full = VAEModel(vae_encoder, vae_decoder, 10000)

        opti = Adam(lr=LEARNING_RATE)
        vae_full.compile(optimizer=opti)
        
        return (vae_full,vae_encoder, vae_decoder)

    def set_weights(self, filepath):
        self.full_model.load_weights(filepath)

    def train(self, data):

        self.full_model.fit(data, data,
                shuffle=True,
                epochs=1,
                batch_size=BATCH_SIZE)
        
    def save_weights(self, filepath):
        self.full_model.save_weights(filepath)

问题:

vae = VAE()
vae.set_weights(filepath)

抛出:

File
"/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/training.py",
line 2200, in load_weights
    'Unable to load weights saved in HDF5 format into a subclassed ' ValueError: Unable to load weights saved in HDF5 format into a
subclassed Model which has not created its variables yet. Call the
Model first, then load the weights.

我不确定这意味着什么,因为我对 OOP 并不那么精通。令人惊讶的是,上面的代码一直在工作,直到它停止工作。该模型正在从头开始训练,并将权重保存在 filepath 中。但是当我现在加载相同的重量时,它会抛出上述错误!

【问题讨论】:

    标签: python keras tensorflow2.0


    【解决方案1】:

    如果您在加载模型权重之前设置model.built = True,它会起作用。

    【讨论】:

    • 我认为这有点捷径......恕我直言,在指定模型架构之后,您应该调用 build(input_shape) 来构建它。然后你就可以加载权重了。
    • 这不是正确的方法,应该被否决/删除。层连接是完全未知的,也无法说是否会运行正确的架构,因为模型还没有真正运行它的构建功能。它会尝试将权重放入构建中,但如果您使用不同的批量大小,您将遇到问题。请在未来使用 TF 格式并在加载权重之前在单个批次上运行。
    【解决方案2】:

    您运行的是哪个版本的 TF?有一段时间,默认的保存格式是 hdf5,但是这种格式不能很容易地支持子类模型,所以你得到这个错误。可以通过先在单个批次上训练它然后加载权重来解决(以确定部件的连接方式,而不是保存在 hdf5 中)。

    以后我会建议确保所有保存都使用 TF 文件格式,但这样可以省去额外的工作。

    【讨论】:

    • 我使用的是 Tensorflow 2.3 我通过将其降级到 Tensorflow 1.14.0 来修复它(很好)
    • 您是否尝试在单个批次上运行然后加载重量?我相信这会起作用,您不必降级 TF 并失去最新版本的功能
    • 我很好奇为什么会在单个批处理上运行帮助
    • 我相信 hdf5 不存储层的连接方式,并且子类网络可以在顺序格式之外连接,因此这些信息是未知的。然后在单个批次上运行将设置变量的连接方式,然后加载权重应该可以工作
    • @UlfAslak 不幸的是,如果您保存在 hdf5 中,这是最好的方法,因为它不存储重新创建模型所需的信息。请注意,有 model.train_on_batch() 可能更有效。我相信最好的解决方案是将其保存为 .tf 格式,因为这应该保存连接信息,因此您无需在单个批次上进行训练。
    【解决方案3】:

    正如alwaysmvp45 指出的“hdf5 不存储层的连接方式”。为了使这些层连接起来,另一种方法是在加载权重之前调用模型来预测具有输入形状 ((1,w,h,c)) 的 zeros 数组:

    model(np.zeros((1,w,h,c)))
    

    【讨论】:

      【解决方案4】:

      我在通过加载权重时遇到了同样的错误

      model.load_weights("Detection_model.h5")
      

      ValueError:无法将保存为 HDF5 格式的权重加载到尚未创建其变量的子类模型中。先调用模型,然后加载权重。

      通过在加载权重之前构建模型解决了这个问题

      model.build(input_shape = <INPUT_SHAPE>)
      model.load_weights("Detection_model.h5")
      

      ps,张量流版本:2.5.0

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-11-21
        • 2020-02-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-09-24
        • 1970-01-01
        相关资源
        最近更新 更多