GAN:Generative Adversarial Nets论文阅读


[toc]

1. Generative Adversarial Nets

arXiv:1406.2661 [stat.ML]
tensorflow2代码:https://github.com/zhangkaihua88/ML_Paper


1.1. 摘要

通过对抗过程估计生成模型的框架,同时训练两个模型:
生成模型G用来获取数据分布
判别模型D估计样本来自训练数据而不是G的概率
G的训练目标是为了最大化D产生错误的概率
在任意函数G和D的空间中存在唯一的解,其中G恢复训练数据分布,并且D处处都等于\frac{1}{2}。


1.2. 介绍

最成功的的模型之一就是判别式模型
通常它们将高维丰富的感知器输入映射到类标签上。
主要是基于反向传播和丢弃算法来实现的,特别是具有特别良好梯度的分段线性单元。

对抗网络

  1. 生成模型通过将随机噪声传输到多层感知机来生成样本的特例
  2. 判别模型通过多层感知机去判别一个样本是来自模型分布还是数据分布
  3. 生成模型和判别模型互相对抗

可以仅使用非常成熟的反向传播和丢弃算法训练两个模型,生成模型在生成样本时只使用前向传播算法。并且不需要近似推理和马尔可夫链作为前提。


1.3. 对抗网络

对抗模型框架是最直接的应用是多层感知机

1.3.1. 符号定义

x \rightarrow 真实数据
z \rightarrow 噪音(生成器的输入数据)
p_x \rightarrow 真实数据的分布
p_{z}(z) \rightarrow 原始噪音数据的分布
p_g \rightarrow 经过生成器后数据的分布
G() \rightarrow 生成映射函数(可微),结构为多层感知机,参数\theta_{g}
D() \rightarrow 判别映射函数(可微),结构为多层感知机,参数\theta_2cccccccc8
G(z;\theta_{g}) \rightarrow 将噪音z映射到新的数据空间
D(x ; \theta_2cccccccc8) \rightarrow x来自真实数据而不是生成数据的概率(真=1,假=0)

1.3.2. 极大似然估计

对于真实数据x和生成数据G(z),经过判别器判别后的,D认为x是真样本的概率为D(x)D认为G(z)是假样本的概率为1-D(G(z)),那么对于Dlog似然函数为:
L=log[D(x)*(1-D(G(z)))] \tag{1}

1.3.3. 目标函数

\min _{G}\max _{ D } V(D,G)={ \mathbb{E} }_{ x ~ { p }_ { data } (x) }[logD(x)] + { \mathbb{E} }_{ z ~ { p }_{ z }(z) }[log(1-D(G(z)))] \tag{2}
D(x)D(G(z))分别表示xG(z)经过判别器D的判别后,D认为输入样本是真样本的概率,则1-D(G(z))表示D将假样本判断为假的概率;那么,真实的概率分布与D判断出来的情况列表如下:

D D将真样本x判断为真的概率:D(x) D将假样本G(z)判断为假的概率:1-D(G(z))
真实情况 真样本x为真的概率:1 假样本G(z)为假的概率:1
用交叉熵作为目标函数 1*log[D(x)]对应第一项 1*log[1-D(G(z))]对应第二项

Note:D输出的是概率,那么D的输出层的激活函数必须是sigmoid

1.3.4. 对抗

判别器D的目标

  1. 要尽可能把真的样本判断为真,对应最大化第一项:{ E }_{ x ~ { p }_ { data } (x) }[logD(x)]
  2. 把假的样本判断为假,对应最大化第二项:{ E }_{ z ~ { p }_{ z }(z) }[log(1-D(G(z)))]
  • 总之,也就是说判别器D要最大化目标函数;

生成器G的目标

  1. 要尽可能的让D将生成的假样本判断为真,对应最小化第二项:{ E }_{ z ~ { p }_{ z }(z) }[log(1-D(G(z)))]
  • 总之,也就是说生成器G要最小化目标函数;

总的来说,这是一个MinMax Game
Note:实际训练当中,训练G的时候D的参数是固定的,G并不干扰D对真实数据的判断,G需要D的正确引导,G只是不断提升自己生成数据的能力。

1.3.5. Loss Function

D的损失函数(最小化):
Loss_D = -[1*logD(x) + 1*log(1-D(G(z)))] \tag{3}
G的损失函数(最小化):
Loss_G = 0*logD(x) + 1*log(1-D(G(z)))=log(1-D(G(z))) \tag{4}

