第十六章 异常检测

该系列文章为,观看“吴恩达机器学习”系列视频的学习笔记。虽然每个视频都很简单,但不得不说每一句都非常的简洁扼要,浅显易懂。非常适合我这样的小白入门。

本章含盖

  • 16.1 问题动机
  • 16.2 高斯分布
  • 16.3 算法
  • 16.4 开发和评估异常检测系统
  • 16.5 异常检测 VS 监督学习
  • 16.6 选择要使用的功能
  • 16.7 多变量高斯分布
  • 16.8 使用多变量高斯分布的异常检测

16.1 问题动机

在接下来的一系列视频中,我将向大家介绍异常检测(Anomaly detection)问题。这是机器学习算法的一个常见应用。这种算法的一个有趣之处在于:它虽然主要用于非监督学习问题,但从某些角度看,它又类似于一些监督学习问题。

什么是异常检测呢?

为了解释这个概念,让我举一个例子吧:

假想你是一个飞机引擎制造商,当你生产的飞机引擎从生产线上流出时,你需要进行QA(质量控制测试),而作为这个测试的一部分,你测量了飞机引擎的一些特征变量,比如引擎运转时产生的热量,或者引擎的振动等等。



这样一来,你就有了一个数据集,从x^(1) 到 x^(m),如果你生产了m个引擎的话,你将这些数据绘制成图表,看起来就是这个样子:

这里的每个点、每个叉,都是你的无标签数据。这样,异常检测问题可以定义如下:我们假设后来有一天,你有一个新的飞机引擎从生产线上流出,而你的新飞机引擎有特征变量x_test。所谓的异常检测问题就是:我们希望知道这个新的飞机引擎是否有某种异常,或者说,我们希望判断这个引擎是否需要进一步测试。因为,如果它看起来像一个正常的引擎,那么我们可以直接将它运送到客户那里,而不需要进一步的测试。

如果更正式的定义,异常检测问题,那么我们有一些数据 x^(1) 到 x^(m),我们通常假定这 m 个样本都是正常的,或者说不是异常的。 然后,我们需要一个算法来告诉我们一个新的样本数据 x_test 是否是异常。我们需要采取的方法是,给定无标签训练集,我们将对数据建模,即 p(x)。也就说,我们将对 x 的分布概率建模,其中 x 是这些特征变量,例如飞机引擎。因此,当我们建立了 x 的概率模型之后,对于新的飞机引擎,也就是 x_test,如果概率 p 低于阈值 ε。那么就将其标记为“异常”(即,p(x_test) < ε);否则,任务它是正常的(即,p(x_test) >= ε)。

当 x_test 落到中心那个圈内时,p(x_test)的值会很大。

上图中,在蓝色圈内的数据属于该组数据的可能性较高,而越是偏远的数据,其属于该组数据的可能性就越低。

这种方法称为密度估计,表达如下:

欺诈检测:x^(i)=用户的第 i个活动特征

模型p(x) 为我们其属于一组数据的可能性,通过p(x)<ε检测非正常用户。

给定数据集 x(1),x(2),..,x^(m),我们假使数据集是正常的,我们希望知道新的数据 x_test 是不是异常的,即这个测试数据不属于该组数据的几率如何。我们所构建的模型应该能根据该测试数据的位置告诉我们其属于一组数据的可能性 p(x)。

异常检测算法的应用案例:

异常检测主要用来识别欺骗。例如在线采集而来的有关用户的数据,一个特征向量中可能会包含如:用户多久登录一次,访问过的页面,在论坛发布的帖子数量,甚至是打字速度等。尝试根据这些特征构建一个模型,可以用这个模型来识别那些不符合该模式的用户。

再一个例子是检测一个数据中心,特征可能包含:内存使用情况,被访问的磁盘数量,CPU的负载,网络的通信量等。根据这些特征可以构建一个模型,用来判断某些计算机是不是有可能出错了。

16.2 高斯分布

在这个视频中,我将介绍高斯分布,也称为正态分布。回顾高斯分布的基本知识。


