03 降维

之前的文章提及数据集的大小(缩放)对算法的准度的影响比较大。例如BP神经网络对输入“千”和“万”级的数据,准度相差一倍。但是有时候不做处理,哪怕几十兆的数据,在两两计算相似度也会出现上亿的计算量,影响计算效率。所以本章探讨一个主题,如何在保持准度情况下,降低数据纬度(降维,dimensionality reduction)。

3.1 无监督学习主要用于预处理和探索

首先把研究点缩小,到底研究降维在什么方面的问题:数据集的无监督变换(unsupervised transformation)——是创建数据新的表示的算法,与原始的数据相比,新的表示可能更容易被人或其他机器学习算法所理解。可以更容易“发现、追踪”社交媒体上的话题讨论,比如选举、商品或流行歌手等话题

综上,无监督学习的一个主要是评估算法是否学到了有用的新东西。无监督学习算法一般用于不包含任何标签信息的数据,所以我们不知道正确的输出应该是什么。因此很难判断一个模型是否“表现很好”。通常来说,评估无监督算法结果的唯一方法就是人工检查。

因此,无监督算法通常可用于探索性的目的,而不是作为大型自动化系统的一部分(重点)。无监督算法的另一个常见应用是作为监督算法的预处理步骤(重点)。学习数据的一种新表示,有时可以提高监督算法的精度,或者可以减少内存占用和时间开销。在开始学习“真正的”无监督算法之前,我们先简要讨论几种简单又常用的预处理方法。虽然预处理和缩放通常与监督学习算法一起使用,但缩放方法并没有用到与“监督”有关的信息,所以它是无监督的。

接下来我们讨论三种聚类算法:Kmeans、DBSCAN 和凝聚聚类。三种方法都可以用于大型的现实世界数据集,都相对容易理解,也都可以聚类成多个簇。每种算法的优点稍有不同。Kmeans可以用簇的平均值来表示簇。它还可以被看作一种分解方法,每个数据点都由其簇中心表示。DBSCAN 可以检测到没有分配任何簇的“噪声点”,还可以帮助自动判断簇的数量。DBSCAN 有时会生成大小差别很大的簇,这可能是它的优点,也可能是缺点。凝聚聚类可以提供数据的可能划分的整个层次结构,可以通过树状图轻松查看

归一化/标准化/正则化[1]:
StandardScaler 确保每个特征的平均值为 0、方差为 1,使所有特征都位于同一量级。
MinMaxScaler 移动数据,使所有特征都刚好位于 0 和 1 之间。
Normalizer 它对每个数据点进行缩放,使得特征向量的欧式长度等于 1 。

下面举一个归一化的例子(数据缩放,也可以理解为压缩数据),在乳腺癌数据集,观察使用 MinMaxScaler 对学习 SVC 的作用。首先,为了对比,我们再次在原始数据上拟合 SVC,再用 MinMaxScaler 对数据进行缩放,然后再拟合 SVC:


MinMaxScaler在svc上的应用

正如我们上面所见,数据缩放的作用非常显著。由原来的0.63提升到0.97了。

3.2 预处理和探索

既然了解了无监督学习进行数据变换(预处理和探索)可能有很多种目的(上面缩放数据只是预处理中一种干预)。下面继续学习利用无监督学习最主要的几个功能。
无监督学习最常见的优化目的就是可视化、压缩数据,以及寻找信息量更大的数据表示以用于进一步的处理。分别对应的算法有:主成分分析(PCA)、非负矩阵分解(NMF)和 t-SNE,前者通常用于特征提取,后两者通常用于二维散点图的可视化(这3个算法都可以用这两个功能,只是大多数人用PCA是做特征提取,不代表NMF不能做特征提取)。重点说PCA在两方面(特征提取和特征可视化)的应用。

3.2.1 特征提取

