算法小白的機(jī)器學(xué)習(xí)入門實(shí)踐,從零到上線

本實(shí)踐使用了阿里云機(jī)器學(xué)習(xí)平臺PAI

項(xiàng)目背景

原本業(yè)務(wù)內(nèi)容是比較常見的判定業(yè)務(wù)漆弄,即輸入為某個(gè)實(shí)體有一定誤差的測量信息和相關(guān)參考信息睦裳,輸出為其應(yīng)當(dāng)歸屬的實(shí)體。套用一個(gè)簡單場景就是輸入一篇未署名文章撼唾,根據(jù)文風(fēng)歸屬到庫中已存在的作者名下廉邑,抑或是歸屬到一個(gè)新建的匿名作者名下。

問題的難點(diǎn)在于:

  • 分類實(shí)體數(shù)量較多,在百萬量級
  • 分類數(shù)量不確定蛛蒙,且在動(dòng)態(tài)變化糙箍,即有新增和過期
  • 測量存在誤差
  • 場景較多

評價(jià)標(biāo)準(zhǔn):

  • 歸屬要準(zhǔn)確(作者名下文章不要錯(cuò))
  • 少遺漏(文章能盡量找到作者)
  • 避免錯(cuò)誤創(chuàng)建(同一作者不要?jiǎng)?chuàng)建多個(gè)實(shí)體)

原解決方案也比較傳統(tǒng),即制定了一套策略牵祟,將策略組合為一顆決策樹結(jié)構(gòu)深夯,邏輯較重的同時(shí)需要很多先驗(yàn)知識。套用場景即根據(jù)常用的人稱代詞课舍、語法結(jié)構(gòu)來判斷是否屬于同一作者塌西。

典型的決策樹

隨著準(zhǔn)確率要求不斷提高,策略組合的調(diào)整和維護(hù)愈發(fā)困難筝尾,主要原因在于:

  • 策略不斷增加捡需,維護(hù)難度提升
  • 為兼容誤差打了不少補(bǔ)丁,維護(hù)難度提升
  • 閾值筹淫、策略調(diào)整僅憑經(jīng)驗(yàn)站辉,每次調(diào)整需要回歸驗(yàn)證的數(shù)據(jù)較多
  • 場景較多,要針對每個(gè)場景制定對應(yīng)的優(yōu)化策略的工作量較大

總之一句話损姜,可預(yù)見的未來策略會繼續(xù)膨脹饰剥,維護(hù)難度也會進(jìn)一步提升。意識到技術(shù)風(fēng)險(xiǎn)后摧阅,組內(nèi)討論認(rèn)為如果使用機(jī)器學(xué)習(xí)方案一方面可降低解決方案的復(fù)雜度(降低維護(hù)成本)汰蓉,另一方面利于后期場景擴(kuò)展和能力遷移。至少也應(yīng)該能做到模型解決通用場景棒卷,在此基礎(chǔ)上再定制優(yōu)化策略(降低開發(fā)成本)顾孽。

本次幸運(yùn)地被選中承擔(dān)調(diào)研工作,盡管之前沒有使用模型解決問題的經(jīng)驗(yàn)(純小白)若厚,但剛好有個(gè)拓寬技術(shù)面的機(jī)會肯定是不能放過的。于是現(xiàn)學(xué)現(xiàn)賣記錄一下趟坑過程灾常,也希望能給其他有興趣的非算法攻城獅們一點(diǎn)信心肃晚,其實(shí)(浮于表面的)模型應(yīng)用并沒有通常大家認(rèn)為的那么難。

前期準(zhǔn)備

問題定義

問題的本質(zhì)是匹配吧碾,即目標(biāo)比較兩個(gè)向量的距離落剪。有很多方式可以實(shí)現(xiàn)這個(gè)比較呢堰,比如

  • 分類:根據(jù)標(biāo)注好的各類別數(shù)據(jù)參與訓(xùn)練鞋拟,預(yù)測新數(shù)據(jù)屬于哪一原定分類
  • 聚類:把相似數(shù)據(jù)聚合為一類,最終得到多個(gè)分類
  • 回歸:多用于根據(jù)標(biāo)注好的數(shù)據(jù)和原預(yù)測值獲得一個(gè)擬合函數(shù),預(yù)測新數(shù)據(jù)的值

回歸問題介紹