假设 x 是一个实数的随机变量。如果 x 的概率分布服从高斯分布,其中均值为 μ,方差为 σ 平方。
σ:标准差,它确定了高斯分布概率密度函数的宽度;而,σ^2 称之为“方差”。
那么,将它记作 x ~ N(μ, σ^2)


高斯分布有两个参数,一个是均值 μ,一个是方差 σ^2。参数 μ 控制曲线的中心位置;σ 控制曲线的宽度,因此,参数 σ 有时也称作“一个标准差”。这条钟型曲线决定了 x 取不同值时的概率。因此,x 取中心这些值的时候,输出的概率相当大。

👆这个代表 x 的概率分布,这个概率由 μ 和 σ^2 决定。

高斯分布例子:

因为这是一个概率分布,所以阴影部分的积分一定为 1。这是概率分布的一个特征。所以“ μ = 0;σ = 0.5 ”的图像比“ μ = 0;σ = 1 ”的图像更高(即,只有一半的标准差,但是它有两倍的高)。

接下来,我们来讨论下参数估计的问题。
那么,什么是参数估计问题?
假设,我们有一个数据集,其中有 m 个样本,从 x^(1) 到 x^(m),假设它们都是实数。图中的横轴是样本 x 的值。
而,参数估计问题就是,假设我猜测这些样本,来自一个高斯分布的总体,假设我猜测每个样本 x^(i) 服从高斯分布。但是,我不知道高斯部分的两个参数 μ 和 σ^2 的值是多少?参数的估计问题就是,给定数据集,我希望能找到能够估算出 μ 和 σ^2 的值。

均值参数 μ 的估计方式:

方差参数 σ^2 的估计方式:

注:机器学习中对于方差我们通常只除以m而非统计学中的(m-1)。这里顺便提一下,在实际使用中,到底是选择使用1/m还是1/(m-1)其实区别很小,只要你有一个还算大的训练集,在机器学习领域大部分人更习惯使用1/m这个版本的公式。这两个版本的公式在理论特性和数学特性上稍有不同,但是在实际使用中,他们的区别甚小,几乎可以忽略不计。

16.3 算法

使用高斯分布来构建一个异常检测算法。


异常检测算法:

对于给定的数据集 x^(1), x^(2), ..., x^(m),我们要针对每一个特征计算 μ 和 σ^2 的估计值。


一旦我们获得了平均值和方差的估计值,给定新的一个训练实例,根据模型计算 p(x):

“Π(大写希腊字母π)” 表示“乘积式,即,一些列数值的乘积”
当p(x)<ε时,为异常。btw,👆这个估计问题的分布项 p(x) ,有时也称作是“密度估计问题”

整理一下:这就是我们的异常检测算法
  1. 选择特征量,或是想出一些特征量 x_i,它们能够帮助我们指出哪些反常的样本。通常来说,会选择那些能够描述你所想的能够描述你所收集的数据的一般特性的特征。
  2. 给出训练集,也就是 m 个未标记的样本,从 x^(1) 到 x^(m)。之后,我们进行参数拟合,μ_1 到 μ_n,(σ_1)^2 到 (σ_n)^2。
  3. 最后,给定一个样本,计算该样本的 p(x)。如果,这个概率值很小,那么你就将这一项标注为异常
应用这种方法的一个案例

👆的三维图表示的是密度估计函数,z轴为根据两个特征的值所估计p(x)值。

事实上,我们可以改良这个方法。意思是,看这个三维曲面图,你可以看出所有的 x_1 和 x_2 值其所在位置都是比较高的,对应的是无异常的情况。相反,所有那些更远的点(粉色圈外的点),所有这些点其概率都相当小,所以我们会将这些点标注为异常。因此,可以定义某个范围,看起来可能是这样👇(粉丝圈)

我们选择一个ε,将p(x)=ε作为我们的判定边界,当p(x)>ε时预测数据为正常数据,否则为异常。
在这段视频中,我们介绍了如何拟合p(x),也就是 x 的概率值,以开发出一种异常检测算法。同时,在这节课中,我们也给出了通过给出的数据集拟合参数,进行参数估计,得到参数 μ 和 σ,然后检测新的样本,确定新样本是否是异常。
在接下来的课程中,我们将深入研究这一算法,同时更深入地介绍,怎样让算法工作地更加有效。

