深度框架 MXNet/Gluon 初體驗(yàn)

MXNet: A flexible and efficient library for deep learning.

這是MXNet的官網(wǎng)介紹泉手,“MXNet是靈活且高效的深度學(xué)習(xí)庫(kù)”。

歡迎Follow我的GitHubhttps://github.com/SpikeKing

MXNet

MXNet是主流的三大深度學(xué)習(xí)框架之一:

  • TensorFlow:Google支持拓售,其簡(jiǎn)化版是Keras
  • PyTorch:Facebook支持,其工業(yè)版是Caffe2
  • MXNet:中立发魄,Apache孵化器項(xiàng)目,也被AWS選為官方DL平臺(tái)俩垃;

MXNet的優(yōu)勢(shì)是励幼,其開(kāi)發(fā)者之一李沐,是中國(guó)人????口柳,在MXNet的推廣中具有語(yǔ)言優(yōu)勢(shì)(漢語(yǔ))苹粟,有利于國(guó)內(nèi)開(kāi)發(fā)者的學(xué)習(xí)。同時(shí)跃闹,推薦李沐錄制的教學(xué)視頻嵌削,非常不錯(cuò)。

MXNet的高層接口是Gluon望艺,Gluon同時(shí)支持靈活的動(dòng)態(tài)圖和高效的靜態(tài)圖苛秕,既保留動(dòng)態(tài)圖的易用性,也具有靜態(tài)圖的高性能找默,這也是官網(wǎng)介紹的flexibleefficient的出處艇劫。同時(shí),MXNet還具備大量學(xué)術(shù)界的前沿算法惩激,方便移植至工業(yè)界店煞。希望MXNet團(tuán)隊(duì)再接再勵(lì),在深度學(xué)習(xí)框架的競(jìng)賽中咧欣,位于前列浅缸。

因此轨帜,掌握 MXNet/Gluon 很有必要魄咕。

本文以深度學(xué)習(xí)的多層感知機(jī)(Multilayer Perceptrons)為算法基礎(chǔ),數(shù)據(jù)集選用MNIST蚌父,介紹MXNet的工程細(xì)節(jié)哮兰。

本文的源碼https://github.com/SpikeKing/gluon-tutorial


數(shù)據(jù)集

在虛擬環(huán)境(Virtual Env)中毛萌,直接使用pip安裝MXNet即可:

pip install mxnet

如果下載速度較慢,推薦使用阿里云的pypi源:

-i http://mirrors.aliyun.com/pypi/simple --trusted-host mirrors.aliyun.com

MNIST就是著名的手寫(xiě)數(shù)字識(shí)別庫(kù)喝滞,其中包含0至9等10個(gè)數(shù)字的手寫(xiě)體阁将,圖片大小為28*28的灰度圖,目標(biāo)是根據(jù)圖片識(shí)別正確的數(shù)字右遭。

MNIST庫(kù)在MXNet中被封裝為MNIST類做盅,數(shù)據(jù)存儲(chǔ)于.mxnet/datasets/mnist中。如果下載MNIST數(shù)據(jù)較慢窘哈,可以選擇到MNIST官網(wǎng)下載吹榴,放入mnist文件夾中即可。在MNIST類中:

  • 參數(shù)train:是否為訓(xùn)練數(shù)據(jù)滚婉,其中true是訓(xùn)練數(shù)據(jù)图筹,false是測(cè)試數(shù)據(jù);
  • 參數(shù)transform:數(shù)據(jù)的轉(zhuǎn)換函數(shù)让腹,lambda表達(dá)式远剩,轉(zhuǎn)換數(shù)據(jù)和標(biāo)簽為指定的數(shù)據(jù)類型;

源碼:

# 參數(shù)train
if self._train:
    data, label = self._train_data, self._train_label
else:
    data, label = self._test_data, self._test_label
    
# 參數(shù)transform
if self._transform is not None:
    return self._transform(self._data[idx], self._label[idx])
return self._data[idx], self._label[idx]

在MXNet中骇窍,數(shù)據(jù)加載類被封裝成DataLoader類瓜晤,迭代器模式,迭代輸出與批次數(shù)相同的樣本集像鸡。在DataLoader中活鹰,

  • 參數(shù)dataset:數(shù)據(jù)源,如MNIST只估;
  • 參數(shù)batch_size:訓(xùn)練中的批次數(shù)量志群,在迭代中輸出指定數(shù)量的樣本;
  • 參數(shù)shuffle:是否洗牌蛔钙,即打亂數(shù)據(jù)锌云,一般在訓(xùn)練時(shí)需要此操作。

