通向深度神經(jīng)網(wǎng)絡(luò)之路

A Road to Deep Neural Networks

作????者:XU Ruilin
Master's degree candidate, major in pattern recognition and intelligent system.
(本文收錄于專(zhuān)題《神經(jīng)網(wǎng)絡(luò)擷英》)


導(dǎo)??語(yǔ):人工神經(jīng)網(wǎng)絡(luò)(Artificial Neural Network, ANN)簡(jiǎn)稱(chēng)神經(jīng)網(wǎng)絡(luò)(Neural Network, NN)绿语,是一個(gè)大量簡(jiǎn)單元件相互連接而成的復(fù)雜網(wǎng)絡(luò)源内,具有高度的非線性系瓢,能夠進(jìn)行復(fù)雜的邏輯操作和非線性關(guān)系實(shí)現(xiàn)的系統(tǒng)。本文從淺層到深層對(duì)人工神經(jīng)網(wǎng)絡(luò)進(jìn)行了簡(jiǎn)要總結(jié)胖缤。主要內(nèi)容來(lái)自Andrew Ng的Coursera深度學(xué)習(xí)系列課程桥嗤,符號(hào)記法也采用Andrew Ng的記法。


1?從生物學(xué)而來(lái)的M-P神經(jīng)元模型

????在高中二年級(jí)的生物課上疚沐,我們學(xué)過(guò)神經(jīng)元是一個(gè)由“樹(shù)突——胞體——軸突——軸突末梢”組成的細(xì)胞(Fig.1)栽燕。1943年罕袋,Warren McCulloch和 Walter Pitts參考生物神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)改淑,提出了M-P神經(jīng)元模型碍岔。

Figure 1. 生物的神經(jīng)元結(jié)構(gòu)

????M-P神經(jīng)元模型的結(jié)構(gòu)如 Fig.2 所示,x_1, x_2, x_3可以視作為神經(jīng)元樹(shù)突傳入的電信號(hào)朵夏,三個(gè)箭頭可以視作為樹(shù)突蔼啦,中間的圓圈可以視作為神經(jīng)元胞體,從圓圈出來(lái)的箭頭可以視作是軸突仰猖,y可以視作為神經(jīng)元傳出的電信號(hào)(神經(jīng)沖動(dòng))捏肢。電信號(hào)x_1, x_2, x_3在胞體中的\Sigma單元進(jìn)行線性相加處理。

Figure 2. M-P神經(jīng)元的結(jié)構(gòu)

????初等數(shù)學(xué)告訴我們饥侵,在表達(dá)能力上鸵赫,有限次連續(xù)線性變換與一次線性變換相同 [注1] 。如果只進(jìn)行線性變換躏升,不管網(wǎng)絡(luò)的規(guī)模多模龐大辩棒,有多少個(gè)神經(jīng)元節(jié)點(diǎn),其表達(dá)能力與一個(gè)神經(jīng)元沒(méi)有區(qū)別膨疏。

注1?設(shè)有f_1(x)=a_1x+b_1, f_2(x)=a_2x+b_2,f_3(x)=a_3x+b_3;
????則??F(x)=f_1 \circ f_2 \circ f_3=a_1(a_2(a_3x+b_3)+b_2)+b_1)
??????????=a_1(a_2a_3x+a_2b_3 +b_2)+b_1
??????????=(a_1a_2a_3)x+(a_1a_2b_3+a_1b_2+b_1);
????記??A=a_1a_2a_3, B=a_1a_2b_3+a_1b_2+b_1,F(x)=Ax+B.

????同理一睁,遞歸到f_n也是一個(gè)線性變換。

????因此佃却,在神經(jīng)元胞體中引入了非線性函數(shù)g(\cdot)來(lái)進(jìn)行非線性變換者吁,用以解決更為復(fù)雜的非線性問(wèn)題。在M-P神經(jīng)元模型中饲帅,作者為了模擬神經(jīng)元的膜電位閾值被激活的過(guò)程复凳,使用符號(hào)函數(shù){\mathrm{sgn}}\;(x)作為非線性函數(shù)瘤泪,此處不做贅述。

2?單層神經(jīng)網(wǎng)絡(luò)

????在M-P神經(jīng)元中育八,顯然電信號(hào)刺激x_1, x_2, x_3強(qiáng)度是不同的均芽,在神經(jīng)網(wǎng)絡(luò)模型中,我們采用參數(shù)(parameters)w_1, w_2, w_3來(lái)表示這種強(qiáng)度单鹿,w代表權(quán)重(weights)掀宋。同時(shí),引入偏置(bias)項(xiàng)參數(shù)b仲锄,來(lái)表示神經(jīng)元細(xì)胞膜電位閾值 [注2]劲妙。

注2?參數(shù)w的意義是比較易于理解的,而關(guān)于偏置b(在統(tǒng)計(jì)學(xué)中也稱(chēng)偏差)儒喊,分兩個(gè)角度解釋——
????從生物學(xué)角度看镣奋,在生物體中,神經(jīng)元的興奮程度超過(guò)了某個(gè)限度怀愧,也就是細(xì)胞膜去極化程度超過(guò)了某個(gè)閾值電位時(shí)侨颈,神經(jīng)元被激發(fā)而輸出神經(jīng)脈沖。人工神經(jīng)網(wǎng)絡(luò)借鑒了這種閾值特性芯义,神經(jīng)元激活與否取決于某一閾值哈垢,即只有其輸入綜合超過(guò)閾值時(shí),神經(jīng)元才會(huì)被激活扛拨,這個(gè)閾值體現(xiàn)在線性單元中耘分,就是偏置項(xiàng)b.
????從數(shù)學(xué)角度看,神經(jīng)網(wǎng)絡(luò)模型的初衷是解決分類(lèi)(Classification)問(wèn)題(當(dāng)然現(xiàn)在的神經(jīng)網(wǎng)絡(luò)也可以解決回歸/Regression問(wèn)題)绑警。以最簡(jiǎn)單的二分類(lèi)問(wèn)題為例求泰,就是用一條直線將兩類(lèi)樣本點(diǎn)分開(kāi),如果沒(méi)有偏置項(xiàng)b计盒,那么用于分類(lèi)的所有直線都只能通過(guò)原點(diǎn)渴频,這顯然是不能很好地解決分類(lèi)問(wèn)題的(神經(jīng)網(wǎng)絡(luò)中的偏置項(xiàng)b到底是什么[EB/OL].(2018-07-05)[2020-02-19])。

