赞
踩
list of list
每一个list,由N个tuple组成,第一个tuple是开始的,
(["<s>", "<d>", "</s>"] ,0, None)
其他的每个tuple,
meta = (vec_a_meta, vec_b_meta, l["topic"])
vec_{}_meta = [{}_age, {}_edu, 1, 0] #{}.format(a or b) [1, 0] or [0, 1]
list of tuple
每一个tuple也有三项,
list of list,
就是所有的消息,和dialog不同的是没有说话人和消息向量这两个。
统计训练语料中所有单词的词频,只保留词频在前10000个。OOV在0.008035
vocab:list of str,就是所有的单词,再加上两个 <pad>
和 <unk>
(未知单词)
rev_vocab:dict,key是单词,value是在词表的位置
也是按照topic频率建立,一共有67个topic
同上,一共有42个dialog_act
epoch_init
:backward_size
:step_size
:算出一共可以分成几个batch,记录每个batch包含的训练数据。
每一batch返回前,要做如下处理
每一个数据单元都是一轮会话,把最后一句作为out
,前面的都是 context
返回的是一批输入context
,一批out
相关变量:
context_lens, list of int 每个训练样本有几句输入
context_utts, list of list 每个训练样本中的输入句子(补齐长度)
floors, list of [0/1] 每个训练样本中的输入句子,和`out`是不是同一个人
out_utts, list of list 每个`out`
out_lens, list of int 每个`out` 长度
out_floors, list of int,每个`out`说话人
out_das, list of list,每个`out`的语料
Returns:
vec_context: 一个np矩阵,第一维`batch_id`, 第二三维就是`context`向量,用0补齐
vec_context_lens:np数组,
vec_floors:np数组,第一维`batch_id`
my_profiles = np.array([meta[out_floors[idx]] for idx, meta in enumerate(meta_rows)])
ot_profiles = np.array([meta[1-out_floors[idx]] for idx, meta in enumerate(meta_rows)])
后来重新看了一下meta
的内容,my_profiles
和 ot_profiles
是说话两方
out_floors[idx]
取值0,1,1-out_floors[idx]
取值1,0每一个meta是一个list,
[m_meta, o_meta, topic_idx]
每一个dialog是一个list
['statement-non-opinion', [0.149, 0.851, 0.0, -0.4215]]
类型 | 词向量长度 | 矩阵 | 方式 |
---|---|---|---|
主题Topic | 30维 | 67 * 30 | 查表 |
对话行为DialogAct | 30维 | 67 * 30 | 查表 |
词库voca | 200维 | 1000*200 | tf.nn.bidirectional_dynamic_rnn ,初始化时还是查表 |
[ μ log ( σ 2 ) ] = W r [ x c ] + b r \left[
with variable_scope.variable_scope("recognitionNetwork"):
recog_input = tf.concat([cond_embedding, output_embedding, attribute_fc1], 1)
recog_mulogvar = layers.fully_connected(recog_input, config.latent_size * 2, activation_fn=None, scope="muvar")
recog_mu, recog_logvar = tf.split(recog_mulogvar, 2, axis=1) # 从公式看出是将两个参数一起训练的,所以用tf.split得到训练后的结果。
[ μ ′ log ( σ ′ 2 ) ] = MLP p ( c ) \left[
with variable_scope.variable_scope("priorNetwork"):
# P(XYZ)=P(Z|X)P(X)P(Y|X,Z)
prior_fc1 = layers.fully_connected(cond_embedding, np.maximum(config.latent_size * 2, 100),
activation_fn=tf.tanh, scope="fc1")
prior_mulogvar = layers.fully_connected(prior_fc1, config.latent_size * 2, activation_fn=None,
scope="muvar")
prior_mu, prior_logvar = tf.split(prior_mulogvar, 2, axis=1)
# use sampled Z or posterior Z
latent_sample = tf.cond(self.use_prior,
lambda: sample_gaussian(prior_mu, prior_logvar),
lambda: sample_gaussian(recog_mu, recog_logvar))
# 这里, self.use_prior 是bool的False,所以执行的后面那个函数,就是trick,见下面
其实很简单,就是我们要从 $p(Z|X_{k})$
中采样一个
Z
k
Z_{k}
Zk出来,尽管我们知道了
p
(
Z
∣
X
k
)
p(Z|X_{k})
p(Z∣Xk) 是正态分布,但是均值方差都是靠模型算出来的,我们要靠这个过程反过来优化均值方差的模型,但是“采样”这个操作是不可导的,而采样的结果是可导的,于是我们利用了一个事实:
从 N ( μ , σ 2 ) \mathcal{N}\left(\mu, \sigma^{2}\right) N(μ,σ2)中采样一个 Z Z Z,相当于从 N ( 0 , I ) \mathcal{N}\left(0, I\right) N(0,I)中采样一个 ϵ \epsilon ϵ,然后让 Z = μ + ε × σ Z=\mu+\varepsilon \times \sigma Z=μ+ε×σ
这样一来,“采样”这个操作就不用参与梯度下降了,改为采样的结果参与,使得整个模型可训练了
对应的代码实现
def sample_gaussian(mu, logvar):
epsilon = tf.random_normal(tf.shape(logvar), name="epsilon")
std = tf.exp(0.5 * logvar)
z= mu + tf.multiply(std, epsilon)
return z
在前面的讨论中,我们希望 $X$
经过编码后,$Z$
的分布都具有零均值和单位方差,这个“希望”是通过加入了 KL loss
来实现的。
如果现在多了类别信息 $Y$
,我们可以希望同一个类的样本都有一个专属的均值 $\mu^{Y}$
(方差不变,还是单位方差),这个 $\mu^{Y}$
让模型自己训练出来。
这样的话,有多少个类就有多少个正态分布,而在生成的时候,我们就可以通过控制均值来控制生成图像的类别。
事实上,这样可能也是在 VAE 的基础上加入最少的代码来实现 CVAE 的方案了,因为这个“新希望”也只需通过修改 KL loss
实现:
L μ , σ 2 = 1 2 ∑ i = 1 d [ ( μ ( i ) − μ ( i ) Y ) 2 + σ ( i ) 2 − log σ ( i ) 2 − 1 ] \mathcal{L}_{\mu, \sigma^{2}}=\frac{1}{2} \sum_{i=1}^{d}\left[\left(\mu_{(i)}-\mu_{(i)}^{Y}\right)^{2}+\sigma_{(i)}^{2}-\log \sigma_{(i)}^{2}-1\right] Lμ,σ2=21i=1∑d[(μ(i)−μ(i)Y)2+σ(i)2−logσ(i)2−1]
def gaussian_kld(recog_mu, recog_logvar, prior_mu, prior_logvar):
kld = -0.5 * tf.reduce_sum(1 + (recog_logvar - prior_logvar)
- tf.div(tf.pow(prior_mu - recog_mu, 2), tf.exp(prior_logvar))
- tf.div(tf.exp(recog_logvar), tf.exp(prior_logvar)), reduction_indices=1)
return kld
模型训练中,计算loss时有一处不是很明白
self.log_p_z = norm_log_liklihood(latent_sample, prior_mu, prior_logvar)
self.log_q_z_xy = norm_log_liklihood(latent_sample, recog_mu, recog_logvar)
self.est_marginal = tf.reduce_mean(rc_loss + bow_loss - self.log_p_z + self.log_q_z_xy)
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。