集成樹模型(Ensemble)

博客園:梯度提升樹(GBDT)原理小結(jié)
博客園:一步一步理解GB、GBDT、xgboost
知乎:機(jī)器學(xué)習(xí)算法中GBDT和XGBOOST的區(qū)別有哪些?

介紹下rf,adaboost,gbdt,xgboost的算法原理?(注意adaboost,gbdt,xgboost的區(qū)別)

  1. RF的算法原理:
    隨機(jī)森林是有很多隨機(jī)得決策樹構(gòu)成,它們之間沒有關(guān)聯(lián)。得到RF以后,在預(yù)測(cè)時(shí)分別對(duì)每一個(gè)決策樹進(jìn)行判斷,最后使用Bagging的思想進(jìn)行結(jié)果的輸出;
    **主要步驟: **
    現(xiàn)在有N個(gè)訓(xùn)練樣本,每個(gè)樣本的特征為M個(gè),需要建K顆樹
    1)從N個(gè)訓(xùn)練樣本中有放回的取N個(gè)樣本作為一組訓(xùn)練集(其余未取到的樣本作為預(yù)測(cè)分類,評(píng)估其誤差)
    2)從M個(gè)特征中取m個(gè)特征左右子集特征
    3)重復(fù)上述過(guò)程K次
    4)行程隨機(jī)森林,通過(guò)投票表決確定分類;

  2. Adaboost算法原理:
    該算法是模型為加法模型,損失函數(shù)為指數(shù)函數(shù),學(xué)習(xí)算法為前向分步算法時(shí)的學(xué)習(xí)方法。Adaboost的訓(xùn)練誤差是以指數(shù)速率下降的,它具有自適應(yīng)性,它能自適應(yīng)弱分類器的訓(xùn)練誤差率。另外, Adaboost算法是穩(wěn)健的,具有robost,調(diào)參數(shù)沒有這么麻煩。一般適用于分類問(wèn)題,也可用于回歸。傳統(tǒng)的adaboost算法只能適用于二分類的情況。也可以將adaboost算法調(diào)整到適合處理多分類任務(wù)的方法。
    目標(biāo)函數(shù)只能是:指數(shù)函數(shù)。
    主要步驟:
    1) 初始化樣本的權(quán)值為1/n。
    2) 基于樣本與權(quán)值訓(xùn)練弱分類器;這里的弱分類器就是個(gè)二分類器。
    3) 根據(jù)分類器對(duì)樣本進(jìn)行判別,如果判別正確,此樣本的權(quán)值降低,判別錯(cuò)誤,降低樣本的權(quán)值,同時(shí)根據(jù)識(shí)別率計(jì)算出此分類器的權(quán)值;
    4) 利用改變權(quán)值的樣本訓(xùn)練下一個(gè)分類器;
    5) 循環(huán)得到N個(gè)分類器與其對(duì)應(yīng)的權(quán)值;
    6) 基于加權(quán)的分類器組合成為最終的模型。

  3. gbdt的算法原理:
    gbdt是一種提升樹算法,它每次迭代產(chǎn)生一個(gè)弱分類器模型,并且累加到總模型中。但是gbdt每一次迭代中弱分類器的生成都是依據(jù)損失函數(shù)的梯度方向,也就是用梯度下降的方法來(lái)擬合殘差。
    目標(biāo)函數(shù):分類(對(duì)數(shù)似然損失,指數(shù)損失(sklearn中,如果函數(shù)是指數(shù),則等價(jià)于adaboost))
    回歸(‘LS’均方差, ‘lad’ 絕對(duì)誤差, Hube損失(魯棒性回歸損失,lad和LS的結(jié)合))
    gbdt與adaboost的區(qū)別(除了目標(biāo)函數(shù)外,其他一樣),gbdt將adaboost模型中的所分類器改為回歸決策樹(如果處理分類問(wèn)題,是通過(guò)設(shè)定閾值的方法),目標(biāo)函數(shù)不同,優(yōu)化過(guò)程不同。
    主要步驟:
    1) 將基本學(xué)習(xí)器初始化為一個(gè)常數(shù);
    2) 開始迭代:a.根據(jù)給定的誤差函數(shù),來(lái)計(jì)算當(dāng)前模型的梯度,近似殘差(對(duì)于最小均方誤差來(lái)說(shuō),梯度就是當(dāng)前模型的結(jié)果和label的殘差);b.根據(jù)梯度(也叫作偽殘差)擬合下一個(gè)基學(xué)習(xí)器。c.根據(jù)一維線性搜索來(lái)計(jì)算步長(zhǎng);d.根據(jù)步長(zhǎng)和學(xué)習(xí)率對(duì)當(dāng)前模型進(jìn)行更新;

  4. xgboost的算法原理:
    xgboost可以說(shuō)是一種基于梯度提升的加強(qiáng)版本;GBDT通過(guò)梯度來(lái)擬合殘差,只用到了一階導(dǎo)數(shù)信息。而xgboost對(duì)目標(biāo)函數(shù)進(jìn)行二階泰勒展開,同時(shí)用到了一階導(dǎo)數(shù)和二階導(dǎo)數(shù)信息來(lái)擬合殘差,得到新的目標(biāo)函數(shù)。同時(shí)定義的每棵樹的復(fù)雜度結(jié)構(gòu)部分q和葉子權(quán)重部分w,作為正則項(xiàng)加入到新的目標(biāo)函數(shù)中。然后通過(guò)貪心算法獲取最優(yōu)切分點(diǎn),進(jìn)行劃分直到滿足某個(gè)閾值或得到純節(jié)點(diǎn)。
    除此之外,xgboost還有其他優(yōu)點(diǎn):支持線性分類器,列抽樣,缺失值的處理,并行計(jì)算等;

  5. 補(bǔ)充LightGBM的特點(diǎn):
    微軟出了個(gè)LightGBM,號(hào)稱性能更強(qiáng)勁,速度更快。
    性能提升的原因主要是兩個(gè):①histogram算法替換了傳統(tǒng)的Pre-Sorted,某種意義上是犧牲了精度(但是作者聲明實(shí)驗(yàn)發(fā)現(xiàn)精度影響不大)換取速度,直方圖作差構(gòu)建葉子直方圖挺有創(chuàng)造力的。(xgboost的分布式實(shí)現(xiàn)也是基于直方圖的,利于并行)②帶有深度限制的按葉子生長(zhǎng) (leaf-wise) 算法代替了傳統(tǒng)的(level-wise) 決策樹生長(zhǎng)策略,提升精度,同時(shí)避免過(guò)擬合危險(xiǎn)。