16.4 开发和评估异常检测系统

实数评估的重要性。它的主要思想是,当你为某个应用开发一个学习算法时,你需要进行一系列的选择,比如,选择使用什么特征,等等。如果你有某种方法,通过返回一个实数,来评估你的算法,那么对这些选择做出决定,往往会容易很多。比如,现在有一个新特性,你需要决定该不该纳入这个特征?如果你分别在纳入该特征和不纳入该特征情况下运行算法,然后算法返回一个数字,来告诉你这个特征对算法的影响是好是坏。这样的话,你就能更简单地决定要不要纳入这个特征。

so,为了能够快速地开发出这样一个算法评估系统。这里有一个很好的方法,来评估一个异常检测系统。
假设,我们有一些带标签的数据,这些数据中有正常的数据,也有异常的数据。用 y = 0 表示正常样本,用 y = 1 表示异常样本。

那么异常检测算法的开发过程,以及评估方法。如下所示:

假设有一个训练集,并将它看作是无标签的。所以它是一个很大的正常样本的集合。通常来说,我把它们看作是无异常样本,即便遛进了一些异常样本也没关系。接下来,我们要定义一个交叉验证集和测试集,用来评估这个异常检测算法。具体来说,对交叉验证集和测试集,我们假设在交叉验证集和测试集中包含一些已知是异常的样本。所以,在测试集中我们有一些标签是 y = 1 的样本。

具体的例子:

例如:我们有10000台正常引擎的数据,有20台异常引擎的数据。 我们这样分配数据:
6000台正常引擎的数据作为训练集
2000台正常引擎和10台异常引擎的数据作为交叉检验集
2000台正常引擎和10台异常引擎的数据作为测试集

具体的评价方法如下:
  1. 根据测试集数据,我们估计特征的平均值和方差并构建p(x)函数

  2. 对交叉检验集,我们尝试使用不同的ε值作为阀值,并预测数据是否异常,根据F1值或者查准率与查全率的比例来选择 ε
    因为,我们的数据很倾斜(即,大部分数据的 y 都等于 0)。那么分类正确率就不是一个好的评价指标。相比之下,如果我们用的是 true positive,false positive,false negative,true negative 的比率;或者计算出算法的正确率和召回率;或者计算出想F_1-score,它是一个实数,来总结和反映精度。
    通过这些方法,你就可以评估你的异常检测算法,在交叉验证和测试集样本中的表现。

  3. 选出 ε 后,针对测试集进行预测,计算异常检验系统的F1值,或者查准率与查全率之比。

16.5 异常检测 VS 监督学习

前面我们构建的异常检测系统也使用了带标记的数据,与监督学习有些相似,下面的对比有助于选择采用监督学习还是异常检测:
  1. 它的正常样本数量很少(即,y = 1 的例子,这表示它是一个异常样例),数量大致在 0 ~ 20 个,或者50个,那么你可以考虑使用一个异常检测算法。与此相反,在一个典型的异常检测算法中,我们经常会有一个比起正常样本数量大得多的负样本(即,y = 0 的样本),我们可以用这些庞数量的负样本来拟合出 p(x) 的值。因此在许多异常检测应用中,有这样一个思想:你有很多少的正样本和很多的负样本,当我们在处理估计p(x)的值,拟合所有的高斯参数的过程中,我们只需要负样本就够了。所以,如果你有大量的负样本,我们仍然可以很好的拟合p(x)的值。
    与此相反,对于监督学习来说,更典型的情况是:在合理范围内会有大量的正样本和负样本。

  2. 还有另外一种人们经常考虑异常检查算法的方法,对于异常检测应用来说,经常有许多不同类型的异常。因此,如果是这种情况,你有很少数量的正样本,那么对一个算法就很难,很难去从你的小数量的正样本中去学习异常是什么。尤其是,未来可能出现的异常看起来可能会与已有的截然不同。如果是这种情况,那么更有可能的是对负样本用高斯分布模型p(x)来建模,而不是费尽心思的对正样本建模。
    相反,在一些其他问题中,你有足够数量的正样本,或是一个已经能识别正样本的算法。尤其是,假如你认为未来可能出现的正样本与你当前训练集中的正样本类似。那么,这种情况下,使用一个监督学习算法会更合理。它能查看大量正样和大量负样本来学到相应特征,并且能够尝试区分正样本和负样本