迭代器的測(cè)試吁脱,每次輸出樣本個(gè)數(shù)(第1維)與指定的批次數(shù)量相同:

for data, label in train_data:
    print(data.shape)  # (64L, 28L, 28L, 1L)
    print(label.shape)  # (64L,)
    break

load_data()方法中桑涎,輸出訓(xùn)練和測(cè)試數(shù)據(jù),數(shù)據(jù)類型是0~1(灰度值除以255)的浮點(diǎn)數(shù)兼贡,標(biāo)簽類型也是浮點(diǎn)數(shù)攻冷。

具體實(shí)現(xiàn):

def load_data(self):
    def transform(data, label):
        return data.astype(np.float32) / 255., label.astype(np.float32)
    train_data = DataLoader(MNIST(train=True, transform=transform),
                            self.batch_size, shuffle=True)
    test_data = DataLoader(MNIST(train=False, transform=transform),
                           self.batch_size, shuffle=False)
    return train_data, test_data

模型

網(wǎng)絡(luò)模型使用MXNet中Gluon的樣式:

  1. 創(chuàng)建Sequential()序列,Sequential是全部操作單元的容器遍希;
  2. 添加全連接單元Dense等曼,參數(shù)units是輸出單元的個(gè)數(shù),參數(shù)activation是激活函數(shù);
  3. 初始化參數(shù):
    • init是數(shù)據(jù)來(lái)源禁谦,Normal類即正態(tài)分布胁黑,sigma是正態(tài)分布的標(biāo)準(zhǔn)差;
    • ctx是上下文州泊,表示訓(xùn)練中參數(shù)更新使用CPU或GPU丧蘸,如mx.cpu();

Gluon的Sequential類與其他的深度學(xué)習(xí)框架類似遥皂,通過(guò)有序地連接不同的操作單元力喷,組成不同的網(wǎng)絡(luò)結(jié)構(gòu),每一層只需設(shè)置輸出的維度演训,輸入維度通過(guò)上一層傳遞冗懦,轉(zhuǎn)換矩陣在內(nèi)部自動(dòng)計(jì)算。

實(shí)現(xiàn):

def model(self):
    num_hidden = 64
    net = gluon.nn.Sequential()
    with net.name_scope():
        net.add(gluon.nn.Dense(units=num_hidden, activation="relu"))
        net.add(gluon.nn.Dense(units=num_hidden, activation="relu"))
        net.add(gluon.nn.Dense(units=self.num_outputs))

    net.collect_params().initialize(init=mx.init.Normal(sigma=.1), ctx=self.model_ctx)
    print(net)  # 展示模型
    return net

其中仇祭,net.name_scope()為Sequential中的操作單元自動(dòng)添加名稱披蕉。

模型可視化

直接使用print(),打印模型結(jié)構(gòu)乌奇,如print(net)

Sequential(
  (0): Dense(None -> 64, Activation(relu))
  (1): Dense(None -> 64, Activation(relu))
  (2): Dense(None -> 10, linear)
)

或没讲,使用稍復(fù)雜的jupyter繪制模型,安裝jupyter包(Python 2.x):

pip install ipython==5.3.0
pip install jupyter==1.0.0

啟動(dòng)jupyter服務(wù)礁苗,訪問(wèn)http://localhost:8888/

jupyter notebook

新建Python 2文件爬凑,編寫(xiě)繪制網(wǎng)絡(luò)的代碼。代碼的樣式是试伙,在已有模型之后嘁信,添加“繪制邏輯”,調(diào)用plot_network()即可繪圖疏叨。如果替換Sequential類為HybridSequential類潘靖,可以提升繪制效率,不替換也不會(huì)影響繪制效果

網(wǎng)絡(luò)模型和繪制邏輯:

import mxnet as mx
from mxnet import gluon

num_hidden = 64
net = gluon.nn.HybridSequential()
with net.name_scope():
    net.add(gluon.nn.Dense(num_hidden, activation="relu"))
    net.add(gluon.nn.Dense(num_hidden, activation="relu"))
    net.add(gluon.nn.Dense(10))

# 繪制邏輯
net.hybridize()
net.collect_params().initialize()
x = mx.sym.var('data')
sym = net(x)
mx.viz.plot_network(sym)

