卷积网络

卷积网络(convolutional network)(LeCun, 1989),也叫做卷积神经网络(CNN),是一种专门用来处理具有类似网格结构的数据的神经网络。例如时间序列数据(可以认为是在时间轴上有规律地采样形成的一维网格)和图像数据(可以看作是二维的像素网格)。卷积网络在诸多应用领域都表现优异。“卷积神经网络’’ 一词表明该网络使用了卷积(convolution)这种数学运算。卷积是一种特殊的线性运算。卷积网络是指那些至少在网络的一层中使用卷积运算来替代一般的矩阵乘法运算的神经网络。

1、卷积运算

在通常形式中,卷积是对两个实变函数的一种数学运算。

假设x(t)表示传感器测量的宇宙飞船在时刻t的位置。xt都是实值的,若传感器有噪声,为得到飞船位置的低噪估计,我们对得到的测量结果进行平均。显然,时间上越近的测量结果越相关,采用一个加权函数w(a)来实现,其中a表示测量结果距当前时刻的时间间隔。得到一个新的对于飞船位置的平滑估计函数s

s(t)=\int x(a) w(t-a) d a

这种运算就叫做卷积(convolution)。卷积运算通常用星号表示:

s(t)=(x * w)(t)

在卷积网络的术语中,卷积的第一个参数(本例中为函数 x)通常叫做输入(input),第二个参数(函数w)叫做核函数(kernel function)。输出有时被称作特征映射(feature map)

当我们用计算机处理数据时,时间会被离散化,传感器会定期地反馈数据。所以在我们的例子中,假设传感器每秒反馈一次测量结果是比较现实的。这样,时刻t只能取整数值。如果我们假设xw都定义在整数时刻t上,就可以定义离散形式的卷积:

s(t)=(x * w)(t)=\sum_{a=-\infty}^{\infty} x(a) w(t-a)

多项式相乘可表示为一维卷积的形式,如下图所示,U_i表示第一个多项式Ui次项的系数,H_j表示第二个多项式Hj次项的系数,将U的系数由低次到高次排列,将H的系数有高次到低次排列,然后滑动H的系数,并在滑动过程中计算各个卷积项作为乘积结果的对应次项系数。设结果为R,当K=2时,有

R_2=U_0\times H_2+U_1\times H_1+U_2\times H_0

此处R_2表示乘积结果的二次项系数。