????應(yīng)用新的參數(shù)表示法后北启,神經(jīng)網(wǎng)絡(luò)模型變成了如 Fig.3 所示的結(jié)構(gòu)卜朗,在一些文獻(xiàn)中稱(chēng)其為感知機(jī)(Preception)模型。若記x=[x_1, x_2, x_3]^\top暖庄,w=[w_1, w_2, w_3]^\top聊替,則線性單元可以表述為w^\top x+bg(\cdot)是非線性函數(shù)培廓。

Figure 3. 感知機(jī)模型

????觀察這個(gè)模型可以發(fā)現(xiàn)(如果有機(jī)器學(xué)習(xí)算法基礎(chǔ))惹悄,我們知道在分類(lèi)問(wèn)題中常用的邏輯斯蒂回歸(Logistic Regression)方法與上述模型具有相同的結(jié)構(gòu)。

2.1?從邏輯斯蒂回歸說(shuō)起

????我們以一個(gè)簡(jiǎn)單的二分類(lèi)問(wèn)題為例來(lái)介紹邏輯斯蒂回歸肩钠。假如要判斷x是不是新型冠狀病毒COVID-19泣港,用y=1表示“是”暂殖,y=0表示“不是”,那么數(shù)據(jù)對(duì)(x,y)就可以表示這個(gè)實(shí)例当纱。假設(shè)輸入x的特征有x_1,x_2,\cdots, x_nn個(gè)呛每,分別表示n種檢測(cè)方法測(cè)得的指標(biāo)值,記x=[x_1,x_2,\cdots,x_n]^\top坡氯。我們對(duì)采納這n種檢測(cè)方法的權(quán)重為w_1,w_2,\cdots,w_n晨横,記w=[w_1,w_2,\cdots,w_n]^\top,樣本偏差為b箫柳。輸出的結(jié)果記為\hat{y}手形,表示x是新冠病毒的概率,用條件概率表達(dá)為P(y=1|x)悯恍。
????在經(jīng)過(guò)計(jì)算z=w^\top x+b后库糠,由于z并不一定收斂于區(qū)間[0,1]內(nèi),因此要對(duì)z進(jìn)行歸一化(Normalization)處理涮毫。在Logistic Regression中瞬欧,使用Sigmoid函數(shù)進(jìn)行歸一化。
????Sigmoid函數(shù)(Fig.4)定義為\sigma(z)=\frac{1}{1+e^{-z}}

Figure 4. Sigmoid函數(shù)

????Sigmoid函數(shù)就是神經(jīng)網(wǎng)絡(luò)模型中非線性函數(shù)g(\cdot)的一種罢防,在神經(jīng)網(wǎng)絡(luò)中艘虎,我們稱(chēng)這種非線性函數(shù)為激活函數(shù)(Activation Function),這樣篙梢,例子中的問(wèn)題就變成了\hat{y}=g(z)=g(w^\top x+b), {\rm where}\; g(z)=\sigma(z)=\frac{1}{1+e^{-z}}; {\rm given\;}(x,y),\;{\rm want}\;\hat{y}\approx y.????那么顷帖,我們?nèi)绾卧u(píng)價(jià)我們分類(lèi)模型的效果呢?在統(tǒng)計(jì)機(jī)器學(xué)習(xí)中渤滞,對(duì)于單個(gè)樣本數(shù)據(jù),我們常用損失函數(shù)(Loss Function)來(lái)評(píng)估機(jī)器學(xué)習(xí)算法榴嗅。在Logistic Regression中妄呕,LOSS函數(shù)為[注3][注4]
\mathcal{L}(\hat{y},y)=-y\log \hat{y}-(1-y)\log (1-\hat{y})

注3?在上式中,對(duì)數(shù)\log應(yīng)為以自然常數(shù)e=\lim_\limits{n \to \infty}(1+\frac{1}{n})^n為底的自然對(duì)數(shù)嗽测,在數(shù)學(xué)教材中習(xí)慣記為\ln x.
????此外绪励,關(guān)于未指明底數(shù)的\log用法,在數(shù)學(xué)中一般指常用對(duì)數(shù)\lg x(底為10)唠粥;在計(jì)算機(jī)科學(xué)中(如微機(jī)原理疏魏、數(shù)據(jù)結(jié)構(gòu)、算法等)一般指底為2的對(duì)數(shù)\log _2 x晤愧;在編程語(yǔ)言中一般指自然對(duì)數(shù)\ln x.奇怪的知識(shí)增加了大莫!

注4?為什么損失函數(shù)長(zhǎng)這個(gè)樣子?
????在Logistic Regresion中官份,我們的目標(biāo)是要使\hat{y}盡可能地接近y只厘。前面我們說(shuō)到烙丛,\hat{y}=P(y=1|x),那么1-\hat{y}=P(y=0|x).
????由于這是一個(gè)二分類(lèi)問(wèn)題羔味,y\in \left \{0,1\right \}河咽,因此,經(jīng)過(guò)代數(shù)變幻的鬼斧神工我們將上述兩個(gè)條件概率合并成一個(gè)表達(dá)式P(y|x)=\hat{y}^y(1-\hat{y})^{1-y}????我們驗(yàn)證一下就可以知道赋元,當(dāng)y=1時(shí)忘蟹,P(y=1|x)=\hat{y}^1(1-\hat{y})^0=\hat{y};當(dāng)y=0時(shí),P(y=0|x)=\hat{y}^0(1-\hat{y})^1=1-\hat{y}.
????由于\log x(這里指\ln x)是嚴(yán)格單調(diào)遞增函數(shù)搁凸,則\log P(y|x)的單調(diào)性與P(y|x)完全一致寒瓦。
????又因?yàn)?img class="math-block" src="https://math.jianshu.com/math?formula=%5Clog%20P(y%7Cx)%3Dy%5Clog%20%5Chat%7By%7D%2B(1-y)%5Clog%20(1-%5Chat%7By%7D)" alt="\log P(y|x)=y\log \hat{y}+(1-y)\log (1-\hat{y})" mathimg="1">????要使P(y|x)最大,就是使損失(LOSS)最小坪仇,因此取負(fù)號(hào)得\mathcal{L}(\hat{y},y)=-\log P(y|x)=-y\log \hat{y}-(1-y)\log (1-\hat{y}).

