ML-主成分分析PCA與梯度上升法

算法特點(diǎn)
非監(jiān)督機(jī)器學(xué)習(xí)算法贵试,主要用于數(shù)據(jù)降維;降維可以提高算法效率凯正,同時(shí)幫助可視化毙玻,以便于人類理解更好的理解數(shù)據(jù);去噪廊散。

1桑滩、 PCA的基本原理

樣本在其特征空間的分布表現(xiàn)是其各特征軸上記錄信息的綜合呈現(xiàn)形式。 PCA 分析基于能夠捕獲原始樣本最大信息量為目標(biāo)在樣本的原始特征空間尋找一個(gè)新的坐標(biāo)系允睹,并通過在新坐標(biāo)系中挑選能夠解釋樣本絕大部分信息的前n個(gè)軸來描述樣本运准,從而完成數(shù)據(jù)的 降維

1.1 二維空間的降維

對(duì)于包含二維特征的樣本集缭受,如果要將這個(gè)數(shù)據(jù)集從二維平面降到一維空間胁澳,通過在樣本的二維特征空間中尋找一條直線w,將空間上的所有樣本點(diǎn) 向直線作投影米者,使得直線上的 投影點(diǎn)間距離相對(duì)較大同時(shí)擁有較高的區(qū)分度韭畸,從而在直線所代表的一維空間上,投影點(diǎn)的分布與原二維空間上樣本點(diǎn)的空間分布盡可能相似蔓搞,這條一維直線上的投影點(diǎn)就是二維空間樣本的降維結(jié)果胰丁。

在尋找空間中最優(yōu)的樣本投影直線過程中,樣本間距 由統(tǒng)計(jì)學(xué)中的描述 數(shù)據(jù)的離散程度(疏密)方差(Variance) 所度量喂分;方差大樣本分布越稀疏锦庸,方差小樣本分布越緊密。所以最優(yōu)的投影軸的判斷條件即使得樣本空間的所有點(diǎn)映射到這條軸后蒲祈,方差最大甘萧。同時(shí),由于這條投影軸上的投影點(diǎn)分布具有最大方差梆掸,稱為 第一主成分幔嗦。
Var(x) = \frac {1}{m}\sum _{i=1}^{m}(x_i-\overline x)^2

2、 PCA 降維操作的基本步驟

  • Step.1 將樣例 均值歸零(demean) 沥潭,x_{i} - \overline x邀泉;該過程不改變樣本分布。但樣例的方差計(jì)算將簡化為:
    \overline x = 0, Var(x) = \frac {1}{m}\sum _{i=1}^{m}x_i^2

  • Step.2demean 后的樣本空間中尋找一個(gè)方向?yàn)?img class="math-inline" src="https://math.jianshu.com/math?formula=(w_1%2Cw_2)" alt="(w_1,w_2)" mathimg="1">的直線\vec w(除了方向,投影直線的大小以及偏移都不影響投影點(diǎn)間距汇恤,所以直接從中心化后的樣本空間坐標(biāo)原點(diǎn)確定直線的方向即可)庞钢,使得所有樣本映射到\vec w所在直線以后,投影點(diǎn)間方差最大:


Var(X_{project}) = \frac {1}{m}\sum _{i=1}^{m} {(x^{(i)}_{project} - \overline x_{project})^2}
\because 這里由于樣例中心為原點(diǎn)因谎,所以\overline x_{project} = \overline x = 0
\therefore Var(X_{project}) = \frac {1}{m}\sum _{i=1}^{m} {\|x^{(i)}_{project} \|^2}
\because 根據(jù) 向量投影 基括,結(jié)合方向向量 \vec w 的模為 1可有 \|x^{(i)}_{project}\| = x^{(i)} \cdot \vec w

