正则化——由浅入深的进阶之路

Regularization

作    者: Wang Fengxiang
just a bachelor's degree candidate.


导  语:正则化(Regularization)方法是为解决过拟合(overfitting)问题,而向原始模型引入额外信息,以便防止过拟合和提高模型泛化性能的一类方法的统称。本文将从过拟合问题引入,并通过在线性回归和logistic回归中进行正则化帮助理解思想。最后通过解读应用正则化思想的相关文献来贯通正则化的应用,此部分为选读内容。主要内容来自Andrew Ng的Coursera机器学习课程,符号记法也采用Andrew Ng的记法。


我们假设你已阅读本系列文章《通往深度学习之路》中关于线性回归、logistic回归和梯度下降的相关内容

一、 过拟合(overfitting)问题

    以新型冠状肺炎发病人数y随时间x变化为例(Fig.1)。

Figure1.新型冠状肺炎患病人数的线性回归模型

    图中选取了几个不同时间下的发病人数的样本点,时间轴开始时发病人数少,随着时间轴推进,发病人数极速增长在2月中下旬达到峰值,随后增长速率放缓。
    (a)模型拟合了一阶线性函数,可以明显看出该模型没有很好地拟合训练数据,具有高偏差,我们称该问题为欠拟合(underfitting)。即该算法不顾数据的不符合,有很强的偏见地认为时间与患病人数时线性相关的,最终导致数据拟合效果很差。
    (b)模型拟合了二阶多项式函数,效果不错。
    (c)模型拟合了一个四阶多项式函数,该曲线绘制后全部通过每个数据点,看似很好的拟合训练数据 [注1],但曲线扭曲上下波动明显,具有高方差,所以这并不是一个很好的预测模型,我们称该问题为过拟合(overfitting)。即直观上来看,过拟合的算法虽然能集合几乎所有数据,但是拟合的假设函数(hypothesis)会太过庞大、变量太多。虽然该例子只有五项\Theta参数不够明显,但倘若我们每一个小时更新患病人数,为完全拟合数据,函数会有极多项\Theta,同时这也导致对该假设函数我们没有足够的数据进行训练,因为数据全用来拟合函数。
    总结过拟合问题:拥有太多变量的训练好的假设模型会近乎完美地拟合训练集,但会难以泛化(generalize)[注2]新的样本。

[注1]:拟合得好是说该模型的代价函数(cost function)约为零,在线性回归模型中即为                J(\Theta )= \frac{1}{2m}\sum_{m}^{i=1}(h_{\Theta }(x^{i})-y^{i})^{2}\approx 0

[注2]:’泛化‘术语是指:一个假设模型(hypothesis)应用到新样本的能力。其中,在本例中新的样本是说没有出现在训练集的不同时间的患病人数。

    事实上,新冠肺炎的发病人数变化并不仅仅与时间有关,更与在汉医护人员数量、口罩数量、消毒剂酒精的每日使用量、人员流动性程度等诸多变量有关,这也符合我们在实际中机器学习模型会拥有诸多特征变量(features),而不仅仅是单一变量。
    但拥有太多变量,显而易见绘图会变得更加困难,因此通过数据的可视化来决定保留哪些特征变量会更为困难。正如我们之前所讲的,多特征变量、数据量不足会导致过拟合问题,为解决过拟合问题,我们有如下的几个思路:

  • 1.减少特征变量(features)的数量
    • 人工检查变量清单
    • 模型选择算法(model selection algorithm)

    该思路可以有效的减少过拟合现象的发生,但其缺点是舍弃了一部分变量,即舍弃了一部分关于问题的信息,如我们新冠肺炎的发病人数例子中,舍弃了口罩数量、消毒剂酒精的每日使用量、人员流动性程度等诸多变量,但所有的变量或多或少都对预测有用,实际上我们并不想丢失这些信息。

  • 2.正则化(Regularization)方法
    • 保留所有变量,但减少量级(magnitude)或参数(parameters)\Theta _{j} 的大小

该思路相较于第一种方法,保留了所有对结果y有用的信息,对过拟合问题效果良好。

