西瓜書筆記

嵌入式視覺發表於2023-01-06

第 2 章 模型評估與選擇

2.1 經驗誤差與過擬合

  • 精度:精度=1-錯誤率。如果在 \(m\) 個樣本中有 \(a\) 個樣本分類錯誤,則錯誤率 \(E=a/m\),精度 = \(1-a/m\)
  • 誤差:一般我們把學習器的實際預測輸出與樣本的真實輸出之間的差異稱為“誤差”(error)。學習器在訓練集上的誤差稱為“訓練誤差”(training error),在新樣本上的誤差稱為“泛化誤差”(generalization error)。
  • 過擬合:學習器把訓練樣本自身的一些特點當作了所有潛在樣本都會具有的一般性質,從而導致泛化效能下降,這種現象稱為”過擬合“(overfitting)。過擬合是機器學習演算法面臨的一個關鍵問題。
  • 欠擬合:和過擬合想法,指的是學習器對訓練樣本的一般性質都未學號。欠擬合比較容器解決,在決策樹中增加分治、在神經網路學習中學習訓練輪數(Epoch)等方法都是有效的。

好的學習器應該儘可能學出適用於所有潛在樣本的”普遍規律“。由於事先無法知道新樣本是什麼樣子,所以無法直接獲得泛化誤差,同時訓練誤差又由於過擬合現象的存在而不適合作為標準,那麼現實中如何進行模型評估與選擇就是一個重要的問題了。

2.2 評估方法

通常使用一個測試集來評估學習器對新樣本的判別能力,把測試集上的”測試誤差“(testing error)作為泛化誤差的近似。值得注意的是,測試集應該儘可能與訓練集互斥,即測試樣本儘量不在訓練集中出現(學習器之前沒有見到過)。

對於一個包含 \(m\) 個樣本的資料集 \(D = {(x_1, y_1)}, (x_2, y_2),...,(x_m, y_m)\),將其劃分為訓練集 \(S\) 和測試集 \(T\),有兩種常見的方法:留出法和交叉驗證法

2.2.1 留出法

”留出法“(hold-out) 直接將資料集 \(D\) 劃分為兩個戶次互斥的集合,一個集合作為訓練集 \(S\),另一個作為測試集 \(T\),即 \(D = S \cup T\)\(S \cap T = \emptyset\)。值得注意的是,訓練/測試集的劃分應該儘可能保持資料分佈的一致性,避免資料劃分過程引入額外的偏差而對最終結果產生影響。從取樣(sampling)的角度來看資料集的劃分過程,則保留類別比例的取樣方式稱為”分層取樣“(stratified sampling)。例如資料集 \(D\)1000 個樣本,800 個正樣本,200 個負樣本,將 70% 的樣本作為訓練集,30% 的樣本作為測試集。考慮分層取樣,則訓練 \(S\) 集的構成為:正樣本 \(= 1000\times 70\% \times (800/1000) = 560\),負樣本 \(=1000\times 70\% \times (200/1000) = 140\),同理可得測試集 T 包含 240 個正樣本,60 個負樣本。

另一個問題是即使在給定訓練集/測試集樣本比例後,依然存在多種劃分方式對樣本 \(D\) 進行分割,例如前 280 個正樣本和後 280 個正樣本構建的訓練集是不一樣的。因此,單次使用留出法得到的的估計結果往往不可靠,在使用留出法時,一般採用若干次隨機劃分、重複進行實驗評估後取平均值作為留出法的評估結果。

2.2.2 交查驗證法

”交叉驗證法“(cross validation)先將資料集 \(D\) 劃分為 \(k\) 個大小相似的互斥子集,即 \(D = D_1\cup D_2\cup...\cup D_k,D_i \cap D_j = \emptyset\)。同時每個子集都應該儘可能保持資料分佈的一致性,即類別比例相等,從 \(D\) 中透過分層取樣得到。然後,每次用 \(k-1\) 個子集的並集作為訓練集,剩下的一個子集作為測試集,這樣可獲得 \(k\) 組訓練集/測試集,從而可進行 \(k\) 組訓練和測試,把 \(k\) 次測試結果取平均後返回。交叉驗證法評估結果的穩定性和保真性在很大程度上取決於 \(k\) 的取值,為了強調這一點,通常把交叉驗證法稱為“\(k\) 折交叉驗證”(k-fold cross validation)。\(k\) 的常用取值分別是 10、5、20 等。圖 2.2 給出了 10 折交叉驗證的示意圖。

10折交叉驗證示意圖

“10 次 10 折交叉驗證法”與 “100 次留出法“都是進行了 100 次訓練/測試。

交叉驗證法的一個特例是留一法(Leave-One-Out,簡稱 LDO),留一法不受隨機樣本劃分方式的影響,因為 \(m\) 個樣本只有唯一的劃分方式劃分為 \(m\) 個子集-每個子集包含一個樣本。雖然留一法的評估結果往往被認為比較準確,但是訓練開銷簡直太大了,真實專案中很少見到有人這樣用,而且留一法的估計結果未必永遠比其他評估方法準確,畢竟“天下沒有免費的午餐”。

2.2.3 自助法

“自助法”(bootstrapping) :給定包含 \(m\) 個樣本的資料集 \(D\),對它進行取樣產生資料集 \({D}'\):每次隨機從 \(D\) 中挑選一個樣本,將其複製放入 \({D}'\),然後再將其放回 \(D\) 中,下次取樣依然可能被取樣到;這個過程重複 \(m\) 次,就得到了包含 \(m\) 個樣本的資料集 \({D}'\)。顯然,\(D\) 中有一部分樣本會在 \({D}'\) 中多次出現,另外一部分樣本不出現。做一個簡單估計,樣本在 \(m\) 次取樣中始終不被採到的機率是 \((1-\frac{1}{m})^m\),取極限得到如下所式:

\[(1-\frac{1}{m})^m \rightarrow \frac{1}{e}\approx 0.368 \]

即透過自助取樣,初始資料集 \(D\) 中約有 36.8% 的樣本未出現在取樣資料集 \({D}'\) 中。

自助法只適用於資料集較小、難以有效劃分訓練/測試集的情況。值得注意的是,自助法產生的資料集改變了初始資料集的分佈,這回引入估計偏差。

2.2.4 調參與最終模型

需要認為設定的引數稱為超引數,模型訓練無法最佳化它的。現實當中常對每個引數選定一個範圍和變化補償,例如在 [0,0.2] 範圍內以 0.05 為補償,要評估的的候選引數有 5 個最終選定的引數從這 5 個候選值中產生,結果也許不是最佳值,但這是計算開銷和效能估計之間進行折中的結果。

在模型評估與選擇過程中由於需要流出一部分資料進行評估測試,事實上我們只使用了一部分資料訓練模型。因此,在模型選擇完成後,學習演算法和引數配置已定,此使應該用資料集 \(D\) 重新訓練模型。這個模型在訓練過程中使用了所有 \(m\) 個訓練樣本,這個模型也是最終提交給使用者的模型。

另外,值得注意的是,我們通常把學得模型在實際使用過程中遇到的資料集稱為測試資料,為了加以區分,前面講到的模型評估與選擇中用於評估測試的資料常稱為“驗證集(validation set)”。

在研究對比不同演算法的泛化效能時,我們用測試集上的判別效果來估計模型在實際使用時的泛化能力,而把訓練資料另外劃分為訓練集和驗證集,基於驗證集上的效能來進行模型選擇和調參。

2.3 效能度量

對學習器的泛化效能進行評估,不僅需要有效可行的實驗估計方法,還需要衡量模型泛化能力的評價標準,這就是效能度量(performance measure)。

在預測任務中,給定樣本集 \(D={(x_1,y_1),(x_2,y_2),...,(x_m,y_m)}\),其中 \(y_i\) 是示例 \(x_i\) 的真實標籤。要評估學習器 \(f\) 的效能,需要把學習器預測結果 \(f(x)\) 與真實標籤 \(y\) 進行比較。

迴歸任務最常用的效能度量是“均方誤差”(mean squared error)。

\[E(f;D) = \frac{1}{m}\sum_{i=1}^{m}(f(x_i)-y_i)^2 \]

2.3.1 錯誤率與精度

  • 錯誤率:分類錯誤的樣本數佔樣本總數的比例;
  • 精度:分類正確樣本的樣本數佔樣本總數的比例。

錯誤率和精度是分類任務中最常用的兩種效能度量,適用於二分類,也適用於多分類任務。分類錯誤率和精度的定義如下:

\[E(f;D) = \frac{1}{m}\sum_{i=1}^{m}(f(x_i) \neq y_i)^2 \]

\[acc(f;D) = \frac{1}{m}\sum_{i=1}^{m}(f(x_i) = y_i)^2 = 1 - E(f;D) \]

2.3.2 查準率、查全率與F1

錯誤率和精度雖然常用,但是並不能滿足所有任務需求。比如以西瓜問題為例,假設瓜農拉來一車西瓜,我們用訓練好的模型對西瓜進行判別,現如精度只能衡量有多少比例的西瓜被我們判斷類別正確(兩類:好瓜、壞瓜)。但是若我們更加關心的是“挑出的西瓜中有多少比例是好瓜”,或者”所有好瓜中有多少比例被挑出來“,那麼精度和錯誤率這個指標顯然是不夠用的。

對於二分類問題,可將樣例根據真實類別與學習器預測類別的組合劃分為真正例(true positive)、假正例(false positive)、真反例(true negative)、假反例(false negative)四種情況,令 \(TP、FP、TN、FN\) 分別表示其對應的樣例數,顯然有 $TP+FP+TN+FN = $ 樣例總數。分類結果的”混淆矩陣“(confusion matrix)如下表所示。

混淆矩陣

查準率(精確率) \(P\) 與查全率(召回率) \(R\) 分別定義為:

\[P = \frac{TP}{TP+FP} \\ R = \frac{TP}{TP+FN} \]

查準率和查全率是一對矛盾的的度量。一般來說,查全率高時,查準率往往偏低;而查全率高時,查準率往往偏低。通常只有在一些簡單任務中,才可能使查全率和查準率都很好高。

精準率和召回率的關係可以用一個 P-R 圖來展示,以查準率 P 為縱軸、查全率 R 為橫軸作圖,就得到了查準率-查全率曲線,簡稱 P-R 曲線,PR 曲線下的面積定義為 AP

PR曲線圖

為了繪圖方便和美觀,示意圖顯示出單調平滑曲線,但現實任務中的 P-R 曲線是非單調、不平滑的,且在很多區域性有上下波動。

如何理解 P-R 曲線呢

可以從排序型模型或者分類模型理解。以邏輯迴歸舉例,邏輯迴歸的輸出是一個 01 之間的機率數字,因此,如果我們想要根據這個機率判斷使用者好壞的話,我們就必須定義一個閾值 。通常來講,邏輯迴歸的機率越大說明越接近 1,也就可以說他是壞使用者的可能性更大。比如,我們定義了閾值為 0.5,即機率小於 0.5 的我們都認為是好使用者,而大於 0.5 都認為是壞使用者。因此,對於閾值為 0.5 的情況下,我們可以得到相應的一對查準率和查全率。
但問題是:這個閾值是我們隨便定義的,我們並不知道這個閾值是否符合我們的要求。 因此,為了找到一個最合適的閾值滿足我們的要求,我們就必須遍歷 01 之間所有的閾值,而每個閾值下都對應著一對查準率和查全率,從而我們就得到了 PR 曲線。
最後如何找到最好的閾值點呢? 首先,需要說明的是我們對於這兩個指標的要求:我們希望查準率和查全率同時都非常高。 但實際上這兩個指標是一對矛盾體,無法做到雙高。圖中明顯看到,如果其中一個非常高,另一個肯定會非常低。選取合適的閾值點要根據實際需求,比如我們想要高的查全率,那麼我們就會犧牲一些查準率,在保證查全率最高的情況下,查準率也不那麼低。

在進行效能比較時,如果一個學習器的曲線被另一個學習器的曲線完全包住,則可斷言後者效能優於前者,如圖 2.3,學習器 A 效能優於學習器 C。比較 P-R 曲線下面積的大小,也可判別學習器的優劣,它在一定程度上表徵了學習器在查準率和查全率上取得”雙高“的比例,但這個值不容易估算,因此人們又設計了一些綜合考慮查準率、查全率的效能度量,如”平衡點(Break-Event Point,簡稱 BEP)“。

BEP 是”查準率=查全率“時的取值,基於學習器的比較,可以認為學習器 A 優於 B。但 BEP 過於簡單了,更為常用的是 \(F1\) 度量。

\[F1 = \frac{2\times P\times R}{P+R} = \frac{2\times TP}{樣例總數+TP-TN} \]

\(F1\) 度量的一般形式:\(F_{\beta}\),能讓我們表達出對查準率/查全率的偏見,\(F_{\beta}\) 計算公式如下:

\[F_{\beta} = \frac{1+\beta^{2}\times P\times R}{(\beta^{2}\times P)+R} \]

其中 β > 1 對查全率有更大影響,\(\beta < 1\) 對查準率有更大影響。

很多時候我們會有多個混淆矩陣,例如進行多次訓練/測試,每次都能得到一個混淆矩陣;或者是在多個資料集上進行訓練/測試,希望估計演算法的”全域性“效能;又或者是執行多分類任務,每兩兩類別的組合都對應一個混淆矩陣;....總而來說,我們希望能在 \(n\) 個二分類混淆矩陣上綜合考慮查準率和查全率。

一種直接的做法是先在各混淆矩陣上分別計算出查準率和查全率,記為\((P_1,R_1),(P_2,R_2),...,(P_n,R_n)\)然後取平均,這樣得到的是”宏查準率(Macro-P)“、”宏查準率(Macro-R)“及對應的”宏\(F1\)Macro-F1)“:

\[\begin{aligned} Macro\ P &= \frac{1}{n}\sum_{i=1}^{n}P_i \\ Macro\ R &= \frac{1}{n}\sum_{i=1}^{n}R_i \\ Macro\ F1 &= \frac{2 \times Macro\ P\times Macro\ R}{Macro\ P + Macro\ R} \end{aligned}\]

另一種做法是將各混淆矩陣對應元素進行平均,得到 \(TP、FP、TN、FN\) 的平均值,再基於這些平均值計算出”微查準率“(Micro-P)、”微查全率“(Micro-R)和”微\(F1\)“(Mairo-F1

\[\begin{aligned} Micro\ P &= \frac{\overline{TP}}{\overline{TP}+\overline{FP}} \\ Micro\ R &= \frac{\overline{TP}}{\overline{TP}+\overline{FN}} \\ Micro\ F1 &= \frac{2 \times Micro\ P\times Micro\ R}{MacroP+Micro\ R} \end{aligned}\]

2.3.3 ROC 與 AUC

ROC 曲線示意圖如下。

PR曲線圖

2.5 偏差與方差

透過前面的學習,我們已經知道如何設計實驗(訓練集、驗證集的劃分)來對學習器的泛化誤差進行評估,並且也瞭解了諸如精度、查準率、查全率及 F1 等效能度量指標。但這不夠,我們還希望瞭解”為什麼“具有這樣的效能。”偏差-方差分解“(bias-variance decomposition)是解釋學習演算法泛化效能的一種重要工具。

假設對於測試樣本 \(x\),令 \(y_D\)\(x\) 在資料集中的標記(即標籤,可能會存在噪聲),\(y\) 才是 \(x\) 的真實標記,\(f(x;D)\) 為訓練集 \(D\) 上學得模型 \(f\)\(x\) 上的預測輸出。以迴歸任務為例,演算法的泛化誤差計算如下:

\[E(f;D) = \mathbb{E}_{D} [(f(x;D) - y_{D})^2] \]

直接計算上式是不行的,我們得進行分解,分解之前需要先知道方差、偏差、噪聲的定義。學習演算法的期望預測

\[\bar{f}(x) = \mathbb{E}_{D} [(f(x;D)] \]

方差定義: 模型預測的期望值與預測值之差的平方的期望值,使用樣本數相同的不同訓練集產生的方差

\[D(x) = var(x) = \mathbb{E}_{D}[(f(x;D) - \mathbb{E}_{D}[(f(x;D)])^2] = \mathbb{E}_{D}[(f(x;D) - \bar{f}(x))^2] \]

方差在統計描述和機率分佈中各有不同的定義,並有不同的公式。

噪聲

\[\varepsilon^2 = \mathbb{E}_{D}[(y_{D} - y)^2] \]

模型預測的期望值與真實值的差稱為偏差bias),即

\[bias^2(x) = (\bar{f}(x)-y)^2 \]

假定噪聲為 0 ,即 \(\mathbb{E}_{D}[(y_{D}-y)]=0\),有了以上定義,透過多項式展開合併,並利用恆等變形、期望的運算性質可將期望泛化誤差公式進行分解得到:

公式推理證明,可參考這裡

\[E(f;D) = \mathbb{E}_{D}[(f(x;D)-\bar{f}(x))^2] + (\bar{f}(x)-y)^2 + \mathbb{E}_{D}[(y_{D}-y)^2] \]

於是,

\[E(f;D) = var(x) + bias^2(x) + \varepsilon^2 \]

透過上式,可知泛化誤差可分解為方差、偏差與噪聲之和。回顧偏差、方差、噪聲的定義:

  • 偏差:度量了學習演算法的期望預測與真實結果的偏離程度,刻畫了學習演算法本身的擬合能力。
  • 方差:度量了同樣大小的訓練集的變動導致的學習效能的變化,刻畫了資料擾動所造成的影響,或者說刻畫了模型的穩定性和泛化能力。
  • 噪聲:表達了當前任務上任何學習演算法所能達到的期望泛化誤差的下界,即刻畫了學習問題本身的難度。

透過對泛化誤差進行分解說明,模型泛化效能是由學習演算法的能力、資料的充分性以及任務本身的難度所共同決定的。模型欠擬合表現為偏差較大, 此時偏差主導了泛化錯誤率;模型過擬合表現為偏差小但是方差很大,方差主導了泛化錯誤率。

一般來說,偏差與方差是有衝突的,這稱為偏差-方差窘境(bias-variane dilemma)。

泛化誤差與偏差方差的關係示意圖

第 3 章 線性模型

3.5 多分類學習

3.6 類別不平衡問題

\[\frac{y'}{1-y'} = \frac{y}{1-y}\times \frac{m^-}{m^+} \]

公式中,\(y\) 是預測值,分類器決策規則為:若 \(\frac{y}{1-y}\) 則預測為正例。令 \(m^+\) 表示正例數目, \(m^-\) 表示反例數目,則觀測機率是 \(\frac{m^-}{m^+}\)

類別不平衡學習的一個基本策略是 “再縮放”(rescaling)。再縮放技術主要有三種方法實現:

  • 對訓練集的反類樣例進行“欠取樣”(undersampling),即去除一些反例使得正負樣例數目接近,然後再進行學習。
  • 對訓練集的正類樣例進行“過取樣”(oversampling),即增加一些正例使得正、負樣例數目接近,然後再進行學習(或者叫模型訓練)。
  • 直接對原始訓練集進行學習,但是在對訓練好的分類器進行預測時,將式(3.48)嵌入到分類器推理過程中,稱為“閾值移動”(threshold-moving)。

值得注意的是過取樣的方法不能簡單地對初始正例樣本進行重複取樣,否則會招致嚴重的過擬合;過取樣方法的代表性演算法 SMOTE 是透過對訓練集的正例進行插值來產生額外的正例(影像資料就進行資料增強)。

第 5 章 神經網路

5.1 神經元模型

神經網路有很多種定義,一種較為廣泛的定義是,其是由具有適應性的簡單單元組成的廣泛並行互連的網路,它的組織能夠模擬生物神經系統對真實世界物體所作出的互動反應。

神經網路中最基本的成分是神經元(neuron)模型,即上述定義中的簡單單元。經典的"M-P神經元模型”如下所示,其中的 \(f\) 表示啟用函式,\(w\) 表示神經元權重。

M-P神經元模型

5.2 感知機與多層網路

感知機(perception)由兩層神經元組成,如下圖所示,輸入層接收外界輸入訊號後傳遞給輸出層,輸出層是 M-P 神經元,也稱“閾值邏輯單元”(threshold logic unit)。感知機能容易地實現邏輯與、或、非運算,只需要設定合理的 \(w\)\(\theta\) 引數。感知機模型的公式可表示為:

\[y_j = f(\sum_{i}w_ix_i - \theta_j) \]

M-P神經元模型

給定訓練資料集,感知機的 \(w\)\(\theta\) 引數可透過學習得到。其學習規則很簡單,對於訓練樣本\((x,y)\),如果感知機輸出為 \(\hat{y}\),則感知機的引數將做如下調整:

\[w_{i} \leftarrow w_{i} + \Delta w_i \\ \Delta w_i = \eta(y - \hat{y})x \]

其中 \(\eta\) 稱為學習率,從上式可以看出當感知機預測輸出 \(\hat{y}\) 和樣本標籤 \(y\) 相等時,引數不改變;否則將根據偏差的嚴重程度進行相應調整。

需要注意的是,感知機只能解決與、或、非這樣的線性可分(即存在一個線性超平面將它們分開)問題,但是甚至不能解決異或這樣簡單的非線性可分問題。

要解決非線性可分問題,可以使用多功能神經元。如下圖所示的就是一種常見的“多層前饋神經網路”(multi-layer feedforward neural),每層神經元與下一層神經元全互連,同層神經元之間不連線,也不存在跨層連線。

“前饋” 並不意味著網路中訊號不能反向傳播,而單純是指網路拓撲結構上不存在環或迴路。

多層前饋神經網路

5.3 誤差反向傳播演算法

很明顯多層神經網路的學習能力比單層網路(單層感知機)強得多。感知機引數的學習規則很簡單,因此其對於多層神經網路是不夠用的,由此,誕生了強大的誤差反向傳播(error BackPropagation,簡稱 BP)演算法,並使用至今,現階段的所有深度神經網路的引數都是由 BP 演算法訓練得到的。

反向傳播指的是計算神經⽹絡引數梯度的⽅法。總的來說,反向傳播依據微積分中的鏈式法則,沿著從輸出層到輸⼊層的順序,依次計算並儲存⽬標函式有關神經⽹絡各層的中間變數以及引數的梯度

前向傳播:輸入層-->輸出層;反向傳播:輸出層-->輸入層。

下面透過前饋神經網路的 BP 演算法來深入理解 BP 過程。

給定訓練集 \(D = {(x_1, y_1), (x_2, y_2),...,(x_m, y_m)}, x \in \mathbb{R}^d, y_i \in \mathbb{R}^l\),即每個輸入樣本都由 \(d\) 個屬性表徵,模型輸出的是 \(l\) 維實值向量。為了便於 BP 演算法的推導,下圖給出了一個擁有 \(d\) 個輸入神經元、\(l\) 個輸出神經元、\(q\) 個隱層神經元的多層前饋神經網路,其中輸出層第 \(j\) 個神經元的閾值用 \(\theta_j\) 表示,隱層第 \(h\) 個神經元的閾值用 \(\gamma_h\) 表示。輸入層第 \(i\) 個神經元與隱層第 \(h\) 個神經元之間的連線權重引數為 \(v_{ih}\),隱層第 \(h\) 個神經元與輸出層第 \(j\) 個神經元之間的連線權為 \(w_{hj}\)。記隱層第 \(h\) 個神經元接收到的輸入為 \(\alpha_h = \sum_{i=1}^{d}v_{ih}x_i\),輸出層第 \(j\) 個神經元接收到的輸入為 \(\beta_j = \sum_{h=1}^{q}w_{hj}b_h\),其中 \(b_h\) 為隱層第 \(h\) 個神經元的輸出。這裡假設隱層和輸出層神經元的啟用函式都為 Sigmoid 函式。

BP網路

對訓練樣本 \((x_k,y_k)\),假設神經網路的輸出為 \(\hat{y}_k =(\hat{y}_1^k,\hat{y}_2^k,...,\hat{y}_l^k)\),即

\[\hat{y}_j^k = f(\beta_j - \theta_j)\tag{5.3}, \]

則網路在 \((x_k,y_k)\) 上的均方誤差損失為

\[E_k = \frac{1}{2}\sum_{j=1}^{l}(\hat{y}_j^k - y_k)^2\tag{5.4}, \]

輸入層到隱層需要 \(d \times q\) 個權重引數、隱層到輸出層需要需要 \(q \times l\) 個權重引數,以及 \(q\) 個隱層的神經元閾值、\(l\) 個輸出層的神經元閾值。BP 是一個迭代學習演算法,在迭代的每一輪中採用廣義的感知機學習規則對引數進行更新估計,因此任意引數 \(v\) 的更新估計表示式都可為

\[v\leftarrow v + \Delta v\tag{5.5} \]

下面我會首先推匯出隱層到輸出層的權重 \(w_{hj}\) 更新公式,而後類別推導 \(\theta_{j}\)\(v_{ih}\)\(\gamma_{h}\)

BP 演算法是基於梯度下降(gradient desent)策略,以目標的負梯度方向對引數進行調整,對式\((5.4)\)的誤差 \(E_k\),給定學習率 \(\eta\),可得權重引數更新公式如下:

\[w \leftarrow w + -\eta \frac{\partial E_k}{\partial w} \]

同時,

\[\Delta w_{hj} = -\frac{\partial E_k}{\partial w_{hj}}\tag{5.6} \]

注意到 \(w_{hj}\) 先影響到第 \(j\) 個輸出層神經元的輸入值 \(\beta_j\),再影響到其輸出值 \(\hat{y}_j^k\),最後才影響到損失 \(E_k\),根據梯度的鏈式傳播法則,有

\[\frac{\partial E_k}{\partial w_{hj}} = \frac{\partial E_k}{\partial \hat{y}_j^k}\frac{\partial \hat{y}_j^k}{\partial \beta_j}\frac{\partial \beta_j}{\partial w_{hj}} \tag{5.7} \]

根據前面 \(\beta_j\) 的定義,顯然有

\[\frac{\partial \beta_j}{\partial w_{hj}} = b_h \tag{5.8} \]

再因為 Sigmoid 函式的一個很好的性質:

\[{f}'(x) = f(x)(1-f(x)) \tag{5.9} \]

再聯合式\((5.3)\)\((5.4)\),有:

\[\begin{align} -\frac{\partial E_k}{\partial \hat{y}_j^k} \frac{\partial \hat{y}_j^k}{\partial \beta_j} &= -\frac{\partial \left [\frac{1}{2} \sum_{j=1}^{l}(\hat{y}_{j}^{k} - y_{j}^{k})^{2}\right ]}{\partial \hat{y}_{j}^{k}} \frac{\partial \left [f(\beta_{j} - \theta_{j})\right ]}{\partial \beta_{j}} \nonumber \\ &= -\frac{1}{2}\times 2(\hat{y}_j^k - y_j^k) {f}'(\beta_j - \theta_j) \nonumber \\ &= -(\hat{y}_j^k - y_j^k) f(\beta_j - \theta_j)\left [1-f(\beta_j - \theta_j)\right ] \nonumber\\ &= -(\hat{y}_j^k - y_j^k) \hat{y}_j^k (1-\hat{y}_j^k) \nonumber\\ &= \hat{y}_j^k (1-\hat{y}_j^k) (y_j^k - \hat{y}_j^k ) \tag{5.10} \end{align}\]

注意這裡的 \(f\)Sigmoid 函式。令 \(g_{j} = \hat{y}_j^{k}(1-\hat{y}_j^{k})(y_{j}^{k} - \hat{y}_{j}^{k})\) 。將 \(g_{j}\) 和式 \((5.8)\) 帶入式 \((5.6)\),就得到了 BP 演算法中關於 \(w_{hj}\) 的更新公式:

\[\Delta w_{hj} = \eta g_{j}b_{h} \tag{5.11} \]

類似式 \((5.10)\) 的推導過程可得其他引數的更新公式:

\[\Delta \theta_j = -\eta g_j \tag{5.12} \]

\[\Delta v_{ih} = -\eta e_{h}x_{i} \tag{5.13} \]

\[\Delta \theta_j = -\eta e_h \tag{5.14} \]

\(v_{ih}\) 梯度的詳細推導公式如下所示。因為,

\[\begin{aligned} \cfrac{\partial E_k}{\partial v_{ih}} &= \sum_{j=1}^{l} \cfrac{\partial E_k}{\partial \hat{y}_j^k} \cdot \cfrac{\partial \hat{y}_j^k}{\partial \beta_j} \cdot \cfrac{\partial \beta_j}{\partial b_h} \cdot \cfrac{\partial b_h}{\partial \alpha_h} \cdot \cfrac{\partial \alpha_h}{\partial v{ih}} \\ &= \sum_{j=1}^{l} \cfrac{\partial E_k}{\partial \hat{y}_j^k} \cdot \cfrac{\partial \hat{y}_j^k}{\partial \beta_j} \cdot \cfrac{\partial \beta_j}{\partial b_h} \cdot \cfrac{\partial b_h}{\partial \alpha_h} \cdot x_i \\ &= \sum_{j=1}^{l} \cfrac{\partial E_k}{\partial \hat{y}_j^k} \cdot \cfrac{\partial \hat{y}_j^k}{\partial \beta_j} \cdot \cfrac{\partial \beta_j}{\partial b_h} \cdot f^{\prime}(\alpha_h-\gamma_h) \cdot x_i \\ &= \sum_{j=1}^{l} \cfrac{\partial E_k}{\partial \hat{y}_j^k} \cdot \cfrac{\partial \hat{y}_j^k}{\partial \beta_j} \cdot w_{hj} \cdot f^{\prime}(\alpha_h-\gamma_h) \cdot x_i \\ &= \sum_{j=1}^{l} (-g_j) \cdot w_{hj} \cdot f^{\prime}(\alpha_h-\gamma_h) \cdot x_i \\ &= -f^{\prime}(\alpha_h-\gamma_h) \cdot \sum_{j=1}^{l} g_j \cdot w_{hj} \cdot x_i \\ &= -b_h(1-b_h) \cdot \sum_{j=1}^{l} g_j \cdot w_{hj} \cdot x_i \\ &= -e_h \cdot x_i \end{aligned}\]

所以

\[\Delta v_{ih} =-\eta \cfrac{\partial E_k}{\partial v_{ih}} =\eta e_h x_i \]

v_{ih} 梯度的詳細推導公式

最後一層啟用使用 softmax 啟用和交叉熵損失函式的反向傳播推導,可參考這裡

學習率 \(\eta \in (0,1)\) 控制著演算法每一輪迭代中更新的步長,若太大則容易振盪,太小則收斂速度幽會過慢。有時為了做精細調節,可令式\((5.11)\)\((5.12)\)使用 \(\eta_1\), 式\((5.13)\)\((5.14)\)使用 \(\eta_2\),兩者未必相等。

下圖給出了 BP 演算法的工作流程:

BP演算法流程

對每個訓練樣本,BP 演算法操作流程如下:

  1. 前向傳播:將輸入樣本輸入給輸入神經元,然後逐層將訊號前向傳播,直到輸出層產生結果。
  2. 反向傳播:計算輸出層的誤差,沿著輸出層到輸入層的順序,依次計算並儲存損失函式有關各層的中間變數及引數梯度,並對引數進行調整。
  3. 1,2 過程迴圈進行,直到達到某些停止條件為止,如訓練誤差已達到一個很小的值。

停止條件與緩解 BP 過擬合的策略有關。

值得注意的是,BP 演算法的目標是要最小化訓練集 \(D\) 上的累計誤差:

\[E = \frac{1}{m}\sum_{k=1}{m}E_k,\tag{5.16} \]

但是我們前面描述的“標準 BP 演算法”的計算過程,其實每次僅針對一個訓練樣本更新連線權重和閾值的,因此,圖5.8中演算法發更新規則同樣也是基於單個 \(E_k\) 推導而得的。如果類似地推匯出基於累計誤差最小化的更新規則,就得到了累計誤差反向傳播(accumulated error backpropagation)演算法。

一般來說,標準 BP 演算法每次更新僅針對單個樣本,引數更新很頻繁,而且不同樣本對進行更新的效果可能出現“抵消”現象。因此,為了達到同樣的累計誤差極小點,標準 BP 演算法往往需要進行更多次數的迭代。而累計 BP 演算法直接將累計誤差最小化,它是在讀取整個訓練集 \(D\) 一遍(one epoch)後才對神經網路各層權重引數進行更新,其引數更新頻率低得多。但是在很多工中,累計誤差下降到一定程度後,進一步下降會非常緩慢,這是標準 BP 往往會更快獲得較好的解,尤其是在訓練集 \(D\) 非常大時很明顯。

標準 BP 演算法和累計 BP 演算法的區別類似於隨機梯度下降(stochastic gradient descent,簡稱 SGD)與標準梯度下降之間的區別。

[Hornik et al.,1989] 證明,只需一個包含足夠多神經元的隱層(即深度神經網路層數足夠多),多層前饋神經網路就能以任意精度逼近任意複雜度的連續函式。但是,深度神經網路層數的選擇依然是一個未決問題,在實際應用中通常依靠“試錯法”(trial-by-error)調整。

因為神經網路的表示能力太過強大,因此 BP 神經網路在訓練過程中經常遭遇過擬合,即訓練誤差持續降低,但驗證集誤差卻可能上升。目前常用來緩解 BP 網路過擬合問題的策略,有以下兩種:

第一種策略是“早停”(early stopping):將資料分為訓練集和驗證集,訓練集用來更新權重引數,驗證集用來估計誤差,若訓練集誤差降低但驗證集誤差升高,則停止訓練,同時返回具有最小驗證集誤差的權重引數模型。

第二種策略是“正則化”(regulazation):其基本思想是在誤差目標函式中增加一個用於描述網路複雜度的部分,例如連線權重與閾值的平方和。仍令 \(E_k\) 表示第 \(k\) 個訓練樣本上的誤差,\(w_i\)表示連線權重和閾值,則誤差目標函式\((5.16)\)更改為:

\[E = \lambda \frac{1}{m}\sum_k^m E_k + (1- \lambda)\sum_{i} w_i^2 \tag{5.17} \]

其中 \(\lambda \in (0,1)\)用於對經驗誤差與網路複雜度這兩項進行折中,常透過交叉驗證法估計。

常用的刻畫模型複雜度 \(R(w)\) 的函式有兩種,一種是 \(L1\) 正則化,即絕對值的之和;另一種是 \(L2\) 正則化,即絕對值平方之和,計算公式如下:

\[R(w) = ||w||_1 = \sum_i|w_i| \\ R(w) = ||w||_2 = \sum_i|w_i^2| \]

無論是哪一種正則化,其基本思想都是希望透過限制權重的大小,使得模型不能任意擬合訓練資料中隨機噪聲。\(L1\)\(L2\) 有很大區別,\(L1\) 正則化會讓引數變得更加稀疏,而 \(L2\) 不會。所謂引數變得更加稀疏是指會有更多的引數變為 0,這樣可以達到類似特徵選取的功能。

L2範數正則化(regularization)等價於權重衰減的概念。

5.4 全域性最小與區域性最小

若用 \(E\) 表示神經網路在訓練集上的誤差,則它顯然是關於連線權重 \(w\) 和閾值 \(\theta\) 的函式。此使,神經網路的訓練過程可看作是一個引數尋優的過程,即在引數空間中,尋找一組最優引數使得 \(E\) 最小。

顯然,引數空間內梯度為零的點,只要其誤差函式值小於零點的誤差函式值,就是區域性極小點;可能存在多個區域性極小值,但有且僅有一個全域性最小值。

基於梯度的搜尋是使用最為廣泛的引數尋優方法。在這類方法中,一般先從引數隨機初始解出發,迭代尋找最優引數解。每次迭代我們先計算誤差函式在當前點的梯度,然後根據梯度確定搜尋方向。例如,由於負梯度方向是函式值下降最快的方向,因此梯度下降法就是沿著負梯度方向搜尋最優解。若誤差函式在當前點的梯度為零,則已達到區域性極小,引數更新量也將為零,也意味著引數的迭代更新將在此停止。

區域性最小與全域性最小

在現實任務中,我們常用以下啟發式策略(非理論策略)來試圖“跳出”區域性極小,從而進一步接近全域性最小:

  • 以多組不同引數值初始化多個神經網路,按標準方法訓練後,取其中最小的解作為最終引數。
  • 使用”模擬退火“(simulated annealing)技術。模擬退火在每一步都以一定的機率接受比當前解更差的結果,從而有助於”跳出“區域性極小。在每次迭代過程中,接收”次優解“的機率要隨著時間的推移而逐漸降低,從而保證演算法的穩定性。
  • 使用隨機梯度下降演算法。

5.5 其他常見神經網路

2010 年之前常見的神經網路有 RBF 網路、ART 網路、SOM 網路、級聯相關網路Elman網路Boltzmann 機。

5.6 深度學習

典型的深度學習模型就是很深層(層數很多)的神經網路。值得注意的是,從增加模型複雜度的角度來看,增加隱藏層的數目顯然比增加隱藏層神經元的數目更有效,即網路的“深”比“寬”重要。因為隱藏層層數的增加不僅增加了擁有啟用函式神經元的數目,還增加了啟用函式巢狀的層數,即非線效能力進一步增強

第 9 章 聚類

9.1 聚類任務

在“無監督學習”中,訓練樣本是無標籤資訊的,目標是透過對無標記訓練樣本的學習來揭示資料的內在性質和規律,為進一步的資料分析提供基礎。這類學習任務中應用最廣的就是“聚類”(clustering)演算法,其他的無監督學習任務還有密度估計(density estimation)、異常檢測(anomaly detection)等。

聚類的任務是將資料集中的樣本劃分為若干個通常是不相交的子集,每個子集稱為一個“簇”(cluster),簇所對應的概念和語義由使用者來把握。

聚類可用作其他學習任務的一個前驅過程。基於不同的學習策略,有著多種型別的聚類演算法,聚類演算法涉及的兩個基本問題是效能度量和距離計算。

9.2 效能度量

聚類效能度量也叫聚類“有效性指標”(validity index),和監督學習的效能度量作用類似,都是用來評估演算法的好壞,同時也是聚類過程中的最佳化目標。

聚類效能度量大致有兩類。一類是將聚類結果與某個“參考模型(reference model)”進行比較,稱為“外部指標(external index)”;另一類是直接考察聚類結果而不利用任何參考模型,稱為“內部指標”(inderna index)。

外部指標包括 Jaccard 指數(簡稱 JC)、FM 指數(簡稱 FMI)和 Rand 指數(簡稱 RI),範圍在 [0,1] 之間,且越大越好;內部指標包括 DB 指數(簡稱 DBI)和 Dunn 指數(簡稱 DI),DBI 值越小越好,DI 越大越好。

具體計算公式太多了,這裡不給出,可以參考原書 199 頁。

9.3 距離計算

函式 \(dist(\cdot,\cdot)\) 用於計算兩個樣本之間的距離,如果它是一個“距離度量”(distance measure),則需滿足一些基本性質:

  • 非負性:\(dist(x_i,x_j) \geq 0\)
  • 同一性:\(dist(x_i,x_j)=0\) 當前僅當 \(x_i = x_j\)
  • 對稱性:\(dist(x_i,x_j) = dist(x_j,x_i)\)
  • 直遞性:\(dist(x_i,x_j \geq dist(x_i,x_k) + dist(x_k,x_j))\)

給定樣本 \(x_i = (x_{i1};x_{i2};...;x_{in})\)\(x_j = (x_{j1};x_{j2};...;x_{jn})\),最常用的是“閔可夫斯距離”(Minkowski distance)。

\[dist_{mk}(x_i,x_j) = (\sum_{u=1}^{n}\left | x_{iu} - x_{ju} \right |^p)^\frac{1}{p} \]

上式其實就是 \(x_i - x_j\)\(L_p\) 範數 \(\left \| x_i - x_j \right \|_p\)\(p = 2\),上式為歐氏距離。

屬性通常劃分為“連續屬性”(continuous attribute)和“離散屬性”(categotical attribute),前者在定義域上有無窮多個可能的取值,後者在定義域上是有限個取值。但是在涉及距離計算時,屬性上定義了“序”更為重要。能直接在屬性上計算距離:“1” 和 “2” 比較近、和“4”比較遠,這樣的屬性稱為“有序屬性”(ordinal attribute );而定義域為{汽車、人、椅子}這樣的離散屬性則不能直接在屬性上計算距離,稱為“無序屬性”(non-ordinal atribute)。顯然,閔可夫斯距離可用於有序屬性

對無序屬性採用 VDMValue Difference Metric),同時將閔可夫斯距離和 VDM 集合可處理混合屬性。

9.4 原型聚類

原型聚類演算法假設聚類結構能透過一組原型刻畫,這裡的原型是指樣本空間中具有代表性的點。一般演算法先對原型進行初始化,然後對原型進行迭代更新求解。採用不同的原型表示、不同的求解方式,將產生不同的演算法。

9.4.1 k 均值演算法

K-Means 演算法的思想很簡單,對於給定的樣本集,按照樣本之間的距離大小,將樣本集劃分為 \(K\) 個簇,讓簇內的點儘量緊密的連在一起,而讓簇間的距離儘量的大。

給定樣本集 \(D = \{x_1, x_2,...,x_m\}\),假設簇劃分為 \(C = \{C_1,C_2,...,C_m\}\),演算法目標是最小化平方誤差。

\[E = \sum_{i=1}^{k}\sum_{x \in C_{i}}\left \| x - u_i \right \|_2^2 \]

其中 \(u_i=\frac{1}{C_i}\sum_{x \in C_{i}}x\) 是簇 \(C_i\) 的均值向量,也稱質心。上式一定程度上刻畫了簇內樣本圍繞簇均值向量的緊密程度,\(E\) 值越小簇內樣本相似程度越高。

找到 \(E\) 的最優解需要靠擦樣本集 \(D\) 所有可能的簇劃分,這是一個 \(NP\) 難問題。\(k\) 均值演算法採用了貪心策略,透過迭代最佳化近似求解,演算法流程如圖 9.2 所示。其中第 1 行對均值向量進行初始化,4-8 行與 9-16 行依次對當前簇劃分即均值向量迭代更新,若更新後聚類結果保持不變,則在第 18 行將當前簇劃分結果返回。

k-means演算法流程

參考此文章的程式碼,我修改為如下精簡版的 K-Means 演算法程式碼。

def kmeans(dataset, k):
    """K-means 聚類演算法

    Args:
        dataset ([ndarray]): 資料集,二維陣列
        k ([int]): 聚簇數量
    """
    m = np.shape(dataset)[0]  # 樣本個數
    
    # 1, 隨機初始化聚類中心點
    center_indexs = random.sample(range(m), k)
    center = dataset[center_indexs,:]
    
    cluster_assessment = np.zeros((m, 2))
    cluster_assessment[:, 0] = -1  # 將所有的類別置為 -1
    cluster_changed = True 
    while cluster_changed:
        cluster_changed = False
        # 4-8,計算樣本x_i與各聚類中心的距離,根據距離最近的聚類中心確定x_j的簇標記,並將對應樣本x_i劃入相應的簇
        for i in range(m):
            # 初始化樣本和聚類中心的距離,及樣本對應簇
            min_dist = inf
            c = 0
            # 確定每一個樣本離哪個中心點最近,和屬於哪一簇
            for j in range(k):
                dist = distEclud(dataset[i,:], center[j,:])
                if dist < min_dist:
                    min_dist = dist
                    c = i
            # 更新樣本所屬簇
            if cluster_assessment[i, 0] != c:  # 仍存在資料在前後兩次計算中有類別的變動,未達到迭代停止要求
                cluster_assessment[i, :] = c, min_dist  # 更新樣本所屬簇
                cluster_changed = True
        # 9-16 更新簇中心點位置
        for j in range(k):
            changed_center = dataset[cluster_assessment[:,0] == j].mean(axis=0)
            center[j,:] = changed_center
            
    return cluster_assessment, center

if __name__ == '__main__':
    x1 = np.random.randint(0, 50, (50, 2))
    x2 = np.random.randint(40, 100, (50, 2))
    x3 = np.random.randint(90, 120, (50, 2))
    x4 = np.random.randint(110, 160, (50, 2))
    test = np.vstack((x1, x2, x3, x4))

    # 對特徵進行聚類
    result, center = kmeans(test, 4, is_kmeans=False, is_random=False)
    print(center) # 列印簇類中心點

參考資料

《機器學習》-周志華

相關文章