\therefore Var(X_{project}) = \frac {1}{m}\sum _{i=1}^{m} {(x^{(i)}\cdot \vec w )^2}
推廣到n維樣本點(diǎn),展開為: Var(X_{project}) = \frac {1}{m}\sum _{i=1}^{m} {(x^{(i)}_{1}\cdot \vec w_{1} + ... + x^{(i)}_{n}\cdot \vec w_{n})^2}

  • Step.3 求解使得目標(biāo)函數(shù) Var(X_{project}) 取最大值對(duì)應(yīng)的\vec w财岔,從而獲得最優(yōu)的投影坐標(biāo)軸风皿。其中使用搜索的方式 進(jìn)行求解的方案為 梯度上升法

目標(biāo):\vec w匠璧,使得f(x) = \frac {1}{m}\sum _{i=1}^{m} {(x^{(i)}_{1}\cdot \vec w_{1} + ... + x^{(i)}_{n}\cdot \vec w_{n})^2} 最大桐款;
注意:PCA的 目標(biāo)函數(shù)形成的曲面 本身沒有極大值存在,直接使用梯度法求解的時(shí)候并不會(huì)收斂夷恍,這里前提是基于約束條件進(jìn)行的梯度法求解魔眨。所以這是一個(gè)帶約束的求極值問題。這個(gè)約束就是酿雪,\vec w的模要為1遏暴。PCA本身具有非常好的 數(shù)學(xué)解,梯度法搜索并不是最好的求解策略指黎,但可以用于理解PCA過程朋凉。
求關(guān)于\vec w每個(gè)維度的梯度(偏導(dǎo))

\nabla f= \begin{bmatrix} \partial f/ \partial w_{1} \\ \partial f/ \partial w_{2} \\ ... \\ \partial f/ \partial w_{n} \end{bmatrix} =\frac{2}{m} \begin{bmatrix} \sum_{i=1}^{m}{(x^{(i)}_{1}\cdot \vec w_{1} + ... + x^{(i)}_{n}\cdot \vec w_{n})\cdot (x^{(i)}_1)} \\ \sum_{i=1}^{m}{(x^{(i)}_{1}\cdot \vec w_{1} + ... + x^{(i)}_{n}\cdot \vec w_{n})\cdot (x^{(i)}_2)}\\... \\ \sum_{i=1}^{m}{(x^{(i)}_{1}\cdot \vec w_{1} + ... + x^{(i)}_{n}\cdot \vec w_{n})\cdot (x^{(i)}_n)} \end{bmatrix} = \frac{2}{m} \begin{bmatrix} \sum_{i=1}^{m}{(x^{(i)}\cdot \vec w)\cdot x^{(i)}_1} \\ \sum_{i=1}^{m}{(x^{(i)}\cdot \vec w)\cdot x^{(i)}_2} \\... \\ \sum_{i=1}^{m}{(x^{(i)}\cdot \vec w)\cdot x^{(i)}_n} \end{bmatrix} = (\frac{2}{m} \cdot (X \cdot \vec w)^{T} \cdot X) ^{T} = \frac{2}{m} \cdot X^{T} \cdot (X\vec w)

2.2 PCA與數(shù)據(jù)歸一化

  • 歸一化 (Standar Scaler) 處理樣本的特征數(shù)據(jù),會(huì)非線性地改變數(shù)據(jù)的特征量綱醋安,從而進(jìn)行主成分分析時(shí)需要考慮實(shí)際需求選擇性進(jìn)行數(shù)據(jù)的歸一化侥啤。比如只是利用PCA對(duì)原始數(shù)據(jù)進(jìn)行降噪不降維的處理,則不能進(jìn)行歸一化的數(shù)據(jù)預(yù)處理茬故,只需要進(jìn)行數(shù)據(jù)平移(如 demean 操作)即可盖灸。
  • 對(duì)于需要無偏差考量不同特征對(duì)樣本輸出標(biāo)記貢獻(xiàn)率的分析任務(wù),則需要注意樣本特征數(shù)量級(jí)帶來的方差影響影響(如一個(gè)特征的量綱從km更改為cm就會(huì)放大它的方差)磺芭,其中具有較大方差的特征將主導(dǎo)第一主成分的方差貢獻(xiàn)赁炎。因此對(duì)每個(gè)特征進(jìn)行歸一化后再進(jìn)行PCA降維處理才變得有意義(比如在聚類分析上,樣本的相似性度量就需要在同一尺度上來處理特征對(duì)樣本輸出標(biāo)記的影響)钾腺。更多討論請(qǐng)參考: normalization - Why do we need to normalize data before principal component analysis (PCA)? - Cross Validated (stackexchange.com)