二、 正则化(Regularization)

2.1 引入正则化思想

    前面我们已经得到了解决过拟合问题采用减少量级或减少参数大小的正则化方法最为有效。那我们接下来继续讨论,正则化是怎么做到减少参数值的大小的呢?

Figure 2.新冠肺炎拟合较好与过拟合的模型

    我们再次回到最初关于新冠状肺炎的例子中,Fig 2.(b)模型的 二阶函数 [注2]Fig 2.(c)模型的四阶函数[注3]相比,显然只要四阶函数的参数(parameters)\Theta _{3}\Theta _{4}都非常小,两者函数就会相似。为了达到这个目的,我们惩罚(penalize)参数\Theta _{3}\Theta _{4}使其变小,我们来看下该过程在线性规划中是如何实现的。

注2:二阶函数为\Theta _{0} + \Theta _{1}x + \Theta _{2}x^{2}
注3:四阶函数为\Theta _{0} + \Theta _{1}x + \Theta _{2}x^{2} + \Theta _{3}x^{3} + \Theta _{4}x^{4}

    线性回归中,我们的优化目标是要最小化其均方误差代价函数(square error cost function)。在不进行惩罚时,优化目标的函数描述为
                   min_{(\Theta)}\frac{1}{2m}\sum_{i=1}^{m}(h_{\Theta }(x^{i})-y^{i})^{2}

现在我们要对函数进行一些修改,即增加两项10000 \Theta _{3} ^{2}10000\Theta _{4}^{2}。此时,优化目标的函数描述变为
           min_{(\Theta)} \frac{1}{2m}\sum_{i=1}^{m}(h_{\Theta }(x^{i})-y^{i})^{2}+10000 \Theta _{3} ^{2} +10000 \Theta _{4} ^{2}

    其中,10000是我们随便选取的较大的数方便直观理解。此时,因为参数\Theta _{3}\Theta _{4}都与10000相乘,为了最小化整体的函数,我们就需要使参数\Theta _{3}\Theta _{4}尽量接近于0。而如果\Theta _{3}\Theta _{4}都很小的话,我们的四阶函数假设模型就大致相当于二阶函数模型了,这就是我们正则化惩罚的思想。
    但我们在实际中,比如新冠肺炎发病人数的例子,口罩数量、消毒剂酒精的每日使用量、人员流动性程度等诸多特征变量(features)都与预测结果有关,而每个特征变量在我们总体的衡量得失中所占有的比重我们并不能一开始就准确地知道,那我们要如何跟上述例子一样选择具体确切的变量\Theta _{3}\Theta _{4}进行惩罚(penalize)呢?
    因此实际问题上对每个变量权重并不准确了解,对此我们就采用将所有变量均缩小的办法。
    回到上述例子中,我们就是要将所有参数(parameters)\Theta _{i}均缩小,通过将代价函数(cost function)后加一个额外的正则化项实现,该项的作用是缩小每一个参数\Theta _{i}的值,修改后如下:
                J(\Theta )= \frac{1}{2m}[\sum_{i=1}^{m}(h_{\Theta }(x^{i})-y^{i})^{2}+ \lambda \sum_{i=1}^{m}\Theta _{i} ^{2}]
    其中,正则化项中的\lambda正则化参数[注4],其作用是控制两个不同目标[注5]之间的取舍来避免出现过拟合的情况。

[注4]:关于正则化参数\lambda我们前面例子中为方便理解设为10000,大家可以考虑下,如果设置得过大如10000会有什么样的影响?
    所有的参数会接近于零,即相当于忽略掉假设函数的全部项。在本例中,如果参数\Theta _{i}从1到n全部忽略不计,那拟合的曲线模型就变为:
        h_{\Theta}(x)=\Theta _{0}+ \not{\Theta _{1}}\not{x} + \not{ \Theta _{2}}\not{x^{2}} + \not{\Theta _{3}}\not{x^{3} }+ \not{ \Theta _{4}}\not{x^{4}}
这差不多相当于用一条水平的直线来拟合训练数据集,显然与数据集不符合,具有高偏差,这样的模型就犯了我们第一部分所讲到的欠拟合问题