特征提取目的是找到一种数据表示,比给定的原始表示更适合于分析。特征提取一个很好的应用实例就是图像识别。图像由像素组成,通常存储为红绿蓝(RGB)强度。图像中的对象通常由上千个像素组成,它们只有放在一起才有意义。图像中很常见任务是人脸识别。看某个前所未见的人脸是否属于数据库中的某个已知人物。解决人脸这个问题的方法之一就是构建一个分类器,每个人都是一个单独的类别。但人脸数据库中通常有许多不同的人,而同一个人的图像很少(也就是说,每个类别的训练样例很少)。这使得大多数分类器的训练都很困难。另外,通常你还想要能够轻松添加新的人物,不需要重新训练一个大型模型。

我们将给出用 PCA 对图像做特征提取的一个简单应用,即处理 Wild 数据集 Labeled Faces(标记人脸)中的人脸图像。这一数据集包含从互联网下载的名人脸部图像,它包含从 21 世纪初开始的政治家、歌手、演员和运动员的人脸图像。我们使用这些图像的灰度版本,并将它们按比例缩小以加快处理速度。


labeled faces 信息

每个人有多少张图片

以上两段代码透漏重点信息:一共有 3023 张图像,每张大小为 87 像素×65 像素,分别属于 62 个不同的人。重点:随机猜测的精度约为 1/62=1.5%。也就是识别准度至少要比随机要高。
首先用knn来尝试一下,设置k=1的情况,准度是0.23.

knn走一遭

想要度量人脸的相似度,计算原始像素空间中的距离是一种相当糟糕的方法。用像素表示来比较两张图像时,我们比较的是每个像素的灰度值与另一张图像对应位置的像素灰度值。这种表示与人们对人脸图像的解释方式有很大不同。(简单的说,就是比较两个图是否像,两个图是1024768的分辨率,我们就要比较1024768=786432个点,两两是否相似,这个计算机量非常大,但如何我们比较两个人是否一样,他们脸上都有明显的1处胎记,这样就计算1次就完成了)。

我们希望,使用沿着主成分方向的距离可以提高精度。这里我们启用 PCA 的白化(whitening)选项,它将主成分缩放到相同的尺度。变换后的结果与使用 StandardScaler 相同。白化不仅对应于旋转数据,还对应于缩放数据使其形状是圆形而不是椭圆。

pca优化

精度有了相当显著的提高,从 26.6% 提升到 31%,当然这个结果还不够好(因为我们只用了相速度,还没有用年龄、性别等特征),但这证实了我们的想法,即主成分可能提供了一种更好的优化方式。

3.2.2 特征可视化

对于图像数据,我们还可以很容易地将找到的主成分可视化。成分对应于输入空间里的方向。这里的输入空间是 87 像素×65 像素的灰度图像,所以在这个空间中的方向也是 87 像素×65 像素的灰度图像。我们来看一下前几个主成分:

人脸特征的可视化

虽然我们肯定无法理解这些成分的所有内容,但可以猜测一些主成分捕捉到了人脸图像的哪些方面。第一个主成分似乎主要编码的是人脸与背景的对比,第二个主成分编码的是人脸左半部分和右半部分的明暗程度差异,如此等等。
虽然这种表示比原始像素值的语义稍强,但它仍与人们感知人脸的方式相去甚远。由于 PCA 模型是基于像素的,因此人脸的相对位置(眼睛、下巴和鼻子的位置)和明暗程度都对两张图像在像素表示中的相似程度有很大影响。但人脸的相对位置和明暗程度可能并不是人们首先感知的内容。在要求人们评价人脸的相似度时,他们更可能会使用年龄、性别、面部表情和发型等属性,而这些属性很难从像素强度中推断出来。
本测试的重点:算法对数据(特别是视觉数据,比如人们非常熟悉的图像)的解释通常与人类的解释方式大不相同。机器学习PCA对人类识别的比较过程类似如下处理:
pca处理人脸相似度

