推薦系統(tǒng)之Deep&Cross模型原理以及代碼實(shí)踐

簡(jiǎn)介

本文要介紹的是由斯坦福大學(xué)聯(lián)合Google的研究人員發(fā)表的論文《Deep & Cross Network for Ad Click Predictions》中提出的Deep&Cross模型,簡(jiǎn)稱DCN遣铝。DCN模型是Wide&Deep的改進(jìn)版本佑刷,其中Deep部分的設(shè)計(jì)思路與Wide&Deep沒有發(fā)生本質(zhì)的變化,DCN主要是重新設(shè)計(jì)了Cross部分以增加特征之間的交互力度酿炸,使用了多層特征交叉層對(duì)輸入向量進(jìn)行特征交叉瘫絮,以獲得更加強(qiáng)壯的特征表達(dá)能力。
關(guān)于Wide&Deep模型介紹可以參考推薦系統(tǒng)之Wide&Deep模型原理以及代碼實(shí)踐填硕。

摘要

點(diǎn)擊率(CTR)預(yù)估任務(wù)是一個(gè)大規(guī)模的問題麦萤,尤其是對(duì)于價(jià)值數(shù)百億美元的在線廣告業(yè)務(wù)。在廣告界扁眯,廣告商向發(fā)布商付款壮莹,以便在發(fā)布商的網(wǎng)站上展示其廣告。較為主流的付款方式是根據(jù)每次點(diǎn)擊付款(cost-per-click)姻檀,即當(dāng)用戶點(diǎn)擊了一次廣告之后命满,發(fā)布商就可以向廣告商索取費(fèi)用。因此绣版,對(duì)于發(fā)布商而言胶台,其預(yù)測(cè)廣告點(diǎn)擊率的能力直接決定了其營(yíng)收。
做出較為準(zhǔn)確的點(diǎn)擊率預(yù)測(cè)的關(guān)鍵是要識(shí)別出經(jīng)常預(yù)測(cè)的特征杂抽,并且同時(shí)挖掘出不常見的交叉特征信息诈唬。然而,用于Web級(jí)推薦系統(tǒng)的數(shù)據(jù)通常是離散的缩麸,且大多是類別數(shù)據(jù)铸磅,這就導(dǎo)致了一個(gè)非常龐大且稀疏的特征空間,對(duì)特征探索提出了巨大的挑戰(zhàn)。這也使得大多數(shù)大型系統(tǒng)受限于使用簡(jiǎn)單的線性模型愚屁,比如邏輯回歸济竹。線性模型很簡(jiǎn)單,解釋性很強(qiáng)霎槐,并且計(jì)算快速。然而梦谜,這也限制了它的表達(dá)能力丘跌。交叉特征已經(jīng)被證明對(duì)提高模型的表達(dá)能力很有效。然而它一般需要手工特征工程或者紛繁復(fù)雜的搜索才能找到唁桩;此外闭树,它也很難推廣到那些看不見的特征交互上。
作者在這篇論文中引入了一個(gè)新型的神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)荒澡,即DCN报辱。它避免了傳統(tǒng)的針對(duì)特定任務(wù)的特征工程,依靠神經(jīng)網(wǎng)絡(luò)強(qiáng)大的學(xué)習(xí)能力单山,在一定程度上實(shí)現(xiàn)自動(dòng)學(xué)習(xí)交叉特征組合碍现。

Deep&Cross 網(wǎng)絡(luò)模型

Deep&Cross模型,簡(jiǎn)稱DCN米奸。DCN模型的輸入是稠密和稀疏向量昼接,可以自動(dòng)進(jìn)行特征學(xué)習(xí),有效捕捉有限度的特征交互悴晰,學(xué)習(xí)高度非線性的特征之間的交互慢睡,無需復(fù)雜繁瑣的特征工程和詳細(xì)的特征搜索,并且具備較低的計(jì)算成本铡溪。模型的整體結(jié)構(gòu)圖如下:
DCN模型

DCN模型整體結(jié)構(gòu)比較簡(jiǎn)單漂辐,下面分別進(jìn)行描述。

Embedding和Stack層