2.2?用矩陣描述問(wèn)題

????如果要編程來(lái)實(shí)現(xiàn)前述的單樣本Logistic Regression問(wèn)題萝衩,我們要寫(xiě)一個(gè)for循壞——

# Python 3
# input w,x,b
for i in range(n):
    z += w[i]x[i]
z += b

????實(shí)際上,在之前的描述中臊泰,我們已經(jīng)采用了一種記法缔御,記x=[x_1,x_2,\cdots,x_n]^\top,記w=[w_1,w_2,\cdots,w_n]^\top皆刺,然后用w^\top x來(lái)代替\Sigma ^n_{i=1}w_ix_i的過(guò)程少辣。在Python 3中,我們通過(guò)調(diào)用第三方庫(kù)numpy羡蛾,就可以用一行代碼z = np.dot(w.T,x) + b解決上面的問(wèn)題漓帅。
????那么如果有m份病毒樣本,這個(gè)檢測(cè)問(wèn)題又該如何表示痴怨?
????現(xiàn)有m份病毒樣本x^{(1)},x^{(2)},\cdots,x^{(m)}忙干,其中每份病毒樣本的n個(gè)特征為x^{(i)}=[x_1^{(i)},x_2^{(i)},\cdots,x_n^{(i)}]^\top,上標(biāo)^{(i)}表示第i份樣本浪藻,下標(biāo)_j表示第j個(gè)特征捐迫,例如x_1^{(3)}表示第3份病毒樣本的第1個(gè)特征。
????那么爱葵,我們的問(wèn)題變成了\hat{y}^{(i)}=g(z^{(i)})=g(w^\top x^{(i)}+b), {\rm where}\; g(z)=\sigma(z)=\frac{1}{1+e^{-z}}; {\rm given\;}\left \{ (x^{(1)},y^{(1)}),(x^{(2)},y^{(2)}),\cdots,(x^{(m)},y^{(m)})\right \},\;{\rm want}\;\hat{y}^{(i)}\approx y^{(i)}.????也就是把一個(gè)樣本的Logistic Regression重復(fù)m遍施戴。我們現(xiàn)在從編程的角度來(lái)思考一下,對(duì)于m份萌丈,每份有n個(gè)特征的樣本赞哗,要如何實(shí)現(xiàn)?
????顯然辆雾,我們要用2個(gè)for循環(huán)才能實(shí)現(xiàn)m個(gè)樣本肪笋,以及每個(gè)樣本n個(gè)特征的線性計(jì)算。

# Python 3
import numpy as np

def sigmoid(x):
    return 1/(1 + np.exp(-x))

# input: w,x,b

for i in range(m):
    for j in range(n):
        z += w[j] * x[i,j]
    z += b
    y_hat = sigmoid(z)
    z = 0

????這種方法的時(shí)間復(fù)雜度為O(n^2),是一個(gè)P問(wèn)題涂乌,還是過(guò)于復(fù)雜艺栈。我們考慮將前述的行向量乘列向量的做法推廣到m個(gè)樣本的情況下——
????記w=[w_1,w_2,\cdots,w_n]^\top(此時(shí)的權(quán)重還不會(huì)隨樣本變化,因此每個(gè)樣本在神經(jīng)網(wǎng)絡(luò)中施加的刺激強(qiáng)度都是同等的湾盒,等看完2.3節(jié)之后就知道權(quán)重變化時(shí)是什么情況了)湿右,記輸入為矩陣XXX = {\begin{bmatrix}x^{(1)}_1 & x^{(2)}_1 & \cdots & x^{(m)}_1\\ x^{(1)}_2 & x^{(2)}_2 & \cdots & x^{(m)}_2\\ \vdots & \vdots & \quad & \vdots\\ x^{(1)}_n & x^{(2)}_n & \cdots &x^{(m)}_n\\ \end{bmatrix}}_{n \times m}????我們用本科二年級(jí)學(xué)過(guò)的矩陣乘法就可以知道w^\top X = {\begin{bmatrix} w_1 & w_2 & \cdots & w_n \end{bmatrix}}_{1 \times n}{\begin{bmatrix} x^{(1)}_1 & x^{(2)}_1 & \cdots & x^{(m)}_1\\ x^{(1)}_2 & x^{(2)}_2 & \cdots & x^{(m)}_2\\ \vdots & \vdots &\quad &\vdots\\ x^{(1)}_n & x^{(2)}_n & \cdots &x^{(m)}_n\\ \end{bmatrix}}_{n \times m}????也即w^\top X = {\begin{bmatrix} \Sigma ^n_{i=1}w_ix^{(1)}_i & \Sigma ^n_{i=1}w_ix^{(2)}_i & \cdots & \Sigma ^n_{i=1}w_ix^{(m)}_i \end{bmatrix}}_{1 \times m}????繼而Z={\begin{bmatrix} z_1 & z_2 & \cdots & z_n \end{bmatrix}}_{1 \times m}=w^\top X+{\begin{bmatrix} b & b & \cdots & b \end{bmatrix}}_{1 \times m} Z={\begin{bmatrix} \Sigma ^n_{i=1}w_ix^{(1)}_i+b & \Sigma ^n_{i=1}w_ix^{(2)}_i+b & \cdots & \Sigma ^n_{i=1}w_ix^{(m)}_i+b \end{bmatrix}}_{1 \times m}????這在Python 3中可以寫(xiě)成Z = np.dot(w.T,X) + b[注5]罚勾。這種直接加常數(shù)b的操作毅人,就是將breshape到與之相加的矩陣維度再相加,Python中稱(chēng)之為廣播(Broadcasting)尖殃。