效果圖:

模型

訓(xùn)練

在訓(xùn)練前蚤蔓,加載數(shù)據(jù)卦溢,創(chuàng)建網(wǎng)絡(luò)。

train_data, test_data = self.load_data()  # 訓(xùn)練和測(cè)試數(shù)據(jù)
net = self.model()  # 模型

接著秀又,創(chuàng)建交叉熵的接口softmax_cross_entropy单寂,創(chuàng)建訓(xùn)練器trainer

訓(xùn)練器的參數(shù)包含:網(wǎng)絡(luò)中參數(shù)吐辙、優(yōu)化器宣决、優(yōu)化器的參數(shù)等。

epochs = 10
smoothing_constant = .01
num_examples = 60000

softmax_cross_entropy = gluon.loss.SoftmaxCrossEntropyLoss()  # 交叉熵
trainer = gluon.Trainer(params=net.collect_params(),
                        optimizer='sgd',
                        optimizer_params={'learning_rate': smoothing_constant})

循環(huán)epoch訓(xùn)練網(wǎng)絡(luò)模型:

  1. 從迭代器train_data源中昏苏,獲取批次數(shù)據(jù)和標(biāo)簽:
  2. 指定數(shù)據(jù)和標(biāo)簽的執(zhí)行環(huán)境ctx是CPU或GPU尊沸,同時(shí)展開(kāi)數(shù)據(jù)為1行昵时;
  3. 自動(dòng)梯度計(jì)算autograd.record(),網(wǎng)絡(luò)預(yù)測(cè)數(shù)據(jù)椒丧,輸出output,計(jì)算交叉熵loss救巷;
  4. 對(duì)于loss反向傳播求導(dǎo)壶熏,設(shè)置訓(xùn)練器trainer的步驟為批次數(shù);
  5. cumulative_loss中浦译,累加每個(gè)批次的損失loss棒假,計(jì)算全部損失;
  6. 在訓(xùn)練一次epoch之后精盅,計(jì)算測(cè)試和訓(xùn)練數(shù)據(jù)的準(zhǔn)確率accuracy帽哑;

不斷循環(huán),直至執(zhí)行完成全部epochs為止叹俏。

訓(xùn)練的實(shí)現(xiàn):

for e in range(epochs):
    cumulative_loss = 0  # 累積的
    for i, (data, label) in enumerate(train_data):
        data = data.as_in_context(self.model_ctx).reshape((-1, 784))  # 數(shù)據(jù)
        label = label.as_in_context(self.model_ctx)  # 標(biāo)簽

        with autograd.record():  # 梯度
            output = net(data)  # 輸出
            loss = softmax_cross_entropy(output, label)  # 輸入和輸出計(jì)算loss

        loss.backward()  # 反向傳播
        trainer.step(data.shape[0])  # 設(shè)置trainer的step
        cumulative_loss += nd.sum(loss).asscalar()  # 計(jì)算全部損失

    test_accuracy = self.__evaluate_accuracy(test_data, net)
    train_accuracy = self.__evaluate_accuracy(train_data, net)
    print("Epoch %s. Loss: %s, Train_acc %s, Test_acc %s" %
          (e, cumulative_loss / num_examples, train_accuracy, test_accuracy))

在預(yù)測(cè)接口evaluate_accuracy()中:

  1. 創(chuàng)建準(zhǔn)確率Accuracy類acc妻枕,用于統(tǒng)計(jì)準(zhǔn)確率;
  2. 迭代輸出批次的數(shù)據(jù)和標(biāo)簽粘驰;
  3. 預(yù)測(cè)數(shù)據(jù)不同類別的概率屡谐,選擇最大概率(argmax)做為類別;
  4. 通過(guò)acc.update()更新準(zhǔn)確率蝌数;

最終返回準(zhǔn)確率的值愕掏,即acc的第2維acc[1],而acc的第1維acc[0]是acc的名稱顶伞。

def __evaluate_accuracy(self, data_itertor, net):
    acc = mx.metric.Accuracy()  # 準(zhǔn)確率
    for i, (data, label) in enumerate(data_iterator):
        data = data.as_in_context(self.model_ctx).reshape((-1, 784))
        label = label.as_in_context(self.model_ctx)
        output = net(data)  # 預(yù)測(cè)結(jié)果
        predictions = nd.argmax(output, axis=1)  # 類別
        acc.update(preds=predictions, labels=label)  # 更新概率和標(biāo)簽
    return acc.get()[1]  # 第1維是數(shù)據(jù)名稱饵撑,第2維是概率