X犀利(可能是):先旋转数据,然后删除方差较小的成分。X1...Xn是这个数据点的主成分的系数(PCA 旋转后的新特征值),使我们可以将测试点表示为主成分的加权求和。

3.2.3 其他两种方法

非负矩阵分解(non-negative matrix factorization,NMF)是另一种无监督学习算法,其目的在于提取有用的特征。它的工作原理类似于 PCA,也可以用于降维。但在 PCA 中,我们想要的是正交分量,并且能够解释尽可能多的数据方差;而在 NMF 中,我们希望分量和系数均为非负,也就是说,我们希望分量和系数都大于或等于 0。因此,这种方法只能应用于每个特征都是非负的数据,因为非负分量的非负求和不可能变为负值。

将数据分解成非负加权求和的这个过程,对由多个独立源相加(或叠加)创建而成的数据特别有用,比如多人说话的音轨或包含多种乐器的音乐。在这种情况下,NMF 可以识别出组成合成数据的原始分量。总的来说,与 PCA 相比,NMF 得到的分量更容易解释,因为负的分量和系数可能会导致难以解释的抵消效应(cancellation effect),具体参考[2]。

虽然 PCA 通常是用于变换数据的首选方法,使你能够用散点图将其可视化,但这一方法的性质(先旋转然后减少方向)限制了其有效性,正如我们在 Wild 数据集 Labeled Faces 的散点图中所看到的那样。有一类用于可视化的算法叫作流形学习算法(manifold learning algorithm),它允许进行更复杂的映射,通常也可以给出更好的可视化。其中特别有用的一个就是 t-SNE 算法。

流形学习算法主要用于可视化,其中一些算法(包括 t-SNE)计算训练数据的一种新表示,但不允许变换新数据。这意味着这些算法不能用于测试集:更确切地说,它们只能变换用于训练的数据。流形学习对探索性数据分析是很有用的,但如果最终目标是监督学习的话,则很少使用

t-SNE 背后的思想是找到数据的一个二维表示,尽可能地保持数据点之间的距离。t-SNE 首先给出每个数据点的随机二维表示,然后尝试让在原始特征空间中距离较近的点更加靠近,原始特征空间中相距较远的点更加远离。t-SNE 重点关注距离较近的点,而不是保持距离较远的点之间的距离。换句话说,它试图保存那些表示哪些点比较靠近的信息。我们将对 scikit-learn 包含的一个手写数字数据集应用 t-SNE 流形学习算法。在这个数据集中,每个数据点都是 0 到 9 之间手写数字的一张 8×8 灰度图像。


PCA效果

t-SNE效果

t-SNE 的结果非常棒。所有类别都被明确分开。数字 1 和 9 被分成几块,但大多数类别都形成一个密集的组。重点:它完全是无监督的。但它能够找到数据的一种二维表示,仅根据原始空间中数据点之间的靠近程度就能够将各个类别明确分开。

3.3 Kmeans

首先明确一点KNN与Kmeans的算法的区别:
1.KNN算法是分类算法,我们第一章涉及的就是用KNN。分类算法肯定是需要有学习语料,然后通过学习语料的学习之后的模板来匹配我们的测试语料集,将测试语料集合进行按照预先学习的语料模板来分类
2Kmeans算法是聚类算法,聚类算法与分类算法最大的区别是聚类算法没有学习语料集合。

3.3.1 Kmeans原理

Kmeans算法的确很好理解,一两行代码即可以表述清楚。簇中心用三角形表示,而数据点用圆形表示。颜色表示簇成员。我们指定要寻找三个簇,所以通过声明三个随机数据点为簇中心来将算法初始化(见图中“Initialization”/“初始化”)。然后开始迭代算法。


kmeans原理

最下面的图,既把数据分为三类。

3.3.2 Kmeans优势

优势就是简单,简单介绍下图的1234框表示的内容:
框1:跑一些random的模拟数据,对数据调用 fit 方法(其实重点就这句)。如果不指定 n_clusters,它的默认值是 8。
框2:把模拟数据类型都打印出来。