注5?為什么numpy中應(yīng)用矩陣操作可以降低時(shí)間復(fù)雜度丈莺?
????實(shí)際上,在numpy算法底層送丰,運(yùn)用了一種稱(chēng)為單指令多數(shù)據(jù)流(Single Instruction Multiple Data, SIMD)指令的操作缔俄,它使得多維數(shù)據(jù)可以在CPU中進(jìn)行并行計(jì)算,因此比for循環(huán)低效占用CPU的計(jì)算效率更高器躏。

????這里對(duì)mn在神經(jīng)網(wǎng)絡(luò)中的意義再作進(jìn)一步解釋?zhuān)?strong>n是每個(gè)樣本的特征總數(shù)俐载,決定了我們的神經(jīng)網(wǎng)絡(luò)有多少個(gè)輸入。m是樣本總數(shù)登失,決定了我們的神經(jīng)網(wǎng)絡(luò)要運(yùn)行多少次遏佣。
????到目前為止,我們?cè)谇拔乃龅墓ぷ骼空悖簿褪窃谏窠?jīng)網(wǎng)絡(luò)中進(jìn)行的從輸入到輸出的過(guò)程状婶,成為前向傳播(Forward Propagation)
????這時(shí)馅巷,在m個(gè)樣本的情況下膛虫,第i個(gè)樣本的損失函數(shù)就變成了\mathcal{L}(\hat{y}^{(i)},y^{(i)})=-y^{(i)}\log \hat{y}^{(i)}-(1-y^{(i)})\log (1-\hat{y}^{(i)});????我們用代價(jià)函數(shù)(Cost Function)來(lái)衡量共m個(gè)樣本的效果,記\mathcal{J}(\hat{y},y)=\frac{1}{m}\Sigma _{i=1}^m \mathcal{L}(\hat{y}^{(i)},y^{(i)});????又\hat{y}=\sigma(w^\top x+b)令杈,而x,y是樣本數(shù)據(jù)[注6]走敌,所以代價(jià)函數(shù)也可以改寫(xiě)為\mathcal{J}(w,b)=\frac{1}{m} \Sigma _{i=1}^m \mathcal{L}(\hat{y}^{(i)},y^{(i)}).

注6?在算法中,學(xué)習(xí)者必須明確區(qū)分代數(shù)符號(hào)表述的對(duì)象是變量(Variable)還是參量/參數(shù)(Parameter)逗噩。實(shí)際上,變量和參量要根據(jù)面對(duì)的問(wèn)題進(jìn)行具體分析跌榔。例如上例中异雁,w,b是參量,x,y是變量僧须。
????讀者可以嘗試分析纲刀,在本文介紹邏輯斯蒂回歸和梯度下降兩個(gè)算法中所用的代數(shù)符號(hào),哪些是參量担平?那些是變量示绊?

2.3?讓模型不斷優(yōu)化

????我們之前已經(jīng)介紹了損失函數(shù)\mathcal{L}(\hat{y},y)是對(duì)分類(lèi)結(jié)果的度量锭部。那么,如何讓LOSS盡可能的忻婧帧拌禾?也就是使\hat{y}更接近y,即P(y|x)最大展哭?

2.3.1?一點(diǎn)數(shù)理統(tǒng)計(jì)和微分操作

????在本科二年級(jí)湃窍,我們?cè)跀?shù)理統(tǒng)計(jì)中的參數(shù)估計(jì)部分學(xué)過(guò)極大似然估計(jì)(log-likelihood)方法。我們先從一個(gè)樣本開(kāi)始——\mathcal{L}(\hat{y},y)=-y\log \hat{y}-(1-y)\log (1-\hat{y})????在這個(gè)問(wèn)題中匪傍,我們估計(jì)的對(duì)象是\hat{y}您市,用極大似然估計(jì),求導(dǎo)有\frac{\mathrmmqmuei0\mathcal{L}(\hat{y},y)}{\mathrmgsq2gau\hat{y}}=-\frac{y}{\hat{y}}+\frac{1-y}{1-\hat{y}}????接著令\frac {\mathrmmmkywqo\mathcal{L}(\hat{y},y)}{\mathrmiweqoku\hat{y}}=0役衡,求使\mathcal{L}(\hat{y},y)取極小的\hat{y}即可茵休。
????這種表達(dá)實(shí)際上與我們的本科數(shù)學(xué)知識(shí)不太一致,實(shí)際上手蝎,\hat{y}是關(guān)于w,b的函數(shù)榕莺,那么我們將損失函數(shù)改寫(xiě)為\mathcal{L}(w,b),然后對(duì)兩個(gè)參數(shù)w,b偏導(dǎo)數(shù)柑船,然后采用同樣的極大似然估計(jì)方法帽撑,令——\frac {\partial\mathcal{L}(w,b)}{\partial w}=0,\frac {\partial\mathcal{L}(w,b)}{\partial b}=0????接著取最優(yōu)估計(jì)的參數(shù)w,b就完成了這個(gè)過(guò)程[注7]

注7?本文中的w,b都是向量鞍时,在數(shù)學(xué)上應(yīng)當(dāng)采用矢量運(yùn)算亏拉。本文的記法并不嚴(yán)格符合數(shù)學(xué)規(guī)則,僅說(shuō)理用逆巍。

2.3.2?梯度下降

