機器學(xué)習(xí)實戰(zhàn)(二)-決策樹的構(gòu)造和繪制

一浑玛、前言

你是否玩過二十個問題的游戲趾断?游戲規(guī)則很簡單:參與游戲的一方在腦海中想某個事物拒名,其他參與者向其提問,只允許提二十個問題芋酌,而且問題的答案只能用對和錯來回答增显。問問題的人通過答案進行推斷,逐步縮小猜測事物的范圍脐帝。決策樹原理與二十個問題類似同云,用戶給出一次列輸入數(shù)據(jù),然后分類器給出答案腮恩。

決策樹流程圖

圖 3-1 的流程圖就是一個決策樹梢杭,其中正方形表示判斷模塊,橢圓形表示終止模塊秸滴。

二武契、決策樹構(gòu)造原理

在構(gòu)造決策樹時,我們首先需要考慮的問題就是哪個特征在劃分數(shù)據(jù)集時起決定性作用。為了找到?jīng)Q定性特征咒唆,劃分出最佳結(jié)果届垫,我們需要對每個特征進行評估。完成測試后全释,原始數(shù)據(jù)集就會被分成幾個數(shù)據(jù)子集装处。這些數(shù)據(jù)子集會分布在第一個決策點的所有分支上。如果某個分支上的數(shù)據(jù)已經(jīng)屬于某一類別浸船,那么該數(shù)據(jù)子集已經(jīng)被正確分類妄迁,無需進一步劃分,反之則需要進一步劃分李命,直到所有相同類型的數(shù)據(jù)在同一個數(shù)據(jù)集中為止登淘。

一些決策樹采用二分法劃分數(shù)據(jù),但本文將使用 ID3 算法劃分數(shù)據(jù)集封字。每次劃分數(shù)據(jù)集只需選擇一個特征黔州,但如果某個數(shù)據(jù)集中有 20 個特征,應(yīng)該如何選壤选流妻?為了解決這個問題,我們必須采用量化的方法判斷如何劃分數(shù)據(jù)笆制,這需要用到信息論的知識绅这。

三、決策樹先導(dǎo)知識

1. 信息增益

劃分數(shù)據(jù)集的大原則是:將無序的數(shù)據(jù)變得有序在辆。組織雜亂無章的數(shù)據(jù)的一種方法就是使用信息論度量信息君躺,我們可以在劃分數(shù)據(jù)前使用信息論度量信息的內(nèi)容。

在劃分數(shù)據(jù)集前后开缎,信息發(fā)生的變化叫做信息增益,知道如何計算信息增益林螃,我們就可以計算每個特征劃分數(shù)據(jù)集后的信息增益奕删,然后選擇信息增益最大的特征。因此疗认,為了解決這個問題完残,我們必須學(xué)習(xí)如何計算信息增益。

香農(nóng)熵(熵)

集合信息的度量方式横漏。熵是對混亂的度量谨设。

熵定義為信息的期望值,在明晰這個概念之前缎浇,我們必須知道信息的定義扎拣。如果待分類的事物可能劃分在多個分類中,則符號 xi 的信息定義為:


xi 的信息定義

其中
pxi

是選擇該分類的概率。

為了計算熵二蓝,我們需要所有類別所有可能值包含的信息期望值誉券,可以通過如下公式得到:

信息熵

其中 n 是分類的數(shù)目。

計算給定數(shù)據(jù)集的香農(nóng)熵

from math import log
import operator
import matplotlib.pyplot as plt
import pandas as pd
from sklearn.preprocessing import LabelEncoder

'''
函數(shù)說明:構(gòu)造數(shù)據(jù)集
參數(shù):無
返回值:新構(gòu)造的數(shù)據(jù)集
'''
def createDataSet():
    dataSet = [[1,1,'yes'],
                [1,1,'yes'],
                [1,0,'no'],
                [0,1,'no'],
                [0,1,'no']]
    labels = ['no surfacing','flippers']
    return dataSet,labels

dataSet,labels = createDataSet()
# print(labels)