輸入數(shù)據(jù)包含稠密和稀疏向量棕硫。在Web級(jí)的推薦系統(tǒng)任務(wù)中髓涯,比如點(diǎn)擊率預(yù)估,其輸入大都是類別向量饲帅,比如“國(guó)家=中國(guó)”复凳。這樣的特征通常被編碼成one-hot向量,比如這樣“[0,1,0]”灶泵;但是如果稀疏向量很多育八,且類別較大,那么這將導(dǎo)致一個(gè)超高維的特征空間赦邻,同時(shí)造成空間浪費(fèi)以及計(jì)算復(fù)雜度高髓棋。為了減少維度,通常采用embedding處理(即上圖紅色矩形框部分),將這些二值化特征轉(zhuǎn)化為包含實(shí)數(shù)的稠密向量按声,也叫做嵌入向量(embedding vector)膳犹。轉(zhuǎn)換公式如下:

其中x_{embed,i}就是embedding向量,x_i是第i個(gè)類別向量的二值輸入签则,并且W_{embed,i} \in \mathbb R^{n_e \times n_v}是對(duì)應(yīng)的embedding矩陣须床,這個(gè)矩陣也會(huì)隨著網(wǎng)絡(luò)的其他參數(shù)一起更新。隨后渐裂,將embedding向量和經(jīng)過歸一化處理的稠密向量x_{dense}聚合成一個(gè)輸入向量x_0豺旬,定義如下:

Cross網(wǎng)絡(luò)

Cross網(wǎng)絡(luò)是DCN模型中最關(guān)鍵的部分,它以一種高效的方式來進(jìn)行特征交叉柒凉。Cross網(wǎng)絡(luò)包含若干個(gè)cross層族阅,每一層都通過以下公式計(jì)算:


其中x_l, x_{l+1}是第l和第l+1層cross層的列向量。w_lb_l是第l層cross層的權(quán)重和偏置參數(shù)膝捞。每一層在進(jìn)行特征交叉f之后都會(huì)加上本層的輸入x_l坦刀。映射函數(shù)f: \mathbb R^d → \mathbb R^d代表著x_{l+1} - x_l,即殘差蔬咬。
cross層的工作示意圖如下:

其中x'x的轉(zhuǎn)置鲤遥。
這種結(jié)構(gòu)的設(shè)計(jì)使得特征交叉的力度隨著cross層深度的加深而逐漸加大。對(duì)于第l層 layer计盒,它的最高多項(xiàng)式階(在輸入x_0上)是l+1渴频。實(shí)際上,cross network由這些交叉項(xiàng)x_1^{\alpha_1} x_2^{\alpha_2} … x_d^{\alpha_d} 組成北启,對(duì)應(yīng)的階從1到l + 1卜朗。

Cross Layer 設(shè)計(jì)的巧妙之處全部體現(xiàn)在上面的計(jì)算公式中,我們先看一些明顯的細(xì)節(jié):1) 每層的神經(jīng)元個(gè)數(shù)都相同咕村,都等于輸入x_0的維度d,也即每層的輸入輸出維度都是相等的场钉;2) 受殘差網(wǎng)絡(luò)(Residual Network)結(jié)構(gòu)啟發(fā),每層的函數(shù)擬合f的是x_{l+1} ? x_l的殘差懈涛,殘差網(wǎng)絡(luò)有很多優(yōu)點(diǎn)逛万,其中一點(diǎn)是處理梯度消失的問題,使網(wǎng)絡(luò)可以“更深”批钠。
那為什么這樣設(shè)計(jì)呢宇植?對(duì)此論文中給出了定理3.1以及相關(guān)證明,但定理與證明過程都比較晦澀埋心,為了直觀清晰地講解清楚指郁,我們直接看一個(gè)具體的例子。加入Cross有2層拷呆,設(shè)置x_0 = \begin{vmatrix} x_{0,1} \\ x_{0,2}\\ \end{vmatrix}闲坎,為了便于討論疫粥,令b_i=0,則有:


最后得到y_{cross} = x_2^T * w_{crovs} \in \mathbb R參與到最后的loss計(jì)算腰懂」4可以看到x_1包含了原始特征x_{0,1}, x_{0,2}從一階到二階的所有可能的叉乘組合,而x_2則包含了其從一階到三階的所有可能叉乘組合⌒辶铮現(xiàn)在大家應(yīng)該可以理解cross layer計(jì)算公式的設(shè)計(jì)意圖了慷彤。這個(gè)例子可以幫助我們更加深入理解cross層的設(shè)計(jì):

  1. 有限高階:叉乘階數(shù)由網(wǎng)絡(luò)深度決定,深度L_c對(duì)應(yīng)最高的L_c+1階的叉乘
  2. 自動(dòng)叉乘: Cross輸出包含了原始特征從一階到L_c+1階的所有叉乘組合怖喻,而模型的參數(shù)量?jī)H僅隨著輸入維度成線性增加瞬欧。
  3. 參數(shù)共享:不同叉乘項(xiàng)對(duì)應(yīng)的權(quán)重不同,單并非每個(gè)叉乘組合對(duì)應(yīng)獨(dú)立的權(quán)重罢防,通過參數(shù)共享,cross有效降低了參數(shù)量唉侄。此外咒吐,參數(shù)共享還使得模型具有更強(qiáng)的泛化性魯棒性。例如属划,如果獨(dú)立訓(xùn)練權(quán)重恬叹,當(dāng)訓(xùn)練集中x_i \ne 0 \cap x_j \ne 0這個(gè)叉乘特征沒有出現(xiàn),對(duì)應(yīng)的權(quán)重肯定為0同眯,而參數(shù)共享不會(huì)绽昼。類似地,數(shù)據(jù)集中的一些噪聲可以由大部分正常樣本來糾正權(quán)重參數(shù)的學(xué)習(xí)须蜗。

復(fù)雜度計(jì)算

L_c為cross層的數(shù)量硅确,d代表輸入向量的維度,那么cross層的參數(shù)量是:
d \times L_c \times 2
即cross層的時(shí)間和空間復(fù)雜度是輸入向量的維度的線性函數(shù)明肮。相比deep層菱农,cross層引入的復(fù)雜度微不足道,這就保證了DCN的復(fù)雜度跟DNN是差不多的柿估。

論文表示循未,cross網(wǎng)絡(luò)之所以能夠高效地學(xué)習(xí)組合特征,就是因?yàn)?img class="math-inline" src="https://math.jianshu.com/math?formula=x_0%20%5Ctimes%20x_l%5ET" alt="x_0 \times x_l^T" mathimg="1">的秩為1秫舌,使得我們不用計(jì)算并存儲(chǔ)整個(gè)矩陣就可以得到所有的cross items的妖。

我們?cè)賮碛^察一下cross層的計(jì)算迭代公式:


假如輸入向量維度為dx_0x_l^T是兩個(gè)矩陣相乘足陨,結(jié)果還是一個(gè)d \times d的矩陣嫂粟,然后接著乘以w_l,當(dāng)d很大的時(shí)候钠右,這個(gè)計(jì)算過程其實(shí)非常耗時(shí)赋元。仔細(xì)觀察發(fā)現(xiàn),x_l^Tw_l其實(shí)是兩個(gè)向量叉乘,其結(jié)果是一個(gè)標(biāo)量搁凸,再乘以x_0的話媚值,速度會(huì)很快』ぬ牵考慮到矩陣相乘是滿足乘法結(jié)合律的褥芒,即(AB)C=A(BC)。因此我們可以先計(jì)算x_l^Tw_l嫡良,最后再乘以x_0锰扶。
實(shí)際代碼調(diào)試的時(shí)候,兩種方法都實(shí)驗(yàn)了寝受,在我的電腦上測(cè)試發(fā)現(xiàn)坷牛,使用優(yōu)化過的計(jì)算方式大概可以將速度提升6倍左右。

Deep網(wǎng)絡(luò)

Deep層比較簡(jiǎn)單很澄,就是一個(gè)全連接前向神經(jīng)網(wǎng)絡(luò)京闰,每一層的計(jì)算方式如下:


其中h_l \in \mathbb R^{n_l}, h_{l+1} \in \mathbb R^{n_{l+1}}代表第l和第l+1個(gè)隱層。W_l甩苛, b_l代表對(duì)應(yīng)的權(quán)重和偏置參數(shù)蹂楣,f(\cdot)代表ReLU激活函數(shù)。

復(fù)雜度計(jì)算