????和對(duì)導(dǎo)數(shù)表爛熟于心的我們不同及塘,計(jì)算機(jī)對(duì)f(x)=x^2,則f^\prime (x)=2x這類(lèi)符號(hào)計(jì)算并不十分擅長(zhǎng)锐极。相反笙僚,計(jì)算機(jī)相比人腦在計(jì)算方面的最大優(yōu)勢(shì)在于數(shù)值計(jì)算,也就是說(shuō)灵再,在求導(dǎo)問(wèn)題上肋层,計(jì)算機(jī)更喜歡求函數(shù)在某一個(gè)點(diǎn)的導(dǎo)數(shù)值,而不是求導(dǎo)函數(shù)表達(dá)式翎迁。我們?cè)谇拔奶岬降囊粋€(gè)簡(jiǎn)單的求導(dǎo)(當(dāng)讓如果函數(shù)復(fù)雜來(lái)求顯式解析解可能也不那么簡(jiǎn)單)取0的步驟栋猖,在計(jì)算機(jī)中需要像微分的定義一樣一步步求一個(gè)精度閾值內(nèi)的近似解(閱讀參考)。
????在我們參數(shù)估計(jì)問(wèn)題中汪榔,計(jì)算機(jī)不能一步找到這個(gè)最優(yōu)的w,b蒲拉,那么,有沒(méi)有一種辦法,可以讓計(jì)算機(jī)更快地找到w,b雌团,更迅速地下降到\mathcal{L}(w,b)的最低點(diǎn)呢燃领?
????如果我們對(duì)多元函數(shù)微分學(xué)還有那么一點(diǎn)殘存的記憶,那么我們可以知道锦援,函數(shù)的方向?qū)?shù)在梯度方向上取得最大猛蔽。換言之,函數(shù)沿著梯度方向下降最快雨涛。借由這一點(diǎn)枢舶,我們給出了梯度下降(Gradient Descent)算法。
????Fig.5 是梯度下降的圖示替久。在多元函數(shù)微分學(xué)中凉泄,我們用\nabla \mathcal{J}(w^{(0)},b^{(0)})表示函數(shù)在(w^{(0)},b^{(0)})點(diǎn)處的梯度。梯度下降算法用遞歸表示就是——(w^{(i+1)},b^{(i+1)})=(w^{(i)},b^{(i)})-\alpha \nabla \mathcal{J} (w^{(i)},b^{(i)})????式中\alpha表示每次下降的步長(zhǎng)蚯根。

Figure 5.?梯度下降
????顯然后众,如果只有一個(gè)樣本,那么梯度下降只進(jìn)行一次颅拦,其效果當(dāng)然不會(huì)特別好蒂誉,這也就是為什么我們需要大量樣本的原因。
????在m個(gè)樣本的情況下距帅,我們進(jìn)行m次迭代右锨,就能準(zhǔn)確快速地估計(jì)出最優(yōu)參數(shù)(w,b)的值。我們發(fā)現(xiàn)此時(shí)(w,b)是隨樣本逐代變化的碌秸,這就可以理解為一種簡(jiǎn)單的學(xué)習(xí)機(jī)制绍移,我們前述的步長(zhǎng)\alpha也被稱(chēng)為學(xué)習(xí)率(Learning Rate)我們重復(fù)用m個(gè)樣本投入神經(jīng)網(wǎng)絡(luò)的過(guò)程,在機(jī)器學(xué)習(xí)中讥电,就是訓(xùn)練(Training)蹂窖。到這里,我認(rèn)為可以說(shuō)我們的神經(jīng)網(wǎng)絡(luò)具備了一種初級(jí)的智能要素恩敌。
????當(dāng)然瞬测,梯度下降也可能存在陷入局部最優(yōu)的問(wèn)題,所以一般在初始化梯度下降時(shí)纠炮,我們會(huì)根據(jù)經(jīng)驗(yàn)確定參數(shù)初值(w^{(0)},b^{(0)})月趟,也可能把它們定為隨機(jī)數(shù)或者零向量,以及學(xué)習(xí)率\alpha的大小恢口。也就是說(shuō)狮斗,從什么地方開(kāi)始下降(w,b),還有每一步跨越多少(α)非常重要弧蝇。關(guān)于梯度下降,你也可以在這里找到參考。
????我們現(xiàn)在用計(jì)算圖(Fig.6)回顧一下前文所述的過(guò)程看疗。從左到右計(jì)算分類(lèi)結(jié)果的過(guò)程(邏輯斯蒂回歸)稱(chēng)為前向傳播(Forward Propagation)過(guò)程沙峻;從右到左通過(guò)求導(dǎo)(這里多元函數(shù)求偏導(dǎo)數(shù)應(yīng)當(dāng)遵循鏈?zhǔn)椒▌t)估計(jì)最優(yōu)參數(shù)的過(guò)程(梯度下降)稱(chēng)為后向傳播(Backward Propagation)過(guò)程。通過(guò)前向傳播和反向傳播两芳,我們就構(gòu)建了一個(gè)比較完整的摔寨、由單個(gè)神經(jīng)元組成的神經(jīng)網(wǎng)絡(luò)。

Figure 6.?前向傳播與反向傳播

????讀者可以自行思考怎么把后向傳播(梯度下降)過(guò)程也用矩陣描述怖辆,然后編程實(shí)現(xiàn)是复。當(dāng)然,如果存在困難竖螃,記得善用搜索引擎和代碼托管平臺(tái)淑廊。

3?多層神經(jīng)網(wǎng)絡(luò)

????這種單層神經(jīng)網(wǎng)絡(luò)顯然只能解決線性分類(lèi)任務(wù)(Logistic回歸的特性導(dǎo)致的),不能解決現(xiàn)實(shí)的復(fù)雜問(wèn)題特咆。不過(guò)季惩,我們不妨回到我們開(kāi)始的地方,想想生物是怎么做的腻格。我們?cè)诟咧猩镏袑W(xué)過(guò)画拾,許多形態(tài)相似的細(xì)胞及細(xì)胞間質(zhì)構(gòu)成了生物組織,比如上皮組織菜职、結(jié)締組織等青抛。這些生物組織以及可以實(shí)現(xiàn)一些簡(jiǎn)單的人體機(jī)能。所以酬核,我們當(dāng)然也可以把神經(jīng)元組織起來(lái)去解決更復(fù)雜的問(wèn)題蜜另。

3.1?兩層神經(jīng)網(wǎng)絡(luò)

????我們給神經(jīng)網(wǎng)絡(luò)再加3個(gè)神經(jīng)元,這樣它就變成了有3個(gè)輸入特征x_1,x_2,x_3愁茁,4個(gè)神經(jīng)節(jié)點(diǎn)蚕钦,1個(gè)輸出\hat{y}的神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)(Fig.7)。