分類問題介紹

模型選擇

聚類模型

思路:特征聚為一類說明向量距離接近萝毛,屬于同一分類。

使用聚類模型則似乎不利于實(shí)現(xiàn)在線預(yù)測(每次預(yù)測都要聚類歉胶,投入較高),且常用的聚類模型存在一些限制條件,如:

  • K-means等,需要預(yù)設(shè)類簇個(gè)數(shù)K,不適合本業(yè)務(wù)場景
  • DBScan等即硼,需要一些先驗(yàn)知識如向量間的距離閾值等层皱,在本場景中較難確定
  • 聚類模型很難支持百萬量級類簇?cái)?shù)量的聚類

回歸模型

實(shí)在不知如何將向量匹配問題轉(zhuǎn)換為回歸問題瓮增,所以干脆沒怎么嘗試凡资。

多分類模型

思路:認(rèn)為每個(gè)應(yīng)當(dāng)歸屬同一實(shí)體的數(shù)據(jù)屬于一個(gè)分類,為所有特征計(jì)算分類伞访。

多分類本質(zhì)上是為每個(gè)類訓(xùn)練了一個(gè)分類器掂骏,但訓(xùn)練上百萬個(gè)分類器顯然也并不合理弟灼,放棄方案级解。

二分類模型

通過研究某屆天池競賽發(fā)現(xiàn),直接計(jì)算兩個(gè)特征向量的“差異”并根據(jù)最終是否匹配進(jìn)行標(biāo)注缴挖,是個(gè)比較合理的思路同蜻,最終便選擇了二分類模型棚点。

舉例來說是這樣:

x_diff y_diff match
0.1 0.1 true
0.9 0.9 false

簡而言之,原本決策引擎使用的是多個(gè)isMatch(v1, v2, threshold)規(guī)則組成的規(guī)則組默责,滿足一組特定規(guī)則的就認(rèn)為是同一類贱鼻;而在使用機(jī)器學(xué)習(xí)模型后舱呻,使用的是[a1-a2, b1-b2, ... , x1-x2]向量映射在高維空間的結(jié)果,由模型劃線分類蕊程。

分類決策的本質(zhì)

特征工程

基礎(chǔ)數(shù)據(jù)

基礎(chǔ)屬性數(shù)據(jù)盡量選擇與結(jié)果有相關(guān)性的攘烛,避免為明顯毫無關(guān)聯(lián)的屬性計(jì)算特征參與訓(xùn)練扎即。

特征計(jì)算

如前所述遏插,最終特征的形式是輸入與候選間同一屬性維度的diff缸榄,最終形成的向量則是N個(gè)維度diff的結(jié)果。

特殊處理

  1. 首先明確泛释,機(jī)器學(xué)習(xí)模型并不清楚特征各個(gè)維度之間的聯(lián)系,也不知道特征維度的diff如何計(jì)算温算,所以需要做一些處理怜校;
  2. 其次,可以做一些特殊處理使得基礎(chǔ)特征與結(jié)果關(guān)聯(lián)性更強(qiáng)注竿,比如將x茄茁、y坐標(biāo)轉(zhuǎn)為二維坐標(biāo)魂贬,使得最終的diff結(jié)果由x_diff、y_diff轉(zhuǎn)化為(x, y)間的歐式距離

通過將一些非數(shù)值類特征通過特殊手段處理映射為(連續(xù)的)數(shù)值特征裙顽,對模型訓(xùn)練結(jié)果會有明顯幫助:

  • 文本類:可以嘗試Levenshtein距離(編輯距離)
  • 枚舉類:可嘗試One-Hot編碼距離
  • 距離類:可嘗試余弦相似度付燥、曼哈頓距離等

具體處理方式還是依業(yè)務(wù)而定,并非任何維度特征都應(yīng)當(dāng)處理愈犹。

數(shù)據(jù)準(zhǔn)備

總數(shù)據(jù)量

通過特征工程計(jì)算的10w+特征向量键科。

打標(biāo)

二分類模型需要將數(shù)據(jù)分為兩個(gè)類,如0類和1類漩怎,或a類和b類等勋颖,分類標(biāo)簽需要體現(xiàn)在訓(xùn)練時(shí)的特征數(shù)據(jù)中,也就是說訓(xùn)練數(shù)據(jù)實(shí)際上是特征向量+分類標(biāo)簽勋锤。