效果:

Epoch 0. Loss: 1.2743850797812144, Train_acc 0.846283333333, Test_acc 0.8509
Epoch 1. Loss: 0.46071574948628746, Train_acc 0.884366666667, Test_acc 0.8892
Epoch 2. Loss: 0.37149955205917357, Train_acc 0.896466666667, Test_acc 0.9008
Epoch 3. Loss: 0.3313815038919449, Train_acc 0.908366666667, Test_acc 0.9099
Epoch 4. Loss: 0.30456133014361064, Train_acc 0.915966666667, Test_acc 0.9172
Epoch 5. Loss: 0.2827877395868301, Train_acc 0.919466666667, Test_acc 0.9214
Epoch 6. Loss: 0.2653073514064153, Train_acc 0.925433333333, Test_acc 0.9289
Epoch 7. Loss: 0.25018166739145914, Train_acc 0.92965, Test_acc 0.9313
Epoch 8. Loss: 0.23669789231618246, Train_acc 0.933816666667, Test_acc 0.9358
Epoch 9. Loss: 0.22473177655935286, Train_acc 0.934716666667, Test_acc 0.9337

GPU

對(duì)于深度學(xué)習(xí)而言,使用GPU可以加速網(wǎng)絡(luò)的訓(xùn)練過(guò)程唆貌,MXNet同樣支持使用GPU訓(xùn)練網(wǎng)絡(luò)滑潘。

檢查服務(wù)器的Cuda版本,命令:nvcc --version锨咙,用于確定下載MXNet的GPU版本众羡。

nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2016 NVIDIA Corporation
Built on Sun_Sep__4_22:14:01_CDT_2016
Cuda compilation tools, release 8.0, V8.0.44

則,當(dāng)前服務(wù)器的Cuda版本是8.0蓖租。

將MXNet由CPU版本轉(zhuǎn)為GPU版本粱侣,卸載mxnet,安裝mxnet-cu80蓖宦。

pip uninstall mxnet
pip install mxnet-cu80

當(dāng)安裝完成GPU版本之后齐婴,在Python Console中,執(zhí)行如下代碼稠茂,確認(rèn)MXNet的GPU庫(kù)可以使用柠偶。

>>> import mxnet as mx
>>> a = mx.nd.ones((2, 3), mx.gpu())
>>> b = a * 2 + 1
>>> b.asnumpy()
array([[ 3.,  3.,  3.],
       [ 3.,  3.,  3.]], dtype=float32)

檢查GPU數(shù)量情妖,命令:nvidia-smi

+-----------------------------------------------------------------------------+
| NVIDIA-SMI 375.26                 Driver Version: 375.26                    |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  TITAN X (Pascal)    Off  | 0000:02:00.0     Off |                  N/A |
| 28%   49C    P2    84W / 250W |  12126MiB / 12189MiB |     25%      Default |
+-------------------------------+----------------------+----------------------+
|   1  TITAN X (Pascal)    Off  | 0000:03:00.0     Off |                  N/A |
| 24%   39C    P2    57W / 250W |  12126MiB / 12189MiB |     33%      Default |
+-------------------------------+----------------------+----------------------+
|   2  TITAN X (Pascal)    Off  | 0000:83:00.0     Off |                  N/A |
| 25%   41C    P2    58W / 250W |  12126MiB / 12189MiB |     37%      Default |
+-------------------------------+----------------------+----------------------+
|   3  TITAN X (Pascal)    Off  | 0000:84:00.0     Off |                  N/A |
| 23%   31C    P2    53W / 250W |  11952MiB / 12189MiB |      2%      Default |
+-------------------------------+----------------------+----------------------+

則,當(dāng)前服務(wù)器的GPU數(shù)量是4诱担。

設(shè)置參數(shù)環(huán)境ctx為GPU的列表毡证,即[mx.gpu(0), mx.gpu(1), ...]

GPU_COUNT = 4
ctx = [mx.gpu(i) for i in range(GPU_COUNT)]

在網(wǎng)絡(luò)net中使用GPU初始化initialize()參數(shù)params蔫仙,然后創(chuàng)建trainer訓(xùn)練器料睛。

net = self.model()  # 模型
net.collect_params().initialize(init=mx.init.Normal(sigma=.1), ctx=ctx)