Figure 7.?兩層神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)

????我們將從左到右的節(jié)點(diǎn)分為三層鹅很,第0層嘶居,用上標(biāo)^{[0]}表示,稱(chēng)為輸入層(Input Layer);第1層促煮,用上標(biāo)^{[1]}表示邮屁,稱(chēng)為隱藏層(Hidden layer);第2層菠齿,用上標(biāo)^{[2]}表示佑吝,稱(chēng)為輸出層(Output Layer)。在這里用a^{[1]}_1表示第1層(隱藏層)的第1個(gè)神經(jīng)元進(jìn)行的運(yùn)算后的輸出绳匀,用a^{[2]}表示輸出層神經(jīng)元的運(yùn)算后的輸出\hat{y}芋忿。
????現(xiàn)在網(wǎng)絡(luò)中的所有連接(連線)都對(duì)應(yīng)著自己的權(quán)重w炸客,每層都對(duì)應(yīng)一個(gè)自己的偏差b(層內(nèi)的節(jié)點(diǎn)公用一個(gè)參數(shù)b)。我們將傳入每個(gè)神經(jīng)元的wb記為一組戈钢。例如痹仙,以隱藏層第1個(gè)神經(jīng)元為例,w_1^{[1]}=[w_{(1,1)}^{[1]},w_{(2,1)}^{[1]},w_{(3,1)}^{[1]}]^\top就相當(dāng)于原來(lái)單層神經(jīng)網(wǎng)絡(luò)中的w殉了,記神經(jīng)元輸入為a^{[0]}=x=[x_1,x_2,x_3]^\top類(lèi)似地开仰,我們的計(jì)算就成為了——a^{[1]}_1=\sigma({w^{[1]}_1}^\top a^{[0]}+b^{[1]});????對(duì)應(yīng)有a^{[1]}_2=\sigma({w^{[1]}_2}^\top a^{[0]}+b^{[1]}),其中w_2^{[1]}=[w_{(1,2)}^{[1]},w_{(2,2)}^{[1]},w_{(3,2)}^{[1]}]^\top .
????第2層為a^{[2]}=\sigma({w^{[2]}}^\top a^{[1]}+b^{[2]})=\hat{y};????其中w^{[2]}=[w_1^{[2]},w_2^{[2]},w_3^{[2]},w_4^{[2]}]^\top,a^{[1]}=[a^{[1]}_1,a^{[1]}_2,a^{[1]}_3,a^{[1]}_4]^\top.
????如果也擴(kuò)充到m個(gè)樣本(每個(gè)樣本n個(gè)特征)的情況薪铜,仍然用上標(biāo)^{(i)}表示第i個(gè)樣本众弓,那么,我們用前述的矩陣表達(dá)把這些向量堆疊起來(lái)隔箍,就有——W^{[1]}={\begin{bmatrix} w^{[1](1)}_1 & w^{[1](1)}_2 & \cdots & w^{[1](1)}_n\\ w^{[1](2)}_1 & w^{[1](2)}_2 & \cdots& w^{[1](2)}_n\\ \vdots& \vdots & \quad &\vdots\\ w^{[1](m)}_1 & w^{[1](m)}_2 & \cdots & w^{[1](m)}_n \end{bmatrix}}_{m \times n}????通過(guò)類(lèi)似的方法谓娃,我們就可以逐層完成表示,也就是前向傳播過(guò)程鞍恢。相應(yīng)地傻粘,反向傳播的過(guò)程就是將求導(dǎo)的對(duì)象堆疊起來(lái),此處不再贅述帮掉。
????理論上弦悉,兩層神經(jīng)網(wǎng)絡(luò)可以無(wú)限逼近任意連續(xù)函數(shù)。作者個(gè)人并不十分喜歡這句話(huà)蟆炊,在目前的深度學(xué)習(xí)教材和專(zhuān)著中經(jīng)常能看見(jiàn)這句話(huà)稽莉,但對(duì)于其原因都未作解釋。作者在Colah的博客中找到了一個(gè)反面的驗(yàn)證涩搓。實(shí)際上就是污秆,面對(duì)復(fù)雜的非線性分類(lèi)任務(wù),兩層(帶一個(gè)隱藏層)神經(jīng)網(wǎng)絡(luò)可以分類(lèi)的很好昧甘。

Figure 8.?兩層神經(jīng)網(wǎng)絡(luò)的決策分界

????在 Fig.8 中可以看到良拼,這個(gè)兩層神經(jīng)網(wǎng)絡(luò)的決策分界是非常平滑的曲線,而且分類(lèi)的很好充边∮雇疲可是單層網(wǎng)絡(luò)只能解決線性分類(lèi)任務(wù),而兩層神經(jīng)網(wǎng)絡(luò)中的后一層也是線性分類(lèi)層浇冰,應(yīng)該只能做線性分類(lèi)任務(wù)贬媒。為什么兩個(gè)線性分類(lèi)任務(wù)結(jié)合就可以做非線性分類(lèi)任務(wù)?

Figure 9.?空間變換后的決策分界

????我們把輸出層的決策分界單獨(dú)拿出來(lái)看(Fig.9)肘习,輸出層的決策分界仍然是直線际乘。關(guān)鍵就是,從輸入層到隱藏層時(shí)漂佩,數(shù)據(jù)發(fā)生了空間變換脖含。也就是說(shuō)罪塔,兩層神經(jīng)網(wǎng)絡(luò)中,隱藏層對(duì)原始的數(shù)據(jù)進(jìn)行了一個(gè)空間變換器赞,使其可以被線性分類(lèi)垢袱,然后輸出層的決策分界劃出了一個(gè)線性分類(lèi)分界線,對(duì)其進(jìn)行分類(lèi)港柜。這樣就導(dǎo)出了兩層神經(jīng)網(wǎng)絡(luò)可以做非線性分類(lèi)的關(guān)鍵——隱藏層。我們知道咳榜,矩陣和向量相乘夏醉,本質(zhì)上就是對(duì)向量的坐標(biāo)空間進(jìn)行一個(gè)變換。因此涌韩,隱藏層的參數(shù)矩陣的作用就是使得數(shù)據(jù)的原始坐標(biāo)空間從線性不可分(Fig.8 的紅藍(lán)區(qū)域曲線邊界)畔柔,轉(zhuǎn)換成了線性可分(Fig.9 的紅藍(lán)區(qū)域直線邊界)。
????簡(jiǎn)而言之臣樱,隱藏層干了什么靶擦?隱藏層對(duì)向量空間進(jìn)行了空間變換,使得非線性分類(lèi)問(wèn)題在變換后的向量空間下變成了線性分類(lèi)問(wèn)題雇毫。

