Wandererℵ 2023-04-23 15:57 采纳率: 0%
浏览 66

ValueError: 添加到顺序模型的所有层都应具有唯一的名称

在训练一个用于音乐生成的VAE模型时,遇到报错:

ValueError       Traceback (most recent call last)
/tmp/ipykernel_27/1449102967.py in <module>
     98 
     99 random_vector_for_generation = tf.random.normal(shape = [num_examples_to_generate, latent_dim])
--> 100 model = CVAE(latent_dim)

/tmp/ipykernel_27/1449102967.py in __init__(self, latent_dim)
     52 
     53                 layers.Flatten(name = 'flatten'),
---> 54                 layers.Dense(latent_dim + latent_dim, name = 'dense'),
     55             ]
     56         )
...

报错:

All layers added to a Sequential model should have unique names. Name "" is already the name of a layer in this model. Update the name argument to pass a unique name.

python version:3.7
tensorflow version:2.3

class Resnet1DBlock(tf.keras.Model):
    def __init__(self, kernel_size, filters, type = 'encode', prefix = ''):
        super(Resnet1DBlock, self).__init__(name = '')
    
        if type == 'encode':
            self.conv1a = layers.Conv1D(filters, kernel_size, 2, padding = "same", \
                                        name = prefix + 'conv1a')
            self.conv1b = layers.Conv1D(filters, kernel_size, 1, padding = "same", \
                                        name = prefix + 'conv1b')
            self.norm1a = tfa.layers.InstanceNormalization(name =  prefix + 'norm1a')
            self.norm1b = tfa.layers.InstanceNormalization(name =  prefix + 'norm1b')
        elif type == 'decode':
            self.conv1a = layers.Conv1DTranspose(filters, kernel_size, 1, padding = "same", \
                                                name =  prefix + 'conv1a')
            self.conv1b = layers.Conv1DTranspose(filters, kernel_size, 1, padding = "same", \
                                                name =  prefix + 'conv1b')
            self.norm1a = tf.keras.layers.BatchNormalization(name =  prefix + 'norm1a')
            self.norm1b = tf.keras.layers.BatchNormalization(name =  prefix + 'norm1b')
        else:
            return None

    def call(self, input_tensor):
        x = tf.nn.relu(input_tensor)
        x = self.conv1a(x)
        x = self.norm1a(x)
        x = layers.LeakyReLU(0.4)(x)

        x = self.conv1b(x)
        x = self.norm1b(x)
        x = layers.LeakyReLU(0.4)(x)

        x += input_tensor
        return tf.nn.relu(x)
    
class CVAE(tf.keras.Model):

    def __init__(self, latent_dim):
        super(CVAE, self).__init__()
        self.latent_dim = latent_dim
        self.encoder = tf.keras.Sequential(
            [
                tf.keras.layers.InputLayer(input_shape = (1, 90001), name = 'input_encoder'),

                layers.Conv1D(64, 1, 2, name = 'conv1_layer1'),
                Resnet1DBlock(64, 1, 'encode', prefix = 'res1_'),
                layers.Conv1D(128, 1, 2, name = 'conv1_layer2'),
                Resnet1DBlock(128, 1, 'encode', prefix = 'res2_'),
                layers.Conv1D(128, 1, 2, name = 'conv1_layer3'),
                Resnet1DBlock(128, 1, 'encode', prefix = 'res3_'),
                layers.Conv1D(256, 1, 2, name = 'conv1_layer4'),
                Resnet1DBlock(256, 1, 'encode', prefix = 'res4_'),

                layers.Flatten(name = 'flatten'),
                layers.Dense(latent_dim + latent_dim, name = 'dense'),
            ]
        )
        self.decoder = tf.keras.Sequential(
            [
                tf.keras.layers.InputLayer(input_shape = (latent_dim,), name = 'input_decoder'),
                layers.Reshape(target_shape = (1, latent_dim)),
                Resnet1DBlock(512, 1, 'decode', prefix = 'res1_'),
                layers.Conv1DTranspose(512, 1, 1, name = 'Conv1Trans_Layer1'),
                Resnet1DBlock(256, 1, 'decode', prefix = 'res2_'),
                layers.Conv1DTranspose(256, 1, 1, name = 'Conv1Trans_Layer2'),
                Resnet1DBlock(128, 1, 'decode', prefix = 'res3_'),
                layers.Conv1DTranspose(128, 1, 1, name = 'Conv1Trans_Layer3'),
                Resnet1DBlock(64, 1, 'decode', prefix = 'res4_'),
                layers.Conv1DTranspose(64, 1, 1, name = 'Conv1Trans_Layer4'),
                layers.Conv1DTranspose(90001, 1, 1, name = 'Conv1Trans_Layer5')
            ]
        )
        
# 省略了与报错无关的函数
optimizer = tf.keras.optimizers.Adam(0.0003, beta_1 = 0.9, beta_2 = 0.999, epsilon = 1e-08)