[注5]:两个不同的目标,第一个目标是指前面项的累加,是为更好地拟合数据和训练集;第二个目标是指我们要尽可能地是参数值小,这与目标函数的第二项即正则化项有关 。

    在新冠肺炎的例子中,如果我们采用上述正则化后的代价函数J(\Theta),那我们拟合的曲线虽然不会如二阶函数般契合,但是一定比四阶函数模型曲线更加平滑更加简单。

2.2 从线性回归说起正则化

    通过前一小节的引入,我们已经介绍了正则化后的线性回归模型的代价函数和优化目标分别为:
             J(\Theta )= \frac{1}{2m}[\sum_{i=1}^{m}(h_{\Theta }(x^{(i)})-y^{(i)})^{2}+ \lambda \sum_{i=1}^{m}\Theta _{i} ^{2}]
               min_{(\Theta)} \frac{1}{2m}[\sum_{i=1}^{m}(h_{\Theta }(x^{(i)})-y^{(i)})^{2}+ \lambda \sum_{i=1}^{m}\Theta _{i} ^{2}]
    接下来我们将分别介绍两种求解线性回归模型算法(梯度下降算法正规方程法)的正则化形式。


    在不加入正则化的时候,我们使用了梯度下降(gradient descent)进行常规的线性回归,算法如下:
  Repeat{    
\Theta_{0}:=\Theta_{0}-\alpha\frac{1 }{m}\sum_{i=1}^{m}(h_{\Theta }(x^{(i)})-y^{(i)})x_{0}^{(i)} \Theta_{j}:=\Theta_{j}-\alpha\frac{1 }{m}\sum_{i=1}^{m}(h_{\Theta }(x^{(i)})-y^{(i)})x_{j}^{(i)}
                               (j=0,1,2,3,4......,n)
        }
    我们可以注意到算法中标红出处,我们是将j=0的情况单独拿了出来进行迭代更新(update),为什么要这么做呢?
    不知道大家有没有注意,我们前面正则化对参数进行的惩罚对象是从参数\Theta_{1}开始的,并不包含参数\Theta_{0}!!!我们从参数\Theta_{1}开始加入正则化项后,算法修改如下:
  Repeat{                        
               \Theta_{0}:=\Theta_{0}-\alpha\frac{1 }{m}\sum_{i=1}^{m}(h_{\Theta }(x^{(i)})-y^{(i)})x_{0}^{(i)}
               \Theta_{j}:=\Theta_{j}-\alpha[\frac{1 }{m}\sum_{i=1}^{m}(h_{\Theta }(x^{(i)}-y^{(i)})x_{j}^{(i)} +\frac{ \lambda }{m}\Theta_{j}]
                                     (j=1,2,3,4......,n)
        }

    我们假设了大家已经阅读了本系列文章关于梯度下降的内容,我这里就不具体用微积分展开证明:算法中方括号部分就是J(\Theta)\Theta_{j}的偏导数,要注意J(\Theta)是我们正则化后的包含正则化项的函数。

    梯度下降算法中对于变量\Theta从1到n的更新(update),去掉中括号后更新式变为如下:
            \Theta_{j}:=\Theta_{j}(1- \alpha\frac{ \lambda }{m})-\alpha \frac{1 }{m}\sum_{i=1}^{m}(h_{\Theta }(x^{(i)}-y^{(i)})x_{j}^{(i)}
    该变式的第一项中,通常是学习率\lambda很小,但m却很大,那整体的\alpha\frac{ \lambda }{m}就会很小,即第一项就是\Theta_{j}乘一个比1略小的数。
    该变式的第二项,实际上与我们未进行正则化的梯度下降更新项是一样。


    我们来看下线性回归模型求解的第二种算法:正规方程法(normal equation)的正则化形式。
    该方法原有形式为:
              X=\begin{pmatrix}(x^{(1)})^{T}\\ ·······\\ (x^{(m)})^{T} \end{pmatrix}            y=\begin{pmatrix} y^{(1)} \\ ·······\\ y^{(m)}\end{pmatrix}
                            min_{\Theta}J(\Theta)

    即经过最小化代价函数,我们可以得到:
                        \Theta=(x^{T}x)^{-1}x^{T}y
    如果我们使用正则化,那该式需要增加一个矩阵,修改后如下:

            \Theta=(x^{T}x+\lambda\begin{bmatrix}0&0 &0 &··· &0 \\ 0&1 &0 &··· &0 \\ 0&0 &1 &··· &0 \\ ···&··· &··· &··· &··· \\ 0&0 &0 &··· &1 \end{bmatrix})^{-1}x^{T}y
    该式中的矩阵为n+1·n+1阶的矩阵,n表示特征变量的数量。进行正则化后还有一个好处是,即使样本总量小于特征变量数,也不需要担心该修改后的式子是不可逆(non-invertible)[注6]的。

[注6]:不可逆问题是线性代数关于逆矩阵方面的基本问题,请自行参考线代知识。这里需要提及的一点是:即使是未进行正则化的式子存在不可逆的可能,但我们在使用matlab进行计算时,采用的pinv函数会直接求伪逆。

2.3 从logistic回归续谈正则化

    logistic回归章的讲解在大家已经阅读完线性回归内容后,很多内容会不再进行赘述,主要通过代码实现让大家理解更深刻。

    回归的代价函数为解决过拟合现象,在添加正则化项以达到惩罚参数的目的后,代价函数变为如下形式:
        J(\Theta)=-[\frac{1}{m}\sum_{i=1}^{m}y^{(i)}log h_{\Theta}(x^{i})+(1-y^{(i)})log(1-h_{\Theta}(x^{(i)}))]+\frac{\lambda}{2m}\sum_{i=1}^{m}\Theta_{j}^{2}
    与线性回归的正则化类似,该正则化项的作用是减小参数。


    logistic回归的梯度下降算法形式上与线性回归相似,其区别在于假设模型(hypothesis) 是不一样的,logistics回归的假设模型为:
                    h_{\Theta }(x)=\frac{1}{1+e^{-\Theta ^{T}x}}
    但梯度下降算法的形式与线性回归一致:

  Repeat{                        
               \Theta_{0}:=\Theta_{0}-\alpha\frac{1 }{m}\sum_{i=1}^{m}(h_{\Theta }(x^{(i)})-y^{(i)})x_{0}^{(i)}
               \Theta_{j}:=\Theta_{j}-\alpha[\frac{1 }{m}\sum_{i=1}^{m}(h_{\Theta }(x^{(i)}-y^{(i)})x_{j}^{(i)} +\frac{ \lambda }{m}\Theta_{j}]
                                     (j=1,2,3,4......,n)
        }


    我们在本章更为关注如何实现正则化后的logistic回归模型,并且我们会通过学习率\lambda的取值分别展现出过拟合(overfitting)、欠拟合(underfitting)和正则化(regularize)后的情况。

    首先,我们建立一个命名为costFunction的函数,该函数需要返回两个值,第一个值是计算代价函数J(\Theta)的值,第二个需要返回值是梯度(gradient),即分别对于每个i值的梯度我们进行求导:
                            \frac{\partial J(\Theta) }{\partial \Theta_{i}}

# Matlab

function [J, grad] = costFunctionReg(theta, X, y, lambda)

m = length(y); % number of training examples
J = 0;
grad = zeros(size(theta));
hy = sigmoid(X*theta)
J = sum(-y.*log(hy)-(1-y).*log(1-hy))/m + lambda*sum(theta(2:size(theta)(1)).^2)/(2*m);
grad(1) = ((hy-y)'*X(:,1))/m;
A = ((hy-y)'*X(:,2:size(X)(2)))/m;
grad(2:size(X)(2)) = A' + lambda*theta(2:size(theta)(1))/m;

end

    我们建立的costfunction函数返回的两个值需要返回到我们的主函数中,主函数要做的主要功能是将costfunction最小化。
    另外为了清晰地绘制简单明了的图像方便大家理解,编写了函数mapfeature来将数据绘制在图中;函数plotDecisonBoundary绘制决策边界(DecisonBoundary);函数sigmoid表示假设模型(hypothesis);这些简易函数与本章无关就不尽兴一一赘述,具体可参考Github中吴恩达的作业

# Matlab

clear ; close all; clc
data = load('ex2data2.txt');
X = data(:, [1, 2]); y = data(:, 3);
plotData(X, y);
xlabel('Microchip Test 1')
ylabel('Microchip Test 2')
legend('y = 1', 'y = 0')
hold off;
X = mapFeature(X(:,1), X(:,2));
initial_theta = zeros(size(X, 2), 1);
lambda = 1;
options = optimset('GradObj', 'on', 'MaxIter', 400);
[theta, J, exit_flag] = ...
    fminunc(@(t)(costFunctionReg(t, X, y, lambda)), initial_theta, options);
plotDecisionBoundary(theta, X, y);
hold on;
title(sprintf('lambda = %g', lambda))
xlabel('Microchip Test 1')
ylabel('Microchip Test 2')
legend('y = 1', 'y = 0', 'Decision boundary')
hold off;
p = predict(theta, X);
fprintf('Train Accuracy: %f\n', mean(double(p == y)) * 100);
fprintf('Expected accuracy (with lambda = 1): 83.1 (approx)\n');

    我们可以得到在学习率\lambda为1的情况下我们正则化后的决策边界较为理想,如Fig.3所示。

Figure 3.学习率为1


    那如果我们的学习率\lambda为0和100情况分别会怎么样呢?

Figure 4.学习率为0

    我们可以看到Fig .4的处理相当于没有正则化处理的logistic回归模型,即具有过拟合问题。近乎很好的拟合所有数据,但带来的问题是边界曲线显然扭曲,上下波动明显,具有高方差。


Figure 5.学习率为100

    Fig .5的处理情况,就是我们的欠拟合现象,即具有高偏差,与数据集是显然不符合的。


三、 正则化的应用之路

    我们以一篇文献EEG-Based Emotion Recognition Using Regularized Graph Neural Networks(基于正则化图神经网络的脑电情绪识别)来应用正则化的思想。

我们只关注其中的正则化内容,略掉其余的不同领域的背景相关知识,包括关于作者利用脑电图信号的拓扑结构建立稀疏邻接矩阵,以及简单图卷积网络(graph convolution network)和对无向连接图采用切比雪夫多项式(Chebyshev polynomials)来代替卷积核的图傅里叶变换进行滤波 。
对相关知识感兴趣可以参考文献和一篇该方向研究生的论文解读,本部分主要基于两者。

    作者采用了一个正则化的图神经网络(RGNN)来解决在基于脑电图的情绪识别方面噪音标签问题。具体而言,对图神经网络模型的正则化,其整体框架Fig 6.是结合作者提出的一个节点域对抗训练(NodeDAT)基于情绪感知的分布学习(EmotionDL)计算两者总体的损失函数(cost function)。总体损失函数计算如下:
                          {\Phi}''= {\Phi}'+ \Phi_{D}
    {\Phi}'\Phi_{D}分别为节点域对抗训练(NodeDAT)基于情绪感知的分布学习(EmotionDL)的损失函数。

Figure 6.RGNN整体框架

    FC表示全链接的图层(fully-connected layer),CE表示交叉熵损失(cross-entropy loss),GRL是节点域对抗训练中采用的梯度反转层(GRL)具体后述会展开,KL表示Kullback-Leibler散度是我们情感分布学习中的模型函数。
    该整体框架表述的思想简而言之,就是对训练数据集(Training Samples)一方面采用分布学习计算损失函数,另一方面,训练数据集和训练测试集(Texting Samples)共同经过领域分类器即NodeDAT采用梯度反转层(GRL)计算可得其主损失函数和相关的分类标签。
    其伪代码如下:

Figure.7 RGNN的伪代码

    上面的伪代码有没有熟悉的感觉?对于变量的更新(update)与我们线性回归模型的梯度下降算法是不是很相似!梯度下降算法中的方括号部分内容正是对代价函数的求导,我们下面附上梯度下降算法在线性回归中的形式以供对比参考:
  Repeat{                        
               \Theta_{0}:=\Theta_{0}-\alpha\frac{1 }{m}\sum_{i=1}^{m}(h_{\Theta }(x^{(i)})-y^{(i)})x_{0}^{(i)}
               \Theta_{j}:=\Theta_{j}-\alpha[\frac{1 }{m}\sum_{i=1}^{m}(h_{\Theta }(x^{(i)}-y^{(i)})x_{j}^{(i)} +\frac{ \lambda }{m}\Theta_{j}]
                                     (j=1,2,3,4......,n)
        }
    我们可以看到还是RGNN的实现只不过在一般梯度下降算法中采用了结合两个代价函数的方法,即对13、14步中对W和A的更新是混合节点域对抗训练(NodeDAT)基于情绪感知的分布学习(EmotionDL)的损失函数的梯度,\beta表示节点域对抗训练中域分离器所使用梯度反转层(GRL)[注7]的比例因子。

[注 7]:梯度反转层是指在反向传播期间反转域分类器的梯度。
        节点域对抗训练就是一个域分类器。


    下面我们分别介绍节点域对抗训练(NodeDAT)基于情绪感知的分布学习(EmotionDL)。对于域分类器我们只写出其损失函数,不具体展开推导以及详细优势和实现过程,选择展开讲解情绪感知的分布学习。
    领域分类器的目标是最小化以下两个二进制交叉熵损失的总和:
            \Phi_{D}=-\sum_{i=1}^{N}\sum_{j=1}^{n}(log(p_{D}(0|X_{i}^{S})_{j}+log(p_{D}(1|X_{i}^{T})_{j}))
    其中,X^{S}表示给定源域数据,X^{T}表示未标记的目标域数据。


    在SEED与SEED-IV脑电图数据集上,分别可以划分为三类和四类情绪。SEED有积极、中性和消极三类情绪,并有相应的类指标分别是 0 1 2,将每个训练样本标签Y_{i}\in {0,1......,C-1}转化为所有类的先验概率分布\hat{Y}_{i}如下:
                    \hat{Y}_{i}=\left\{\begin{matrix} (1-\frac{2\epsilon }{3},\frac{2\epsilon }{3},0),Y_{i}=0\\ (\frac{\epsilon }{3},1-\frac{2\epsilon}{3},\frac{\epsilon }{3}),Y_{i}=1 \\ (0,\frac{2\epsilon }{3},1-\frac{2\epsilon }{3}),Y_{i}=2 \end{matrix}\right.
    其中,\epsilon \in[0,1]表示在训练标签中控制噪声水平的超参数。在SEED-IV的四类情绪分类的先验概率分布\hat{Y}_{i}与之类似,不再进行赘述。
    在得到转换后的类分布Y后,我们的模型可以通过最小化以下Kullback-Leibler (KL) 散度[注8]来进行优化:
                 {\Phi}'=\sum_{i=1}^{N}KL(p(Y|X_{i},\Theta),\hat{Y}_{I})+\alpha \left \| A \right \|_{1}

注8:  KL 散度(Kullback-Leibler Divergence)是一个用来衡量两个概率分布的相似性的一个度量指标。
    一般来说,我们无法获取数据的总体,我们只能拿到数据的部分样本,根据数据的部分样本,我们会对数据的整体做一个近似的估计,而数据整体本身有一个真实的分布(我们可能永远无法知道),那么近似估计的概率分布和数据整体真实的概率分布的相似度,或者说差异程度,可以用 KL 散度来表示。具体可以参考关于KL散度的CSDN博客


作者后记

    完成本篇文章耗时大概一周,文章写到后来尤其是关于应用文献部分很多没有再展开讲解,留下许多待展开的地方。也是本人的文献阅读能力囿于一定水平,参考了许多别人的资料才勉勉强强完成,也希望自己在未来的两三年水平真正有所长进,以本篇为始,只是向上走!!

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

推荐阅读更多精彩内容