knn优势

框3:把kmeans预测的结果输出。切记!切记!切记!这里的分类的名字123是“假”的。因为聚类算法与分类算法有些相似,分类是每个元素都有一个标签,但聚类规律好,没有名字,但是也要表示,所以给个标签,但并不存在真实的标签。
框4:打印出来看看。

3.3.3 Kmeans劣势

劣势很简单:Kmeans分别复杂的数据,分的稀烂。我们如果希望聚类算法能够发现两个半月形。但利用 k 均值算法是不可能做到这一点的。


kmeas分复杂数据

3.4 凝聚聚类

3.4.1 凝聚聚类原理

凝聚聚类(agglomerative clustering)指的是许多基于相同原则构建的聚类算法,这一原则是:算法首先声明每个点是自己的簇,然后合并两个最相似的簇,直到满足某种停止准则为止。scikit-learn 中实现的停止准则是簇的个数,因此相似的簇被合并,直到仅剩下指定个数的簇。最开始,每个点自成一簇。然后在每一个步骤中,相距最近的两个簇被合并。在前四个步骤中,选出两个单点簇并将其合并成两点簇。在步骤 5(Step 5)中,其中一个两点簇被扩展到三个点,以此类推。在步骤 9(Step 9)中,只剩下 3 个簇。由于我们指定寻找 3 个簇,因此算法结束。


agglomerative.png

当我们import 凝聚聚类(agglomerative clustering)包后,scikit-learn 中实现了以下三种选项。

ward默认选项。ward 挑选两个簇来合并,使得所有簇中的方差增加最小。这通常会得到大小差不多相等的簇。
average链接将簇中所有点之间平均距离最小的两个簇合并。
complete链接(也称为最大链接)将簇中点之间最大距离最小的两个簇合并。
ward 适用于大多数数据集,在我们的例子中将使用它。如果簇中的成员个数非常不同(比如其中一个比其他所有都大得多),那么 average 或 complete 可能效果更好。

我们来看一下凝聚聚类对我们这里使用的简单三簇数据的效果如何。由于算法的工作原理,凝聚算法不能对新数据点做出预测。因此 AgglomerativeClustering 没有 predict 方法。为了构造模型并得到训练集上簇的成员关系,可以改用 fit_predict 方法,算法完美地完成了聚类,如上图所示。

3.4.1 凝聚聚类优势

凝聚聚类处理多维数据集

凝聚聚类有另一个将层次聚类可视化的工具,叫作树状图(dendrogram),它可以处理多维数据集。不幸的是,目前 scikit-learn 没有绘制树状图的功能。但你可以利用 SciPy 轻松生成树状图。SciPy 的聚类算法接口与 scikit-learn 的聚类算法稍有不同。SciPy 提供了一个函数,接受数据数组 X 并计算出一个链接数组(linkage array),它对层次聚类的相似度进行编码。然后我们可以将这个链接数组提供给 scipy 的 dendrogram 函数来绘制树状图。这样的方法可以处理增量的归类

3.4.1 凝聚聚类劣势

凝聚聚类仍然无法分离像 two_moons 数据集这样复杂的形状。但我们要学习的下一个算法 DBSCAN 可以解决这个问题。

3.5 DBSCAN

3.5.1 DBSCAN原理

另一个非常有用的聚类算法是 DBSCAN(density-based spatial clustering of applications with noise,即“具有噪声的基于密度的空间聚类应用”)。DBSCAN 的主要优点是它不需要用户先验地设置簇的个数,可以划分具有复杂形状的簇,还可以找出不属于任何簇的点。DBSCAN 比凝聚聚类和 k 均值稍慢,但仍可以扩展到相对较大的数据集。

DBSCAN 的原理是识别特征空间的“拥挤”区域中的点,在这些区域中许多数据点靠近在一起。这些区域被称为特征空间中的密集(dense)区域。DBSCAN 背后的思想是,簇形成数据的密集区域,并由相对较空的区域分隔开。