希望这节课能让你明白一个学习问题的什么样的特征,能让你把这个问题当作是一个异常检测,或者是一个监督学习的问题。二者的关键不同在于,在异常检测中,我们通常只有少量的正样本,因此对于一个学习算法而言,它是不可能从这些正样本中学习到足够的知识的。所以我们要做的,是使用大量负样本,让这个算法学到足够多的内容,从那些负样本中学习p(x)的值。我们保留小数量的正样本,来评估我们的算法。这个算法用于交叉验证或测试集。

另外,对于很多技术公司可能会遇到的一些问题,通常来说,正样本的数量很少,甚至有时候是0,也就是说,出现了太多没见过的不同的异常类型,那么对于这些问题,通常应该使用的算法就是异常检测算法。

异常检测算法,例子:欺诈行为检测 生产(例如飞机引擎)检测数据中心的计算机运行状况
监督学习算法,例子:邮件过滤器 天气预报 肿瘤分类

16.6 选择要使用的功能

事实上,当你应用异常检测时,其中有一个因素对运行有很大影响,那就是你使用什么特征,或者说选择什么特征,来实现异常检测算法。

如何设计和选择异常检测算法的特征??
在我们的异常检测算法中,我们所做的其中一件事是,使用高斯分布来对特征建模。


异常检测假设特征符合高斯分布,如果数据的分布不是高斯分布,异常检测算法也能够工作,但是最好还是将数据转换成高斯分布(因为这么做的话,算法也许能运行的更好),例如使用对数函数:x=log(x+c),其中 c 为非负常数; 或者 x=x^c,c为 0-1 之间的一个分数,等方法。这些参数 c 都是可调的,目的是让你的数据更符合一个高斯分布。
我们用拟合后的 x 来计算高斯分布的参数 μ 和 σ^2

如何得到异常检测算法的特征??
我们通常用的办法是,通过一个误差分析。我的意思是,这跟我们之前讨论监督学习时,误差分析的步骤类似的。我们先完整的训练出一个算法,然后在一组交叉验证上运行算法,然后找出那些预测出错的样本。并看看我们能否找到一些其他的特征来帮助学习算法,让那些在交叉验证中判断出错的样本表现的更好。



举例:在一个正常样本很多,异常样本很少的情况下。
一个常见的问题是一些异常的数据可能也会有较高的p(x)值,因而被算法认为是正常的。这种情况下误差分析能够帮助我们,我们可以分析那些被算法错误预测为正常的数据,观察能否找出一些问题。我们可能能从问题中发现我们需要增加一些新的特征,增加这些新特征后获得的新算法能够帮助我们更好地进行异常检测。
异常检测误差分析:


最后,我想与你分享一些,我平时在为异常检测算法选择特征变量时的一些思考:


通常来说,我选择特征的方法是,我会选那些,既不会特别特别大,也不会特别特别小的特征,对于那些我认为很可能异常的样本。
我们通常可以通过将一些相关的特征进行组合,来获得一些新的更好的特征(异常数据的该特征值异常地大或小),例如,在检测数据中心的计算机状况的例子中,我们可以用CPU负载与网络通信量的比例作为一个新的特征,如果该值异常地大,便有可能意味着该服务器是陷入了一些问题中。

在这段视频中,我们介绍了如何选择特征,以及对特征进行一些小小的转换,让数据更像正态分布,然后再把数据输入异常检测算法。同时也介绍了建立特征时,进行的误差分析方法,来捕捉各种异常的可能。希望你通过这些方法,能够了解如何选择好的特征变量,从而帮助你的异常检测算法,捕捉到各种不同的异常情况。

16.7 多变量高斯分布

举例:


两个特征,x_1 CPU 负载;x_2 内存使用

假如,我们的存在这么一个样本(绿色)


对应 CPU Load 为 0.4 ;Memory Use 为 1.5。将这个样本分别带入 x_1(CPU Load)和 x_2(Memory Use)的高斯分布图,对应的结果都不太差,因此这个异常样本在此异常检测中会被识别为“正常的样本”。。。

我们发现,异常检测算法不能识别这个蓝色的椭圆。它认为同一个粉色圈类的样本具有相同的概率。

假使我们有两个相关的特征,而且这两个特征的值域范围比较宽,这种情况下,一般的高斯分布模型可能不能很好地识别异常数据。其原因在于,一般的高斯分布模型尝试的是去同时抓住两个特征的偏差,因此创造出一个比较大的判定边界。
上图中是两个相关特征,洋红色的线(根据ε的不同其范围可大可小)是一般的高斯分布模型获得的判定边界,很明显绿色的X所代表的数据点很可能是异常值,但是其p(x)值却仍然在正常范围内。多元高斯分布将创建像图中蓝色曲线所示的判定边界。

解决方案:使用“多元高斯分布”,或者叫做“多元正态分布”

具体做法:我们有特征变量 x ,它属于 R^n。我们不要为 p(x_1)、p(x_2)分别建模,而是要建立一个整体的 p(x) 模型。多元高斯分布的参数是 μ 和 ∑(协方差矩阵)
| ∑ | :👈叫做矩阵的行列式,它是一个矩阵的数学函数。

在一般的高斯分布模型中,我们计算 p(x) 的方法是: 通过分别计算每个特征对应的几率然后将其累乘起来,在多元高斯分布模型中,我们将构建特征的协方差矩阵,用所有的特征一起来计算 p(x)。

我们首先计算所有特征的平均值,然后再计算协方差矩阵:

注:其中μ 是一个向量,其每一个单元都是原特征矩阵中一行数据的均值。最后我们计算多元高斯分布的p(x):
多元高斯分布的例子:

假设,我们有两个特征变量 x_1 和 x_2

对应于特定的 x_1 和 x_2,这个面的高度,就是 p(x) 的值。

在👇此参数设定下:当,x_1 和 x_2 都等于 0 时,p(x)取到最大值。

多元高斯分布的一个很棒的事情是,你可以用它,给数据的相关性建立模型。

👆非对角线上的元素,你会得到一种不同的高斯分布。所以当我将非对角线的元素,从 0.5 增加到 0.8 时,我会得到一个更加窄和高的,沿着 x = y 这条线的分布。然后,这个等高线图告诉我们 x 和 y 看起来是一起增加的。即,x_1 和 x_2 同时处于高概率时,p(x)才处于高概率。。

当 协方差矩阵∑ 的非对角线上的元素,设置成负数时,得到的模型是,大部分的概率都在 x_1 和 x_2 负相关的区域上 所以大多数的概率都落在 x_1 等于 -x_2 附近的区域,而不是 x1 = x_2。

另外,你还看有改变 平均参数 μ

图1:峰值在 x_1 = x_2 = 0 处
图2:峰值在 x_1 = 0;x_2 = 0.5 处
图3:峰值在 x_1 = 1.5;x_2 = -0.5 处

所以改变参数 μ 值,就是在移动整个分布的中心

上图是5个不同的模型,从左往右依次分析:

  1. 是一个一般的高斯分布模型
  2. 通过协方差矩阵,令特征1拥有较小的偏差,同时保持特征2的偏差
  3. 通过协方差矩阵,令特征2拥有较大的偏差,同时保持特征1的偏差
  4. 通过协方差矩阵,在不改变两个特征的原有偏差的基础上,增加两者之间的正相关性
  5. 通过协方差矩阵,在不改变两个特征的原有偏差的基础上,增加两者之间的负相关性

16.8 使用多变量高斯分布的异常检测

多元高斯分布的参数拟合

