Classification
此博文是 An Introduction to Statistical Learning with Applications in R 的系列讀書筆記,作為本人的一份學習總結,也希望和朋友們進行交流學習。
該書是The Elements of Statistical Learning 的R語言簡明版,包含了對算法的簡明介紹以及其R實現,最讓我感興趣的是算法的R語言實現。
【轉載時請注明來源】:http://www.cnblogs.com/runner-ljt/
Ljt 勿忘初心 無畏未來
作為一個初學者,水平有限,歡迎交流指正。
前一篇博文講的線性回歸模型主要針對因變量是定量的情形,而對於因變量是定性的情況則需要采用分類算法。
本篇將講述三類常用的分類算法:邏輯回歸 Logistic Regression(LR)
線性/二次判別分析 Linear Discriminant Analysis(LDA) / Quadratic Discriminant Analysis(QDA)
K最近鄰法 K-nearest neighbors(KNN)
首先,本文將從整體上來比較這三類分類算法:
(1) 當真實的分類邊界是線性時,LR和LDA通常會表現更好;當真實的分類邊界是一般的非線性時,QDA通常會表現更好;當真實的分類邊界
更為復雜時, KNN 通常會表現的更好。
(2) LR和LDA 都將產生線性分類邊界,兩種唯一的不同是LR的系數估計是通過極大似然法,而LDA的系數是運用正態分布的均值和方差的估計
值計算得到的;LR適用於二分類問題,對於多分類問題,LDA則更為常見。
(3) 當樣本能夠被完全線性分類時,LR的參數估計將會出現不穩定情況,此時LR方法不適用(詳細見另一篇博文 廣義線性模型 R--glm函數),
LDA參數估計則不會出現這種情況;當樣本量較小且自變量的分布近似於狀態分布時,LDA會比LR表現的更好。
(4) LDA和QDA都是建立在自變量服從正態分布的假設上,所以當自變量的分布確實是幾乎服從正態分布時,這兩種方法會表現的較好;
LDA和QDA 的區別在於LDA假設所有類別的自變量都服從方差相同的正態分布,而QDA假設對於因變量屬於不同類別的自變量服從方差不
同的正態分布,選擇LDA和QDA的關鍵在於偏置--方差的權衡。
(5) QDA可以認為是非參數學習法KNN和具有線性分類邊界的LR及LDA方法的折中,QDA假設分類邊界是二次的,所以它能夠比線性模型更准
確的為更多的問題建立模型;同時由於其二次邊界的額外假設,當樣本量較小時,其能夠優於KNN方法。
(6) KNN是非參數學習方法,因此它不對分類邊界做任何假設,當分類邊界為高度非線性是便會優於RL和LDA,但是其不能反映每個自變量對因
變量的影響。
(7) LR可以適用於含有定性自變量的模型,對於定性的自變量LR會將其轉換為虛擬變量,但是LDA、QDA及KNN都不適用於定性的自變量。
Logistic Regression
(1)廣義線性回歸:glm(formula, family = gaussian, data, subset)
family: binomial(link = "logit") 因變量服從伯努利分布,連接函數為logit;
gaussian(link = "identity") 因變量服從高斯分布,連接函數為identity;
poisson(link = "log") 因變量服從泊松分布,連接函數為log.
subset :可選向量,用於指定data中用於測試的數據集 .
(2)預測函數:predict(object, newdata = NULL, type = c("link", "response", "terms"))
newdata:預測樣本數據,當為NULL時預測樣本為測試樣本,data.frame格式;
type : link --- 連接函數 ΘX 的值 【 p(y=1)=1/(1+e-ΘX ) 】 ;
response ---預測結果是樣本類別為1的概率 ;
terms --- The 'terms' option returns a matrix giving the fitted values of each term in the model formula
on the linear predictor scale.
(3)虛擬變量設置:contrasts(x)
在預測結果中的概率為樣本結果是1類的概率(即虛擬變量為1所代表的類別)
> library(ISLR) > head(Smarket) Year Lag1 Lag2 Lag3 Lag4 Lag5 Volume Today Direction 1 2001 0.381 -0.192 -2.624 -1.055 5.010 1.1913 0.959 Up 2 2001 0.959 0.381 -0.192 -2.624 -1.055 1.2965 1.032 Up 3 2001 1.032 0.959 0.381 -0.192 -2.624 1.4112 -0.623 Down 4 2001 -0.623 1.032 0.959 0.381 -0.192 1.2760 0.614 Up 5 2001 0.614 -0.623 1.032 0.959 0.381 1.2057 0.213 Up 6 2001 0.213 0.614 -0.623 1.032 0.959 1.3491 1.392 Up > >glm.fit<-glm(Direction~Lag1+Lag2+Lag3+Lag4+Lag5+Volume,data=Smarket,family=binomial) > summary(glm.fit) Call: glm(formula = Direction ~ Lag1 + Lag2 + Lag3 + Lag4 + Lag5 + Volume, family = binomial, data = Smarket) Deviance Residuals: Min 1Q Median 3Q Max -1.446 -1.203 1.065 1.145 1.326 Coefficients: Estimate Std. Error z value Pr(>|z|) (Intercept) -0.126000 0.240736 -0.523 0.601 Lag1 -0.073074 0.050167 -1.457 0.145 Lag2 -0.042301 0.050086 -0.845 0.398 Lag3 0.011085 0.049939 0.222 0.824 Lag4 0.009359 0.049974 0.187 0.851 Lag5 0.010313 0.049511 0.208 0.835 Volume 0.135441 0.158360 0.855 0.392 (Dispersion parameter for binomial family taken to be 1) Null deviance: 1731.2 on 1249 degrees of freedom Residual deviance: 1727.6 on 1243 degrees of freedom AIC: 1741.6 Number of Fisher Scoring iterations: 3 > > #預測 > glm.probs<-predict(glm.fit,type='response') > glm.probs[1:10] 1 2 3 4 5 6 7 8 9 10 0.5070841 0.4814679 0.4811388 0.5152224 0.5107812 0.5069565 0.4926509 0.5092292 0.5176135 0.4888378 > contrasts(Smarket$Direction) Up Down 0 Up 1 > #衡量模型效果 > glm.pred<-rep('Down',1250) > glm.pred[glm.probs>0.5]<-'Up' > table(glm.pred,Direction) Error in table(glm.pred, Direction) : object 'Direction' not found > table(glm.pred,Smarket$Direction) glm.pred Down Up Down 145 141 Up 457 507 >
Linear Discriminant Analysis
(1) 線性判別分析 lda(formula, data, ..., subset)
返回結果: 先驗概率 Prior probabilities of groups
各類別種每個自變量的均值 Group means
判別邊界系數 Coefficients of linear discriminants
y= - 0.7567605*Lag1 - 0.4707872*Lag2
(2) 預測:predict(lda.fit)
返回結果:預測類別class
類的后驗概率 posterior (每一樣本屬於各類別的后驗概率,通常以0.5為界進行分類,但可以指定后驗概率為α來分類)
> library(MASS) > lda.fit<-lda(Direction~Lag1+Lag2,data=Smarket) > lda.fit Call: lda(Direction ~ Lag1 + Lag2, data = Smarket) Prior probabilities of groups: Down Up 0.4816 0.5184 Group means: Lag1 Lag2 Down 0.05068605 0.03229734 Up -0.03969136 -0.02244444 Coefficients of linear discriminants: LD1 Lag1 -0.7567605 Lag2 -0.4707872 > #預測 > lda.pred<-predict(lda.fit) > names(lda.pred) [1] "class" "posterior" "x" > lda.class<-lda.pred$class > lda.class[1:10] [1] Up Down Down Up Up Up Down Up Up Down Levels: Down Up > table(lda.class) lda.class Down Up 216 1034 > table(lda.class,Smarket$Direction) lda.class Down Up Down 114 102 Up 488 546 > #改變判別准則 > lda.pred$posterior[1:10,] Down Up 1 0.4861024 0.5138976 2 0.5027466 0.4972534 3 0.5104516 0.4895484 4 0.4817860 0.5182140 5 0.4854771 0.5145229 6 0.4920394 0.5079606 7 0.5085978 0.4914022 8 0.4896886 0.5103114 9 0.4774690 0.5225310 10 0.5049515 0.4950485 > #將概率大於0.5就判為UP類在准則改為大於0.51 > sum(lda.pred$posterior[,2]>0.51) [1] 822
Quadratic Discriminant Analysis
二次判別分析 qda(formula, data, ..., subset)
> > library(MASS) > qda.fit<-qda(Direction~Lag1+Lag2,data=Smarket) > qda.fit Call: qda(Direction ~ Lag1 + Lag2, data = Smarket) Prior probabilities of groups: Down Up 0.4816 0.5184 Group means: Lag1 Lag2 Down 0.05068605 0.03229734 Up -0.03969136 -0.02244444 > qda.pred<-predict(qda.fit,Smarket) > names(qda.pred) [1] "class" "posterior" > qda.pred$class[1:10] [1] Up Up Down Up Up Up Down Up Up Up Levels: Down Up > qda.pred$posterior[1:10,] Down Up 1 0.4754475 0.5245525 2 0.4944981 0.5055019 3 0.5083068 0.4916932 4 0.4780731 0.5219269 5 0.4773961 0.5226039 6 0.4836726 0.5163274 7 0.5013701 0.4986299 8 0.4916379 0.5083621 9 0.4675238 0.5324762 10 0.4967838 0.5032162 > table(qda.pred$class,Smarket$Direction) Down Up Down 109 94 Up 493 554 >
K-Nearest Neighbors
K最近鄰 knn(train, test, cl, k = 1)
測試集(matrix/data.frame) train ; 訓練集(matrix/data.frame) test ; 測試集的正確類 cl ; 參考的鄰近元個數 k
在使用knn(...)之前需要設置隨機種子,因為當最K鄰近元的個數超過K時,對第K最鄰近元會隨機選擇,設置隨機種子可以保證模型結果的可重復
> > library(class) > attach(Smarket) > train<-Year<2005 > #測試集和訓練集 > train.X<-cbind(Lag1,Lag2)[train,] > test.X<-cbind(Lag1,Lag2)[!train,] > train.Y<-Direction[train] > #設置隨機種子 > set.seed(1) > knn.pred<-knn(train.X,test.X,train.Y,k=1) > knn.pred[1:10] [1] Up Down Up Up Up Down Down Down Down Up Levels: Down Up >#K=1 > table(knn.pred,Direction[!train]) knn.pred Down Up Down 43 58 Up 68 83 > #K=3 > knn.pred<-knn(train.X,test.X,train.Y,k=3) > table(knn.pred,Direction[!train]) knn.pred Down Up Down 48 54 Up 63 87 >