GBDT算法和隨機(jī)森林的區(qū)別?

  1. 組成隨機(jī)森林的樹可以是分類樹,也可以是回歸樹;而GBDT只由回歸樹組成
  2. 組成隨機(jī)森林的樹可以并行生成;而GBDT只能是串行生成
  3. 對(duì)于最終的輸出結(jié)果而言,隨機(jī)森林采用多數(shù)投票等;而GBDT則是將所有結(jié)果加權(quán)累加起來(lái)
  4. 隨機(jī)森林對(duì)訓(xùn)練集一視同仁,GBDT是基于權(quán)值的弱分類器的集成
  5. 隨機(jī)森林對(duì)異常值不敏感,GBDT對(duì)異常值非常敏感
  6. 隨機(jī)森林是通過(guò)減少模型方差提高性能,GBDT是通過(guò)減少模型偏差提高性能

GBDT和XGBOOST的區(qū)別?

  1. 傳統(tǒng)GBDT以CART作為基分類器,xgboost還支持線性分類器,這個(gè)時(shí)候xgboost相當(dāng)于帶L1和L2正則化項(xiàng)的邏輯斯蒂回歸(分類問(wèn)題)或者線性回歸(回歸問(wèn)題)。
  2. 傳統(tǒng)GBDT在優(yōu)化時(shí)只用到一階導(dǎo)數(shù)信息,xgboost則對(duì)代價(jià)函數(shù)進(jìn)行了二階泰勒展開,同時(shí)用到了一階和二階導(dǎo)數(shù)。順便提一下,xgboost工具支持自定義代價(jià)函數(shù),只要函數(shù)可一階和二階求導(dǎo)。
  3. xgboost在代價(jià)函數(shù)里加入了正則項(xiàng),用于控制模型的復(fù)雜度。正則項(xiàng)里包含了樹的葉子節(jié)點(diǎn)個(gè)數(shù)、每個(gè)葉子節(jié)點(diǎn)上輸出的score的L2模的平方和。從Bias-variance tradeoff角度來(lái)講,正則項(xiàng)降低了模型的variance,使學(xué)習(xí)出來(lái)的模型更加簡(jiǎn)單,防止過(guò)擬合,這也是xgboost優(yōu)于傳統(tǒng)GBDT的一個(gè)特性。
  4. Shrinkage(縮減),相當(dāng)于學(xué)習(xí)速率(xgboost中的eta)。xgboost在進(jìn)行完一次迭代后,會(huì)將葉子節(jié)點(diǎn)的權(quán)重乘上該系數(shù),主要是為了削弱每棵樹的影響,讓后面有更大的學(xué)習(xí)空間。實(shí)際應(yīng)用中,一般把eta設(shè)置得小一點(diǎn),然后迭代次數(shù)設(shè)置得大一點(diǎn)。(補(bǔ)充:傳統(tǒng)GBDT的實(shí)現(xiàn)也有學(xué)習(xí)速率)
  5. 列抽樣(column subsampling)。xgboost借鑒了隨機(jī)森林的做法,支持列抽樣,不僅能降低過(guò)擬合,還能減少計(jì)算,這也是xgboost異于傳統(tǒng)gbdt的一個(gè)特性。
  6. 對(duì)缺失值的處理。對(duì)于特征的值有缺失的樣本,xgboost可以自動(dòng)學(xué)習(xí)出它的分裂方向。
  7. xgboost工具支持并行。xgboost的并行是在特征粒度上的。xgboost在訓(xùn)練之前,預(yù)先對(duì)數(shù)據(jù)進(jìn)行了排序,然后保存為block結(jié)構(gòu),后面的迭代中重復(fù)地使用這個(gè)結(jié)構(gòu),大大減小計(jì)算量。這個(gè)block結(jié)構(gòu)也使得并行成為了可能,在進(jìn)行節(jié)點(diǎn)的分裂時(shí),需要計(jì)算每個(gè)特征的增益,最終選增益最大的那個(gè)特征去做分裂,那么各個(gè)特征的增益計(jì)算就可以開多線程進(jìn)行。
  8. 可并行的近似直方圖算法。樹節(jié)點(diǎn)在進(jìn)行分裂時(shí),我們需要計(jì)算每個(gè)特征的每個(gè)分割點(diǎn)對(duì)應(yīng)的增益,即用貪心法枚舉所有可能的分割點(diǎn)。當(dāng)數(shù)據(jù)無(wú)法一次載入內(nèi)存或者在分布式情況下,貪心算法效率就會(huì)變得很低,所以xgboost還提出了一種可并行的近似直方圖算法,用于高效地生成候選的分割點(diǎn)。

