可以轉載,禁止修改。轉載請註明作者以及原文鏈接 註:本文是從貝葉斯分類器的角度來討論判別分析,有關貝葉斯分類器的概念可參考文末延伸閱讀第1-2篇文章。至於Fisher判別分析,未來會連同PCA一同討論。 判別分析也是一種分類器,與邏輯回歸相比,它具有以下優勢: 當類別的區分度高的時候,邏輯回歸的參數 ...
可以轉載,禁止修改。轉載請註明作者以及原文鏈接
註:本文是從貝葉斯分類器的角度來討論判別分析,有關貝葉斯分類器的概念可參考文末延伸閱讀第1-2篇文章。至於Fisher判別分析,未來會連同PCA一同討論。
判別分析也是一種分類器,與邏輯回歸相比,它具有以下優勢:
- 當類別的區分度高的時候,邏輯回歸的參數估計不夠穩定,它點線上性判別分析中是不存在的;
- 如果樣本量n比較小,而且在每一類響應變數中預測變數X近似服從正態分佈,那麼線性判別分析比邏輯回歸更穩定;
- 多於兩類的分類問題時,線性判別分析更普遍。
貝葉斯分類器
貝葉斯分類的基本思想是:對於多分類(大於等於2類)的問題,計算在已知條件下各類別的條件概率,取條件概率最大的那一類作為分類結果。用公式描述如下:
其中,是第k類的先驗概率,是第k類的概率密度(當然如果是離散型變數就是條件概率,本文考慮連續型變數)。這個公式就是貝葉斯定理。
線性判別分析(Linear Discriminant Analysis, LDA)
1、 一元線性判別分析
假設特征變數滿足正態分佈,即:
線性判別分析有一個重要假設:假設所有K類的劃分方差相同,即==……=。根據貝葉斯定理有:
對分子取對數轉換,可見最大等價於下式最大:
(這裡十分誠意地附上推導過程,沒興趣的可以直接跳過:)
所以只要找到令上式最大的k值即可。從上式可看出,一共有、、這三種參數需要估計擬合。先驗概率可以根據業務知識進行預先估計,如果不行也可以直接以樣本中第k類的樣本在所有類的總樣本中的比例當作先驗概率,即
至於期望和方差,直接根據各類的觀測值計算即可:
從上上式(我就不編號)可看出,是的線性函數,這也是LDA名為“線性”的原因。
2、多元線性判別分析
多元LDA由於涉及到多個特征變數,因此用協方差矩陣來代替一維方差(協方差矩陣的概念可參考延伸閱讀文獻3)。這裡直接給結論,線性模型就變成:
除了方差變成協方差矩陣,和也變成了向量。註意這裡的還是一次,仍然是線性模型。
二次判別分析(Quadratic Discriminant Analysis, QDA)
在LDA中假設所有的K類方差(或協方差矩陣)都相同,但這個假設有些嚴苛,如果放寬這個假設,允許每一類的觀測都各自服從一個正態分佈,協方差矩陣可以不同,LDA就變成了QDA。這裡依然直接給公式:
可見是的二次函數,故名“二次判別分析”。
QDA與LDA的關係類似於多項式回歸與線性回歸的關係,本質上仍是偏差和方差的權衡,這也是Machine Learning領域的一個核心問題。QDA比LDA光滑,偏差更小,但方差更大。那麼它們的適用條件呢?
一般而言,如果訓練觀測數據量相對較少,LDA是一個比QDA更好的決策,降低模型的方差很有必要。相反地,如果訓練集非常大,則更傾向於使用QDA,這時分類器的方差不再是一個主要關心的問題,或者說K類的協方差矩陣相同的假設是站不住腳的。
實戰:用LDA(QDA)再次預測股票漲跌
這裡為了方(tou)便(lan),依然使用延伸閱讀文獻4里的數據集,即ISLR
包里的Smarket
數據集。用不同方法做同樣的事,其實也方便將不同方法進行對比。
> library(ISLR)
> library(MASS)
> attach(Smarket)
> lda.fit=lda(Direction~Lag1+Lag2,data=Smarket, subset=Year<2005)
> lda.fit
Call:
lda(Direction ~ Lag1 + Lag2, data = Smarket, subset = Year <
2005)
Prior probabilities of groups:
Down Up
0.491984 0.508016
Group means:
Lag1 Lag2
Down 0.04279022 0.03389409
Up -0.03954635 -0.03132544
Coefficients of linear discriminants:
LD1
Lag1 -0.6420190
Lag2 -0.5135293
Prior probabilities of groups
是先驗概率,實際上就是各類別在訓練集中的比例:
> table(Smarket[Year<2005,9])/nrow(Smarket[Year<2005,])
Down Up
0.491984 0.508016
Group means
是對每類每個變數計算平均,用來估計參數。通過Group means
矩陣可看出:當股票下跌時,前兩天的投資回報率會趨向於正;當股票上漲時,前兩天的投資回報率會趨向於負。Coefficients of linear discriminants
則是線性模型的繫數,說明當很大時,LDA分類器預測上漲;很小時,LDA分類器預測下跌。
> plot(lda.fit)
上面的圖是對LDA模型的可視化,實際上它是訓練集的分別在Down
類和Up
類的直方圖。下麵驗證比較一下:
library(dplyr)
Lag1_1 <- Smarket %>% filter(Year<"2005", Direction=="Down") %>% select(Lag1)
Lag2_1 <- Smarket %>% filter(Year<"2005", Direction=="Down") %>% select(Lag2)
Lag1_2 <- Smarket %>% filter(Year<"2005", Direction=="Up") %>% select(Lag1)
Lag2_2 <- Smarket %>% filter(Year<"2005", Direction=="Up") %>% select(Lag2)
lm_1 <- (-0.6420190*Lag1_1-0.5135293*Lag2_1)[,1]
lm_2 <- (-0.6420190*Lag1_2-0.5135293*Lag2_2)[,1]
par(mfrow=c(2,1))
hist(lm_1,breaks=16,freq = F,col="lightblue")
hist(lm_2,breaks=16,freq = F,col="lightblue")
可見直方圖形狀完全一致。
以上在訓練集中對LDA模型的訓練過程。下麵在測試集中驗證LDA模型。
> Smarket.2005=subset(Smarket,Year==2005)
> lda.pred=predict(lda.fit,Smarket.2005)
> class(lda.pred)
[1] "list"
> names(lda.pred)
[1] "class" "posterior" "x"
> data.frame(lda.pred)[1:5,]
class posterior.Down posterior.Up LD1
999 Up 0.4901792 0.5098208 0.08293096
1000 Up 0.4792185 0.5207815 0.59114102
1001 Up 0.4668185 0.5331815 1.16723063
1002 Up 0.4740011 0.5259989 0.83335022
1003 Up 0.4927877 0.5072123 -0.03792892
> table(lda.pred$class,Smarket.2005$Direction)
Down Up
Down 35 35
Up 76 106
> mean(lda.pred$class==Smarket.2005$Direction)
[1] 0.5595238
比較一下上一篇邏輯回歸(延伸閱讀文獻4)中的結果:
> glm.fit=glm(Direction~Lag1+Lag2,data=Smarket,family=binomial, subset=train)
> glm.probs=predict(glm.fit,newdata=Smarket[!train,],type="response")
> glm.pred=ifelse(glm.probs >0.5,"Up","Down")
> table(glm.pred,Direction.2005)
Direction.2005
glm.pred Down Up
Down 35 35
Up 76 106
> mean(glm.pred==Direction.2005)
[1] 0.5595238
LDA的結果與邏輯回歸完全一致!以一個數據分析獅敏銳的第六感,我們可以大膽猜測:LDA與邏輯回歸這兩種演算法可能有某種內在聯繫!
這裡不做嚴謹的推導(深層的推導可參考延伸閱讀文獻6),只作一個簡單的驗證比較。為了簡單起見,只考慮二分類問題,多分類問題可同理類推。
$$
log(\frac{p_1(x)}{1-p_1(x)})=log(\frac{p_1(x)}{p_2(x)})=log(p_1(x))-log(p_2(x))=x*\frac{\mu_1-\mu_2}{\sigma^2}-\frac{\mu_1^2-\mu_2^2}{2\sigma^2}+log(\frac{\pi_1}{\pi_2})
$$
可見這仍是關於x的線性函數,與邏輯回歸形式一致!雖然形式一致,但邏輯回歸的參數是通過極大似然法估計出來的,LDA的參數是概率密度函數計算出來的。
由於LDA與邏輯回歸形只是擬合過程不同,因此二者所得的結果應該是接近的。事實上,這一情況經常發生,但並非必然。LDA假設觀測服從每一類的協方差矩陣都相同的正態分佈,當這一假設近似成立時,LDA效果比邏輯回歸好;相反,若這個假設不成立,則邏輯回歸效果比LDA好。
下麵練習QDA:
> qda.fit=qda(Direction~Lag1+Lag2,data=Smarket,subset=train)
> qda.fit
Call:
qda(Direction ~ Lag1 + Lag2, data = Smarket, subset = train)
Prior probabilities of groups:
Down Up
0.491984 0.508016
Group means:
Lag1 Lag2
Down 0.04279022 0.03389409
Up -0.03954635 -0.03132544
> qda.class=predict(qda.fit,Smarket.2005)$class
> table(qda.class,Direction.2005)
Direction.2005
qda.class Down Up
Down 30 20
Up 81 121
> mean(qda.class==Direction.2005)
[1] 0.5992063
可見QDA的準確率稍高於LDA。
參考文獻
Gareth James et al. An Introduction to Statistical Learning.
延伸閱讀
- 演算法雜貨鋪——分類演算法之朴素貝葉斯分類(Naive Bayesian classification)
- 演算法雜貨鋪——分類演算法之貝葉斯網路(Bayesian networks)
- 協方差的意義和計算公式
- 邏輯回歸模型預測股票漲跌
- 機器學習筆記 線性判別分析(上)
- 機器學習筆記 線性判別分析(中)
-
在上一篇博客中,筆者分享了一些從頁面整體的角度對頁面與ViewModel的思考。在本文中筆者希望從相對細節的角度分享一些對頁面與ViewModel的思考。 比如,當我們在更新View Model中的綁定數據時,應該怎樣更新呢?簡單的自然可以用新的數據實例直接替代舊的,但是這樣容易造成UI界面閃爍。尤 ...
-
在很多情況下,我們利用IOC控制反轉可以很方便實現一些介面的適配處理,可以在需要的時候切換不同的介面實現,使用這種方式在調用的時候,只需要知道相應的介面介面,具體調用哪個實現類,可以在配置文件中動態指定,本篇主要介紹AutoFac的IOC組件的使用,用來實現微信介面處理的控制反轉功能。 ...
-
工具:svcutil.exe 參數:指定wsdl、輸出源碼文件、輸出配置文件 示例: D:\>svcutil.exe http://localhost:8087/DataService/?wsdl /out:Client.cs /config:app.configMicrosoft (R) Serv ...
-
密封類 密封類使用sealed修飾符聲明。 密封類中不可能有抽象方法【因為:抽象方法必須在抽象類中,而抽象類不能是密封的或者是靜態的,也就是說abstract 和sealed不能同時修飾一個類】 ...
-
抽象類使用abstract修飾符聲明; 不能創建抽象類的實例; 抽象類只能用作其他類的基類; 抽象類中可以包含抽象成員和普通的非抽象成員; 抽象類自己可以派生自另外一個抽象類; 任何派生自抽象類的【類】,必須使用override關鍵字,實現該類所有的成員,除非派生類自己也是抽象類。 示例: 1.基類 ...
-
技術綜合 《小黃鴨調試法,每個程式員都要知道的》 《開發一個這樣的 APP 要多長時間?》 《一段代碼讓你覺得人類智慧可以璀璨無比》 《成人網站有多大?》 《輸入Google網址回車之後發生了什麼?》 《為什麼有些大公司技術弱爆了?》 《高效 MacBook 工作環境配置》 《如何編寫讓別人能讀懂的 ...
-
ASP.net 第一章:ASP.NET介紹 1.搭建ASP.NET開發環境; 2.理解ASP.NET運行機制; 3.掌握ASP.NET兩種編碼方式。 4.Http協議。 關鍵點: 1.BS的工作原理是什麼? 2.伺服器端開發技術有哪些? Asp 、aspx、jsp、php 3.ASP.NET發展史。 ...
-
摘自:http://blog.csdn.net/dyllove98/article/details/9289553 資料庫生成位置可控制(其實主要就是DbContext的構造函數) 1.使用DbContext的構造函數:public DbContext(string nameOrConnection ...