2.3 梯度上升的簡單pyhton過程

import numpy as np
### Prepare dataset
X = np.empty((100,2))
X[:,0] = np.random.uniform(0.,100.,size = 100)
X[:,1] =0.75 * X[:,0] + np.random.normal(0.,10.,size = 100)
### 特征均值歸零
X = np.hstack([np.array(X[:,0] - np.mean(X[:,0])).reshape((-1,1)),np.array(X[:,1] - np.mean(X[:,1])).reshape((-1,1))])


### 目標(biāo)函數(shù)
def f(w,X):
    return np.sum(X.dot(w)**2) / len(X)
### 梯度函數(shù)
def df(w,X):
    return X.T.dot(X.dot(w)) *(2./len(X))

### 梯度上升求解過程
w = np.random.randint(10,size = X.shape[1])+ np.random.normal(size = X.shape[1]) ### 初始化參數(shù)集
w =  w / np.linalg.norm(w) ### 約束w為單位向量
for cur_iter in range(int(1e4)):
    last_w = w
    w = w + .001 * df(w,X)
    w = w / np.linalg.norm(w) ### 約束w為單位向量
    if(abs(f(w,X) - f(last_w,X)) < 1e-8):break

print(w)

2.4 數(shù)據(jù)的前n個(gè)主成分

PCA 工作的本質(zhì)是 對(duì)特征空間的坐標(biāo)軸重新排列徙垫,在樣本的原始特征空間內(nèi)尋找一套新的坐標(biāo)軸替換掉樣本的原始坐標(biāo)軸;在這套新的坐標(biāo)軸里放棒,第一主成分軸捕獲了樣本最大的方差姻报,第二主成分軸軸次之,第三主成分軸再次之间螟,以此類推吴旋;

所以损肛,對(duì)屬于n維特征空間的樣本,如果僅僅找出包含它們投影最大方差的 第一主成分 軸(\vec w)荣瑟,在該軸上的投影向量結(jié)果 \vec x^{(i)}_{project} = \| x^{(i)}_{project}\|\cdot \vec w = x^{(i)} \vec w \cdot \vec w 并不是一維數(shù)據(jù)治拿, 依舊還是n維向量,也就并沒有完成數(shù)據(jù)的降維笆焰。為了完成 降維 ,有必要繼續(xù)尋找其特征空間的其它n-1個(gè)主成分劫谅。

第一主成分 的前提下,計(jì)算 第二組主成分嚷掠。
向量投影 一章的內(nèi)容作為鋪墊捏检。當(dāng) 樣本向量\vec c 向第一主成分軸\vec w 進(jìn)行投影后,在第一主成分軸上的 投影向量\vec b 僅包含了原樣本向量的部分信息不皆,其中未被捕獲的信息由 原樣本向量投影向量垂直軸上投影向量\vec a 所捕獲贯城。