1.3.6. 具体算法过程

20190816181118.png

Note:

  1. 生成对抗网络的minibatch随机梯度下降训练
  2. 先更新D,再更新G,只有D有了正确的判断能力,G才能按照D的指示来更新;
  3. 可以设置一个超参数k来协调D、G两者之间更新的次数比例,在实验中k=1,使消耗最小;
  4. 在训练G的时候D的参数要固定,在训练D的时候G的参数要固定;

1.4. 改进

1.4.1. G替代版的Loss Function

由于G(z)是从噪声中生成的样本,所以在最开始G生成的样本非常假,很容易被D抓出来,也就是说D(G(z))非常小,那么Loss_G = log(1-D(G(z)))就非常接近0,在反向传播的时候就不能够传播足够的梯度给G来更新参数,所以我们从Heuristic的角度来理解:我们本身是要最小化D抓出来假样本的概率,现在我们可以换成最大化D抓不出来的概率(\log D(G(z))),也就是将G的损失函数换成:
Loss_G=-logD(G(z))
由于D是按照:
Loss_G = log(1-D(G(z)))
训练的,那么如果损失函数更换,这两项不是等价的,所以D给出的值就能够提供足够的梯度。

Note:
Loss_G =log(1-D(G(z)))对应的GAN叫做MMGAN
Loss_G=-logD(G(z))对应的GAN叫做NSGAN
改进后的仍然存在些许问题,见与定理1:全局最优的Note3

从函数图像上,可以直观的看出,两种损失函数的梯度变化趋势:


损失函数图像

1.5. 补充知识

1.5.1. 信息量

I(x) = -\log {p(x)} = \log { \frac { 1}{ p (x) } }
一个事件发生的概率越大,这件事情发生所包含的信息量就越小,比如说一个高富帅追求一个白富美,追到手了没有什么稀奇的,因为这是一件概率很高的事情,但是如果一个矮穷矬追求一个白富美,追到手了,这种事情发生的概率很低,其中一定有其他的原因:比如这个矮穷矬救过白富美的命或者这个矮穷矬器大活好不黏人,所以概率低的事情发生所包含的信息量大;两个相互独立的事情同时发生的信息量是两者单独发生的信息量之和。

1.5.2. 信息熵

信息量的均值
H(x) = - \sum _{ x } p(x)log p(x)

1.5.3. 交叉熵

H(P, Q) = - \sum _{ x } p(x)log q(x)
用估计编码q(x)近似真实编码p(x)需要的平均编码长度

1.5.4. KL散度(Kullback–Leibler散度,相对熵)