參數(shù)調(diào)節(jié)

GBDT調(diào)節(jié)參數(shù)?

我們把重要參數(shù)分為兩類,第一類是Boosting框架的重要參數(shù),第二類是弱學(xué)習(xí)器即CART回歸樹的重要參數(shù)。一般先調(diào)框架參數(shù),再調(diào)弱學(xué)習(xí)器的參數(shù);

boosting框架相關(guān)的重要參數(shù)

  • n_estimators: 也就是弱學(xué)習(xí)器的最大迭代次數(shù),或者說(shuō)最大的弱學(xué)習(xí)器的個(gè)數(shù)。一般來(lái)說(shuō)n_estimators太小,容易欠擬合,n_estimators太大,又容易過(guò)擬合,一般選擇一個(gè)適中的數(shù)值。默認(rèn)是100。在實(shí)際調(diào)參的過(guò)程中,我們常常將n_estimators和下面介紹的參數(shù)learning_rate一起考慮。
  • learning_rate: 即每個(gè)弱學(xué)習(xí)器的權(quán)重縮減系數(shù),也稱作步長(zhǎng),所以這兩個(gè)參數(shù)n_estimators和learning_rate要一起調(diào)參。一般來(lái)說(shuō),可以從一個(gè)小一點(diǎn)的步長(zhǎng)開始調(diào)參,默認(rèn)是1。
  • subsample: 樣本子采樣比例,取值為(0,1]。
  • init: 即我們的初始化的時(shí)候的弱學(xué)習(xí)器,常數(shù);一般用在我們對(duì)數(shù)據(jù)有先驗(yàn)知識(shí),或者之前做過(guò)一些擬合的時(shí)候,如果沒有的話就不用管這個(gè)參數(shù)了。
  • loss: 即我們GBDT算法中的損失函數(shù)。分類模型和回歸模型的損失函數(shù)是不一樣的。
    對(duì)于分類模型,有對(duì)數(shù)似然損失函數(shù)"deviance"和指數(shù)損失函數(shù)"exponential"兩者輸入選擇。默認(rèn)是對(duì)數(shù)似然損失函數(shù)"deviance"。
    對(duì)于回歸模型,有均方差"ls", 絕對(duì)損失"lad", Huber損失"huber"和分位數(shù)損失“quantile”。如果數(shù)據(jù)的噪音點(diǎn)不多,用默認(rèn)的均方差"ls"比較好。如果是噪音點(diǎn)較多,則推薦用抗噪音的損失函數(shù)"huber"。而如果我們需要對(duì)訓(xùn)練集進(jìn)行分段預(yù)測(cè)的時(shí)候,則采用“quantile”。
  • alpha:這個(gè)參數(shù)只有GradientBoostingRegressor有,當(dāng)我們使用Huber損失"huber"和分位數(shù)損失“quantile”時(shí),需要指定分位數(shù)的值。默認(rèn)是0.9,如果噪音點(diǎn)較多,可以適當(dāng)降低這個(gè)分位數(shù)的值。

