142、机器学习之泰坦尼克号生存预测

本文是有关于在泰坦尼克号上的生存概率预测,这是基于Kaggle上的一个经典比赛项目,有兴趣的朋友可以去了解什么是Kaggle以及如何入门(<u>https://www.zhihu.com/question/23987009/answer/285179721</u>)。

在这次项目中,先在Kaggle上下载所需要的训练数据集和测试数据集,通过训练数据集分析什么类型的人能在这场灾难中生存下来,建立机器学习的模型,再使用这个模型预测测试数据集中所有人的生存情况。

本次项目属于一个典型的二分分类问题,采用逻辑回归的方法建立机器学习模型。

一、项目流程

  1. 提出问题

  2. 理解数据

a. 采集数据

b. 导入数据

c. 查看数据集信息

(describe描述统计信息,info发现缺失值)

  1. 数据清洗

a. 缺失值处理(缺失值填充fillna)

b. 特征提取(One-hot编码(get_dummies),map函数(Series))

c. 特征选择(相关系数法)

  1. 构建模型

a. 训练数据和测试数据:train_test_split

b. 机器学习算法:sklearn

c. 评估模型:score

  1. 方案实施

选取模型进行预测

二、项目具体实现过程

  1. 提出问题

电影《泰坦尼克号》是由真实事件改编的一部电影,讲述的是1912年4月10日,泰坦尼克号的处女航从英国南安普敦出发,计划驶往美国纽约。但在4月14日深夜,这艘堪称“世界上最大的不沉之船”不幸撞上北大西洋上漂浮的冰山而沉没,船上2208名旅客中,仅有705人生还,生还率不到32%,这也成为人类史上最大的海难之一。
导致这么多人遇难的原因之一是乘客和船员没有足够的救生艇。虽然幸存下来的人有运气成分存在,但有一些人比其他人更有可能生存,比如妇女、儿童和上层阶级。沉船前,除了杰克和露丝的爱情外,泰坦尼克号还经历了什么?
所以我们研究的问题是:什么样的人在泰坦尼克号中更容易存活?

  1. 理解数据

(1)采集数据

从Kaggle泰坦尼克号项目页面下载数据:<u>https://www.kaggle.com/c/titanic</u>

(2)导入数据

先导入numpy和pandas模块,并读取训练数据集和测试数据集,最后把两个数据集合并在一个数据集full,方便进行数据清洗:
1.导入数据.png

(3)查看数据集信息

以下是数据集中出现的一些变量名称及其含义:
2.各个变量名称及含义.jpg

数据类型一般划分为数值类型和分类数据两类,其中分类数据也分为有类别和字符串两种,下面是本文中出现的变量的数据类型划分结果:
3.数据类型.jpg

使用describe查看数据集描述统计信息,对整体数据有一个了解及分析:
4.查看数据集信息.png

使用info查看每一列的数据及数据类型,确定这些数据是否存在缺失值:
5.查看每一列数据.png

通过上面的结果发现数据总共有1390行,其中数值类型列:年龄(Age)、船舱号(Cabin)里面有较多缺失数据:

① 年龄(Age)里面数据总数是1046条,缺失了1309-1046=263,缺失率263/1309=20%;

② 船票价格(Fare)里面数据总数是1308条,缺失了1条数据;

字符串列:

③ 登船港口(Embarked)里面数据总数是1307,只缺失了2条数据,缺失比较少;

④ 客舱号(Cabin)里面数据总数是295,缺失了1309-295=1014,缺失率=1014/1309=77.5%,缺失比较大。

⑤ 生存情况(Survived)里面只有891条数据,这是因为只有训练数据集中才有Survived,通过训练数据集中Survived作为标签构建机器学习的模型,最终预测出测试数据集中的Survived情况,这也是本次项目的目的,所以不需要处理这一列的数据。

以上的结果为我们下一步数据清洗指明了方向,只有知道哪些数据缺失数据,我们才能有针对性的处理。

  1. 数据清洗

(1)处理缺失值

① 数值型缺失值处理

年龄(Age)和船票价格(Fare)都存在缺失值,且数据类型都为浮点型,可以使用平均值填充的方法填充缺失值,其中fillna表示数据填充的方法,mean表示使用平均值填充:
6.数值型缺失值处理.png

② 字符串类型缺失值处理

客舱号(Cabin)的数据类型为字符串,通过查看客舱号(Cabin)这一列的数据发现缺失数值较多,缺失率达到77.5%,且无规律可循,这里可以直接填充为U,表示未知(Unknown):
7.字符串类型缺失值处理.png

③ 有类别数据缺失值处理

登船港口(Embarked)属于有类别数据,共分为三类,从结果中可以看出这一列只有两个缺失值,可以使用最频繁出现的值填充:
8.有类别数据缺失值处理.png

最后使用info()函数查看最终缺失值处理情况:
9.查看最终缺失值处理情况.png

从结果中看出,所有缺失值已处理完成,接下来是提取特征。

(2)特征提取

什么是特征工程?

特征工程指的是最大限度地从原始数据中提取特征,以供机器学习算法和模型使用。

特征工程处理方法:
10.特征工程处理方法.jpg

特征提取方法:
11.特征提取方法.jpg

这里主要利用One-host的方法对特征值进行分类提取。

提取性别(Sex)的特征值:
12.提取性别(Sex)的特征值.png

提取登船港口(Embarked)的特征值:
13.提取登船港口(Embarked)的特征值.png

提取客舱等级(Pclass)的特征值:
14.提取客舱等级(Pclass)的特征值.png

从姓名(Name)中提取头衔的特征值:
15.提取姓名(Name)的特征值-1.png
16.提取姓名(Name)的特征值-2 .png

提取客舱号(Cabin)的特征值:
17.提取客舱号(Cabin)的特征值.png

提取家庭类别的特征值:
18.提取家庭类别的特征值.png

提取年龄(Age)的特征值:
19.提取年龄(Age)的特征值.png

最后查看现在已有的特征:
20.查看现在已有的特征.png
21.查看现在已有的特征-2.png

(3)特征选择

通过计算各个特征与标签的相关系数,进行特征选择,先求出相关性矩阵:
22.相关性矩阵.png

查看各个特征与生成情况(Survived)的相关系数:
23.查看各个特征与生成情况(Survived)的相关系数.png

根据各个特征与生存情况(Survived)的相关系数大小,选择以下几个特征作为模型的输入:

头衔(titleDf)、客舱等级(pclassDf)、家庭大小(familyDf)、船票价格(Fare)、性别(Sex)、客舱号(cabinDf)、登船港口(embarkdeDf)
24.特征选择.png
  1. 构建模型

使用训练数据和机器学习算法得到一个机器学习模型,再使用测试数据评估模型

(1)建立训练数据集和测试数据集

① 坦尼克号测试数据集因为是我们最后要提交给Kaggle的,里面没有生存情况的值,所以不能用于评估模型。

我们将Kaggle泰坦尼克号项目给我们的测试数据,叫做预测数据集(记为pred,也就是预测英文单词predict的缩写)。也就是我们使用机器学习模型来对其生存情况就那些预测。使用Kaggle泰坦尼克号项目给的训练数据集,做为我们的原始数据集(记为source):
25.构建模型.jpg
26.建立原始数据集和预测数据集.png

② 从原始数据集(source)中拆分出训练数据集(记为train:用于模型训练)和测试数据集(记为test:用于模型评估):
27.建立训练数据集和测试数据集.png

③ 查看原始数据集标签:
28.查看数据集标签.png

(2)选择机器学习算法

根据之前筛选出的特征值,选择逻辑回归(Logistic Regression)算法训练模型:
29.选择逻辑回归(Logistic Regression)算法.png

(3)训练模型
30.训练模型.png

(4)评估模型

逻辑回归属于分类问题,使用score得到模型正确率:
31.评估模型.png

从结果中可以看到,模型的正确率为84.92%,正确率还是很高的,接下来使用这个模型预测在预测数据集中的生存率。

  1. 实施方案

使用预测数据集进行预测结果,并保存到csv文件中,最后上传到Kaggle中:
32.使用预测数据集进行预测结果.png

保存的csv文件:
33.保存的CSV文件.png

总结

通过这个泰坦尼克号生存预测项目的练习,我从中学到的两点:

一、理解机器学习整个过程,尤其是提取特征时使用One-hot编码(get_dummies)对特征的处理以及机器学习算法的运用;

二、利用kaggle平台学习别人的代码,体会其中的思路,完善自身的不足,提高自学效率。

源码:


**# coding: utf-8**

**# ## 1、导入数据**

**# In[1]:**

**import numpy as np**

**import pandas as pd**

**# In[2]:**

**# 读取训练数据集**

**train = pd.read_csv('D:/Python/notebook/train.csv')**

**# 读取测试数据集**

**test = pd.read_csv('D:/Python/notebook/test.csv')**

**print('训练数据集',train.shape,'测试数据集',test.shape)**

**# In[3]:**

**# 合并数据集,方便同时对两个数据集进行清洗**

**full = train.append(test,ignore_index=True)**

**print('合并后的数据集',full.shape)**

**# ## 2、查看数据集信息**

**# In[4]:**

**# 查看数据**

**full.head()**

**# In[5]:**

**# 获取数据类型列的描述统计信息**

**full.describe()**

**# In[6]:**

**# 查看每一列的数据类型,和数据总数**

**full.info()**

**# ## 3、数据清洗**

**# ### (1)处理缺失值**

**# 数值型缺失值处理**

**# In[7]:**

**'''**

**年龄(Age)和船票价格(Fare)存在缺失值且都为浮点型数据,**

**可以使用平均值填充的方法填充缺失值**

**'''**

**# 年龄(Age)**

**full['Age'] = full['Age'].fillna(full['Age'].mean())**

**# 船票价格(Fare)**

**full['Fare'] = full['Fare'].fillna(full['Fare'].mean())**

**# 字符串类型缺失值处理**

**# In[8]:**

**# 填充客舱号(Cabin),先查看里面的数据**

**full['Cabin'].head()**

**# In[9]:**

**'''**

**客舱号(Cabin)这一列缺失数值较多且无规律可循,**

**直接填充为U,表示未知(Unknown)**

**'''**

**full['Cabin'] = full['Cabin'].fillna('U')**

**# 有类别数据缺失值处理**

**# In[10]:**

**'''**

**先查看 前5行的信息,看看数据的样子**

**出发地点:S=英国 南安普顿Southampton**

**途径地点1:C=法国 瑟堡市Cherbourg**

**途径地点2:Q=爱尔兰 昆士敦Queenstown**

**'''**

**full['Embarked'].head()**

**# In[11]:**

**'''**

**由前面的信息可知,登船港口(Embarked)这一列只有两个缺失值,**

**将缺失值填充为最频繁出现的值:S=英国 南安普顿Southampton**

**'''**

**full['Embarked'] = full['Embarked'].fillna('S')**

**# In[12]:**

**# 查看最终缺失值处理情况**

**full.info()**

**# ### (2)特征提取**

**# #### a.分类数据特征提取:性别**

**# In[13]:**

**'''**

**将性别的值映射为数值**

**男(male)对应数值 1**

**女(female)对应数值 0**

**'''**

**sex_mapDict = {'male':1,**

**               'female':0}**

**# map函数:对于Series每个数据应用自定义函数计算**

**full['Sex'] = full['Sex'].map(sex_mapDict)**

**full.head()**

**# #### b.分类数据特征提取:登船港口**

**# In[14]:**

**# 查看该类数据内容**

**full['Embarked'].head()**

**# In[15]:**

**# 存放提取后的特征**

**embarkedDf = pd.DataFrame()**

**# 使用get_dummies进行one-hot编码,列名前缀为Embarked**

**embarkedDf = pd.get_dummies(full['Embarked'],prefix='Embarked')**

**embarkedDf.head()**

**# In[16]:**

**# 添加one-hot编码产生的虚拟变量(dummy variables)到泰坦尼克号数据集full**

**full = pd.concat([full,embarkedDf],axis=1)**

**'''**

**因为已经使用登船港口(embarkedDf)进行了one-hot编码产生虚拟变量(dummy variables)**

**所以这里把登船港口(embarkedDf)删除**

**'''**

**full.drop('Embarked',axis=1,inplace=True)**

**full.head()**

**# #### c.分类数据特征提取:客舱等级**

**# In[17]:**

**# 存放提取后的特征**

**pclassDf = pd.DataFrame()**

**# 使用get_dummies进行one-hot编码,列名前缀为Pclass**

**pclassDf = pd.get_dummies(full['Pclass'],prefix='Pclass')**

**pclassDf.head()**

**# In[18]:**

**# 添加one-hot编码产生的虚拟变量(dummy variables)到泰坦尼克号数据集full**

**full = pd.concat([full,pclassDf],axis=1)**

**# 删除客舱等级(Pclass)这一列**

**full.drop('Pclass',axis=1,inplace=True)**

**full.head()**

**# #### d.分类数据特征提取:姓名**

**# In[19]:**

**full['Name'].head()**

**# In[20]:**

**# 定义函数: 从姓名中获取头衔**

**# split()通过指定分隔符对字符串进行切片**

**def getTitle(name):           # Braund, Mr. Owen Harris**

**    str1 = name.split(',')[1] # Mr. Owen Harris**

**    str2 = str1.split('.')[0] # Mr**

**    # strip()方法用于移除字符串头尾指定的字符(默认为空格)**

**    str3 = str2.strip()**

**    return str3**

**# 存放提取后的特征**

**titleDf = pd.DataFrame()**

**# map函数:对于Series每个数据应用自定义函数计算**

**titleDf['Title'] = full['Name'].map(getTitle)**

**titleDf.head()**

**# In[21]:**

**# 姓名中头衔字符串与定义头衔类别的映射关系**

**title_mapDict = {**

**    'Capt':        'Officer',**

**    'Col':         'Officer',**

**    'Major':       'Officer',**

**    'Jonkheer':    'Royalty',**

**    'Don':         'Royalty',**

**    'Sir':         'Royalty',**

**    'Dr':          'Officer',**

**    'Rev':         'Officer',**

**    'the Countess':'Royalty',**

**    'Dona':        'Royalty',**

**    'Mme':         'Mrs',**

**    'Mlle':        'Miss',**

**    'Ms':          'Mrs',**

**    'Mr':          'Mr',**

**    'Mrs':         'Mrs',**

**    'Miss':        'Miss',**

**    'Master':      'Master',**

**    'Lady':        'Royalty'**

**}**

**# map函数:对于Series每个数据应用自定义函数计算**

**titleDf['Title'] = titleDf['Title'].map(title_mapDict)**

**# 使用get_dummies进行one-hot编码**

**titleDf = pd.get_dummies(titleDf['Title'])**

**titleDf.head()**

**# In[22]:**

**# 添加one-hot编码产生的虚拟变量(dummy variables)到泰坦尼克号数据集full**

**full = pd.concat([full,titleDf],axis=1)**

**# 删除姓名(Name)这一列**

**full.drop('Name',axis=1,inplace=True)**

**full.head()**

**# #### e.分类数据特征提取:客舱号**

**# In[23]:**

**full['Cabin'].head()**

**# In[24]:**

**# 存放客舱号信息**

**cabinDf = pd.DataFrame()**

**'''**

**客舱号的类别值是首字母,例如:**

**C85 类别映射为首字母C**

**'''**

**full['Cabin'] = full['Cabin'].map(lambda c:c[0]) # 定义匿名函数lambda,用于查找首字母**

**# 使用get_dummies进行one-hot编码,列名前缀为Cabin**

**cabinDf = pd.get_dummies(full['Cabin'],prefix='Cabin')**

**cabinDf.head()**

**# In[25]:**

**# 添加one-hot编码产生的虚拟变量(dummy variables)到泰坦尼克号数据集full**

**full = pd.concat([full,cabinDf],axis=1)**

**# 删除客舱号(Cabin)这一列**

**full.drop('Cabin',axis=1,inplace=True)**

**full.head()**

**# #### f.分类数据特征提取:家庭类别**

**# In[26]:**

**# 存放家庭信息**

**familyDf = pd.DataFrame()**

**'''**

**家庭人数 = 同代直系亲属数(SibSp)+ 不同代直系亲属数(Parch)+ 乘客自己**

**(乘客自己也属于家庭成员一个,所以要加1)**

**'''**

**familyDf['Familysize'] = full['SibSp'] + full['Parch'] + 1**

**'''**

**家庭类别:**

**小家庭Family_Single:家庭人数=1**

**中等家庭Family_Small:2<=家庭人数<=4**

**大家庭Family_Large:家庭人数>=5**

**'''**

**# if条件为真时返回if前面内容,否则返回0**

**familyDf['Family_Single'] = familyDf['Familysize'].map(lambda s: 1 if s==1 else 0)**

**familyDf['Family_Small']  = familyDf['Familysize'].map(lambda s: 1 if 2 <= s <= 4 else 0)**

**familyDf['Family_Large']  = familyDf['Familysize'].map(lambda s: 1 if 5 <= s else 0)**

**familyDf.head()**

**# In[27]:**

**# 添加one-hot编码产生的虚拟变量(dummy variables)到泰坦尼克号数据集full**

**full = pd.concat([full,familyDf],axis=1)**

**full.head()**

**# #### g.分类数据特征提取:年龄**

**# In[28]:**

**# 存放年龄信息**

**ageDf = pd.DataFrame()**

**'''**

**年龄类别:**

**儿童Child:0<年龄<=6**

**青少年Teenager:6<年龄<18**

**青年Youth:18<=年龄<=40**

**中年Middle_aged:40<年龄<=60**

**老年Older:60<年龄**

**'''**

**# if条件为真时返回if前面内容,否则返回0**

**ageDf['Child']       = full['Age'].map(lambda a: 1 if 0 < a <= 6 else 0)**

**ageDf['Teenager']    = full['Age'].map(lambda a: 1 if 6 < a < 18 else 0)**

**ageDf['Youth']       = full['Age'].map(lambda a: 1 if 18 <= a <= 40 else 0)**

**ageDf['Middle_aged'] = full['Age'].map(lambda a: 1 if 40 < a <= 60 else 0)**

**ageDf['Older']       = full['Age'].map(lambda a: 1 if 60 < a else 0)**

**ageDf.head()**

**# In[29]:**

**# 添加one-hot编码产生的虚拟变量(dummy variables)到泰坦尼克号数据集full**

**full = pd.concat([full,ageDf],axis=1)**

**# 删除年龄(Age)这一列**

**full.drop('Age',axis=1,inplace=True)**

**full.head()**

**# In[30]:**

**# 查看现在已有的特征**

**full.shape**

**# ### (3)特征选择**

**# 相关性矩阵**

**# In[31]:**

**# 相关性矩阵**

**corrDf = full.corr()**

**corrDf**

**# In[32]:**

**'''**

**查看各个特征与生成情况(Survived)的相关系数,**

**ascending = False 表示按降序排列**

**'''**

**corrDf['Survived'].sort_values(ascending = False)**

**# 根据各个特征与生存情况(Survived)的相关系数大小,选择以下几个特征作为模型的输入:**

**# 头衔(titleDf)、客舱等级(pclassDf)、家庭大小(familyDf)、船票价格(Fare)、性别(Sex)、客舱号(cabinDf)、登船港口(embarkdeDf)**

**# In[33]:**

**# 特征选择**

**full_X = pd.concat([titleDf,     # 头衔**

**                    pclassDf,    # 客舱等级**

**                    familyDf,    # 家庭大小**

**                    full['Fare'],# 船票价格**

**                    full['Sex'], # 性别**

**                    cabinDf,     # 客舱号**

**                    embarkedDf   # 登场港口**

**                   ],axis=1)**

**full_X.head()**

**# ## 4、构建模型**

**# 使用训练数据和机器学习算法得到一个机器学习模型,再使用测试数据评估模型**

**# ### (1)建立训练数据集和测试数据集**

**# In[34]:**

**# 原始数据共有891行**

**sourceRow = 891**

**'''**

**原始数据集sourceRow是从Kaggle下载的训练数据集,可知共有891条数据**

**从特征集合full_X中提取原始数据集前891行数据时需要减去1,因为行号是从0开始**

**'''**

**# 原始数据集:特征**

**source_X = full_X.loc[0:sourceRow-1,:]**

**# 原始数据集:标签**

**source_y = full.loc[0:sourceRow-1,'Survived']**

**# 测预测数据集:特征**

**pred_X = full_X.loc[sourceRow:,:]**

**# In[35]:**

**# 查看原始数据集有多少行**

**print('原始数据集有多少行:',source_X.shape[0])**

**# 查看预测数据集有多少行**

**print('预测数据集有多少行:',pred_X.shape[0])**

**# In[36]:**

**'''**

**从原始数据集(source)中拆分出用于模型训练的训练数据集(train),用于评估模型的测试数据集(test)**

**train_test_split:是交叉验证中常用的函数,功能是从样本中随机按比例选取train data和test data**

**train_data:所要划分的样本特征集**

**train_target:所要划分的样本结果**

**train_size:样本占比,如果为整数则是样本的数量**

**'''**

**from sklearn.cross_validation import train_test_split**

**# 建立模型所需的训练数据集和测试数据集**

**train_X,test_X,train_y,test_y = train_test_split(source_X,source_y,train_size=0.8)**

**# 输出数据集大小**

**print('原始数据集特征',source_X.shape,**

**      '训练数据集特征',train_X.shape,**

**      '测试数据集特征',test_X.shape)**

**print('原始数据集标签',source_y.shape,**

**      '训练数据集标签',train_y.shape,**

**      '测试数据集标签',test_y.shape)**

**# In[37]:**

**# 查看原始数据集标签**

**source_y.head()**

**# ### (2)选择机器学习算法**

**# 选择一个机器学习算法,用于模型训练,这里选择逻辑回归(logisic regression)**

**# In[38]:**

**# 第1步:导入算法**

**from sklearn.linear_model import LogisticRegression**

**# 第2步:创建模型:逻辑回归(logisic regression)**

**model = LogisticRegression()**

**# In[39]:**

**# 随机森林Random Forests Model**

**#from sklearn.ensemble import RandomForestClassifier**

**#model = RandomForestClassifier(n_estimators=100)**

**#0.7765**

**# In[40]:**

**# 支持向量机Support Vector Machines**

**#from sklearn.svm import SVC,LinearSVC**

**#model = SVC()**

**#0.78**

**# In[41]:**

**# Gradient Boosting Classifier**

**#from sklearn.ensemble import GradientBoostingClassifier**

**#model = GradientBoostingClassifier()**

**#0.81**

**# In[42]:**

**#K-nearest neighbors**

**#from sklearn.neighbors import KNeighborsClassifier**

**#model = KNeighborsClassifier(n_neighbors = 3)**

**#0.75**

**# In[43]:**

**# 朴素贝叶斯Gaussian Naive Bayes**

**#from sklearn.naive_bayes import GaussianNB**

**#model = GaussianNB()**

**#0.81**

**# ### (3)训练模型**

**# In[44]:**

**# 第3步:训练模型**

**model.fit(train_X,train_y)**

**# ### (4)评估模型**

**# In[45]:**

**# 分类问题,score得到的是模型正确率**

**model.score(test_X,test_y)**

**# ## 5、实施方案**

**# 使用预测数据集进行预测结果,并保存到csv文件中,最后上传到Kaggle中**

**# In[46]:**

**# 使用机器学习模型,对预测数据集中的生存情况进行预测**

**pred_y = model.predict(pred_X)**

**'''**

**生成的预测值是浮点数(0.0,1.0)**

**但是Kaggle要求提交的结果是整型(0,1)**

**使用astype对数据类型进行转换**

**'''  **

**pred_y = pred_y.astype(int)**

**# 乘客id**

**passenger_id = full.loc[sourceRow:,'PassengerId']**

**# 数据框:乘客id,预测生存情况**

**predDf = pd.DataFrame({'PassengerId':passenger_id, 'Survived':pred_y})**

**predDf.shape**

**predDf.head()**

**# In[47]:**

**# 保存结果**

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

推荐阅读更多精彩内容