random_vector_for_generation = tf.random.normal(shape = [num_examples_to_generate, latent_dim])
model = CVAE(latent_dim)

我非常疑惑,明明已经给所有网络层命名了。

  • 写回答

2条回答 默认 最新

  • CSDN-Ada助手 CSDN-AI 官方账号 2023-04-23 18:06
    关注
    • 你可以参考下这篇文章:tensorflow+Python ValueError以及解决方法(后续继续更新)
    • 除此之外, 这篇博客: tensorflow2.1.0——如何构建网络(三)中的 3. 以VAE为例,讲解如何解决这些问题 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
      • 首先,我们要思考如何选择网络的构建方式,本质上就是要考虑从损失函数好计算的角度来选择网络构建的方式,下面代码的注释会详细介绍。
        ①考虑使用一个Squential去构建encoder和decoder,这是完全不可行的。一个致命的问题就是无法计算损失函数。其次,也无法单独使用生成器来生成图片。
      # 考虑使用一个Squential构建VAE
      model = tf.keras.Squential([
      encoder,   #伪代码,encoder为神经网络,里边的层请自己脑补
      lambda/自定义层,  # 重采样层
      decoder  # decoder神经网络
      ])
      
      至此,网络结构搭好了。但正如上述所说,loss如何计算呢?
      因为keras.losses库中并没有为VAE准备损失,所以我们肯定考虑我们自己搞一个损失函数就得了,好,那进入下一个问题:
      损失函数有哪些?
      重构误差 + KL(q(z|x)||p(z))
      重构误差:使用交叉熵损失函数,需要y_true,y_pred.
      我们可以定义一个函数去计算loss,包括重构误差和KL散度,**重点看一下KL散度**
      def compute_loss(model,x):
      	"""
      	x:真实的图片
      	model:我们的模型
      	"""
      	# 当decoder最后一层没有使用激活函数时,from_logits置为True,保证数据的稳定性。
      	cross_entropy = tf.keras.losses.BinaryCrossEntropy(from_logit=True)
      	out = model(x)
      	rec_loss = cross_entropy(y_true=x,y_pred=out)
      	
      	# 那么KL散度如何计算,我们得不到encoder的均值和方差,咋弄?
      	
      可以看到,构建方式的选择将会影响我们能否计算loss。
      至此,我们决定放弃第一期讲的构建网络的方式!
      

      ②考虑第二期介绍的构建网络的方式:Input与output

      • 我们在第二期也讲了,通过Input与output构建,增加了构建网络的灵活性,所以,这种方式肯定是可以的。下面直接上代码
      # 定义自己的模型
      latent_dimension = 50
      # 重采样函数,应用在Lambda层
      def sampling(agrs):
          mean,logvar = agrs[0],agrs[1]
          eps = tf.random.normal(tf.shape(mean))
          
          return mean + eps*tf.exp(logvar * 0.5)
      
      
      # 编码阶段
          
      x = layers.Input(shape=(784,)) 
          
      h1 = layers.Dense(200,activation='softplus')(x)
      h2 = layers.Dense(200,activation='softplus')(h1)
      # 均值和方差层不需要激活函数
      mean = layers.Dense(latent_dimension)(h2)
      log_var = layers.Dense(latent_dimension)(h2)
          
      # 将采样过程看成一个Lambda层
      z = layers.Lambda(sampling,output_shape=(latent_dimension,))([mean,log_var])
          
      # 解码阶段
      h3 = layers.Dense(200,activation='softplus')
      h4 = layers.Dense(200,activation='softplus')
      h5 = layers.Dense(200,activation='softplus')
      # No activation
      end = layers.Dense(784)
      z1 = h3(z)
      z2 = h4(z1)
      z3 = h5(z2)
      out = end(z3)
          
      # 建立模型
      model = tf.keras.Model(x,out)
          
      cross_ent = tf.reduce_sum(tf.nn.sigmoid_cross_entropy_with_logits(labels=tf.split(x,num_or_size_splits=2,axis=-1)[0],logits=out),axis=-1) # 重构误差
      KL = -tf.reduce_sum(1+log_var-tf.square(mean)-tf.exp(log_var),axis=-1)
      dvae_loss = tf.reduce_mean(cross_ent + KL)
      model.add_loss(dvae_loss)
      
      # 编译
      model.compile(optimizer='adam')
      # fit
      history = model.fit(train_dataset,epochs=80,validation_data=test_dataset) 
      
      
      # 在训练好模型后,我们肯定是要从生成器中生成模型,这很方便
      
      # 构造生成器
      decoder_input = layers.Input(shape=(latent_dimension,))
      h1_decoder = h3(decoder_input) #200,h3层的参数在之前就训练好了
      h2_decoder = h4(h1_decoder)    #200
      h3_decoder = h5(h2_decoder)    #200
      decoder_output = end(h3_decoder) 
      
      generator = tf.keras.Model(decoder_input,decoder_output)
      
    评论

报告相同问题?

问题事件

  • 创建了问题 4月23日