GBDT類庫(kù)弱學(xué)習(xí)器參數(shù)

  • max_features 劃分時(shí)考慮的最大特征數(shù): 默認(rèn)是"None",意味著劃分時(shí)考慮所有的特征數(shù);如果是"log2"意味著劃分時(shí)最多考慮$log_2N$個(gè)特征;如果是"sqrt"或者"auto"意味著劃分時(shí)最多考慮$\sqrt{N}$個(gè)特征。如果是整數(shù),代表考慮的特征絕對(duì)數(shù)。如果是浮點(diǎn)數(shù),代表考慮特征百分比,即考慮(百分比xN)取整后的特征數(shù)。
  • max_depth 決策樹最大深度。默認(rèn)可以不輸入,如果不輸入的話,決策樹在建立子樹的時(shí)候不會(huì)限制子樹的深度。如果模型樣本量多,特征也多的情況下,推薦限制這個(gè)最大深度,具體的取值取決于數(shù)據(jù)的分布。常用的可以取值10-100之間。
  • min_samples_split 內(nèi)部節(jié)點(diǎn)再劃分所需最小樣本數(shù),默認(rèn)是2.如果樣本量不大,不需要管這個(gè)值。如果樣本量數(shù)量級(jí)非常大,則推薦增大這個(gè)值。
  • min_samples_leaf 葉子節(jié)點(diǎn)最少樣本數(shù)。這個(gè)值限制了葉子節(jié)點(diǎn)最少的樣本數(shù),如果某葉子節(jié)點(diǎn)數(shù)目小于樣本數(shù),則會(huì)和兄弟節(jié)點(diǎn)一起被剪枝。如果樣本量數(shù)量級(jí)非常大,則推薦增大這個(gè)值。
  • min_weight_fraction_leaf 葉子節(jié)點(diǎn)最小的樣本權(quán)重和。這個(gè)值限制了葉子節(jié)點(diǎn)所有樣本權(quán)重和的最小值,如果小于這個(gè)值,則會(huì)和兄弟節(jié)點(diǎn)一起被剪枝。
  • max_leaf_nodes最大葉子節(jié)點(diǎn)數(shù): 通過(guò)限制最大葉子節(jié)點(diǎn)數(shù),可以防止過(guò)擬合;
  • min_impurity_split 節(jié)點(diǎn)劃分最小不純度。這個(gè)值限制了決策樹的增長(zhǎng),如果某節(jié)點(diǎn)的不純度(基于基尼系數(shù),均方差)小于這個(gè)閾值,則該節(jié)點(diǎn)不再生成子節(jié)點(diǎn)。即為葉子節(jié)點(diǎn) 。

XGBOOST調(diào)節(jié)參數(shù)?