smoothing_constant = .01
trainer = gluon.Trainer(params=net.collect_params(),
                        optimizer='sgd',
                        optimizer_params={'learning_rate': smoothing_constant})

循環(huán)執(zhí)行10個(gè)epoch訓(xùn)練模型,train_datavalid_data是迭代器摇邦,每次輸出一個(gè)batch樣本集恤煞。在train_batch()中,依次傳入批次數(shù)據(jù)batch施籍、GPU環(huán)境列表ctx居扒、網(wǎng)絡(luò)net和訓(xùn)練器trainer;在valid_batch()中丑慎,與訓(xùn)練類似喜喂,只是不傳訓(xùn)練器trainer。

epochs = 10
for e in range(epochs):
    start = time()
    for batch in train_data:
        self.train_batch(batch, ctx, net, trainer)
    nd.waitall()  # 等待所有異步的任務(wù)都終止
    print('Epoch %d, training time = %.1f sec' % (e, time() - start))
    correct, num = 0.0, 0.0
    for batch in valid_data:
        correct += self.valid_batch(batch, ctx, net)
        num += batch[0].shape[0]
    print('\tvalidation accuracy = %.4f' % (correct / num))

具體分析批次訓(xùn)練方法train_batch()

  1. 輸入batch是數(shù)據(jù)和標(biāo)簽的集合竿裂,索引0表示數(shù)據(jù)夜惭,索引1表示標(biāo)簽。
  2. 根據(jù)GPU的數(shù)量铛绰,拆分?jǐn)?shù)據(jù)data與標(biāo)簽label诈茧,每個(gè)GPU對(duì)應(yīng)不同的數(shù)據(jù);
  3. 每組數(shù)據(jù)和標(biāo)簽捂掰,分別反向傳播backward()更新網(wǎng)絡(luò)net的參數(shù)敢会;
  4. 設(shè)置訓(xùn)練器trainer的步驟step為批次數(shù)batch_size

多個(gè)GPU是相互獨(dú)立的这嚣,因此鸥昏,當(dāng)使用多個(gè)GPU訓(xùn)練模型時(shí),需要注意不同GPU之間的數(shù)據(jù)融合姐帚。

實(shí)現(xiàn)如下:

@staticmethod
def train_batch(batch, ctx, net, trainer):
    # split the data batch and load them on GPUs
    data = gluon.utils.split_and_load(batch[0], ctx)  # 列表
    label = gluon.utils.split_and_load(batch[1], ctx)  # 列表
    # compute gradient
    GluonFirst.forward_backward(net, data, label)
    # update parameters
    trainer.step(batch[0].shape[0])
    
@staticmethod
def forward_backward(net, data, label):
    loss = gluon.loss.SoftmaxCrossEntropyLoss()
    with autograd.record():
        losses = [loss(net(X), Y) for X, Y in zip(data, label)]  # loss列表
    for l in losses:  # 每個(gè)loss反向傳播
        l.backward()

具體分析批次驗(yàn)證方法valid_batch()

  1. 將全部驗(yàn)證數(shù)據(jù)吏垮,都運(yùn)行于一個(gè)GPU中,即ctx[0]罐旗;
  2. 網(wǎng)絡(luò)net預(yù)測(cè)數(shù)據(jù)data的類別概率膳汪,再轉(zhuǎn)換為具體類別argmax();
  3. 將全部預(yù)測(cè)正確的樣本進(jìn)行匯總九秀,獲得總的正確樣本數(shù)遗嗽;

實(shí)現(xiàn)如下:

@staticmethod
def valid_batch(batch, ctx, net):
    data = batch[0].as_in_context(ctx[0])
    pred = nd.argmax(net(data), axis=1)
    return nd.sum(pred == batch[1].as_in_context(ctx[0])).asscalar()

除了訓(xùn)練部分,GPU的數(shù)據(jù)加載和網(wǎng)絡(luò)模型都與CPU一致鼓蜒。

訓(xùn)練GPU模型痹换,需要連接遠(yuǎn)程服務(wù)器征字,上傳工程。如果無(wú)法使用Git傳輸娇豫,則推薦使用RsyncOSX匙姜,非常便捷的文件同步工具:

RsyncOSX

在遠(yuǎn)程服務(wù)器中,將工程的依賴庫(kù)安裝至虛擬環(huán)境中冯痢,注意需要使用MXNet的GPU版本mxnet-cu80氮昧,接著,執(zhí)行模型訓(xùn)練系羞。