因此,在求算 第二主成分 時(shí)粟焊,原始向量 需要先除去被第一主成分捕獲的信息冤狡,即將數(shù)據(jù)在第一主成分上的分量減掉; 然后對(duì)去掉第一主成分分量的原始樣本向量繼續(xù)找使得它們方差最大的投影直線孙蒙,這條直線所在的軸就是這組數(shù)據(jù)的 第二主成分项棠, 該過程就是 求PCA第一主成分過程的重復(fù)

  • 總結(jié)
  • Step.1 去掉 第一主成分 分量 \vec x^{'(i)} = \vec x^{(i)} - \vec x^{(i)}_{project} 挎峦;
  • Step.2 求新樣本向量的第一主成分香追;
  • 求解第i個(gè)主成分也是類似該過程的重復(fù).
def cur_component(X,w,eta,epsilon):
    w =  w / np.linalg.norm(w) ### 約束w為單位向量
    for cur_iter in range(int(1e4)):
        last_w = w
        gradient = X.T.dot(X.dot(w)) *(2./len(X)) ### 求梯度
        w = w + eta * gradient
        w = w / np.linalg.norm(w) 
        target_f_0 = np.sum(X.dot(last_w)**2) / len(X) ### 目標(biāo)函數(shù)值,求方差
        target_f_1 = np.sum(X.dot(w)**2) / len(X) ### 目標(biāo)函數(shù)值坦胶,求方差
        if(abs(target_f_0 - target_f_1) < epsilon):break
            
    return w

    
def n_components(n,X,eta = .01,n_iters = 1e4 , epsilon = 1e-8):
    X_use = X.copy()
    X_use = X_use - np.mean(X_use,axis=0) ### demean
    res = [] ### 存儲(chǔ)每個(gè)主成分結(jié)果
    for i in range(n):
        initial_w = np.random.random(X_use.shape[1])
        w = cur_component(X_use,initial_w,eta,epsilon) ### 計(jì)算當(dāng)前主成分
        X_use = X_use - X_use.dot(w).reshape((-1,1))*w   ### 除掉上一主成分上的分量
        res.append(w)
    return res



#### Prepare data
import numpy as np
X = np.empty((100,2))
X[:,0] = np.random.uniform(0.,100.,size = 100)
X[:,1] =0.75 * X[:,0] + np.random.normal(0.,10.,size = 100)
#### Test method
n_components(2,X)### 求前兩個(gè)主成分軸方向

2.5 高維數(shù)據(jù)向低維數(shù)據(jù)的映射

當(dāng)在樣本的n維特征空間中透典,按 方差最大化 搜索了前k(k \lt n)個(gè)方向軸,使用這k個(gè)軸來描述樣本分布完成數(shù)據(jù)的降維顿苇。

根據(jù)向量投影峭咒,它在投影軸上的 投影模長 (\| x^{(i)}_{project}\| = x^{(i)} \vec w) 就是它在投影軸上的分布,也就說是這是 向量對(duì)象 脫離原始空間在 投影軸生成空間 內(nèi)的描述坐標(biāo)纪岁。原始數(shù)據(jù)到k個(gè)方向軸的映射(原始坐標(biāo)系到新坐標(biāo)系的轉(zhuǎn)換)為:
X = \begin{bmatrix} x_{1}^{(1)}&x_{2}^{(1)}&...&x_{n}^{(1)} \\ x_{1}^{(2)}&x_{2}^{(2)}&...&x_{n}^{(2)}\\ ...&...&...&... \\ x_{1}^{(m)}&x_{2}^{(m)}&...&x_{n}^{(m)}\end{bmatrix},W_{k} = \begin{bmatrix} w_{1}^{(1)}&w_{2}^{(1)}&...&w_{n}^{(1)} \\ w_{1}^{(2)}&w_{2}^{(2)}&...&w_{n}^{(2)}\\ ...&...&...&... \\ w_{1}^{(k)}&w_{2}^{(k)}&...&w_{n}^{(k)}\end{bmatrix} \rightarrow X_{k} = X\cdot W^{T}
數(shù)據(jù)的維度恢復(fù)
X_{k\_(m*k)} \cdot W_{k\_(k*n)} = X_{recover\_(m*n)} \neq X_{\_(m*n)}
數(shù)據(jù)維度恢復(fù)在數(shù)學(xué)運(yùn)算上雖然成立凑队。但是降維后的數(shù)據(jù)X_k,意味著原始數(shù)據(jù)X發(fā)生了 信息丟失 幔翰,所以通過前k個(gè)主成分來恢復(fù)到n維的話漩氨,恢復(fù)出來的數(shù)據(jù)對(duì)象并不是降維前的對(duì)象.

PCA降維與數(shù)據(jù)噪音
從噪音角度出發(fā),對(duì)于降維造成的 信息丟失 遗增,這部分丟失的信息存在于解釋方差比非常小的成分軸叫惊,這些丟失的信息很大一部分對(duì)于描述對(duì)象來說屬于 噪音。原始數(shù)據(jù)在測量過程中做修,由于儀器誤差霍狰、測量方法缺陷抡草、記錄錯(cuò)誤等因素,都會(huì)造成現(xiàn)實(shí)世界采集的數(shù)據(jù)存在噪音蚓耽。通過 PCA降維去除這些噪音渠牲,能有效提升樣本對(duì)象進(jìn)行識(shí)別分類回歸等分析時(shí)的準(zhǔn)確率。

利用 維度恢復(fù) 方法將降維去噪后的數(shù)據(jù)對(duì)象恢復(fù)到原始維度之后步悠,相當(dāng)于在不損失數(shù)據(jù)特征數(shù)量的前提下對(duì)原始數(shù)據(jù)完成了 去噪 签杈。這在圖像識(shí)別處理上應(yīng)用較多。

3鼎兽、scikit-learn 框架內(nèi)封裝的PCA

from sklearn.decomposition import PCA
pca = PCA(n_components= 2) ### sklearn內(nèi)的pca算法為pca的正規(guī)數(shù)學(xué)解
pca.fit(X)
pca.components_  ### 主成分方向
pca.transform(X) ### 根據(jù)n_components降維

PCA的主成分軸方向向量(pca.components_ )內(nèi)各分量的大小代表了對(duì)應(yīng)特征對(duì)該主成分的 方差貢獻(xiàn)答姥,或者說該方向軸捕獲了方向軸向量內(nèi)最大分量對(duì)應(yīng)特征的最多信息。

3.2 獲取n個(gè)主成分

方法屬性 : pca.explained_variance_ratio_ 返回每個(gè)主成分所解釋 樣本總方差 的比例(特征空間內(nèi)樣本的總方差 為樣本各特征上的方差之和)谚咬。解釋方差比也可理解為捕獲的信息量鹦付。

初始化PCA方法對(duì)象時(shí)如果不指定參數(shù)輸入一個(gè)浮點(diǎn)數(shù)如 pca = PCA(0.95) 來表示降維后希望能夠保留下的 信息量,sklearn-pca 方法將挑選相應(yīng)主成分?jǐn)?shù)目進(jìn)行降維择卦。

