【真实经历】千万别玩笔仙!(胆小慎入)

写在前面:本人真实经历,一晚上没睡觉!不是鼓吹封建迷信!唉,本来我是一个坚定的唯物主义无神论者,这次真的是吓怕了。大家有好奇的听我一句劝,千万别玩笔仙,会后悔的!把我的经历写出来,给大家引以为戒吧,唉。


前几天天夜里,我闲着无聊,实在不知道干什么。室友不是在下面玩游戏,就是在床上看手机。然后我突然想到,室友 A 以前说过,每当半夜里,他的那些 b 站啊,知乎啊什么的就老是给他推恐怖灵异故事,然后他又怕又想看,最后搞得他老是睡不好觉。他对什么成都僵尸啊,猫脸老太太啊都是如数家珍。虽然我是个坚定的唯物主义者,但是我很怕鬼,只要看恐怖电影或者恐怖小说,甚至一些没有恐怖因素的科幻电影,晚上必会做噩梦,有时候就算什么也没干晚上也会莫名其妙地做噩梦。而且我做噩梦了一定会提前醒来。现在在寝室里还好,以前一个人的时候,醒来的时候不知道几点,又不敢看时间,只是一直回想着噩梦的内容,直到闹钟响,十分地煎熬。因此每当室友 A 想开始讲鬼故事的时候,我都会严词阻止他。

但是那天晚上,我不知道怎么回事巨无聊无比,就打算叫女朋友出去玩。好吧其实我没有女朋友,所以我只能自己和自己玩。一件比较有意思的事情是我们寝室的四个人,每个人都玩不同的游戏,因此我们从不联机开黑。人无聊到一定地步胆子就会莫名地大起来,我就突发奇想要试试笔仙。虽然我只有一个人,但是我百度了一下发现一个人也是可以玩的。因为我是一个坚定的唯物主义无神论者,所以我不相信真的有所谓的笔仙,我这么玩其实只是为了日后有吹牛的谈资。而且我觉得寝室里人太多了,没气氛,感觉一栋宿舍楼总有人熬通宵,破坏了午夜的神秘与恐怖。于是呢我决定自己一个人去主楼那边的凉亭下面玩。当时已经一点半了,然而我之后才知道一个人请的话最好在晚上十一点左右,在十二点之前再把笔仙请回去。因为子时初阴气刚刚形成,人的阳气会弱一点,请起来比较容易,但是后半夜阴气极重,在子夜之后请笔仙,那可就保不准请来的是什么东西了。只恨大学生作息紊乱,觉得凌晨平平无奇。当时的想法是,两点半都有人在外面走廊上打王者荣耀,三四点钟的时候楼下还常常传来男女的嬉闹声把人吵醒,我一点半出去玩个笔仙,又算得了什么呢?如果让现在的我回到那时,我恨不得直接紫砂。

于是我就去了主楼那边的凉亭。为了彰显我的唯物主义无神论信仰,我想:已经什么年代,还在玩传统笔仙!毛笔有毛笔仙,铅笔有铅笔仙,那如果我拿出我的 apple pencil,阁下又该如何应对呢?难不成还能招出乔布斯来!所以,我就带了我的 ipad 过去。我检查了一下 ipad 的电量,还很健康。于是我打开 notability,双手悬空,左手和右手手背相碰、指尖朝自己、而后手指互相交叉、apple pencil 握在指尖之间、笔尖朝下。我做的时候还是非常小心的——apple pencil 一支可要 900 多块钱啊!然后我闭上眼睛,轻轻念叨:笔仙啊笔仙,快快显灵吧显灵!我担心 apple pencil 上附着的可能是美国笔仙,听不懂中文,于是我又念:Ouija Board, ah Ouija Board, Get to work, get to work!

体感上没过多久,我就感到一阵阴风吹来,然后我的手腕就不受控制地乱动起来,在我的 ipad 上疯狂点划起来。一时之间,我的心里只有害怕——apple pencil 好像马上就要从我的手指间滑落出来了。等笔停下,我睁眼一看,ipad 屏幕上赫然显示着这样一幅图形!
cb94cd57d4652abdfe0442b19ae2bf21
这下我的无神论信念一下子动摇了。这太不可思议了。我试探着问了一句:Can you speak Chinese?然后笔又动了起来,这次祂写道:

