VAE for 文本生成

该博客详细介绍了VAE(变分自编码器)的工作原理,并重点阐述了其在文本生成领域的应用,包括如何通过随机层结构提取语义丰富的编码,以及如何利用多级解码器捕捉长文本的长期结构。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

VAE详解:https://spaces.ac.cn/archives/5253

      变分自编码器(Variational auto-encoder,VAE)是一类重要的生成模型(generative model),它于2013年由Diederik P.Kingma和Max Welling提出[1]。2016年Carl Doersch写了一篇VAEs的tutorial[2],对VAEs做了更详细的介绍,比文献[1]更易懂。
      VAE的总体目标和GAN基本一致,都是希望通过构建一个从隐变量Z生成目标数据X的模型,他们假设Z服从某种常见分布(比如正态分布),然后训练一个模型X=g(Z),这个模型能够将原来的概率分布映射到训练集的概率分布,这样我们就通过这边模型生成与符合训练数据概率分布的新的数据了。
         
与自编码对比:
      自编码通过编码器将输入x进行编码成z,然后通过解码器将z解码成x`,使得x`与x一样。缺陷:1.需要有原始输入,是有监督的;2.生成的结果是使得x`与原始输入一样,不能泛化生成多样的结果。3.主要用于获取输入的隐藏表示。
     变分自编码结构与自编码类似,也是由编码器和解码器构成,不同的是在编码的目标是生成一个概率分布 q(z|x)代替确定性z来重建输入,强制模型将输入映射到空间的区域而不是单个点,。在这种情况下,实现良好重构误差的最直接方法是预测非常潜在的概率分布,有效地对应于潜在空间中的单个点(Raiko等人2014)。引入 KL divergence 让后验 q(z|x) 接近先验 p(z).
 

VAE在文本生成领域的应用:

  
  实质:以自编码框架为基础,通过分层编码和解码的方式将词与句子信息综合考虑。如下图,虚线部分为attention
          
 
【  Generating Sentences from a Continuous Space】-第20届计算自然语言学习大会 2016
 
     作者为了弥补传统的 RNNLM 结构缺少的一些全局特征(其实可以理解为想要 sentence representation)。其实抛开 generative model,之前也有一些比较成功的 non-generative 的方法,比如 sequence autoencoders[1],skip-thought[2] 和 paragraph vector[3]。但随着 VAE 的加入,generative model 也开始在文本上有更多 的可能性。

文本生成可以使用很多不同的算法和模型,比如基于规则的文本生成、马尔科夫模型、循环神经网络 (RNN)、长短时记忆网络 (LSTM)、生成对抗网络 (GAN)、变分自编码器 (VAE)、自注意力模型 (Transformer) 等等。这里简单介绍一下使用 LSTM 模型实现文本生成的方法。 LSTM (Long Short-Term Memory) 是循环神经网络中一种比较广泛使用的模型,它通过引入记忆单元来解决传统 RNN 模型的梯度消失问题,从而能够更好地捕捉长期的依赖关系。在文本生成中,我们可以将输入的文本序列作为模型的输入,训练模型预测下一个字符或单词的概率分布,然后根据这个分布采样生成新的文本。 以下是一个简单的基于 LSTM 模型的文本生成代码示例: ```python import numpy as np import tensorflow as tf # 读取文本文件 with open('text.txt', 'r', encoding='utf-8') as f: text = f.read() # 将字符转换为数字编码 vocab = sorted(set(text)) char2idx = {c: i for i, c in enumerate(vocab)} idx2char = {i: c for i, c in enumerate(vocab)} encoded_text = np.array([char2idx[c] for c in text]) # 定义模型 model = tf.keras.Sequential([ tf.keras.layers.Embedding(len(vocab), 256, batch_input_shape=[1, None]), tf.keras.layers.LSTM(1024, return_sequences=True, stateful=True, recurrent_initializer='glorot_uniform'), tf.keras.layers.Dense(len(vocab), activation='softmax') ]) # 定义损失函数和优化器 loss_fn = tf.keras.losses.SparseCategoricalCrossentropy() optimizer = tf.keras.optimizers.Adam() # 训练模型 for epoch in range(num_epochs): # 将数据划分为多个序列 seq_length = 100 examples_per_epoch = len(text) // seq_length char_dataset = tf.data.Dataset.from_tensor_slices(encoded_text) sequences = char_dataset.batch(seq_length+1, drop_remainder=True) # 定义训练步骤 @tf.function def train_step(x, y): with tf.GradientTape() as tape: logits = model(x, training=True) loss = loss_fn(y, logits) gradients = tape.gradient(loss, model.trainable_variables) optimizer.apply_gradients(zip(gradients, model.trainable_variables)) return loss # 训练模型 for i, sequence in enumerate(sequences): input_seq = sequence[:-1] target_seq = sequence[1:] loss = train_step(tf.expand_dims(input_seq, 0), target_seq) if i % 100 == 0: print('Epoch {} Batch {} Loss {:.4f}'.format(epoch+1, i, loss)) # 使用模型生成新的文本 def generate_text(model, start_string): num_generate = 1000 input_eval = [char2idx[c] for c in start_string] input_eval = tf.expand_dims(input_eval, 0) text_generated = [] model.reset_states() for i in range(num_generate): logits = model(input_eval) logits = tf.squeeze(logits, 0) predicted_id = tf.random.categorical(logits=logits, num_samples=1)[-1,0].numpy() input_eval = tf.expand_dims([predicted_id], 0) text_generated.append(idx2char[predicted_id]) return start_string + ''.join(text_generated) # 使用模型生成文本 generated_text = generate_text(model, start_string='The ') print(generated_text) ``` 在训练模型时,我们将原始文本划分为多个长度为 100 的序列,每次将一个序列作为输入,将该序列的下一个字符作为输出,训练模型预测下一个字符的概率分布。在使用模型生成新的文本时,我们先给定一个起始字符串,然后使用模型预测下一个字符,并根据该字符的概率分布进行采样,重复这个过程直到生成所需长度的文本。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值