pca = PCA(0.95) 
pca.fit(X)
pca.transform(X)
pca.n_components_ ### 保留用于降維的主成分個(gè)數(shù)

3.3 數(shù)據(jù)集測試

### Prepare data
import numpy as np
from sklearn import datasets
digits = datasets.load_digits() ### 載入手寫數(shù)字?jǐn)?shù)據(jù)集
X = digits.data
y = digits.target
### test_train_split
from sklearn.model_selection import train_test_split
Train_X,Test_X,Train_Y,Test_Y = train_test_split(X,y,test_size= 0.2,random_state=666)

###### scikit-learn PCA reducion #####
from sklearn.decomposition import PCA
pca = PCA(0.8)  ### 降維到僅保留原始樣本80%信息
pca.fit(Train_X)
Train_X_reduc = pca.transform(Train_X) ### 根據(jù)n_components降維訓(xùn)練集
Test_X_reduc  = pca.transform(Test_X ) ### 根據(jù)n_components降維測試集
print(pca.n_components_) ### 保留用于降維的主成分個(gè)數(shù)

###### scikit-learn kNN classifier #####
from sklearn.neighbors import KNeighborsClassifier
kNN_clf = KNeighborsClassifier(n_neighbors=3) 
kNN_clf.fit(Train_X_reduc,Train_Y)
kNN_clf.score(Test_X_reduc,Test_Y)  ### 預(yù)測準(zhǔn)確率