本業(yè)務(wù)中的分類就是兩者是否匹配饭玲。套用場景即每篇文章提供多個(gè)候選作者,與其真正的作者屬性diff形成的特征向量打標(biāo)將會是a叁执,而與其他非真正作者形成的特征向量打標(biāo)將為b茄厘。

鑒于原決策模型準(zhǔn)確率9x%左右,索性直接使用了原本業(yè)務(wù)決策模型輸出的結(jié)果作為分類標(biāo)簽谈宛,當(dāng)然使用人工打標(biāo)結(jié)果效果是更好的次哈,盡管人工打標(biāo)準(zhǔn)確率也不一定是100%。

預(yù)處理

  • 歸一化
    • 避免單一維度影響過大入挣,將每個(gè)維度的值映射到0~1的區(qū)間內(nèi)
    • 計(jì)算方式:normalized_value = (value - min_value) / (max_value - min_value)

建模流程

建模

一個(gè)簡單的XGBoost二分類建模

說明

本流程使用阿里云PAI平臺搭建亿乳,省去搭環(huán)境的痛苦。當(dāng)然径筏,這個(gè)流程平臺無關(guān)葛假,完全也可以自行搭建。

讀數(shù)據(jù)表

打標(biāo)后的特征數(shù)據(jù)輸入滋恬。

預(yù)處理腳本

對某些稀疏矩陣類型的特征進(jìn)行預(yù)處理聊训,轉(zhuǎn)為標(biāo)準(zhǔn)順序格式。即把Java中的Map結(jié)構(gòu)按照擬定的順序轉(zhuǎn)為一維數(shù)組恢氯,由于特征較多带斑,這個(gè)過程使用了代碼生成腳本。

類型轉(zhuǎn)換

某些特征值需要由非數(shù)值類型轉(zhuǎn)為數(shù)值類型勋拟,另外可以做一些缺失值填充。

全表統(tǒng)計(jì)

統(tǒng)計(jì)數(shù)據(jù)表的各項(xiàng)信息敢靡,包括最大最小值啸胧、方差等幔虏。用于在數(shù)據(jù)預(yù)處理時(shí)參考想括,如歸一化計(jì)算用到的每個(gè)維度的最大值最小值烙博。

訓(xùn)練時(shí)的預(yù)測中這不是必須的步驟习勤,輸出的數(shù)據(jù)主要用于脫離平臺使用图毕。

數(shù)據(jù)歸一化

將每個(gè)維度的值映射至0~1。

數(shù)據(jù)拆分

將輸入的全量特征數(shù)據(jù)隨機(jī)拆分成兩個(gè)部分:

  • 訓(xùn)練數(shù)據(jù)
    • 用于訓(xùn)練模型囤官,理論上訓(xùn)練數(shù)據(jù)越多蛤虐,訓(xùn)練好的模型預(yù)測越穩(wěn)定和準(zhǔn)確
  • 預(yù)測數(shù)據(jù)
    • 用于給訓(xùn)練完的模型進(jìn)行預(yù)測測試驳庭,模型對預(yù)測數(shù)據(jù)的預(yù)測結(jié)果將成為模型評估的依據(jù)

在這里可以把訓(xùn)練數(shù)據(jù)與預(yù)測數(shù)據(jù)按7:3或8:2拆分饲常。

XGBoost二分類

XGBoost是基于梯度提升樹(GBDT)算法的模型贝淤,由華人大牛陳天奇博士團(tuán)隊(duì)提出。

GBDT的思想可以用一個(gè)通俗的例子解釋朽基,假如有個(gè)人30歲离陶,我們首先用20歲去擬合招刨,發(fā)現(xiàn)損失有10歲,這時(shí)我們用6歲去擬合剩下的損失,發(fā)現(xiàn)差距還有4歲学密,第三輪我們用3歲擬合剩下的差距传藏,差距就只有一歲了毯侦。如果我們的迭代輪數(shù)還沒有完,可以繼續(xù)迭代下面试幽,每一輪迭代,擬合的歲數(shù)誤差都會減小济榨。
——參考資料

模型預(yù)測

將預(yù)測數(shù)據(jù)輸入訓(xùn)練好的模型預(yù)測绿映,結(jié)果用于模型效果評估叉弦。