在密集区域内的点被称为核心样本(core sample,或核心点),它们的定义如下。DBSCAN 有两个参数:min_samples 和 eps。如果在距一个给定数据点 eps 的距离内至少有 min_samples 个数据点,那么这个数据点就是核心样本。DBSCAN 将彼此距离小于 eps 的核心样本放到同一个簇中。

算法首先任意选取一个点,然后找到到这个点的距离小于等于 eps 的所有的点。如果距起始点的距离在 eps 之内的数据点个数小于 min_samples,那么这个点被标记为噪声(noise),也就是说它不属于任何簇。如果距离在 eps 之内的数据点个数大于 min_samples,则这个点被标记为核心样本,并被分配一个新的簇标签。然后访问该点的所有邻居(在距离 eps 以内)。如果它们还没有被分配一个簇,那么就将刚刚创建的新的簇标签分配给它们。如果它们是核心样本,那么就依次访问其邻居,以此类推。簇逐渐增大,直到在簇的 eps 距离内没有更多的核心样本为止。然后选取另一个尚未被访问过的点,并重复相同的过程。

最后,一共有三种类型的点:核心点、与核心点的距离在 eps 之内的点(叫作边界点,boundary point)和噪声。如果 DBSCAN 算法在特定数据集上多次运行,那么核心点的聚类始终相同,同样的点也始终被标记为噪声。但边界点可能与不止一个簇的核心样本相邻。因此,边界点所属的簇依赖于数据点的访问顺序。一般来说只有很少的边界点,这种对访问顺序的轻度依赖并不重要。

3.5.1 DBSCAN优势

我们将 DBSCAN 应用于演示凝聚聚类的模拟数据集。与凝聚聚类类似,DBSCAN 也不允许对新的测试数据进行预测,所以我们将使用 fit_predict 方法来执行聚类并返回簇标签。


准备好数据

在这张图中,属于簇的点是实心的,而噪声点则显示为空心的。核心样本显示为较大的标记,而边界点则显示为较小的标记。增大 eps(在图中从左到右),更多的点会被包含在一个簇中。这让簇变大,但可能也会导致多个簇合并成一个。增大 min_samples(在图中从上到下),核心点会变得更少,更多的点被标记为噪声。

参数 eps 在某种程度上更加重要,因为它决定了点与点之间“接近”的含义。将 eps 设置得非常小,意味着没有点是核心样本,可能会导致所有点都被标记为噪声。将 eps 设置得非常大,可能会导致所有点形成单个簇。

设置 min_samples 主要是为了判断稀疏区域内的点被标记为异常值还是形成自己的簇。如果增大 min_samples,任何一个包含少于 min_samples 个样本的簇现在将被标记为噪声。因此,min_samples 决定簇的最小尺寸。在图 3-37 中 eps=1.5 时,从 min_samples=3 到 min_samples=5,你可以清楚地看到这一点。min_samples=3 时有三个簇:一个包含 4 个点,一个包含 5 个点,一个包含 3 个点。min_samples=5 时,两个较小的簇(分别包含 3 个点和 4 个点)现在被标记为噪声,只保留包含 5 个样本的簇。


测试结果

在 two_moons 数据集上运行 DBSCAN 的结果。利用默认设置,算法找到了两个半圆形并将其分开:


dbscan和kmeans对比处理数据好很多

3.5.1 DBSCAN劣势

以下评估一下这3种算法的优劣,我们选用两个指标:1调整 rand 指数(adjusted rand index,ARI)2归一化互信息(normalized mutual information,NMI)。,二者都给出了定量的度量,其最佳值为 1,0 表示不相关的聚类(虽然 ARI 可以取负值)。

用真实值评估聚类——ARI 来比较 k 均值、凝聚聚类和 DBSCAN 算法。