假如我有一组样本,从 x^1 到 x^m,这些样本的每一个都是 n 维向量(x ∈ R^n)。并且,我的样本是服从多元高斯分布的。
👆这和我们之前使用PCA,即,主成分分析算法的时候写的 ∑ 是一样的。
完整步骤:
  1. 首先,用我们的数据集来拟合该模型。即,通过设定 μ 和 ∑ 来拟合 p(x)。
  2. 接下来,当你有一个新的样本 x,即一个测试样本。我们需要用拟合出来的多元高斯分布的公式来计算p(x)。如果得到的 p(x) 很小(即,p(x) < ε),就标记该样本为异常。
多元高斯分布 和 原始模型 有着怎样的关系了?

原始模型:

原始模型 对比 多元高斯模型,原始模型的轮廓(等高线)总是轴对其的。所以,你不能对不同特征之间的关系进行建模。

事实上,👆 3 个服从高斯分布的样本,你都可以用原始模型来拟合。也就是说,原始模型是特殊的多元高斯模型。(即,当 ∑ 的非对角线上元素都是 0 时 ),而对角线上元素,也就对应原始模型的 σ^2

如何在两个模型之间进行选择了?
原高斯分布模型 多元高斯分布模型
不能捕捉特征之间的相关性 但可以通过将特征进行组合的方法来解决 自动捕捉特征之间的相关性
计算代价低,能适应大规模的特征 计算代价较高 训练集较小时也同样适用
必须要有 m > n ,不然的话协方差矩阵 不可逆的,通常需要 m > 10 * n 另外特征冗余也会导致协方差矩阵不可逆

原高斯分布模型被广泛使用着,如果特征之间在某种程度上存在相互关联的情况,我们可以通过构造新新特征的方法来捕捉这些相关性。
如果训练集不是太大,并且没有太多的特征,我们可以使用多元高斯分布模型。

  1. 其实,原始模型被用的更频繁一些。反之,多元高斯模型用得要更少一些,但它在捕捉特征间的关系方面有着很多优点。
    假设,你想要进行异常检测,你有一些不同的特征 x_1、x_2 等。你想通过异常检测的组合值来捕捉异常样本。
    如果你使用原始模型来捕捉这样的组合值,你就需要创建一个额外的特征来表示这个多个特征间关系的组合值,将其作为一个新的特征。
    而对比之下,多元高斯模型,就能自动地捕捉这种不同特征之间的关系。

  2. 不过原始模型也有它的优点,原始模型的一个巨大优势就是,它的计算成本比较低。也就是说,它能适应巨大规模的 n(即,适应数量巨大的特征)。当 n = 10000 甚至 n = 100000 的时候。原始模型都能运行得很好。
    而对比之下,对于多元高斯模型,因为需要计算 ∑ 的逆矩阵,而 ∑ 是一个 n*n 的矩阵,因此它的计算成本比较高,特别是在 大规模的 n 的情况下,它的计算成本将会非常高昂。所以,多元高斯模型能适应于的 n 值范围比较小。

  3. 最后,对于原始模型,即时你有一个较小的,有一定相关性的训练集,它也能顺利运行。即便 n 的值只有 50、100 这样。
    而对于,多元高斯分布,这个算法有一些数学性质,也就是你必须保证 m > n,否则,在估计 ∑ 时会导致 ∑ 矩阵不可逆。这将导致你无法使用多元高斯分布。

原则:我会使用多变量高斯分布,当且仅当 m 远大于 n。这算是一种,狭义的数学要求。比如,m 大于 10倍的n。。

ps:因为 ∑ 大多时候是一个对称矩阵,所以它的参数个数更接近于 n^2 / 2 (理论上,∑ 矩阵的参数个数为 n^2)

如果,你在拟合多元高斯模型的时候,发现协方差矩阵 ∑ 是奇异矩阵(即,∑ 矩阵不可逆)。那么,通常是两种情况:
① 一种是,你没有满足 m > n 的条件
② 第二种是,你存在冗余的特征。比如,x_1 = x_2 或 x_3 = x_4 + x_5 ,这里的“x_1” 和 “x_3”都是冗余特征。即,x_1 、x_3 都是满足线性相关的特征 。

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

推荐阅读更多精彩内容