模型導(dǎo)出

將訓(xùn)練好的模型導(dǎo)出為pmml格式文件。

混淆矩陣/二分類評估

用于評估模型效果钝诚。

模型評估

混淆矩陣

結(jié)果


說明

預(yù)測Positive 預(yù)測Negative
真值Positive True Positive,該P(yáng)的P了拧略,正確 False Negative垫蛆,該P(yáng)的N了,錯(cuò)誤
真值Negative False Positive袱饭,該N的P了虑乖,錯(cuò)誤 True Negative疹味,該N的N了糙捺,正確

準(zhǔn)確率

ACC = (TP + TN) / (TP + FN + FP + TN)

即整體準(zhǔn)確率洪灯,所有預(yù)測正確的 / 總預(yù)測量婴渡。

精確率

PPV = TP / (TP + FP)

即該P(yáng)也正確預(yù)測為P的準(zhǔn)確率。也可以計(jì)算N的精確率哄尔。

召回率

TPR = TP / (TP + FN)

即P預(yù)測正確的占真值P的比例柠并。也可計(jì)算N的鸣戴。

總的來說準(zhǔn)確率可以看出綜合分類能力,而精確率和召回率可以看出其中一個(gè)分類的預(yù)測能力入偷。

二分類評估

二分類評估結(jié)果通常是計(jì)算得到ROC/K-S曲線等。

ROC等曲線
評估指標(biāo)

簡單地說丙曙,ROC曲線越靠左上角/AUC越大/F1 score越大/KS越大說明模型效果越好。

特征重要性

XGBoost模型對特征重要性進(jìn)行了評估拆挥,對于貢獻(xiàn)度非常小的特征維度在訓(xùn)練過程中舍棄掉了惰瓜。

同時(shí)备禀,訓(xùn)練好的模型可以輸出特征重要性排序,也就是說可以根據(jù)特征重要性進(jìn)行針對性的優(yōu)化另患。例如租冠,某維度重要特征由某服務(wù)計(jì)算得來顽爹,那么提升這個(gè)服務(wù)能力將比提高其他能力對結(jié)果的影響更大。

服務(wù)集成

模型導(dǎo)出

訓(xùn)練好的模型可導(dǎo)出為標(biāo)準(zhǔn)的pmml格式文件涉馅。

pmml格式是數(shù)據(jù)挖掘的通用規(guī)范格式,pmml文件其實(shí)就是一個(gè)很長的xml桥爽,包含用到的特征及特征間的關(guān)系跪楞。通過pmml文件可以加載訓(xùn)練的模型并執(zhí)行預(yù)測缕碎,也就是說pmml是一個(gè)“類代碼”,用于生成可運(yùn)行的“實(shí)例”寨典。

集成至服務(wù)

可以簡單通過pmml-evaluator包加載pmml文件:

<!-- 依賴 -->
<dependency>
    <groupId>org.jpmml</groupId>
    <artifactId>pmml-evaluator</artifactId>
    <version>1.5.9</version>
</dependency>
/* 集成 */
@Service
public class PmmlDemo {

    /**
     * 模型pmml文件路徑
     */
    private static final String MODEL_PMML_PATH = "/model/gbdt_model_20210106.pmml";

    /**
     * 模型
     */
    private Evaluator model;

    /**
     * 參數(shù)列表
     */
    private List<InputField> paramFields;

    /**
     * Positive目標(biāo)分類,同訓(xùn)練數(shù)據(jù)打標(biāo)中的Positive分類
     */
    private static final Object TARGET_CATEGORY = "0";

    @PostConstruct
    public void init() throws IOException, JAXBException, SAXException {
        model = buildEvaluator();
        paramFields = model.getInputFields();
    }

    /**
     * 加載模型
     * pmml-evaluator 1.5.x版本的使用方式與1.4略有不同
     */
    private static Evaluator buildEvaluator() throws JAXBException, SAXException, IOException {
        InputStream inputStream = PmmlDemo.class.getResourceAsStream(MODEL_PMML_PATH);
        PMML pmml = PMMLUtil.unmarshal(inputStream);
        inputStream.close();

        ModelEvaluatorBuilder evaluatorBuilder = new ModelEvaluatorBuilder(pmml, (String)null)
            .setModelEvaluatorFactory(ModelEvaluatorFactory.newInstance())
            .setValueFactoryFactory(ValueFactoryFactory.newInstance());

        return evaluatorBuilder.build();
    }