统计中的一个概念,时衡量两种概率分布的相似程度,其越小,表示两种概率分布越接近。(当P(x)和Q(x)的相似度越高,KL散度越?。?br> 对于离散的概率分布定义如下:
D_{KL}(P||Q)=- \sum _{ x } p(x)log q(x) + \sum _{ x } p(x)log p(x) =H(P, Q)-H(P)
对于连续的概率分布定义如下:
D_{K L}(P \| Q)=\int_{-\infty}^{\infty} p(x) \log \frac{p(x)}{q(x)} d x
想要将一个随机高斯噪声z通过一个生成网络G得到一个和

  • 性质:
    1. 不对称性
      尽管KL散度从直观上是个度量或距离函数,但它并不是一个真正的度量或者距离,因为它不具有对称性,即D(P||Q) \not= D(Q||P)。
    2. 非负性
      相对熵的值是非负值,即D(P||Q)>0。

1.5.5. JS散度(Jensen-Shannon散度)

D_{JS}(P||Q)={\frac{1}{2}} KL(P||M) + {\frac{1}{2}} KL(Q||M) \quad \quad M = {\frac{1}{2}}(P+Q)

  • 不同于KL主要又两方面:
    1. 值域范围
      JS散度的值域范围是[0,1],相同则是0,相反为1。相较于KL,对相似度的判别更确切了。
    2. 对称性
      即 JS(P||Q)=JS(Q||P),从数学表达式中就可以看出。

1.6. 理论结果

1.6.1. 最优判别器D:D^{*}(x) =\frac{P_{\text {data}}(x)}{P_{\text {data}}(x)+P_{G}(x)}

对于给定生成器G,最大化V(D,G)而得出最优判别器D。原论文中价值函数可写为在x上的积分,即将数学期望展开为积分形式:

\begin{aligned} \max _{ D } V(D,G)&={ E }_{ x ~ { p }_ { data } (x) }[logD(x)] + { E }_{ z ~ { p }_{ z }(z) }[log(1-D(G(z)))]\\ &=\int_{x} p_{d a t a}(x) \log D(x) \mathrm2cccccccc8 x+\int_{z} p(z) \log (1-D(G(z))) \mathrm2cccccccc8 z\\ &=\int_{x} p_{d a t a}(x) \log D(x)+p_{G}(x) \log (1-D(x)) \mathrm2cccccccc8 x \end{aligned}
取函数,求偏导数
(对于任意的(a, b) \in \mathbb{R}^{2} \backslash\{0,0\},函数y \rightarrow a \log (y)+b \log (1-y)[0,1]中的\frac{a}{a+b}处达到最大值)
\begin{aligned} f(D) &=a \log (D)+b \log (1-D) \\ \frac{d f(D)}{d D}&= a \times \frac{1}{D}+b \times \frac{1}{1-D} \times(-1)=0 \\ a \times \frac{1}{D^{*}} &= b \times \frac{1}{1-D^{*}} \\ \Leftrightarrow a \times & (1-D^{*}) =b \times D^{*} & \\ \text{得到最优判别器}&{ D }^{ * }(x):\\ D^{*}(x) &=\frac{P_{\text {data}}(x)}{P_{\text {data}}(x)+P_{G}(x)} \end{aligned}

1.6.2. 最优生成器:p_{g}=p_{\text {data }}

我们知道对于G来说,最好的G是让:
{ P }_{ r }(x) = { P }_{ g }(x)
此时,有:
{ D }^{ * }(x)=1/2
也就是说最好的生成器使最好的判别器无法判别出来样本是生成样本还是真实样本。

1.6.3. 定理1:全局最优

定理1:当且仅当p_{g}=p_{\text {data }}时,C(G)达到全局最小。此时,C(G)的值为?log4。
注意到,判别器D的训练目标可以看作为条件概率P(Y=y | x)的最大似然估计,当y=1时,x来自于p_{\text {data }};当y=0时,x来自p_{g}。公式1中的极小化极大问题可以变形为:
\begin{aligned} C(G) &=\max _{D} V(G, D) \\ &=\mathbb{E}_{\boldsymbol{x} \sim p_{\text {data }}}\left[\log D_{G}^{*}(\boldsymbol{x})\right]+\mathbb{E}_{\boldsymbol{z} \sim p_{\boldsymbol{z}}}\left[\log \left(1-D_{G}^{*}(G(\boldsymbol{z}))\right)\right] \\ &=\mathbb{E}_{\boldsymbol{x} \sim p_{\text {data }}}\left[\log D_{G}^{*}(\boldsymbol{x})\right]+\mathbb{E}_{\boldsymbol{x} \sim p_{g}}\left[\log \left(1-D_{G}^{*}(\boldsymbol{x})\right)\right] \\ &=\mathbb{E}_{\boldsymbol{x} \sim p_{\text {data }}}\left[\log \frac{p_{\text {data }}(\boldsymbol{x})}{P_{\text {data }}(\boldsymbol{x})+p_{g}(\boldsymbol{x})}\right]+\mathbb{E}_{\boldsymbol{x} \sim p_{g}}\left[\log \frac{p_{g}(\boldsymbol{x})}{p_{\text {data }}(\boldsymbol{x})+p_{g}(\boldsymbol{x})}\right] \\ &=\int_{x} p_{\text {data}}(x) \log \left(\frac{p_{\text {data}}(x)}{p_{\text {data}}(x)+p_{g}(x)}\right)+p_{g}(x) \log \left(\frac{p_{g}(x)}{p_{\text {data}}(x)+p_{g}(x)}\right) d x\\&=\int_{x} p_{d a t a}(x) \log \left(\frac{p_{d a t a}(x)}{\frac{p_{d a t a}(x)+p_{g}(x)}{2}}\right)+p_{g}(x) \log \left(\frac{p_{g}(x)}{\frac{p_{d a t a}(x)+p_{g}(x)}{2}}\right) d x-\log (4)\\ &=\underbrace{K L\left(p_{\text {data}}(x) \| \frac{p_{\text {data}}(x)+p_{g}(x)}{2}\right)}_{\geq 0}+\underbrace{K L\left(p_{g}(x) \| \frac{p_{\text {data}}(x)+p_{g}(x)}{2}\right)}_{\geq 0}-\log (4)\\&=2\underbrace{\cdot JSD(p_{data}\|p_{g})}_{\geq 0}-log(4)\\\min _{G} C(G)&=0+0-\log (4)=-\log (4) \end{aligned}
当且仅当p_{\text {data}}(x)=\frac{p_{\text {data}}(x)+p_{g}(x)}{2}p_{g}=p_{\text {data }}时成立,此时C(G)达到全局最小,C(G)的值为?log4
Note1
KL散度:KL({ P }_{ 1 }||{ P }_{ 2 })={ P }_{ 1 }\log { \frac { { P }_{ 1 } }{ { P }_{ 2 } } }
JS散度:JS({ P }_{ 1 }||{ P }_{ 2 })=\frac { 1 }{ 2 } KL({ P }_{ 1 }||\frac { { P }_{ 1 }+{ P }_{ 2 } }{ 2 } )+\frac { 1 }{ 2 } KL({ P }_{ 2 }||\frac { { P }_{ 1 }+{ P }_{ 2 } }{ 2 } )
Note2(MMGAN)Loss_G =log(1-D(G(z)))
当判别器D最优的时候,生成器G是在减小真实分布与生成分布之间的JS散度
<span id="1">Note3(NSGAN)</span>Loss_G=-logD(G(z))
\begin{aligned} KL({ P }_{ g }(x)||{ P }_{ r }(x)) &={ P }_{ g }(x)*\log { \frac { { P }_{ g }(x) }{ { P }_{ r }(x) } } \\ &={ P }_{ g }(x)*\log { \frac { { P }_{ g }(x)/({ P }_{ r }(x)+{ P }_{ g }(x)) }{ { P }_{ r }(x)/({ P }_{ r }(x)+{ P }_{ g }(x)) } } \\ &={ P }_{ g }(x)*\log \frac { 1-D^{ * }(x) }{ D^{ * }(x) } \\ &={ P }_{ g }(x)log[1-D^{ * }(x)]-{ P }_{ g }(x)logD^{ * }(x)\\ -{P}_{g}(x)*logD^*(x)&=KL({ P }_{ g }(x)||{ P }_{ r }(x))-{ P }_{ g }(x)log[1-D^{ * }(x)]\\ Loss_{ G }&=KL({ P }_{ g }(x)||{ P }_{ r }(x))-{ P }_{ g }(x)log[1-D^{ * }(x)]\\ \because {P}_{r}(x)*log[D^*(x)] &+ {P}_{g}(x)*log[1-D^*(x)]=2JS({ P }_{ r }||{ P }_{ g })-2log2\\ \therefore Loss_{ G }=KL({ P }_{ g }(&x)||{ P }_{ r }(x))-2JS({ P }_{ r }||{ P }_{ g })+{P}_{r}(x)*log[D^*(x)]+2log2[1-D^{ * }(x)] \end{aligned}
从上面的式子可以看出KL散度和JS散度同时存在且方向相反,而JS散度和KL散度都是衡量两个分布距离的度量,且是单调性同步的函数,这样的话就会导致梯度的方向不稳定,一会儿上升一会儿下降,所以这个替代版的损失函数也不是一个好的选择。

1.6.4. 算法的收敛性

命题:如果GD有足够的性能,对于算法1中的每一步,给定G时,判别器能够达到它的最优,并且通过更新p_g来提高这个判别准则。
\mathbb{E}_{\boldsymbol{x} \sim p_{\text {data }}}\left[\log D_{G}^{*}(\boldsymbol{x})\right]+\mathbb{E}_{\boldsymbol{x} \sim p_{g}}\left[\log \left(1-D_{G}^{*}(\boldsymbol{x})\right)\right]
p_g收敛为p_{data}。

Note
优化θ_g而不是p_g本身


1.7. 优势和劣势

1.7.1. 优势

  • 根据实际的结果,它们看上去可以比其它模型产生了更好的样本(图像更锐利、清晰)。
  • 生成对抗式网络框架能训练任何一种生成器网络(理论上-实践中,用 REINFORCE 来训练带有离散输出的生成网络非常困难)。大部分其他的框架需要该生成器网络有一些特定的函数形式,比如输出层是高斯的。重要的是所有其他的框架需要生成器网络遍布非零质量(non-zero mass)。生成对抗式网络能学习可以仅在与数据接近的细流形(thin manifold)上生成点。
  • 不需要设计遵循任何种类的因式分解的模型,任何生成器网络和任何鉴别器都会有用。
  • 无需利用马尔科夫链反复采样,无需在学习过程中进行推断(Inference),回避了近似计算棘手的概率的难题。

1.7.2. 劣势

  • 解决不收敛(non-convergence)的问题。
    目前面临的基本问题是:所有的理论都认为 GAN 应该在纳什均衡(Nash equilibrium)上有卓越的表现,但梯度下降只有在凸函数的情况下才能保证实现纳什均衡。当博弈双方都由神经网络表示时,在没有实际达到均衡的情况下,让它们永远保持对自己策略的调整是可能的【OpenAI Ian Goodfellow的Quora】。

  • 难以训练:崩溃问题(collapse problem)
    GAN模型被定义为极小极大问题,没有损失函数,在训练过程中很难区分是否正在取得进展。GAN的学习过程可能发生崩溃问题(collapse problem),生成器开始退化,总是生成同样的样本点,无法继续学习。当生成模型崩溃时,判别模型也会对相似的样本点指向相似的方向,训练无法继续。Improved Techniques for Training GANs

  • 无需预先建模,模型过于自由不可控。
    与其他生成式模型相比,GAN这种竞争的方式不再要求一个假设的数据分布,即不需要formulate p(x),而是使用一种分布直接进行采样sampling,从而真正达到理论上可以完全逼近真实数据,这也是GAN最大的优势。然而,这种不需要预先建模的方法缺点是太过自由了,对于较大的图片,较多的 pixel的情形,基于简单 GAN 的方式就不太可控了(超高维)。在GAN[Goodfellow Ian, Pouget-Abadie J] 中,每次学习参数的更新过程,被设为D更新k回,G才更新1回,也是出于类似的考虑。


1.8. 结论和未来研究方向

该框架允许许多直接的扩展:

  • 条件生成模型p(x | c)可以通过将c作为GD的输入来获得。
  • 给定x,可以通过训练一个任意的模型来学习近似推理,以预测z。这和wake-sleep算法训练出的推理网络类似,但是它具有一个优势,就是在生成器训练完成后,这个推理网络可以针对固定的生成器进行训练。
  • 能够用来近似模型所有的条件概率p\left(\boldsymbol{x}_{S} | \boldsymbol{x}_{\beta}\right),其中S通过训练共享参数的条件模型簇的关于x索引的一个子集。本质上,可以使用生成对抗网络来随机拓展MP-DBM。
  • 半监督学习:当标签数据有限时,判别网络或推理网络的特征不会提高分类器效果。
  • 效率改善:为协调GD设计更好的方法,或训练期间确定更好的分布来采样z,能够极大的加速训练。

1.9. 参考资料

Paper---Generative Adversarial Nets
知乎---GAN入门理解及公式推导
CSDN---GAN论文阅读——原始GAN(基本概念及理论推导)
CSDN---KL散度、JS散度以及交叉熵对比
CSDN---Generative Adversarial Nets论文笔记+代码解析
CSDN---Generative Adversarial Nets(译)
Github---andyhujinzhao/Generative_Adversarial_Nets


最后编辑于
?著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,029评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,238评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,576评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,214评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,324评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,392评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,416评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,196评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,631评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,919评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,090评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,767评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,410评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,090评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,328评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,952评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,979评论 2 351

推荐阅读更多精彩内容

  • 转载自 https://mp.weixin.qq.com/s/OXXtPoBrCADbwxVyEbfbYg 25....
    _龙雀阅读 1,662评论 0 0
  • 在GAN的相关研究如火如荼甚至可以说是泛滥的今天,一篇新鲜出炉的arXiv论文《Wasserstein GAN》却...
    MiracleJQ阅读 2,226评论 0 8
  • 生成对抗网络基本概念 要理解生成对抗模型(GAN),首先要了解生成对抗模型可以拆分为两个??椋阂桓鍪桥斜鹉P停硪?..
    变身的大恶魔阅读 5,518评论 0 7
  • 今天再仔细读正面管教第四章,比以前更深刻地理解了错误目的表里面的所有内容。 书中提到3条线索引导我们去识别孩子的“...
    岁月莲上写诗阅读 1,243评论 0 6
  • 《纸船》 仿佛记得你偷偷撕了书中的彩页, 折成五色的小船。 船优雅,载着你的欢笑我的恼怒, 从柳溪的此岸飘行到彼岸...
    不语不问阅读 213评论 0 2