3.2?深度神經(jīng)網(wǎng)絡(luò)

????如果我們讓網(wǎng)絡(luò)的層數(shù)進(jìn)一步增加會(huì)怎么樣玄捕?在思路上沒(méi)有變化,還是前向傳播加后向傳播的過(guò)程棚放,還是要用矩陣來(lái)描述問(wèn)題枚粘。此時(shí),我們反而更關(guān)注網(wǎng)絡(luò)本身的問(wèn)題飘蚯。

Figure 10.

????Fig.10 中的神經(jīng)網(wǎng)絡(luò)(神經(jīng)元)有3 \times 1=3個(gè)w參數(shù)馍迄,1個(gè)b參數(shù),共有3+1=4個(gè)參數(shù)局骤。

Figure 11.

????Fig.11 中的神經(jīng)網(wǎng)絡(luò)(神經(jīng)元)有3 \times 4+4 \times 1=16個(gè)w參數(shù)攀圈,1+1=2個(gè)b參數(shù),共有16+2=18個(gè)參數(shù)峦甩。

Figure 12.

????Fig.12 中的神經(jīng)網(wǎng)絡(luò)(神經(jīng)元)有8 \times 5+5 \times 5+5 \times 5+ 5 \times 2=100個(gè)w參數(shù)赘来,1+1+1+1=4個(gè)b參數(shù),共有100+4=104個(gè)參數(shù)穴店。注意在 Fig.12 的網(wǎng)絡(luò)中撕捍,與前面介紹的網(wǎng)絡(luò)不同,有3個(gè)輸出泣洞。

Figure 13.

????我們討論參數(shù)有什么意義呢? Fig.13 中忧风,上下兩個(gè)網(wǎng)絡(luò),分別有33+3=36個(gè)和33+5=38個(gè)參數(shù)球凰,它們的w參數(shù)數(shù)量是一致的狮腿,但是層數(shù)卻不同腿宰,分別為3層和5層(第0層輸入層不計(jì)入在內(nèi))。這表明缘厢,我們可以用相同量的參數(shù)吃度,但是更多的層次來(lái)構(gòu)建神經(jīng)網(wǎng)絡(luò),這反映了神經(jīng)網(wǎng)絡(luò)的表達(dá)能力贴硫。神經(jīng)網(wǎng)絡(luò)的表達(dá)能力主要由隱層的層數(shù)和隱層神經(jīng)元個(gè)數(shù)決定椿每。隱藏層的層數(shù)就可以看作是神經(jīng)網(wǎng)絡(luò)的深度(Depth),這也就是在神經(jīng)網(wǎng)絡(luò)中的機(jī)器學(xué)習(xí)稱(chēng)為“深度”學(xué)習(xí)(連接主義學(xué)派)的原因英遭。在參數(shù)數(shù)量一樣的情況下间护,更深的網(wǎng)絡(luò)往往具有比淺層的網(wǎng)絡(luò)更好的識(shí)別效率。
????當(dāng)然挖诸,我們對(duì)參數(shù)的討論還沒(méi)有結(jié)束汁尺。設(shè)計(jì)一個(gè)神經(jīng)網(wǎng)絡(luò)我們要考慮,隱藏層的數(shù)量\rm \#Layer多律,每層的神經(jīng)元數(shù)量\rm \#Neuron痴突,這些量可以視為確定神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)的超參數(shù)(Hyper-parameters)處理。這個(gè)問(wèn)題在卷積神經(jīng)網(wǎng)絡(luò)(Convolutionnal Neural Network, CNN)中更為明顯狼荞。
????在Logistic Regression中辽装,神經(jīng)元的非線性單元使用的激活函數(shù)是Sigmoid函數(shù)\sigma(z)=\frac{1}{1+e^{-z}},實(shí)際上粘秆,目前的神經(jīng)網(wǎng)絡(luò)更常用的激活函數(shù)還有雙曲正切函數(shù)(tanh)如迟、線性整流函數(shù)/修正線性單元(Rectified Linear Unit, ReLU)和帶泄露的修正線性單元(Leaky ReLUs)等。圖像如 Fig.14 所示攻走。具體的用法可以參考這里殷勘,此處不再說(shuō)明。

Figure 14.?非線性激活函數(shù)

4?總??結(jié)