    /**
     * 模型預(yù)測
     */
    public Double getPredictScore(BizFeature feature) throws InvocationTargetException, IllegalAccessException {
        if (feature == null) {
            throw new NullPointerException();
        }
        // 讀取feature數(shù)據(jù)
        Map<String, Object> fieldMap = featureToMap(feature);
        // 填充模型輸入
        Map<FieldName, FieldValue> params = fillParams(fieldMap);
        // 預(yù)測
        ProbabilityDistribution result = predict(params);
        if (result == null) {
            return null;
        }
        return result.getProbability(TARGET_CATEGORY);
    }

    /**
     * 通過反射把業(yè)務(wù)特征BO屬性轉(zhuǎn)為map結(jié)構(gòu)
     * 包括數(shù)據(jù)的預(yù)處理
     */
    private static Map<String, Object> featureToMap(BizFeature feature) throws InvocationTargetException, IllegalAccessException {
        Map<String, Object> output = Maps.newHashMapWithExpectedSize(512);

        Method[] methods = BizFeature.class.getDeclaredMethods();
        for (Method method : methods) {
            String key = method.getName();
            if (!key.startsWith("get")) {
                continue;
            }
            key = key.toLowerCase();
            if (key.contains("bizid") || key.contains("entityid") || key.contains("label")) {
                continue;
            }

            Object value = method.invoke(feature);
            key = key.substring(3);
            put(output, key, value);
        }

        return output;
    }

    /**
     * 數(shù)據(jù)預(yù)處理
     * 這里用到歸一化
     */
    private static void put(Map<String, Object> outputMap, String key, Object value) {
        if (value instanceof Integer) {
            outputMap.put(key, BizFeatureNormalizationHelper.normalization(key, (Integer)value));
        } else if (value instanceof Double) {
            outputMap.put(key, BizFeatureNormalizationHelper.normalization(key, (Double)value));
        }
    }

    /**
     * 根據(jù)模型需要的特征寇仓,提取對應(yīng)的業(yè)務(wù)特征值進(jìn)行填充
     */
    private Map<FieldName, FieldValue> fillParams(Map<String, Object> map) {
        Map<FieldName, FieldValue> params = Maps.newHashMap();
        for (InputField inputField : paramFields) {
            FieldName inputFieldName = inputField.getName();
            Object rawValue = map.get(inputFieldName.getValue());
            FieldValue inputFieldValue = inputField.prepare(rawValue);
            params.put(inputFieldName, inputFieldValue);
        }

        return params;
    }

    /**
     * 預(yù)測似乎是非線程安全的躺枕?使用synchronized
     */
    private synchronized ProbabilityDistribution predict(Map<FieldName, FieldValue> arguments) {
        Map<FieldName, ?> results = model.evaluate(arguments);
        List<TargetField> targetFields = model.getTargetFields();

        if (CollectionUtils.isEmpty(targetFields)) {
            return null;
        }

        TargetField targetField = targetFields.get(0);
        FieldName targetFieldName = targetField.getName();
        return (ProbabilityDistribution)results.get(targetFieldName);
    }

}

注意:pmml-evaluator包1.5以前的版本模型加載方式和1.5.x版本方式不同。

在線預(yù)測

預(yù)測結(jié)果會輸出每個(gè)分類的0~1打分危彩,在二分類中兩個(gè)分類的結(jié)果是互補(bǔ)的,如對a分類預(yù)測分0.3梧奢,則對b分類預(yù)測分就是0.7惦蚊。

通過分類效果評估步驟可以確定一個(gè)合理的預(yù)測分閾值蹦锋,即控制是以0.4分界還是0.6分界兆沙,小于這個(gè)閾值的為a分類,否則為b分類莉掂。

在線預(yù)測結(jié)果跟模型訓(xùn)練階段同一條數(shù)據(jù)的預(yù)測結(jié)果可能有細(xì)微不同葛圃,因?yàn)閿?shù)據(jù)預(yù)處理階段使用的統(tǒng)計(jì)信息不完全相同。本業(yè)務(wù)訓(xùn)練時(shí)使用的歸一化統(tǒng)計(jì)信息和在線預(yù)測時(shí)的略有不同憎妙。