通用參數(shù)

  • booster [default=gbtree] 有兩中模型可以選擇gbtree和gblinear。gbtree使用基于樹的模型進(jìn)行提升計(jì)算,-
  • gblinear使用線性模型進(jìn)行提升計(jì)算。缺省值為gbtree;
  • silent [default=0] 取0時(shí)表示打印出運(yùn)行時(shí)信息,取1時(shí)表示以緘默方式運(yùn)行,不打印運(yùn)行時(shí)信息。缺省值為0
  • nthread XGBoost運(yùn)行時(shí)的線程數(shù)。缺省值是當(dāng)前系統(tǒng)可以獲得的最大線程數(shù)

學(xué)習(xí)目標(biāo)參數(shù)

  • Objective “reg:linear” –線性回歸。“reg:logistic” –邏輯回歸?!癰inary:logistic” –二分類的邏輯回歸問(wèn)題,輸出為概率?!癰inary:logitraw” –二分類的邏輯回歸問(wèn)題,輸出的結(jié)果為wTx?!癱ount:poisson” –計(jì)數(shù)問(wèn)題的poisson回歸,輸出結(jié)果為poisson分布。
  • “multi:softmax” –讓XGBoost采用softmax目標(biāo)函數(shù)處理多分類問(wèn)題,同時(shí)需要設(shè)置參數(shù)num_class(類別個(gè)數(shù))“multi:softprob” –和softmax一樣,但是輸出的是ndata * nclass的向量,可以將該向量reshape成ndata行nclass列的矩陣。沒行數(shù)據(jù)表示樣本所屬于每個(gè)類別的概率?!皉ank:pairwise” –set XGBoost to do ranking task by minimizing the pairwise loss
  • eval_metric:rmse 均方根誤差,mae 平均絕對(duì)誤差,logloss 負(fù)對(duì)數(shù)似然函數(shù)值error 二分類錯(cuò)誤率(閾值為0.5),merror 多分類錯(cuò)誤率,mlogloss 多分類,logloss損失函數(shù),auc 曲線下面積;
    seed:隨機(jī)數(shù)的種子

Parameter for Tree Booster

  • eta [default=0.3] 為了防止過(guò)擬合,更新過(guò)程中用到的收縮步長(zhǎng)。在每次提升計(jì)算之后,算法會(huì)直接獲得新特征的權(quán)重。 eta通過(guò)縮減特征的權(quán)重使提升計(jì)算過(guò)程更加保守。
  • gamma [default=0] 節(jié)點(diǎn)分裂所需的最小損失函數(shù)下降值,這個(gè)參數(shù)越大,算法越保密。
  • max_depth [default=6] 數(shù)的最大深度。缺省值為6取值范圍為:[1,∞]
  • subsample [default=1] GBM中的subsample參數(shù)一樣。這個(gè)參數(shù)控制對(duì)于每棵樹,隨機(jī)采樣的比例
  • colsample_bytree [default=1] 和GBM里面的max_features參數(shù)類似。用來(lái)控制每棵隨機(jī)采樣的列數(shù)的占比(每一列是一個(gè)特征)。
  • min_child_weight [default=1] 孩子節(jié)點(diǎn)中最小的樣本權(quán)重和。如果一個(gè)葉子節(jié)點(diǎn)的樣本權(quán)重和小于-
  • min_child_weight則拆分過(guò)程結(jié)束。
  • max_delta_step [default=0] 這參數(shù)限制每棵樹權(quán)重改變的最大步長(zhǎng)

Parameter for Linear Booster

  • lambda [default=0] L2正則的懲罰系數(shù);
  • alpha [default=0] L1正則的懲罰系數(shù);
  • lambda_bias 在偏置上的L2正則。缺省值為0(在L1上沒有偏置項(xiàng)的正則,因?yàn)長(zhǎng)1時(shí)偏置不重要)
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,702評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,143評(píng)論 3 415
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 175,553評(píng)論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,620評(píng)論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,416評(píng)論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,940評(píng)論 1 321
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,024評(píng)論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,170評(píng)論 0 287
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,709評(píng)論 1 333
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,597評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,784評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,291評(píng)論 5 357
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,029評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,407評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,663評(píng)論 1 280
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,403評(píng)論 3 390
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,746評(píng)論 2 370

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