????生物接受到刺激昔搂,\rm Na^+離子內(nèi)流玲销,產(chǎn)生了一個(gè)電信號(hào),這個(gè)電信號(hào)傳到神經(jīng)元胞體時(shí)摘符,胞體不知道自己對(duì)這個(gè)電信號(hào)的處理所做為何贤斜。但是當(dāng)前860億個(gè)神經(jīng)元組織起來(lái),人就產(chǎn)生了智能逛裤。這種想法未免失之偏頗瘩绒,但在作者看來(lái),人工神經(jīng)網(wǎng)絡(luò)在本質(zhì)上并不復(fù)雜带族,“線性運(yùn)算锁荔、非線性激活、梯度下降尋求最優(yōu)參數(shù)給下一次迭代使用”蝙砌,僅此而已阳堕。但是跋理,當(dāng)神經(jīng)網(wǎng)絡(luò)具備一定的規(guī)模,神經(jīng)元達(dá)到一定的數(shù)量時(shí)恬总,這些簡(jiǎn)單的單元卻形成了強(qiáng)大的計(jì)算合力前普。這樣量變引起質(zhì)變的過(guò)程,也體現(xiàn)著樸素的唯物辯證法壹堰。
????作者認(rèn)為拭卿,人工神經(jīng)網(wǎng)絡(luò)中要把握的幾個(gè)“綱”在于——
????其一,每個(gè)神經(jīng)元在干什么缀旁?前向傳播時(shí)记劈,它們進(jìn)行一次加權(quán)加偏置的線性運(yùn)算,再進(jìn)行一次非線性激活并巍;后向傳播時(shí),它們用鏈?zhǔn)椒▌t求(偏)微分去找最優(yōu)的參數(shù)换途。然后用這組參數(shù)進(jìn)行下一代(下一個(gè)樣本)的前向傳播懊渡。
????其二,隱藏層在干什么军拟?隱藏層對(duì)向量空間進(jìn)行了空間變換剃执,使得非線性分類(lèi)問(wèn)題在變換后的向量空間下變成了線性分類(lèi)問(wèn)題。
????其三懈息,一個(gè)神經(jīng)網(wǎng)絡(luò)是好是壞取決于什么肾档?取決于為解決問(wèn)題而投入大量樣本迭代訓(xùn)練出來(lái)的那些最優(yōu)參數(shù)。(這也就是為什么YOLO等模型中.weights文件十分關(guān)鍵的原因辫继。)

Figure 15.?人工神經(jīng)網(wǎng)絡(luò)的發(fā)展史

????數(shù)十年間怒见,人工神經(jīng)網(wǎng)絡(luò)起起落落(Fig.15),彼時(shí)的算力遠(yuǎn)不及此時(shí)姑宽。而在GPU遣耍、并行計(jì)算、分布式計(jì)算炮车、大數(shù)據(jù)量支持變得尋常的今天舵变,人工神經(jīng)網(wǎng)絡(luò)恰逢其時(shí)。不管符號(hào)主義學(xué)派和連接主義學(xué)派相愛(ài)相殺爭(zhēng)辯到幾時(shí)瘦穆,對(duì)于面向工程問(wèn)題的我們來(lái)說(shuō)纪隙,“不管白貓黑貓,抓到耗子就是好貓扛或∶嘣郏”

Acknowledgement

????在深度神經(jīng)網(wǎng)絡(luò)部分,作者參考了“計(jì)算機(jī)的潛意識(shí)”的這篇博文告喊,全文從神經(jīng)網(wǎng)絡(luò)的歷史角度詳細(xì)介紹了前向傳播網(wǎng)絡(luò)麸拄,一些思想給了作者以很大啟發(fā)派昧,在此致謝。


作者后記

????這篇文檔用了3天寫(xiě)完拢切,本來(lái)是準(zhǔn)備從DNN一直寫(xiě)到CNN蒂萎、RNN,無(wú)奈能力和時(shí)間有限淮椰,文中也有很多坑沒(méi)有填上五慈,等待下次修訂。
????寫(xiě)這篇文檔的過(guò)程主穗,也是我重新理解經(jīng)典人工神經(jīng)網(wǎng)絡(luò)模型的過(guò)程泻拦,在思辨中也補(bǔ)上了很多細(xì)節(jié)『雒剑《論語(yǔ)》說(shuō)争拐,”日知其所亡,月無(wú)忘其所能晦雨,可謂好學(xué)也已矣架曹。“距離這個(gè)境界還差得很遠(yuǎn)闹瞧,只能鞭策自己積跬步以至千里了绑雄。(2020年2月21日子夜)


修訂記錄

[1] 2020年2月21日發(fā)布.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市奥邮,隨后出現(xiàn)的幾起案子万牺,更是在濱河造成了極大的恐慌,老刑警劉巖洽腺,帶你破解...
    沈念sama閱讀 211,561評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件脚粟,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡已脓,警方通過(guò)查閱死者的電腦和手機(jī)珊楼,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,218評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)度液,“玉大人厕宗,你說(shuō)我怎么就攤上這事《榈#” “怎么了已慢?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,162評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)霹购。 經(jīng)常有香客問(wèn)我佑惠,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,470評(píng)論 1 283
  • 正文 為了忘掉前任膜楷,我火速辦了婚禮旭咽,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘赌厅。我一直安慰自己穷绵,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,550評(píng)論 6 385
  • 文/花漫 我一把揭開(kāi)白布特愿。 她就那樣靜靜地躺著仲墨,像睡著了一般。 火紅的嫁衣襯著肌膚如雪揍障。 梳的紋絲不亂的頭發(fā)上目养,一...
    開(kāi)封第一講書(shū)人閱讀 49,806評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音毒嫡,去河邊找鬼癌蚁。 笑死,一個(gè)胖子當(dāng)著我的面吹牛兜畸,可吹牛的內(nèi)容都是我干的匈勋。 我是一名探鬼主播,決...
    沈念sama閱讀 38,951評(píng)論 3 407
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼膳叨,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了痘系?” 一聲冷哼從身側(cè)響起菲嘴,我...
    開(kāi)封第一講書(shū)人閱讀 37,712評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎汰翠,沒(méi)想到半個(gè)月后龄坪,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,166評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡复唤,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,510評(píng)論 2 327
  • 正文 我和宋清朗相戀三年健田,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片佛纫。...
    茶點(diǎn)故事閱讀 38,643評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡妓局,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出呈宇,到底是詐尸還是另有隱情好爬,我是刑警寧澤,帶...
    沈念sama閱讀 34,306評(píng)論 4 330
  • 正文 年R本政府宣布甥啄,位于F島的核電站存炮,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜穆桂,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,930評(píng)論 3 313
  • 文/蒙蒙 一宫盔、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧享完,春花似錦灼芭、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,745評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至倒源,卻和暖如春苛预,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背笋熬。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,983評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工热某, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人胳螟。 一個(gè)月前我還...
    沈念sama閱讀 46,351評(píng)論 2 360
  • 正文 我出身青樓昔馋,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親糖耸。 傳聞我的和親對(duì)象是個(gè)殘疾皇子秘遏,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,509評(píng)論 2 348

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