(图自http://blog.sina.com.cn/s/blog_7445c2940102wmrp.html

在机器学习的应用中,输入通常是多维数组的数据,而核通常是由学习算法优化得到的多维数组的参数。我们把这些多维数组叫做张量。因为在输入与核中的每一个元素都必须明确地分开存储,我们通常假设在存储了数值的有限点集以外,这些函数的值都为零。这意味着在实际操作中,我们可以通过对有限个数组元素的求和来实现无限求和。我们经常一次在多个维度上进行卷积运算。例如,如果把一张二维的图像I作为输入,我们也许也想要使用一个二维的核K

S(i, j)=(I * K)(i, j)=\sum_{m} \sum_{n} I(m, n) K(i-m, j-n)

卷积是可交换的 (commutative),我们可以等价地写作:

S(i, j)=(K * I)(i, j)=\sum_{m} \sum_{n} I(i-m, j-n) K(m, n)
接下来我们看以下2维卷积的直观例子:

这就是上面1维卷积的简单拓展,只不过H滑动的时候要保证重叠部分可以覆盖H,也就是说一开始H(2,2)就应该放在U(0,0)的位置,然后依次右滑和上滑,这体现在二维图像的卷积中就是如下形式:

下图演示了一个在 2 维张量上的卷积运算(没有对核进行翻转)的例子。

离散卷积可以看作矩阵的乘法,然而,这个矩阵的一些元素被限制为必须和另外一些元素相等。例如对于单变量的离散卷积,矩阵除第一行第一列外,其他每个元素都与左上角的元素相同。这种矩阵叫做Toeplitz矩阵(Toeplitz matrix)。对于二维情况,卷积对应着一个双重分块循环矩阵(doubly block circulant matrix)

2、动机

卷积运算通过三个重要思想改进机器学习系统: 稀疏交互(sparse interactions)参数共享(parameter sharing)等变表示(equivariant representations)。另外,卷积提供了一种处理大小可变的输入的方法。

传统的神经网络使用矩阵乘法来建立输入与输出的连接关系。其中,参数矩阵中每一个单独的参数都描述了一个输入单元与一个输出单元间的交互。这意味着每一个输出单元与每一个输入单元都产生交互。然而,卷积网络具有稀疏交互的特征。这是使核的大小远小于输入的大小来达到的。举个例子,当处理一张图像时,输入的图像可能包含成千上万个像素点,但是我们可以通过只占用几十到上百个像素点的核来检测一些小的有意义的特征,例如图像的边缘。这意味着我们需要存储的参数更少,不仅减少了模型的存储需求,而且提高了它的统计效率。这也意味着为了得到输出我们只需要更少的计算量。这些效率上的提高往往是很显著的。

如果有m个输入和n个输出,那么矩阵乘法需要m × n个参数并且相应算法的时间复杂度为O(m × n)。如果我们限制每一个输出拥有的连接数为k,那么稀疏的连接方法只需要k × n个参数以及O(k × n)的运行时间。在很多实际应用中,只需保持km小几个数量级,就能在机器学习的任务中取得好的表现。

那么问题来了,相比全连接,采用卷积的连接稀疏连接方式会不会使得输入单元只能和部分输出单元交互从而减弱模型学习效果呢?其实并不会,如下图所示:

参数共享(parameter sharing)是指在一个模型的多个函数中使用相同的参数。在传统的神经网络中,当计算一层的输出时,权重矩阵的每一个元素只使用一次,当它乘以输入的一个元素后就再也不会用到了。作为参数共享的同义词,我们可以说一个网络含有绑定的权重(tied weights),因为用于一个输入的权重也会被绑定在其他的权重上。在卷积神经网络中,核的每一个元素都作用在输入的每一位置上(是否考虑边界像素取决于对边界决策的设计)。卷积运算中的参数共享保证了我们只需要学习一个参数集合,而不是对于每一位置都需要学习一个单独的参数集合。这虽然没有改变前向传播的运行时间(仍然是O(k × n)),但它显著地把模型的存储需求降低至k个参数,并且k通常要比m小很多个数量级。因为mn通常有着大致相同的大小,k在实际中相对于m × n是很小的。因此,卷积在存储需求和统计效率方面极大地优于稠密矩阵的乘法运算。

作为前两条原则的一个实际例子,下图说明了稀疏连接和参数共享是如何显著提高线性函数在一张图像上进行边缘检测的效率的。

对于卷积,参数共享的特殊形式使得神经网络层具有对平移等变(equivariance)的性质。如果一个函数满足输入改变,输出也以同样的方式改变这一性质,我们就说它是等变 (equivariant) 的。特别地,如果函数 f (x) 与 g(x) 满足f(g(x)) = g(f (x)),我们就说f (x)对于变换g具有等变性。对于卷积来说,如果g是输入的任意平移函数,那么卷积函数对于g具有等变性。

举个例子,令I表示图像在整数坐标上的亮度函数,g表示图像函数的变换函数(把一个图像函数映射到另一个图像函数的函数)使得I^{′} = g(I),其中图像函数I^{′}满足I^{′} (x, y) = I(x − 1, y)。这个函数把I中的每个像素向右移动一个单位。如果我们先对I进行这种变换然后进行卷积操作所得到的结果,与先对I进行卷积然后再对输出使用平移函数g得到的结果是一样的。

当处理时间序列数据时,这意味着通过卷积可以得到一个由输入中出现不同特征的时刻所组成的时间轴。如果我们把输入中的一个事件向后延时,在输出中仍然会有完全相同的表示,只是时间延后。图像与之类似,卷积产生了一个 2 维映射来表明某些特征在输入中出现的位置。如果我们移动输入中的对象,它的表示也会在输出中移动同样的量。

3、池化

卷积网络中一个典型层包含三级(如下图所示)。在第一级中,这一层并行地计算多个卷积产生一组线性激活响应。在第二级中,每一个线性激活响应将会通过一个非线性的激活函数,例如整流线性激活函数。这一级有时也被称为探测级(detector stage)。在第三级中,我们使用池化函数(pooling function)来进一步调整这一层的输出

池化函数使用某一位置的相邻输出的总体统计特征来代替网络在该位置的输出。例如, 最大池化(max pooling)函数 (Zhou and Chellappa, 1988) 给出相邻矩形区域内的最大值。其他常用的池化函数包括相邻矩形区域内的平均值、范数以及基于据中心像素距离的加权平均函数。

不管采用什么样的池化函数,当输入作出少量平移时,池化能够帮助输入的表示近似不变(invariant)。对于平移的不变性是指当我们对输入进行少量平移时,经过池化函数后的大多数输出并不会发生改变。下图用一个例子来说明这是如何实现的。局部平移不变性是一个很有用的性质,尤其是当我们关心某个特征是否出现而不关心它出现的具体位置时。例如,当判定一张图像中是否包含人脸时,我们并不需要知道眼睛的精确像素位置,我们只需要知道有一只眼睛在脸的左边,有一只在右边就行了。但在一些其他领域,保存特征的具体位置却很重要。例如当我们想要寻找一个由两条边相交而成的拐角时,我们就需要很好地保存边的位置来判定它们是否相交。

使用池化可以看作是增加了一个无限强的先验:这一层学得的函数必须具有对少量平移的不变性。当这个假设成立时,池化可以极大地提高网络的统计效率。

对空间区域进行池化产生了平移不变性,但当我们对分离参数的卷积的输出进行池化时,特征能够学得应该对于哪种变换具有不变性。如下图:

因为池化综合了全部邻居的反馈,这使得池化单元少于探测单元成为可能,我们可以通过综合池化区域的k个像素的统计特征而不是单个像素来实现。

在很多任务中,池化对于处理不同大小的输入具有重要作用。例如我们想对不同大小的图像进行分类时,分类层的输入必须是固定的大小,而这通常通过调整池化区域的偏置大小来实现,这样分类层总是能接收到相同数量的统计特征而不管最初的输入大小了。

4、卷积与池化作为一种无限强的先验

先验被认为是强或者弱取决于先验中概率密度的集中程度。弱先验具有较高的熵值,例如方差很大的高斯分布。这样的先验允许数据对于参数的改变具有或多或少的自由性。强先验具有较低的熵值,例如方差很小的高斯分布。这样的先验在决定参数最终取值时起着更加积极的作用。

一个无限强的先验需要对一些参数的概率置零并且完全禁止对这些参数赋值,无论数据对于这些参数的值给出了多大的支持。

我们可以把卷积网络类比成全连接网络,但对于这个全连接网络的权重有一个无限强的先验。这个无限强的先验是说一个隐藏单元的权重必须和它邻居的权重相同,但可以在空间上移动。这个先验也要求除了那些处在隐藏单元的小的空间连续的接受域内的权重以外,其余的权重都为零。总之,我们可以把卷积的使用当作是对网络中一层的参数引入了一个无限强的先验概率分布。这个先验说明了该层应该学得的函数只包含局部连接关系并且对平移具有等变性。类似的,使用池化也是一个无限强的先验:每一个单元都具有对少量平移的不变性

卷积和池化可能导致欠拟合。与任何其他先验类似,卷积和池化只有当先验的假设合理且正确时才有用。如果一项任务依赖于保存精确的空间信息,那么在所有的特征上使用池化将会增大训练误差。一些卷积网络结构 (Szegedy et al., 2014a) 为了既获得具有较高不变性的特征又获得当平移不变性不合理时不会导致欠拟合的特征,被设计成在一些通道上使用池化而在另一些通道上不使用。当一项任务涉及到要对输入中相隔较远的信息进行合并时,那么卷积所利用的先验可能就不正确了。

5、基本卷积函数的变体

首先,当我们提到神经网络中的卷积时,我们通常是指由多个并行卷积组成的运算。这是因为具有单个核的卷积只能提取一种类型的特征,尽管它作用在多个空间位置上。我们通常希望网络的每一层能够在多个位置提取多种类型的特征。

另外,输入通常也不仅仅是实值的网格,而是由一系列观测数据的向量构成的网格。例如,一幅彩色图像在每一个像素点都会有红绿蓝三种颜色的亮度。当处理图像时,我们通常把卷积的输入输出都看作是 3 维的张量,其中一个索引用于标明不同的通道(例如红绿蓝),另外两个索引标明在每个通道上的空间坐标。

因为卷积网络通常使用多通道的卷积,所以即使使用了核翻转,也不一定保证网络的线性运算是可交换的。只有当其中的每个运算的输出和输入具有相同的通道数时,这些多通道的运算才是可交换的。

假定我们有一个 4 维的核张量K,它的每一个元素是K_{i,j,k,l},表示输出中处于通道i的一个单元和输入中处于通道j中的一个单元的连接强度,并且在输出单元和输入单元之间有kl列的偏置。假定我们的输入由观测数据 V组成,它的每一个元素是V_{i,j,k},表示处在通道i中第j行第k列的值。假定我们的输出Z和输入V具有相同的形式。如果输出Z是通过对KV进行卷积而不涉及翻转K得到的,那么:

Z_{i, j, k}=\sum_{l, m, n} V_{l, j+m-1, k+n-1} K_{i, l, m, n}

单看这个公式可能一脸懵逼,结合下图来看就清晰很多:

我们有时会希望跳过核中的一些位置来降低计算的开销(相应代价是提取特征没有先前好了)。我们可以把这一过程看作是对全卷积函数输出的下采样(downsampling)。如果我们只想在输出的每个方向上每间隔s个像素进行采样,那么我们可以定义一个下采样卷积函数c使得:

Z_{i, j, k}=c(\mathbf{K}, \mathbf{V}, s)_{i, j, k}=\sum_{l, m, n}\left[V_{l,(j-1) \times s+m,(k-1) \times s+n,} K_{i, l, m, n}\right]

在任何卷积网络的实现中都有一个重要性质,那就是能够隐含地对输入V用零进行填充(pad)使得它加宽。如果没有这个性质,表示的宽度在每一层就会缩减,缩减的幅度是比核少一个像素这么多。对输入进行零填充允许我们对核的宽度和输出的大小进行独立的控制。如果没有零填充,我们就被迫面临二选一的局面,要么选择网络空间宽度的快速缩减,要么选择一个小型的核——这两种情境都会极大得限制网络的表示能力。

有三种零填充设定的情况值得注意:

  • 不使用零填充的极端情况,并且卷积核只允许访问那些图像中能够完全包含整个核的位置。这称为有效(valid)卷积。在这种情况下,如果输入的图像宽度是m,核的宽度是k,那么输出的宽度就会变成m−k+1如果卷积核非常大的话缩减率会非常显著。

  • 只进行足够的零填充来保持输出和输入具有相同大小。这称为相同(same)卷积。在这种情况下,只要硬件支持,网络就能包含任意多的卷积层,这是因为卷积运算不改变下一层的结构。这可能会导致边界像素存在一定程度的欠表示。

  • 进行足够多的零填充使得每个像素在每个方向上恰好被访问了k次,称为全(full)卷积。最终输出图像的宽度为m + k − 1。在这种情况下,输出像素中靠近边界的部分相比于中间部分是更少像素的函数。这将导致学得一个在卷积特征映射的所有位置都表现不错的单核更为困难。

通常零填充的最优数量(对于测试集的分类正确率)处于 “有效卷积’’ 和“相同卷积’’ 之间的某个位置。

在一些情况下,我们并不是真的想使用卷积,而是想用一些局部连接的网络层(LeCun, 1986, 1989)。在这种情况下,我们的多层感知机对应的邻接矩阵是相同的,但每一个连接都有它自己的权重,用一个6维的张量W来表示。W的索引分别是:输出的通道i,输出的行j和列k,输入的通道 l,输入的行偏置m和列偏置n。局部连接层的线性部分可以表示为:

Z_{i, j, k}=\sum_{l, m, n}\left[V_{l, j+m-1, k+n-1} w_{i, j, k, l, m, n}\right]

这有时也被称为非共享卷积(unshared convolution),因为它和具有一个小核的离散卷积运算很像,但并不横跨位置来共享参数。

当我们知道每一个特征都是一小块空间的函数并且相同的特征不会出现在所有的空间上时,局部连接层是很有用的。例如,如果我们想要辨别一张图片是否是人脸图像时,我们只需要去寻找嘴是否在图像下半部分即可。

使用那些连接被更进一步限制的卷积或者局部连接层也是有用的,例如,限制每一个输出的通道i仅仅是输入通道l的一部分的函数时。实现这种情况的一种通用方法是使输出的前m个通道仅仅连接到输入的前n个通道,输出的接下来的m个通道仅仅连接到输入的接下来的n个通道,以此类推。一个简单的例子如下:

平铺卷积(tiled convolution)(Gregor and LeCun, 2010a; Le et al., 2010) 对卷积层和局部连接层进行了折衷。这里并不是对每一个空间位置的权重集合进行学习,我们学习一组核使得当我们在空间移动时它们可以循环利用。这意味着在近邻的位置上拥有不同的过滤器,就像局部连接层一样,但是对于这些参数的存储需求仅仅会增长常数倍,这个常数就是核的集合的大小,而不是整个输出的特征映射的大小。平铺卷积表达式如下:

Z_{i, j, k}=\sum_{l, m, n} V_{l, j+m-1, k+n-1} K_{i, l, m, n, j \% t+1, k \% t+1}

一般来说,在卷积层从输入到输出的变换中我们不仅仅只用线性运算。我们一般也会在进行非线性运算前,对每个输出加入一些偏置项。这样就产生了如何在偏置项中共享参数的问题。对于局部连接层,很自然地对每个单元都给定它特有的偏置,对于平铺卷积,也很自然地用与核一样的平铺模式来共享参数。对于卷积层来说,通常的做法是在输出的每一个通道上都设置一个偏置,这个偏置在每个卷积映射的所有位置上共享。然而,如果输入是已知的固定大小,也可以在输出映射的每个位置学习一个单独的偏置。分离这些偏置可能会稍稍降低模型的统计效率,但同时也允许模型来校正图像中不同位置的统计差异。例如,当使用隐含的零填充时,图像边缘的探测单元接收到较少的输入,因此需要较大的偏置。

6、卷积网络结构化输出

卷积神经网络可以用于输出高维的结构化对象,而不仅仅是预测分类任务的类标签或回归任务的实数值。通常这个对象只是一个张量,由标准卷积层产生。例如,模型可以产生张量S,其中S_{i,j,k}是网络的输入像素(j, k)属于类i的概率。这允许模型标记图像中的每个像素,并绘制沿着单个对象轮廓的精确掩模(图像掩模是用选定的图像、图形或物体、对待处理的图像(全部或局部)进行遮挡来控制图像处理的区域或处理过程)。

经常出现的一个问题是输出平面可能比输入平面要小。用于对图像中单个对象分类的常用结构中,网络空间维数的最大减少来源于使用大步幅的池化层。为了产生与输入大小相似的输出映射,我们可以避免把池化放在一起。

对图像逐个像素标记的一种策略是先产生图像标签的原始猜测,然后使用相邻像素之间的交互来修正该原始猜测。一旦对每个像素都进行了预测,我们就可以使用各种方法来进一步处理这些预测,以便获得图像在区域上的分割 (Briggman et al., 2009; Turaga et al., 2010;Farabet et al., 2013)。一般的想法是假设大片相连的像素倾向于对应着相同的标签。图模型可以描述相邻像素间的概率关系。或者,卷积网络可以被训练来最大化地近似图模型的训练目标 (Ning et al., 2005; Thompson et al., 2014)。

7、数据类型

卷积网络使用的数据通常包含多个通道,每个通道是时间上或空间中某一点的不同观测量。具有不同维数和通道数的数据类型的例子如下:

到目前为止,我们仅讨论了训练和测试数据中的每个样例都有相同的空间维度的情况。卷积网络的一个优点是它们还可以处理具有可变的空间尺度的输入。这些类型的输入不能用传统的基于矩阵乘法的神经网络来表示。例如,考虑一组图像的集合,其中每个图像具有不同的高度和宽度。目前还不清楚如何用固定大小的权重矩阵对这样的输入进行建模。卷积就可以很直接地应用;核依据输入的大小简单地被使用不同次,并且卷积运算的输出也相应地放缩。卷积可以被视为矩阵乘法;相同的卷积核为每种大小的输入引入了一个不同大小的双重分块循环矩阵。

注意,使用卷积处理可变尺寸的输入,仅对输入是因为包含对同种事物的不同量的观察 (时间上不同长度的记录,空间上不同宽度的观察等) 而导致的尺寸变化这种情况才有意义。如果输入是因为它可以选择性地包括不同种类的观察而具有可变尺寸,使用卷积是不合理的。

8、高效的卷积算法

现代卷积网络的应用通常需要包含超过百万个单元的网络。利用并行计算资源的强大实现是很关键的,然而,在很多情况下,也可以通过选择适当的卷积算法来加速卷积。

卷积等效于使用傅立叶变换将输入与核都转换到频域、执行两个信号的逐点相乘,再使用傅立叶逆变换转换回时域。对于某些问题的规模,这种算法可能比离散卷积的朴素实现更快。

当一个d维的核可以表示成d个向量(每一维一个向量)的外积时,该核被称为可分离的(separable)。当核可以分离时,朴素的卷积是低效的。它等价于组合d个一维卷积,每个卷积使用这些向量中的一个。组合方法显著快于使用它们的外积来执行一个d维的卷积。并且核也只要更少的参数来表示成向量。如果核在每一维都是w个元素宽,那么朴素的多维卷积需要O(w^d ) 的运行时间和参数存储空间,而可分离卷积只需要O(w × d)的运行时间和参数存储空间。当然,并不是每个卷积都可以表示成这种形式。

9、随机或无监督的特征

通常,卷积网络训练中最昂贵的部分是学习特征。输出层的计算代价通常相对不高,因为在通过若干层池化之后作为该层输入的特征的数量较少。当使用梯度下降执行监督训练时,每步梯度计算需要完整地运行整个网络的前向传播和反向传播。减少卷积网络训练成本的一种方式是使用那些不是由监督方式训练得到的特征。

有三种基本策略可以不通过监督训练而得到卷积核。其中一种是简单地随机初始化它们。另一种是手动设计它们,例如设置每个核在一个特定的方向或尺度来检测边缘。最后,可以使用无监督的标准来学习核。例如,Coates et al. (2011) 将k均值聚类算法应用于小图像块,然后使用每个学得的中心作为卷积核。使用无监督的标准来学习特征,允许这些特征的确定与位于网络结构顶层的分类层相分离。然后只需提取一次全部训练集的特征,构造用于最后一层的新训练集。假设最后一层类似逻辑回归或者SVM,那么学习最后一层通常是凸优化问题。

10、CNN训练

这一节是我自己加上的,因为看完这一章节以后我突然想到,为什么CNN训练速度快呢……仅仅是因为相比全连接权重变少了吗……不是,主要是因为共享权重……但是,共享权重的话,用BP咋训练呢……百思不得解……

参考了https://becominghuman.ai/back-propagation-in-convolutional-neural-networks-intuition-and-code-714ef1c38199的理解,算是大概知道CNN用BP训练为什么效率较高了。要点记录如下:

记这一层输出为h,则有:

令:

现在,对于实现当前层的反向传播的步骤,我们可以假定𝜕h作为输入(下一层反向传播的结果),我们的目标是计算𝜕w𝜕x。注意这里把𝜕x理解为上一层的输入(相当于本层反向传播的结果)。

过滤器中的每个权重都会影响输出中的每个像素。因此,过滤器中权重的任何变化都会影响所有输出像素。因此,所有这些变化加起来会导致最终的损失。因此,我们可以计算导数如下:

𝜕x也可以类似地计算。

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