3.4 PCA 去噪

降噪不降維數(shù)學(xué)過程:
X_{n} \rightarrow PCA_{reduction} \rightarrow X_{k} \rightarrow X_{k}\cdot W_{k} = X_{n}^{'}

### Prepare dataset
import numpy as np
X = np.empty((100,2))
X[:,0] = np.random.uniform(0.,100.,size = 100)
X[:,1] = 0.75 * X[:,0] + np.random.normal(0.,4.,size = 100) ### 給y軸添加一個(gè)方差為4的正態(tài)噪音

###### scikit-learn PCA Noise reduction #####
from sklearn.decomposition import PCA
pca = PCA(.5)  ### 降維到僅保留原始樣本50%信息
pca.fit(X) 
X_reduc = pca.transform(X) ### 對(duì)原始矩陣進(jìn)行降維敲长,該過程伴隨維度降低和消除噪音
X_restore = pca.inverse_transform(X_reduc) ### 恢復(fù)降噪降維對(duì)象到原始對(duì)象的維度,從而達(dá)到僅降噪的效果
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末秉继,一起剝皮案震驚了整個(gè)濱河市祈噪,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌尚辑,老刑警劉巖辑鲤,帶你破解...
    沈念sama閱讀 218,036評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異杠茬,居然都是意外死亡月褥,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,046評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門瓢喉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來宁赤,“玉大人,你說我怎么就攤上這事栓票【鲎螅” “怎么了?”我有些...
    開封第一講書人閱讀 164,411評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵逗载,是天一觀的道長哆窿。 經(jīng)常有香客問我,道長厉斟,這世上最難降的妖魔是什么挚躯? 我笑而不...
    開封第一講書人閱讀 58,622評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮擦秽,結(jié)果婚禮上码荔,老公的妹妹穿的比我還像新娘漩勤。我一直安慰自己,他們只是感情好缩搅,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,661評(píng)論 6 392
  • 文/花漫 我一把揭開白布越败。 她就那樣靜靜地躺著,像睡著了一般硼瓣。 火紅的嫁衣襯著肌膚如雪究飞。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,521評(píng)論 1 304
  • 那天堂鲤,我揣著相機(jī)與錄音亿傅,去河邊找鬼。 笑死瘟栖,一個(gè)胖子當(dāng)著我的面吹牛葵擎,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播半哟,決...
    沈念sama閱讀 40,288評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼酬滤,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了寓涨?” 一聲冷哼從身側(cè)響起盯串,我...
    開封第一講書人閱讀 39,200評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎缅茉,沒想到半個(gè)月后嘴脾,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體男摧,經(jīng)...
    沈念sama閱讀 45,644評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蔬墩,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,837評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了耗拓。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片拇颅。...
    茶點(diǎn)故事閱讀 39,953評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖乔询,靈堂內(nèi)的尸體忽然破棺而出樟插,到底是詐尸還是另有隱情,我是刑警寧澤竿刁,帶...
    沈念sama閱讀 35,673評(píng)論 5 346
  • 正文 年R本政府宣布黄锤,位于F島的核電站,受9級(jí)特大地震影響食拜,放射性物質(zhì)發(fā)生泄漏鸵熟。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,281評(píng)論 3 329
  • 文/蒙蒙 一负甸、第九天 我趴在偏房一處隱蔽的房頂上張望流强。 院中可真熱鬧痹届,春花似錦、人聲如沸打月。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,889評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽奏篙。三九已至柴淘,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間秘通,已是汗流浹背悠就。 一陣腳步聲響...
    開封第一講書人閱讀 33,011評(píng)論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留充易,地道東北人梗脾。 一個(gè)月前我還...
    沈念sama閱讀 48,119評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像盹靴,于是被迫代替她去往敵國和親炸茧。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,901評(píng)論 2 355

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