zoukankan      html  css  js  c++  java
  • ISLR系列:(2)分类 Logistic Regression & LDA & QDA & KNN

       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
    > 
    
  • 相关阅读:
    SVN服务器搭建(一)
    排序算法二:冒泡排序
    【LeetCode】136. Single Number
    【LeetCode】217. Contains Duplicate
    【LeetCode】189. Rotate Array
    【LeetCode】122. Best Time to Buy and Sell Stock II
    【LeetCode】26. Remove Duplicates from Sorted Array
    【LeetCode】20. Valid Parentheses
    【LeetCode】680. Valid Palindrome II
    【LeetCode】345. Reverse Vowels of a String
  • 原文地址:https://www.cnblogs.com/runner-ljt/p/4814263.html
Copyright © 2011-2022 走看看