出于簡(jiǎn)化目的讯蒲,我們假設(shè)所有的Deep層都是通用的大小痊土。令L_d代表Deep層的數(shù)量,m代表Deep層的大小墨林,那么Deep網(wǎng)絡(luò)的參數(shù)量為:
d \times m + m + (m^2 + m) \times (L_d - 1)
其中 d \times m + m是第一層的參數(shù)量赁酝,第二層到最后一層的參數(shù)量為(m^2 + m) \times (L_d -1),因?yàn)閺牡诙娱_始萌丈,輸入向量維度就變成了m維赞哗。

聚合層

聚合的作用是將Deep和Cross網(wǎng)絡(luò)的輸出聚合到一個(gè)向量中,并且通過一個(gè)標(biāo)準(zhǔn)的邏輯層辆雾。計(jì)算公式如下:


其中x_{L1}^T肪笋,h_{L2}^T代表cross和deep網(wǎng)絡(luò)的輸出,\sigma是sigmoid函數(shù)度迂。損失函數(shù)是一個(gè)標(biāo)準(zhǔn)的交叉熵函數(shù)加上一個(gè)正則項(xiàng):

主要貢獻(xiàn)

DCN的主要貢獻(xiàn)主要包含以下幾點(diǎn):

  • 提出一種新型的交叉網(wǎng)絡(luò)結(jié)構(gòu)藤乙,可以用來提取交叉組合特征,并不需要人為設(shè)計(jì)的特征工程
  • 這種網(wǎng)絡(luò)結(jié)構(gòu)足夠簡(jiǎn)單同時(shí)也很有效惭墓,可以獲得隨網(wǎng)絡(luò)層數(shù)增加而增加的多項(xiàng)式階(polynomial degree)交叉特征
  • 十分節(jié)約內(nèi)存(依賴于正確地實(shí)現(xiàn))坛梁,并且易于使用
  • 實(shí)驗(yàn)結(jié)果表明,DCN相比于其他模型有更出色的效果腊凶,與DNN模型相比划咐,較少的參數(shù)卻取得了較好的效果

代碼實(shí)踐

模型部分代碼拴念,主要包含了Deep和Cross,以及DeepCross模型實(shí)現(xiàn)褐缠,特別要注意的就是Cross模型中的矩陣計(jì)算的時(shí)候政鼠,有兩種方式,默認(rèn)用的是優(yōu)化過后的方法队魏。

import torch
import torch.nn as nn
from BaseModel.basemodel import BaseModel

class Deep(nn.Module):
    def __init__(self, input_dim, deep_layers):
        super(Deep, self).__init__()

        deep_layers.insert(0, input_dim)
        deep_ayer_list = []
        for layer in list(zip(deep_layers[:-1], deep_layers[1:])):
            deep_ayer_list.append(nn.Linear(layer[0], layer[1]))
            deep_ayer_list.append(nn.BatchNorm1d(layer[1], affine=False))
            deep_ayer_list.append(nn.ReLU(inplace=True))
        self._deep = nn.Sequential(*deep_ayer_list)

    def forward(self, x):
        out = self._deep(x)
        return out

class Cross(nn.Module):
    """
    the operation is this module is x_0 * x_l^T * w_l + x_l + b_l for each layer, and x_0 is the init input
    """
    def __init__(self, input_dim, num_cross_layers):
        super(Cross, self).__init__()
        
        self.num_cross_layers = num_cross_layers
        weight_w = []
        weight_b = []
        batchnorm = []
        for i in range(num_cross_layers):
            weight_w.append(nn.Parameter(torch.nn.init.normal_(torch.empty(input_dim))))
            weight_b.append(nn.Parameter(torch.nn.init.normal_(torch.empty(input_dim))))
            batchnorm.append(nn.BatchNorm1d(input_dim, affine=False))

        self.weight_w = nn.ParameterList(weight_w)
        self.weight_b = nn.ParameterList(weight_b)
        self.bn = nn.ModuleList(batchnorm)

    def forward(self, x):
        out = x
        x = x.reshape(x.shape[0], -1, 1)
        for i in range(self.num_cross_layers):
            # this compute mode is time-consuming.
            # out = torch.matmul(torch.bmm(x, torch.transpose(out.reshape(out.shape[0], -1, 1), 1, 2)), self.weight_w[i]) + self.weight_b[i] + out

            # use this compute mode to speed up calculation
            xxTw = torch.matmul(x, torch.matmul(torch.transpose(out.reshape(out.shape[0], -1, 1), 1, 2), self.weight_w[i].reshape(1, -1, 1)))
            xxTw = xxTw.reshape(xxTw.shape[0], -1)
            out = xxTw + self.weight_b[i] + out

            out = self.bn[i](out)
        return out

class DeepCross(BaseModel):
    def __init__(self, config, dense_features_cols, sparse_features_cols):
        super(DeepCross, self).__init__(config)
        self._config = config
        # 稠密和稀疏特征的數(shù)量
        self._num_of_dense_feature = dense_features_cols.__len__()
        self._num_of_sparse_feature = sparse_features_cols.__len__()

        # For categorical features, we embed the features in dense vectors of dimension of 6 * category cardinality^1/4
        # calculate all the embedding dimension of all the sparse features
        self.embedding_dims = list(map(lambda x: int(6 * pow(x, 0.25)), sparse_features_cols))
        # create embedding layers for all the sparse features
        self.embedding_layers = nn.ModuleList([
            nn.Embedding(num_embeddings=e[0], embedding_dim=e[1], scale_grad_by_freq=True) for e in list(zip(sparse_features_cols, self.embedding_dims))
        ])

        self._input_dim = self._num_of_dense_feature + sum(self.embedding_dims)

        self._deepNet = Deep(self._input_dim, self._config['deep_layers'])
        self._crossNet = Cross(self._input_dim, self._config['num_cross_layers'])

        self._final_dim = self._input_dim + self._config['deep_layers'][-1]
        self._final_linear = nn.Linear(self._final_dim, 1)

    def forward(self, x):
        # 先區(qū)分出稀疏特征和稠密特征公般,這里是按照列來劃分的,即所有的行都要進(jìn)行篩選
        dense_input, sparse_inputs = x[:, :self._num_of_dense_feature], x[:, self._num_of_dense_feature:]
        sparse_inputs = sparse_inputs.long()

        # 求出稀疏特征的隱向量
        sparse_embeds = [self.embedding_layers[i](sparse_inputs[:, i]) for i in range(sparse_inputs.shape[1])]
        sparse_embeds = torch.cat(sparse_embeds, axis=-1)

        # 將dense特征和sparse特征聚合起來
        input = torch.cat([sparse_embeds, dense_input], axis=-1)

        deep_out = self._deepNet(input)
        cross_out = self._crossNet(input)

        final_input = torch.cat([deep_out, cross_out], dim=1)
        output = self._final_linear(final_input)
        output = torch.sigmoid(output)
        return output

測(cè)試數(shù)據(jù)是criteo數(shù)據(jù)集的一個(gè)很小的子集胡桨,測(cè)試代碼如下:

import torch
from DeepCross.trainer import Trainer
from DeepCross.network import DeepCross
from Utils.criteo_loader import getTestData, getTrainData
import torch.utils.data as Data

deepcross_config = \
{
    'deep_layers': [256,128,64,32], # 設(shè)置Deep模塊的隱層大小
    'num_cross_layers': 4, # cross模塊的層數(shù)
    'num_epoch': 2,
    'batch_size': 32,
    'lr': 1e-3,
    'l2_regularization': 1e-4,
    'device_id': 0,
    'use_cuda': False,
    'train_file': '../Data/criteo/processed_data/train_set.csv',
    'fea_file': '../Data/criteo/processed_data/fea_col.npy',
    'validate_file': '../Data/criteo/processed_data/val_set.csv',
    'test_file': '../Data/criteo/processed_data/test_set.csv',
    'model_name': '../TrainedModels/DeepCross.model'
}

if __name__ == "__main__":
    ####################################################################################
    # DeepCross 模型
    ####################################################################################
    training_data, training_label, dense_features_col, sparse_features_col = getTrainData(deepcross_config['train_file'], deepcross_config['fea_file'])
    train_dataset = Data.TensorDataset(torch.tensor(training_data).float(), torch.tensor(training_label).float())
    test_data = getTestData(deepcross_config['test_file'])
    test_dataset = Data.TensorDataset(torch.tensor(test_data).float())

    deepCross = DeepCross(deepcross_config, dense_features_cols=dense_features_col, sparse_features_cols=sparse_features_col)

    ####################################################################################
    # 模型訓(xùn)練階段
    ####################################################################################
    # # 實(shí)例化模型訓(xùn)練器
    trainer = Trainer(model=deepCross, config=deepcross_config)
    # 訓(xùn)練
    trainer.train(train_dataset)
    # 保存模型
    trainer.save()

    ####################################################################################
    # 模型測(cè)試階段
    ####################################################################################
    deepCross.eval()
    if deepcross_config['use_cuda']:
        deepCross.loadModel(map_location=lambda storage, loc: storage.cuda(deepcross_config['device_id']))
        deepCross = deepCross.cuda()
    else:
        deepCross.loadModel(map_location=torch.device('cpu'))

    y_pred_probs = deepCross(torch.tensor(test_data).float())
    y_pred = torch.where(y_pred_probs>0.5, torch.ones_like(y_pred_probs), torch.zeros_like(y_pred_probs))
    print("Test Data CTR Predict...\n ", y_pred.view(-1))

測(cè)試代碼就是對(duì)criteo的測(cè)試集中的每一個(gè)樣本數(shù)據(jù)輸出對(duì)應(yīng)的點(diǎn)擊率預(yù)測(cè)官帘,0或者1。以下是部分測(cè)試結(jié)果:

完整代碼見https://github.com/HeartbreakSurvivor/RsAlgorithms/tree/main/DeepCross昧谊。

參考

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末刽虹,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子呢诬,更是在濱河造成了極大的恐慌状婶,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,183評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件馅巷,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡草姻,警方通過查閱死者的電腦和手機(jī)钓猬,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來撩独,“玉大人敞曹,你說我怎么就攤上這事∽郯颍” “怎么了澳迫?”我有些...
    開封第一講書人閱讀 168,766評(píng)論 0 361
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)剧劝。 經(jīng)常有香客問我橄登,道長(zhǎng),這世上最難降的妖魔是什么讥此? 我笑而不...
    開封第一講書人閱讀 59,854評(píng)論 1 299
  • 正文 為了忘掉前任拢锹,我火速辦了婚禮,結(jié)果婚禮上萄喳,老公的妹妹穿的比我還像新娘卒稳。我一直安慰自己,他們只是感情好他巨,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,871評(píng)論 6 398
  • 文/花漫 我一把揭開白布充坑。 她就那樣靜靜地躺著减江,像睡著了一般。 火紅的嫁衣襯著肌膚如雪捻爷。 梳的紋絲不亂的頭發(fā)上辈灼,一...
    開封第一講書人閱讀 52,457評(píng)論 1 311
  • 那天,我揣著相機(jī)與錄音役衡,去河邊找鬼茵休。 笑死,一個(gè)胖子當(dāng)著我的面吹牛手蝎,可吹牛的內(nèi)容都是我干的榕莺。 我是一名探鬼主播,決...
    沈念sama閱讀 40,999評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼棵介,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼钉鸯!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起邮辽,我...
    開封第一講書人閱讀 39,914評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤唠雕,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后吨述,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體岩睁,經(jīng)...
    沈念sama閱讀 46,465評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,543評(píng)論 3 342
  • 正文 我和宋清朗相戀三年揣云,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了捕儒。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,675評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡邓夕,死狀恐怖刘莹,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情焚刚,我是刑警寧澤点弯,帶...
    沈念sama閱讀 36,354評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站矿咕,受9級(jí)特大地震影響抢肛,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜碳柱,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,029評(píng)論 3 335
  • 文/蒙蒙 一雌团、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧士聪,春花似錦锦援、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)曼库。三九已至,卻和暖如春略板,著一層夾襖步出監(jiān)牢的瞬間毁枯,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評(píng)論 1 274
  • 我被黑心中介騙來泰國(guó)打工叮称, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留种玛,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,091評(píng)論 3 378
  • 正文 我出身青樓瓤檐,卻偏偏與公主長(zhǎng)得像赂韵,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子挠蛉,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,685評(píng)論 2 360

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