是的,我可以使用中文进行交流。请问有什么我可以帮助您的问题吗?
(Yes, I can communicate in Chinese. What can I help you with?)

虽然我的无神论信念已经彻底崩塌了,但我还是一个坚定的唯物主义者。于是我问,你的底层原理是什么?
话音刚落,我的 apple pencil 就刷刷地写了起来。我好奇地看着祂写道:

其实我一直在记录和学习你写的字,试图找出他们有什么特征。你每次写同一个字,写的都不一样,但是又是什么确保了他们是同一个字呢?然后我发现其实你写的字,是由一些我无法直接观测到的变量控制的,那就是你的手腕的动作!为了简便,就称为手势。为了获取这些无法直接观测的潜变量 (latent variable),我把你写的每个字都记录为一个高维的向量 \mathbf X_i ,然后尝试把他们投影到一个低维的向量手势 \mathbf z_i 上,这样我就得到了所有的字符集 \mathbf X 和手势集 \mathbf z 。现在,如果我在手势集 \mathbf z 里挑选一个 \mathbf z_j ,他应该包含了你写的那个字 \mathbf X_j 的特征,所以我只要逆向进行将 \mathbf X 投影到 \mathbf z 的提取特征的过程,就可以还原出你原来写的那个字 \mathbf X_j 了!

我将信将疑地说:听起来有点道理,但是将高维向量压缩到低维,真的不会有信息损失吗?比如多个高维的点被映射到了同一个低维的点上。

我的笔勃然大怒,剧烈抖动起来,写道:

蠢材!不可救药!你知道如何把一个平面上的所有点一一对应映射到一条直线上吗?很简单!取一个点(14.1,1.54),交错排列数位,把他对应到数轴上的 114.514 这个点不就行了吗?容易证明,这是一一对应。虽然一些原本在高维空间中相邻的点,在映射后可能会变得相距遥远,原本相距遥远的点可能变得相邻,也就是所谓的信息损失,但只要保证绝大多数重要信息得以保留,就足以知道哪些字对应哪些手势了。何必要吹毛求疵呢?

我连忙请祂息怒,让祂接着讲下去。
祂接着写道:

为了让我写出来的字尽可能地贴近真实的字,我使用了万能函数拟合器来进行从 \mathbf X\mathbf z 的编码 (encode) 和从 \mathbf z\tilde{\mathbf X} 的解码 (decode),只要让 l=\left \| \mathbf X-\tilde{\mathbf X} \right \|^{2} 作为损失函数,也就是两个向量之间距离的平方,反向传播让他变得尽可能小,拟合的结果就越接近,我生成的 \tilde{\mathbf X} 就与你的字 \mathbf X 十分接近了。
但是,如果我随机生成一个向量 \mathbf z_i ,把他通过解码,生成字符,却往往没有什么意义。很简单,一个随机乱摆的手势,能写出什么字!只有少数情况运气好,才能写出有意义的字来。而且这样子解码,一个手势只能对应一个字,每次写的都一模一样,完全固定死了!
然后,我发现,只有一些特定的手势才能生成出有意义的字。而我用来训练解码器的样本是极为有限的,只能对很小一部分 \mathbf z 有响应。那么为什么不给 \mathbf z 一个很简单的分布,将采样空间缩小呢?这样,有意义的手势就聚集在一起了。
于是我假设,手势服从正态分布, \mathbf{z}\sim N(0,\mathbf{I}) ,I 即单位矩阵,这是一个各维度独立的多元的正态分布。注意,一个维度往往代表了一个特征,比如手横着一划,或者竖着一划。但是我希望各个特征能够分开,而不是纠缠在一起,比如你写横的时候总会慢慢加重,最后收尾会有一顿,我希望一横和一顿是分开来的两个特征,而不是一边横一边顿被算做了同一个特征,因此要保证正态分布的各个维度独立,方差矩阵是一个对角化的矩阵。那么我现在在 p(\mathbf{z}) 中取样得到 \mathbf{z_i} 。同样,我可以得到一个条件分布 p(\mathbf{X}|\mathbf{z_i}) ,也就是已知手势的时候,可以解码得出的字符集的概率分布。简单说来,同一个手势总是对应同一个字 \mathbf{X} ,但是这些字的字形往往不同。现在我从这个条件分布中取样得到一个 \mathbf{X_i} ,他仍然属于那个字 \mathbf{X} ,但是写出来的形状就有所不同,就是我要生成的字啦!
我继续假设,给定任意 \mathbf{z_i} 以后, \mathbf{X} 都满足各个维度独立的多元正态分布。
p_{}(\mathbf{X}|\mathbf{z_i})= N(\mathbf{X}|\mu_{i}(\mathbf{z_i}),\sigma_{i}^{2}(\mathbf{z_i})*\mathbf{I})
那么该如何求这个 p(\mathbf{X}|\mathbf{z_i}) 呢?答案是用万能函数拟合器来拟合。设万能函数拟合器的各个参数,如权重,偏置,合起来记为 \theta ,那么就可以得到
p_{\theta}(\mathbf{X}|\mathbf{z_i})= N(\mathbf{X}|\mu_{i}'(\mathbf{z_i};\theta),\sigma_{i}'^{2}(\mathbf{z_i};\theta)*\mathbf{I})
这样,我只要输入 \mathbf{z_i} 到解码器,就可以得到 \mathbf{\mu_i'}\mathbf{\sigma_i'} ,然后就只要到根据这两个参数确定的正态分布里去取样就行了!实际应用中,往往懒得进行采样,而直接输出均值 \mathbf{\mu_i'} ,不需要 \mathbf{\sigma_i'} ,就是一个有效的字符了。既然不需要 \mathbf{\sigma_i'} ,我就再偷点懒,进一步假设 p_{\theta}(\mathbf{X}|\mathbf{z_i}) 各个维度的方差都是固定的, \mathbf{\sigma_i'} 是看我心情选择的固定的超参数,这样就更方便了。