以下是GPU版本的模型輸出結(jié)果:

Epoch 5, training time = 13.7 sec
    validation accuracy = 0.9277
Epoch 6, training time = 13.9 sec
    validation accuracy = 0.9284
Epoch 7, training time = 13.8 sec
    validation accuracy = 0.9335
Epoch 8, training time = 13.7 sec
    validation accuracy = 0.9379
Epoch 9, training time = 14.4 sec
    validation accuracy = 0.9402

當(dāng)遇到如下警告??時(shí):

only 4 out of 12 GPU pairs are enabled direct access. 
It may affect the performance. You can set MXNET_ENABLE_GPU_P2P=0 to turn it off

關(guān)閉MXNET_ENABLE_GPU_P2P即可,不影響正常的訓(xùn)練過(guò)程霸琴。

export MXNET_ENABLE_GPU_P2P=0

至此 MXNet/Gluon 的工程設(shè)計(jì)椒振,已經(jīng)全部完成,從數(shù)據(jù)集梧乘、模型澎迎、訓(xùn)練、GPU四個(gè)部分剖析MXNet的實(shí)現(xiàn)細(xì)節(jié)选调,MXNet的各個(gè)環(huán)節(jié)設(shè)計(jì)的非常巧妙夹供,也與其他框架類似,容易上手仁堪。實(shí)例雖小哮洽,“五臟俱全”,為繼續(xù)學(xué)習(xí)MXNet框架弦聂,起到拋磚引玉的作用鸟辅。

OK, that's all! Enjoy it!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市莺葫,隨后出現(xiàn)的幾起案子匪凉,更是在濱河造成了極大的恐慌,老刑警劉巖捺檬,帶你破解...
    沈念sama閱讀 221,198評(píng)論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件再层,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡堡纬,警方通過(guò)查閱死者的電腦和手機(jī)聂受,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)烤镐,“玉大人饺饭,你說(shuō)我怎么就攤上這事≈俺担” “怎么了瘫俊?”我有些...
    開(kāi)封第一講書(shū)人閱讀 167,643評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵鹊杖,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我扛芽,道長(zhǎng)骂蓖,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,495評(píng)論 1 296
  • 正文 為了忘掉前任川尖,我火速辦了婚禮登下,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘叮喳。我一直安慰自己被芳,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,502評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布馍悟。 她就那樣靜靜地躺著畔濒,像睡著了一般。 火紅的嫁衣襯著肌膚如雪锣咒。 梳的紋絲不亂的頭發(fā)上侵状,一...
    開(kāi)封第一講書(shū)人閱讀 52,156評(píng)論 1 308
  • 那天,我揣著相機(jī)與錄音毅整,去河邊找鬼趣兄。 笑死,一個(gè)胖子當(dāng)著我的面吹牛悼嫉,可吹牛的內(nèi)容都是我干的艇潭。 我是一名探鬼主播,決...
    沈念sama閱讀 40,743評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼戏蔑,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼暴区!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起辛臊,我...
    開(kāi)封第一講書(shū)人閱讀 39,659評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤仙粱,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后彻舰,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體伐割,經(jīng)...
    沈念sama閱讀 46,200評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,282評(píng)論 3 340
  • 正文 我和宋清朗相戀三年刃唤,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了隔心。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,424評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡尚胞,死狀恐怖硬霍,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情笼裳,我是刑警寧澤唯卖,帶...
    沈念sama閱讀 36,107評(píng)論 5 349
  • 正文 年R本政府宣布粱玲,位于F島的核電站,受9級(jí)特大地震影響拜轨,放射性物質(zhì)發(fā)生泄漏抽减。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,789評(píng)論 3 333
  • 文/蒙蒙 一橄碾、第九天 我趴在偏房一處隱蔽的房頂上張望卵沉。 院中可真熱鬧,春花似錦法牲、人聲如沸史汗。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,264評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)停撞。三九已至,卻和暖如春恶复,著一層夾襖步出監(jiān)牢的瞬間怜森,已是汗流浹背速挑。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,390評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工谤牡, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人姥宝。 一個(gè)月前我還...
    沈念sama閱讀 48,798評(píng)論 3 376
  • 正文 我出身青樓翅萤,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親腊满。 傳聞我的和親對(duì)象是個(gè)殘疾皇子套么,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,435評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容