为了对比,我们还添加了将点随机分配到两个簇中的图像。第一个图为随机。很明显dbscan是最好的。


ari

在没有真实值的情况下评估聚类——轮廓系数(silhouette coeffcient)

刚刚展示了一种评估聚类算法的方法,但在实践中,使用诸如 ARI 之类的指标有一个很大的问题。在应用聚类算法时,通常没有真实值来比较结果。如果我们知道了数据的正确聚类,那么可以使用这一信息构建一个监督模型(比如分类器)。因此,使用类似 ARI 和 NMI 的指标通常仅有助于开发算法,但对评估应用是否成功没有帮助。

有一些聚类的评分指标不需要真实值,比如轮廓系数(silhouette coeffcient)。但它们在实践中的效果并不好。轮廓分数计算一个簇的紧致度,其值越大越好,最高分数为 1。虽然紧致的簇很好,但紧致度不允许复杂的形状。

silhouette coeffcient

k 均值的轮廓分数最高,尽管我们可能更喜欢 DBSCAN 的结果。

对于评估聚类,稍好的策略是使用基于鲁棒性的(robustness-based)聚类指标。这种指标先向数据中添加一些噪声,或者使用不同的参数设定,然后运行算法,并对结果进行比较。其思想是,如果许多算法参数和许多数据扰动返回相同的结果,那么它很可能是可信的。

在没有真实值的情况下人工干预——在人脸数据集上比较算法

我们这里在使用了默认算法后,进行了人工分析,不同于监督学习中自动化的搜索方法。下面我们将继续应用 k 均值为例,dbscan和凝聚聚类就省略。
我们可以首先设置一个比较小的簇的数量,比如 10 个,这样我们可以分析每个簇。如你所见,k 均值聚类将数据划分为大小相似的簇,其大小在 64 和 386 之间。我们可以通过将簇中心可视化来进一步分析 k 均值的结果。我们需要使用 pca.inverse_transform 将簇中心旋转回到原始空间并可视化:


将簇的数量设置为 10 时,k 均值找到的簇中心

k 均值找到的簇中心是非常平滑的人脸。这并不奇怪,因为每个簇中心都是 64 到 386 张人脸图像的平均。使用降维的 PCA 表示,可以增加图像的平滑度。我们对每个簇中心给出了簇中 5 张最典型的图像(该簇中与簇中心距离最近的图像)与 5 张最不典型的图像(该簇中与簇中心距离最远的图像)


k 均值为每个簇找到的样本图像——簇中心在最左边,然后是五个距中心最近的点,然后是五个距该簇距中心最远的点

3.6 总结

本节的内容表明,聚类的应用与评估是一个非常定性的过程,通常在数据分析的探索阶段很有帮助。我们学习了三种聚类算法:k 均值、DBSCAN 和凝聚聚类。这三种算法都可以控制聚类的粒度(granularity)。k 均值和凝聚聚类允许你指定想要的簇的数量,而 DBSCAN 允许你用 eps 参数定义接近程度,从而间接影响簇的大小。三种方法都可以用于大型的现实世界数据集,都相对容易理解,也都可以聚类成多个簇。

每种算法的优点稍有不同。

k 均值可以用簇的平均值来表示簇。它还可以被看作一种分解方法,每个数据点都由其簇中心表示。

凝聚聚类可以提供数据的可能划分的整个层次结构,可以通过树状图轻松查看。

DBSCAN 可以检测到没有分配任何簇的“噪声点”,还可以帮助自动判断簇的数量。与其他两种方法不同,它允许簇具有复杂的形状,正如我们在 two_moons 的例子中所看到的那样。DBSCAN 有时会生成大小差别很大的簇,这可能是它的优点,也可能是缺点。

3.7 参考文献

[1]预处理与缩放 https://www.jianshu.com/p/e291e00374ca
[2]降维(PCA与NMF) https://blog.csdn.net/qq_39293290/article/details/90108213

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