我的兴趣被祂挑动了起来,继续问祂:那损失函数又该如何确定来调整 \theta 呢?
祂写道:

我的全局的最终目标是什么呢?是想得到一个与真实分布 p(\mathbf{X}) 尽可能接近的分布 p_{\theta}(\mathbf{X}) ,也就是全体字符集在空间中的概率分布。在 p_{\theta}(\mathbf{X=X_{i}}) 比较大的地方,这个 \mathbf{X_{i}} 很有可能是一个真实的字符!之前已经可以得到 p_{\theta}(\mathbf{X}|\mathbf{z})p_{}(\mathbf{z}) ,那么我就可以使用全概率公式,得到
p_{\theta}(\mathbf{X})=\int_{\mathbf{z} }^{} p_{\theta}(\mathbf{X}|\mathbf{z})p_{}(\mathbf{z}) d\mathbf{z}
我不可能做这个积分,因为这需要无穷多的 p_{\theta}(\mathbf{X}|\mathbf{z}) ,所以退而求其次,采大量的样本,来近似计算这个积分。
p_{\theta}(\mathbf{X})=\frac{1}{n} \sum_{i=1}^{n} p_{\theta}(\mathbf{X}|\mathbf{z_i})
现在用一下概率统计的知识来确定 \theta ,什么情况下,这个我观察到的这个字符集出现的概率最大?我选择最似然估计。
写出似然函数的对数
\begin{align} \ln L(\theta) & = \sum_{j = 1}^{m} \ln{p_{\theta}(\mathbf{X_j})} \\&=\sum_{j = 1}^{m} \frac{1}{n} \sum_{i = 1}^{n}\ln{p_{\theta}(\mathbf{X_j}|\mathbf{z_i})} \end{align}
那么我的 \theta^{*} 就应该是
\theta^{*}=arg\underset{\theta}{max} \sum_{j = 1}^{m} \frac{1}{n} \sum_{i = 1}^{n}\ln{p_{\theta}(\mathbf{X_j}|\mathbf{z_i})}
由于损失函数都是求最小值,所以我改写一下上式
\theta^{*}=arg\underset{\theta}{min} -\sum_{j = 1}^{m} \frac{1}{n} \sum_{i = 1}^{n}\ln{p_{\theta}(\mathbf{X_j}|\mathbf{z_i})}
我确实可以这么做,但是 \mathbf X_i\mathbf z_i 的维度都不会很小,想要还原成一个比较准确的分布 p_{\theta}(\mathbf{X}) ,依然需要极大量的样本,来获取各个维度所包含的特征,否则效果可能会很差。从实践角度来说,这几乎是行不通的。
但是,仔细想想,我之前已经有一个从你写的有意义的字 \mathbf X_j\mathbf z_j 的编码过程了!从一个字,我可以编码出一系列手势,这些手势往往都是有意义的!这样我获得的样本都有意义,就可以减少需要的样本量了。也就是说,我可以获得 p_{\theta}(\mathbf{z}|\mathbf{X_i}) ,那么 p_{\theta}(\mathbf{X}) 就可以写成
\begin{align} p_{\theta}(\mathbf{X})&=\int_{\mathbf{z} }^{} p_{\theta}(\mathbf{z}|\mathbf{X})p_{\theta}(\mathbf{X})d\mathbf{z}\\&=\int_{\mathbf{z} }^{} p_{\theta}(\mathbf{z}|\mathbf{X})\frac{p_{\theta}(\mathbf{X,z})}{p_{\theta}(\mathbf{z}|\mathbf{X})}d\mathbf{z} \end{align}
虽然看起来还没什么意义,但是让我来看一看怎么求这个 p_{\theta}(\mathbf{z}|\mathbf{X_i}) 吧。
\begin{align} p_{\theta}(\mathbf{z}|\mathbf{X_i})&=\frac{p_{\theta}(\mathbf{X_i,z})}{p_{\theta}(\mathbf{X_i})} \\&=\frac{p_{\theta}(\mathbf{X_i}|\mathbf{z})p_{}(\mathbf{z}) }{p_{\theta}(\mathbf{X_i})} \end{align}
我发现,又有
p_{\theta}(\mathbf{X_i})=\int_{\mathbf{z} }^{} p_{\theta}(\mathbf{X_i}|\mathbf{z})p_{}(\mathbf{z}) d\mathbf{z}
这个讨厌的积分又出现了!前面颠来倒去的不知道在写什么,完全是转了一圈又回来了!
然后我想到,为什么不用万能函数拟合器来拟合这个 p_{\theta}(\mathbf{z}|\mathbf{X_i}) 呢?既然已经有了 p_{\theta}(\mathbf{X}|\mathbf{z})p_{}(\mathbf{z}) 都是正态分布,那么容易证明, p_{\theta}(\mathbf{z}|\mathbf{X_i}) 也应该是正态分布!那么我们就可以用编码器来拟合
p_{\theta}(\mathbf{z}|\mathbf{X_i}) ≈q_{\phi}(\mathbf{z}|\mathbf{X_i})=N(\mathbf{z}|\mu_{i}''(\mathbf{X_i};\phi),\sigma_{i}''^{2}(\mathbf{X_i};\phi)*\mathbf{I})
这样,编码过程我最后让编码器输出 \mu_{i}''\sigma_{i}'' 就可以了。然后就在由 \mu_{i}''\sigma_{i}'' 确定的正态分布中取样得到 \mathbf{z_{i}} ,之后就是刚才说过的解码过程了。