補(bǔ)充

在淌過這條河以后發(fā)現(xiàn)库正,如果并不深究而是淺顯地使用機(jī)器學(xué)習(xí)模型解決問題的話,確實(shí)沒有想象中那么難厘唾。希望這篇簡短的記錄能夠幫助更多人更容易地切換思路褥符,在工具包里添加一項(xiàng)新的利器。

另外抚垃,Java/Python也有現(xiàn)成工具可以直接訓(xùn)練模型喷楣,導(dǎo)出為pmml文件趟大,當(dāng)然平臺會更方便一些就是了。

踩坑經(jīng)歷

  • 一定要定義好問題抡蛙,這可能是小白嘗試機(jī)器學(xué)習(xí)最難的一步(淚)
  • 二分類中樣本數(shù)量最好相近护昧,否則可能會導(dǎo)致模型對某個(gè)分類過擬合
  • 集成pmml后需要做與訓(xùn)練模型時(shí)相同的數(shù)據(jù)預(yù)處理

參考文檔

機(jī)器學(xué)習(xí)-回歸問題(Regression) - 知乎

機(jī)器學(xué)習(xí)系列(七)——分類問題(classification)zxhohai的博客-CSDN博客分類問題

分類器評估指標(biāo)——混淆矩陣 ROC AUC KS AR PSI Lift Gain_snowdroptulip的博客-CSDN博客

java調(diào)用1.5.1版本PMML_bob71的博客-CSDN博客

梯度提升樹(GBDT)原理小結(jié) - 劉建平Pinard - 博客園

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市粗截,隨后出現(xiàn)的幾起案子惋耙,更是在濱河造成了極大的恐慌,老刑警劉巖熊昌,帶你破解...
    沈念sama閱讀 216,591評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件绽榛,死亡現(xiàn)場離奇詭異,居然都是意外死亡婿屹,警方通過查閱死者的電腦和手機(jī)灭美,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來昂利,“玉大人届腐,你說我怎么就攤上這事》浼椋” “怎么了犁苏?”我有些...
    開封第一講書人閱讀 162,823評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長扩所。 經(jīng)常有香客問我围详,道長,這世上最難降的妖魔是什么祖屏? 我笑而不...
    開封第一講書人閱讀 58,204評論 1 292
  • 正文 為了忘掉前任助赞,我火速辦了婚禮,結(jié)果婚禮上袁勺,老公的妹妹穿的比我還像新娘雹食。我一直安慰自己,他們只是感情好期丰,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,228評論 6 388
  • 文/花漫 我一把揭開白布婉徘。 她就那樣靜靜地躺著,像睡著了一般咐汞。 火紅的嫁衣襯著肌膚如雪盖呼。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,190評論 1 299
  • 那天化撕,我揣著相機(jī)與錄音几晤,去河邊找鬼。 笑死植阴,一個(gè)胖子當(dāng)著我的面吹牛蟹瘾,可吹牛的內(nèi)容都是我干的圾浅。 我是一名探鬼主播,決...
    沈念sama閱讀 40,078評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼憾朴,長吁一口氣:“原來是場噩夢啊……” “哼狸捕!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起众雷,我...
    開封第一講書人閱讀 38,923評論 0 274
  • 序言:老撾萬榮一對情侶失蹤灸拍,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后砾省,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體鸡岗,經(jīng)...
    沈念sama閱讀 45,334評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,550評論 2 333
  • 正文 我和宋清朗相戀三年编兄,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了轩性。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,727評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡狠鸳,死狀恐怖揣苏,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情件舵,我是刑警寧澤卸察,帶...
    沈念sama閱讀 35,428評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站芦圾,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏俄认。R本人自食惡果不足惜个少,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,022評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望眯杏。 院中可真熱鬧夜焦,春花似錦、人聲如沸岂贩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,672評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽萎津。三九已至卸伞,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間锉屈,已是汗流浹背荤傲。 一陣腳步聲響...
    開封第一講書人閱讀 32,826評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留颈渊,地道東北人遂黍。 一個(gè)月前我還...
    沈念sama閱讀 47,734評論 2 368
  • 正文 我出身青樓终佛,卻偏偏與公主長得像,于是被迫代替她去往敵國和親雾家。 傳聞我的和親對象是個(gè)殘疾皇子铃彰,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,619評論 2 354

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