'''
函數(shù)說明:計算給定數(shù)據(jù)集的香農(nóng)熵
參數(shù):dataSet -- 數(shù)據(jù)集
返回值:shannonEnt -- 數(shù)據(jù)集的熵
'''
def calcShannonEnt(dataset):
    totalNum = len(dataset)
    labelCounts = {}
    for featVec in dataset:
        currentLabel = featVec[-1]
        if currentLabel not in labelCounts.keys():          
            labelCounts[currentLabel] = 1
        else:
            labelCounts[currentLabel] += 1
    shannonEnt = 0.0
    for key in labelCounts:
        prob = float(labelCounts[key]) / totalNum
        shannonEnt -= prob * log(prob,2)
    return shannonEnt
dataSet,labels = createDataSet()
# print(labels)
shannonEnt = calcShannonEnt(dataSet)
# print(dataSet)
# print(shannonEnt)

執(zhí)行結(jié)果:

數(shù)據(jù)集的信息熵

熵越高刊愚,則混合的數(shù)據(jù)越多踊跟。我們可以在數(shù)據(jù)集中增加分類,觀察熵的變化鸥诽。

dataSet[0][-1] = 'maybe'

執(zhí)行結(jié)果為:


分類越多熵越高

得到熵之后商玫,我們就可以根據(jù)最大信息增益來劃分數(shù)據(jù)集。

2. 根據(jù)給定特征劃分數(shù)據(jù)集

上一節(jié)我們學(xué)習(xí)如何度量數(shù)據(jù)的無序程度牡借,也即是熵的計算拳昌,接下來我們將對每個特征劃分得到的數(shù)據(jù)集進行信息熵計算,然后找出信息增益最大的劃分方式所對應(yīng)的特征蓖捶。

按照給定的特征劃分數(shù)據(jù)集

'''
函數(shù)說明:按照給定特征劃分數(shù)據(jù)集
參數(shù):dataSet -- 待劃分的數(shù)據(jù)集
      axis -- 劃分數(shù)據(jù)集的特征
      value -- 特征的返回值
返回值:retDataSet -- 劃分好的數(shù)據(jù)集
'''
def splitDataSet(dataset,axis,value):
    retDataSet = []
    for featVec in dataset:
        if featVec[axis] == value:
            #把劃分數(shù)據(jù)集的特征從數(shù)據(jù)集中剔除地回,
            reducedFeatVec = featVec[:axis]
            reducedFeatVec.extend(featVec[axis+1:])
            retDataSet.append(reducedFeatVec)
    return retDataSet


# print(splitDataSet(dataSet,0,1))
# print(splitDataSet(dataSet,0,0))

執(zhí)行結(jié)果:


按照給定特征劃分

目前我們只是根據(jù)給定的特征實現(xiàn)了數(shù)據(jù)集的劃分,接下來我們需要遍歷整個數(shù)據(jù)集俊鱼,對每個特征進行劃分并計算信息增益刻像,找到最佳分類特征。

3. 尋找最佳劃分特征

'''
函數(shù)說明:選擇最佳劃分特征
參數(shù):dataset -- 待劃分的數(shù)據(jù)集
返回值:最佳劃分特征
'''
def chooseBestFeatureToSplit(dataset):
    # 數(shù)據(jù)集特征數(shù)
    numFeatures = len(dataset[0]) - 1
    # 原始數(shù)據(jù)的信息熵
    bestEntropy = calcShannonEnt(dataSet)
    #最大信息增益
    bestInfoGain = 0.0
    # 最佳劃分特征
    bestFeature = -1
    for i in range(numFeatures):
        featureList = [example[i] for example in dataset]
        # 特征對應(yīng)的取值
        uniqueVals = set(featureList)
        newEntropy = 0.0
        for value in uniqueVals:
            # 遍歷劃分每個特征的每個取值
            subDataSet = splitDataSet(dataset,i,value)
            prob = len(subDataSet) / float(len(dataSet))
            # 新數(shù)據(jù)集的信息熵
            newEntropy += prob * calcShannonEnt(subDataSet)
        # 信息增益
        infoGain = bestEntropy - newEntropy
        if(infoGain > bestInfoGain):
            bestInfoGain = infoGain
            bestFeature = i
    return bestFeature
# print(dataSet)
# print('最佳劃分特征:特征',chooseBestFeatureToSplit(dataSet))

執(zhí)行結(jié)果:


最佳劃分特征

代碼運行結(jié)果顯示并闲,第 0 個特征是劃分數(shù)據(jù)集的最佳特征细睡。也即是第一個特征取值為 1 的是一組,取值為 0 的是一組帝火×镝悖可以看到,取值為 1 的分組中有兩個是魚類犀填,有一個是非魚類蠢壹;取值為 0 的分組中,兩個都是非魚類九巡。如果按照第二個特征來分類图贸,則取值為 1 的分組中,有兩個是魚類冕广,兩個是非魚類疏日;取值為 0 的分組中,只有一個非魚類撒汉。

4. 遞歸構(gòu)造決策樹

目前我們已經(jīng)得到從數(shù)據(jù)集構(gòu)造決策樹算法所需要的子功能模塊沟优,其工作原理為:得到原始數(shù)據(jù)集,然后基于最佳分類特征對數(shù)據(jù)集進行劃分睬辐,由于特征值可能不止兩個挠阁,所以可能存在大于兩個分支的數(shù)據(jù)集劃分宾肺。第一次劃分之后,數(shù)據(jù)被向下傳遞到數(shù)分支的下一個節(jié)點鹃唯,在這個節(jié)點上爱榕,我們可以再次劃分數(shù)據(jù)。因此我們可以采用遞歸的原則來處理數(shù)據(jù)集坡慌。

遞歸結(jié)束的條件:當程序遍歷完所有劃分數(shù)據(jù)集的屬性或所有分支下的實例都屬于同一個分類黔酥。如果所有實例具有相同的分類,則得到一個葉子節(jié)點或者說終止塊洪橘。任何到達葉子節(jié)點的數(shù)據(jù)必定屬于葉子節(jié)點的分類跪者。

由于特征數(shù)目并不一定每次劃分都會減少,因此這些算法在實際使用時可能會出現(xiàn)一些問題熄求。不過目前我們并不需要考慮這個問題渣玲,我們只需要在算法開始運行前計算出所有列的數(shù)目,查看算法是否使用了所有屬性即可弟晚。如果數(shù)據(jù)集已經(jīng)處理了所有屬性忘衍,但分類標簽并不唯一的情況下,我們通常會采用多數(shù)表決的方法決定該葉子節(jié)點的分類卿城。
在樹頂(根節(jié)點)處熵最高枚钓,逐層降低,直到數(shù)據(jù)被劃分為各自的類型瑟押。

'''
函數(shù)說明:在葉子節(jié)點類別標簽不唯一的情況下搀捷,采用多數(shù)表決的方法決定該葉子節(jié)點的分類
參數(shù):classList -- 數(shù)據(jù)集所有分類標簽
返回值:葉子節(jié)點中出現(xiàn)次數(shù)最多的分類標簽
'''
def majorityCnt(classList):
    #初始化字典用于記錄各分類標簽及其出現(xiàn)的次數(shù)
    classCount = {}
    # 遍歷數(shù)據(jù)集中的所有分類標簽,并統(tǒng)計其出現(xiàn)的次數(shù)
    for vote in classList:
        if vote not in classList.keys():
            classCount[vote] = 0
        else:
            classCount[vote] += 1
    # 對分類標簽出現(xiàn)的次數(shù)進行排序
    sortedClassCount = sorted(classCount.items(),key=operator.itemgetter(1),reverse=True)
    return sortedClassCount[0][0]

'''
函數(shù)說明:創(chuàng)建樹的函數(shù)代碼,構(gòu)造決策樹
參數(shù):dataSet -- 數(shù)據(jù)集
      labels -- 數(shù)據(jù)集所有分類標簽
返回值:根據(jù)數(shù)據(jù)集構(gòu)造得到的決策樹
'''
def createTree(dataSet,labels):
    # 得到數(shù)據(jù)集的所有類別標簽
    classList = [example[-1] for example in dataSet]
    # 如果數(shù)據(jù)集中的所有數(shù)據(jù)都屬于同一類別多望,則停止劃分
    if classList.count(classList[0]) == len(classList):
        return classList[0]
    #當遍歷完所有特征時(即數(shù)據(jù)集的列數(shù)為1時)嫩舟,仍然不能將數(shù)據(jù)集劃分成分類標簽唯一的分組,則返回出現(xiàn)次數(shù)最多的分類標簽
    if len(dataSet[0]) == 1:
        return majorityCnt(classList)
    bestFeat = chooseBestFeatureToSplit(dataSet)
    bestFeatLabel = labels[bestFeat]
    # 由當前最佳分類特征組成的決策樹
    myTree = {bestFeatLabel:{}}
    # 當特征被添加到?jīng)Q策樹中后怀偷,”就將其從分類標簽中刪除
    del(labels[bestFeat])
    # 最佳分類特征的取值
    featValues = [example[bestFeat] for example in dataSet]
    uniqueVals = set(featValues)
    # 刪除最佳分類特征之后的所有分類標簽
    for value  in uniqueVals:
        subLabels = labels[:]
        # 遞歸得到當前數(shù)據(jù)集的最佳分類特征家厌,并構(gòu)造決策樹
        myTree[bestFeatLabel][value] = createTree(splitDataSet(dataSet,bestFeat,value),subLabels)
    return myTree
mytree = createTree(dataSet,labels)
# print(mytree)

執(zhí)行結(jié)果為:

決策樹

變量 mytree 包含了很多代表樹結(jié)構(gòu)信息的嵌套字典,第一個關(guān)鍵字 no surfacing 是第一個最佳數(shù)據(jù)集劃分特征椎工,該關(guān)鍵字的值又是另一個數(shù)據(jù)字典像街。關(guān)鍵字的值可能是分類標簽,也有可能是另一個數(shù)據(jù)字典晋渺。如果值時分類標簽,則該子節(jié)點就是葉子節(jié)點脓斩;否則該節(jié)點就是另一個判斷節(jié)點木西,這種格式不斷重復(fù)就構(gòu)成了整棵樹,也就是我們剛剛看到的執(zhí)行結(jié)果随静。但是以字典的方式呈現(xiàn)決策樹非常不便于理解八千,因此吗讶,我們接下來將繪制決策樹,以更加直觀的方式來觀察決策樹恋捆。

5. 在 Python 中使用 matplotlib 注解繪制決策樹

'''
函數(shù)說明:使用matplotlib繪制樹節(jié)點
參數(shù):nodeText -- 節(jié)點注解
      centerPt -- 子節(jié)點
      parentPt -- 父節(jié)點
      nodeType -- 節(jié)點類型
返回值: 無

'''
# 定義判斷節(jié)點照皆、子節(jié)點以及箭頭的格式
decisionNode = dict(boxstyle = "sawtooth",fc = "0.8")
leafNode = dict(boxstyle = "round4",fc = "0.8")
arrow_args = dict(arrowstyle = "<-")

def plotNode(nodeText,centerPt,parentPt,nodeType):
    # 繪制帶箭頭的注解
    createPlot.ax1.annotate(nodeText,xy=parentPt,xycoords = 'axes fraction',xytext = centerPt,textcoords = 'axes fraction',va = "center",ha = "center",bbox = nodeType,arrowprops = arrow_args)

def createPlot():
    fig = plt.figure(1,facecolor = 'white')
    fig.clf()
    createPlot.ax1 = plt.subplot(111,frameon = False)
    # 繪制判斷節(jié)點
    plotNode('a decison node',(0.5,0.1),(0.1,0.5),decisionNode)
    # 繪制子節(jié)點
    plotNode('a leaf node',(0.8,0.1),(0.3,0.8),leafNode)
    plt.show()

# createPlot()

繪制樹節(jié)點:

繪制樹節(jié)點

現(xiàn)在我們已經(jīng)學(xué)會了樹節(jié)點的繪制,接下來我們將要對整棵樹進行繪制沸停。

繪制一顆完整的數(shù)需要一些技巧膜毁。雖然我們有 x , y 坐標,但如何放置所有的樹節(jié)點是個問題愤钾。我們必須知道有多少個葉節(jié)點瘟滨,以便我們能確定 x 軸的長度;我們還需要知道數(shù)有多少層能颁,以便確定 y 軸的長度杂瘸。因此這里我們定義了兩個函數(shù) getNumLeafs() 和 getTreeDepth() 來獲取葉子節(jié)點的數(shù)目以及數(shù)的高度。

'''
函數(shù)說明:獲取葉子節(jié)點的數(shù)目以及數(shù)的高度
參數(shù):myTree -- 決策樹
返回值: numLeafs -- 葉子節(jié)點數(shù)
        maxDepth -- 數(shù)的高度
'''
def getNumLeafs(myTree):
    #初始化葉子節(jié)點數(shù)
    numLeafs = 0
    #得到第一個關(guān)鍵字
    firstStr = list(myTree.keys())[0]
    # 得到第一個關(guān)鍵字的值伙菊,該值又是一個字典
    secondDict = myTree[firstStr]
    # 遍歷第二個字典的值败玉,判斷是字典還是葉子節(jié)點
    for key in secondDict.keys():
        if type(secondDict[key]).__name__ == 'dict':
            # 遞歸遍歷
            numLeafs += getNumLeafs(secondDict[key])
        else:
            numLeafs += 1
    return numLeafs

numLeafs = getNumLeafs(mytree)
# print('width of tree:',numLeafs)

def getTreeDepth(myTree):
    # 初始化數(shù)的高度
    maxDepth = 0
    firstStr = list(myTree.keys())[0]
    secondDict = myTree[firstStr]
    for key in secondDict.keys():
        if type(secondDict[key]).__name__ == 'dict':
            thisDepth = 1 + getTreeDepth(secondDict[key])
        else:
            thisDepth = 1
        if thisDepth > maxDepth:
            maxDepth = thisDepth
    return maxDepth

treeDepth = getTreeDepth(mytree)
# print('depth of tree:',treeDepth)

計算得到數(shù)的寬度和高度分別為:

計算數(shù)的寬度和高度
'''
函數(shù)說明:在父子節(jié)點之間填充文本信息
參數(shù):cntrPt -- 子節(jié)點
      parentPt -- 父節(jié)點
      txtString -- 文本信息
返回值:無
'''
def plotMidText(cntrPt,parentPt,txtString):
    # 文本信息的橫坐標
    xMid = (parentPt[0] - cntrPt[0]) / 2.0 + cntrPt[0]
    yMid = (parentPt[1] - cntrPt[1]) / 2.0 + cntrPt[1]
    createPlot.ax1.text(xMid,yMid,txtString)

'''
函數(shù)說明:繪制的具體步驟
參數(shù):mytree -- 決策樹
      parentPt -- 父節(jié)點
      nodeTxt -- 節(jié)點信息
返回值:無
'''
def plotTree(myTree,parentPt,nodeTxt):
    numLeafs = getNumLeafs(myTree)
    depth = getTreeDepth(myTree)
    # 決策樹的第一個關(guān)鍵字
    firstStr = list(myTree.keys())[0]
    # 計算子節(jié)點的位置
    cntrPt = (plotTree.xOff + (1.0 + float(numLeafs)) / 2.0 / plotTree.totalW,plotTree.yOff)
    # 在父子節(jié)點之間填充文本信息
    plotMidText(cntrPt,parentPt,nodeTxt)
    # 繪制節(jié)點
    plotNode(firstStr,cntrPt,parentPt,decisionNode)
    secondDict = myTree[firstStr]
    plotTree.yOff = plotTree.yOff - 1.0 / plotTree.totalD
    # 遞歸繪制決策樹
    for key in secondDict.keys():
        if type(secondDict[key]).__name__ == 'dict':
            plotTree(secondDict[key],cntrPt,str(key))
        else:
            plotTree.xOff =  plotTree.xOff + 1 / plotTree.totalW
            plotNode(secondDict[key],(plotTree.xOff,plotTree.yOff),cntrPt,leafNode)
            plotMidText((plotTree.xOff,plotTree.yOff),cntrPt,str(key))
    plotTree.yOff = plotTree.yOff + 1.0 / plotTree.totalD


'''
函數(shù)說明:將決策樹以圖形的形式繪制出來
參數(shù):inTree -- 決策樹
返回值:無
'''
def createPlot(inTree):
    fig = plt.figure(1,facecolor = 'white')
    fig.clf()
    #將xy坐標存放于一個字典內(nèi),不過此時的xy坐標值為空
    axprops = dict(xticks=[],ytick=[])
    createPlot.ax1 = plt.subplot(111,frameon=False)
    # 數(shù)的寬度镜硕,用于計算判斷節(jié)點的位置(應(yīng)該在水平方向和垂直方向的中心位置)
    plotTree.totalW = float(getNumLeafs(inTree))
    plotTree.totalD = float(getTreeDepth(inTree))
    #例如有三個葉子節(jié)點运翼,那么它們將x軸平分為三等分,坐標依次為1/3,2/3,3/3,但此時整個圖像靠右谦疾,并不在畫布的中心南蹂,因此將其向左移
    # plotTree.xOff、plotTree.yOff用于追蹤已繪制節(jié)點的位置念恍,以及放置下一個節(jié)點的位置
    plotTree.xOff = -0.5 / plotTree.totalW
    plotTree.yOff = 1.0
    plotTree(inTree,(0.5,1.0),'')
    plt.show()


# createPlot(mytree)

繪制得到的決策樹如下:

繪制得到的決策樹

到目前為止六剥,我們已經(jīng)學(xué)習(xí)而了如何構(gòu)造決策樹以及繪制樹形圖的方法,下一節(jié)我們將實際使用這些方法峰伙,并從算法和數(shù)據(jù)中得到新知識疗疟。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市瞳氓,隨后出現(xiàn)的幾起案子策彤,更是在濱河造成了極大的恐慌,老刑警劉巖匣摘,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件店诗,死亡現(xiàn)場離奇詭異,居然都是意外死亡音榜,警方通過查閱死者的電腦和手機庞瘸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來赠叼,“玉大人擦囊,你說我怎么就攤上這事违霞。” “怎么了瞬场?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵买鸽,是天一觀的道長。 經(jīng)常有香客問我贯被,道長眼五,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任刃榨,我火速辦了婚禮弹砚,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘枢希。我一直安慰自己桌吃,他們只是感情好,可當我...
    茶點故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布苞轿。 她就那樣靜靜地躺著茅诱,像睡著了一般。 火紅的嫁衣襯著肌膚如雪搬卒。 梳的紋絲不亂的頭發(fā)上瑟俭,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天,我揣著相機與錄音契邀,去河邊找鬼摆寄。 笑死,一個胖子當著我的面吹牛坯门,可吹牛的內(nèi)容都是我干的微饥。 我是一名探鬼主播,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼古戴,長吁一口氣:“原來是場噩夢啊……” “哼欠橘!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起现恼,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤肃续,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后叉袍,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體始锚,經(jīng)...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年喳逛,在試婚紗的時候發(fā)現(xiàn)自己被綠了瞧捌。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,018評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡艺配,死狀恐怖察郁,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情转唉,我是刑警寧澤皮钠,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布,位于F島的核電站赠法,受9級特大地震影響麦轰,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜砖织,卻給世界環(huán)境...
    茶點故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一款侵、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧侧纯,春花似錦新锈、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至娜氏,卻和暖如春拳缠,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背贸弥。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工窟坐, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人绵疲。 一個月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓哲鸳,卻偏偏與公主長得像,于是被迫代替她去往敵國和親最岗。 傳聞我的和親對象是個殘疾皇子帕胆,可洞房花燭夜當晚...
    茶點故事閱讀 42,762評論 2 345

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