我一时觉得很有道理,但又隐隐感觉有些不对,就问:既然 \mathbf{z_{i}} 是由随机采样产生的,那又该怎么反向传播呢?
祂又写道:

你的理解是正确的。所以我采用了一种叫重参数化 (reparameterization) 的技巧。有了 \mu_{i}''\sigma_{i}'' 以后,我不直接采样,而是采用特定的规则生成 \mathbf{z_{i}}
\mathbf{z_{i}}=\mu_{i}''+\sigma_{i}''\odot \epsilon_i, \epsilon\sim N(0,\mathbf{I})
\odot 表示逐元素相乘。
很显然,现在 \mathbf{z_{i}} 依然服从正态分布,而且随机的部分化为了一个参数 \epsilon ,对 \mu_{i}''\sigma_{i}'' 就又可以求导了,这样反向传播就得以进行了。

我接着问:那损失函数又该如何确定呢?
祂回答:

对了,我们再回过头来看这个 p_{\theta}(\mathbf{X}) ,直接对他求一次对数,得到
\begin{align} \ln p_{\theta}(\mathbf{X})&=\int_{\mathbf{z} }^{} q_{\phi}(\mathbf{z}|\mathbf{X})\ln p_{\theta}(\mathbf{X})d\mathbf{z}\\&=\int_{\mathbf{z} }^{} q_{\phi}(\mathbf{z}|\mathbf{X})\ln \frac{p_{\theta}(\mathbf{X,z})}{p_{\theta}(\mathbf{z}|\mathbf{X})}d\mathbf{z} \\&=\int_{\mathbf{z} }^{} q_{\phi}(\mathbf{z}|\mathbf{X})\ln \frac{p_{\theta}(\mathbf{X,z})q_{\phi}(\mathbf{X,z})}{q_{\phi}(\mathbf{X,z})p_{\theta}(\mathbf{z}|\mathbf{X})}d\mathbf{z} \\&=\int_{\mathbf{z} }^{} q_{\phi}(\mathbf{z}|\mathbf{X})\ln \frac{p_{\theta}(\mathbf{X,z})}{q_{\phi}(\mathbf{z}|\mathbf{X})}d\mathbf{z}+\int_{\mathbf{z} }^{} q_{\phi}(\mathbf{z}|\mathbf{X})\ln \frac{q_{\phi}(\mathbf{X,z})}{p_{\theta}(\mathbf{z}|\mathbf{X})}d\mathbf{z} \end{align}
这么写,是因为第二项就是 KL 散度!然后再改写一下
\begin{align} \ln p_{\theta}(\mathbf{X}) &=l(p_{\theta},q_{\phi})+D_{KL}(q_{\phi},p_{\theta}) \end{align}
就得到
\begin{align} l(p_{\theta},q_{\phi}) &=-D_{KL}(q_{\phi},p_{\theta})+\ln p_{\theta}(\mathbf{X}) \end{align}
我们知道,KL 散度是恒大于等于 0 的,因此这个 l(p_{\theta},q_{\phi}) 就是 \ln p_{\theta}(\mathbf{X}) 的下界。之前我已经得到似然函数的对数 \ln L(\theta) = \sum_{j = 1}^{m} \ln{p_{\theta}(\mathbf{x_j})} ,要让他最大化,那么就要让 \ln p_{\theta}(\mathbf{X}) 最大化。显然,我同时也希望 q_{\phi} 能尽可能地逼近 p_{\theta} ,也就是他们的 KL 散度最小化。两者一结合,就是 l(p_{\theta},q_{\phi}) 最大化!
现在来求怎么使 l(p_{\theta},q_{\phi}) 最大化:
\begin{align} l(p_{\theta},q_{\phi})&=\int_{\mathbf{z} }^{} q_{\phi}(\mathbf{z}|\mathbf{X})\ln \frac{p_{\theta}(\mathbf{X,z})}{q_{\phi}(\mathbf{z}|\mathbf{X})}d\mathbf{z} \\&=\int_{\mathbf{z} }^{} q_{\phi}(\mathbf{z}|\mathbf{X})\ln \frac{p_{\theta}(\mathbf{X|z})p(\mathbf{z})}{q_{\phi}(\mathbf{z}|\mathbf{X})}d\mathbf{z} \\&=\int_{\mathbf{z} }^{} q_{\phi}(\mathbf{z}|\mathbf{X})\ln \frac{p(\mathbf{z})}{q_{\phi}(\mathbf{z}|\mathbf{X})}d\mathbf{z}+\int_{\mathbf{z} }^{} q_{\phi}(\mathbf{z|X})\ln p_{\theta}(\mathbf{X|z})d\mathbf{z} \\&=-D_{KL}(q_{\phi},p)+\mathbb{E}_{q_{\phi}}(\ln p_{\theta}(\mathbf{X|z})) \end{align}
实际上,由于我已经假设了 p(\mathbf{z})q_{\phi}(\mathbf{z|X}) 的正态分布, D_{KL}(q_{\phi},p) 其实是可以算出解析解的!
先简单考虑一维的时候,
\begin{align} D_{KL}(q_{\phi},p) &=\int_{\mathbf{z} }^{} q_{\phi}(\mathbf{z}|\mathbf{X})\ln \frac{q_{\phi}(\mathbf{z}|\mathbf{X})}{p(\mathbf{z})}d\mathbf{z} \\&=\int_{\mathbf{z}} \frac{1}{\sqrt{2\pi \sigma ''^{2}}} e^{-\frac{(\mathbf{z}-\mu'')^2}{2\sigma''^2} } \ln \frac{\frac{1}{\sqrt{2\pi \sigma ''^{2}}} e^{-\frac{(\mathbf{z}-\mu'')^2}{2\sigma''^2} }} {\frac{1}{\sqrt{2\pi }} e^{-\frac{\mathbf{z}^2}{2} }} d\mathbf{z} \\&=\int_{\mathbf{z}} \frac{1}{\sqrt{2\pi \sigma ''^{2}}} e^{-\frac{(\mathbf{z}-\mu'')^2}{2\sigma''^2} } (-\frac{(\mathbf{z}-\mu'')^2}{2\sigma''^2}+\frac{\mathbf{z}^2}{2}-\ln \sigma '' )d\mathbf{z} \\&=\frac{1}{2}(-1+\sigma''^2+\mu''^2-\ln \sigma''^2) \end{align}
由于各个维度独立,我们可以得到
\begin{align} D_{KL}(q_{\phi},p) &=\sum_{i=1}^{d} \frac{1}{2}(-1+\sigma''^{(i)2}+\mu''^{(i)2}-\ln \sigma''^{(i)2}) \end{align}
d 为总维度数, \mu''^{(i)} 表示向量 \mu'' 的第 i 个分量。
最后,我只需要求 \mathbb{E}_{q_{\phi}}(\ln p_{\theta}(\mathbf{X|z})) 这一项了!现在,由于我们是在 q_{\phi}(\mathbf{z}|\mathbf{X_i}) 中对 \mathbf{z_i} 进行采样的,由于 q_{\phi}(\mathbf{z}|\mathbf{X_i}) 很快就会接近真实的分布 p_{\theta}(\mathbf{z}|\mathbf{X_i}) ,所以我很容易就能取到与 \mathbf{X_i} 相关联的 \mathbf{z_i} ,那么我就可以推出一个比较接近真实情况的分布。所以,现在就可以用采样来近似计算这个积分了。
\begin{align} \int_{\mathbf{z} }^{} q_{\phi}(\mathbf{z|X})\ln p_{\theta}(\mathbf{X|z})d\mathbf{z}≈\frac{1}{n}\sum_{i=1}^{n} \ln p_{\theta}(\mathbf{X|z_i}) \end{align}
我还知道, \ln p_{\theta}(\mathbf{X|z_i}) 满足一个 k 维的各变量独立的正态分布(设每个字形 \mathbf{X_i} 的维度为 k),
\begin{align} \ln p_{\theta}(\mathbf{X|z_i})&=\ln (\frac{1}{\sqrt{(2\pi)^k |\sigma '|}} e^{-\frac{1}{2}(\mathbf{X}-\mathbf{\mu'})^T\sigma '^{-1}(\mathbf{X}-\mathbf{\mu'}) } ) \\&=-\frac{1}{2} \sum_{i=1}^{k} \frac{(\mathbf{X}^{(i)}-\mu'^{(i)})^2}{\sigma'^{(i)}} -\frac{1}{2}(k\ln (2\pi)+\sum_{i=1}^{k}\ln\sigma'^{(i)}) \end{align}
万事俱备,就可以来求损失函数了。
令损失函数
\begin{align} \mathcal{L}&=-\frac{1}{n}\sum_{i=1}^{n}l(p_{\theta},q_{\phi}) \\&=\frac{1}{n}\sum_{i=1}^{n} D_{KL}(q_{\phi},p)-\frac{1}{nm}\sum_{i=1}^{n}\sum_{j=1}^{m}\ln p_{\theta}(\mathbf{X_i|z_j}) \end{align}
我在实践中发现,对一个特定的字形 \mathbf{X_i} 只要采样一个手势 \mathbf{z_i} ,就能达到比较好的效果了。那么令 m=1
\begin{align} \mathcal{L}&=\frac{1}{n}\sum_{i=1}^{n} D_{KL}(q_{\phi},p)-\frac{1}{n}\sum_{i=1}^{n}\ln p_{\theta}(\mathbf{X_i|z_i}) \\&=\frac{1}{n}\sum_{j=1}^{n}\sum_{i=1}^{d} \frac{1}{2}(-1+\sigma_{j}''^{(i)2}+\mu_{j}''^{(i)2}-\ln \sigma_{j}''^{(i)2}) -\frac{1}{n}\sum_{j=1}^{n}(-\frac{1}{2} \sum_{i=1}^{k} \frac{(\mathbf{X_{j}}^{(i)}-\mu_{j}'^{(i)})^2}{\sigma_{j}'^{(i)}} -\frac{1}{2}(k\ln (2\pi)+\sum_{i=1}^{k}\ln\sigma_{j}'^{(i)}) ) \end{align}
完全的常数项没有意义,可以直接舍去。而 \mathbf{\sigma_i'} 是看我心情选的超参数,那我为了方便,就令 \mathbf{\sigma_i'} 的每一个元素都为 \frac{1}{2} ,那么损失函数就可以进一步简化为
\begin{align} \mathcal{L}&=\frac{1}{n}\sum_{j=1}^{n}\sum_{i=1}^{d} \frac{1}{2}(-1+\sigma_{j}''^{(i)2}+\mu_{j}''^{(i)2}-\ln \sigma_{j}''^{(i)2}) +\frac{1}{n}\sum_{i=1}^{n}\left \| \mathbf{X_{i}}-\mu_{i}' \right \| ^2 \end{align}
然后发现,这个第二项有点眼熟,就是一开始算损失函数的两个向量之间的距离!所以现在的损失函数,就相当于加上了前一项的修正项 (这一项通常称为 Regularization Term,而后一项称为 Reconstruction Loss)。现在,一切的原理都已经贯通了!我把它称之为 Virtual Artifact Emulator。

原来如此!我恍然大悟,但我心里始终有一个小小的问题始终困扰着我。于是我问祂:为什么你生成的字这么糊呢?
这下好像真正地激怒了祂,祂疯狂地转起了圈,啪地一下摔在了地上,没了反应。我想我可能问了什么不该问的事情,沾上不干净的东西了。现在我的身边总是怪事连连。为了拜托阴魂,我反复思考:为什么笔仙生成的字这么糊呢?

我想了想,可能是因为现实中的数据是多峰的,比如我写的字有汉字,字母,阿拉伯数字,这些不同类型的字符的分布各自占据了一个峰。而祂的拟合能力不够强,无法捕捉到潜变量充分的信息使得 p_{\theta}(\mathbf{X|z_i}) 可以用单峰来拟合,因此祂只能把多峰平均,就产生了模糊。
另一方面,可能祂的损失函数对错误的惩罚能力比较强,而对模糊的惩罚能力较弱。设想一个黑白棋盘,如果产生的值黑白都和真实值恰好相反了,那损失函数是最大的,而如果是全灰的,损失函数就比较小。事实在生成中,祂可能直接生成了全灰的,当作一个比较理想的损失的状态。但是全灰和黑白相反的相比,自然就模糊多了。
还有一点,其实祂说的,已经有了 p_{\theta}(\mathbf{X}|\mathbf{z})p_{}(\mathbf{z}) 都是正态分布,那么容易证明, p_{\theta}(\mathbf{z}|\mathbf{X}) 也应该是正态分布,是不对的。因为从 \mathbf{z_i} 解码为 \mathbf{X_i} 的过程中经过了一个非线性的万能函数拟合器,会导致 p_{\theta}(\mathbf{z}|\mathbf{X}) 不是正态分布。很显然, p_{}(\mathbf{z})p_{\theta}(\mathbf{X}|\mathbf{z}) 的均值 \mu 的维度往往是不同的!一个是 \mathbf z_i 的维度,一个是 \mathbf X_i 的维度,不能直接结合得到 p_{\theta}(\mathbf{z}|\mathbf{X}) 的分布,因此不能证明为正态分布。再比如说,从 \mathbf{z_i} 解码为 \mathbf{X_i} ,经过了 \mathrm {ReLu} 函数,把大于 0 的部分映射为本身,小于 0 的部分映射为 0,那么显然,这就已经破坏了正态分布的定义域了!所以, p_{\theta}(\mathbf{z}|\mathbf{X}) 是正态分布,恰恰是祂的最大假设!而这个假设质量很一般,导致了模型的拟合能力一般。
总而言之,生成的内容很模糊,是模型本身的结构的缺陷,想要生成更高质量的内容,最好还是求诸其他模型吧。

现在我还被脏东西缠着,很痛苦。千万不要玩笔仙!这是我的血泪教训。就算一定要玩,也千万不要问祂写出来的字为什么这么糊!

7 Likes

好草啊 vvvvv

喜欢这种知识滑过大脑,又不留痕迹的感觉:sweat_smile:

什么 PRML

知识以一种卑鄙的方式进入我的脑海:joy: