R 支持向量机②

作者: 柳叶刀与小鼠标 | 来源:发表于2018-01-20 15:34 被阅读38次

    介绍

    支持向量机是一个相对较新和较先进的机器学习技术,最初提出是为了解决二类分类问题,现在被广泛用于解决多类非线性分类问题和回归问题。其流行归功于两个方面,一个方面,可以输出比较准确的预测结果;另一方面,模型基于比较优雅的数学理论。
    SVM旨在在多维空间找到一个能将全部样本单元分成两类的最优平面,这一平面应使两类中距离最近的点的间距最大。在间距边界上的点称为支持向量,分割的超平面位于间距中间。SVM函数通过核函数将数据投影到高维,使其在高维线性可分。

    由于方差较大的预测变量通常对SVM影响更大,svm()函数默认在生成模型前对每个变量标准化,使其标准化值为0,标准差为1。

    工作原理

    假设你的数据点分为两类,支持向量机试图寻找最优的一条线(超平面),使得离这条线最近的点与其他类中的点的距离最大。有些时候,一个类的边界上的点可能越过超平面落在了错误的一边,或者和超平面重合,这种情况下,需要将这些点的权重降低,以减小它们的重要性。

    这种情况下,“支持向量”就是那些落在分离超平面边缘的数据点形成的线。

    • 无法确定分类线(线性超平面)时
      此时可以将数据点投影到一个高维空间,在高维空间中它们可能就变得线性可分了。它会将问题作为一个带约束的最优化问题来定义和解决,其目的是为了最大化两个类的边界之间的距离。
    • 数据点多于两个类时
      此时支持向量机仍将问题看做一个二元分类问题,但这次会有多个支持向量机用来两两区分每一个类,直到所有的类之间都有区别。

    线性支持向量机

    • 传递给函数svm()的关键参数是kernel、cost和gamma。
    • Kernel指的是支持向量机的类型,它可能是线性SVM、多项式SVM、径向SVM或Sigmoid SVM。
    • Cost是违反约束时的成本函数,gamma越大,通常导致支持向量越多。我们也可将gamma看作控制训练样本“到达范围”的参数,即gamma越大意味着训练样本到达范围越广,而越小则意味着到达范围越窄。gamma是除线性SVM外其余所有SVM都使用的一个参数。
    • svm()函数默认gamma为预测变量个数的倒数。还有一个类型参数,用于指定该模型是用于回归、分类还是异常检测。但是这个参数不需要显式地设置,因为支持向量机会基于响应变量的类别自动检测这个参数,响应变量的类别可能是一个因子或一个连续变量。所以对于分类问题,一定要把你的响应变量作为一个因子。
    
    > # linear SVM
    > svmfit <- svm(response ~ ., data = inputData, kernel = "linear", 
    +               cost = 10, scale = FALSE) # linear svm, scaling turned OFF
    > print(svmfit)
    
    Call:
    svm(formula = response ~ ., data = inputData, kernel = "linear", 
        cost = 10, scale = FALSE)
    
    
    Parameters:
       SVM-Type:  C-classification 
     SVM-Kernel:  linear 
           cost:  10 
          gamma:  0.5 
    
    Number of Support Vectors:  79
    
    > plot(svmfit, inputData)
    > compareTable <- table (inputData$response, predict(svmfit))  # tabulate
    > mean(inputData$response != predict(svmfit)) # 19.44% misclassification error
    [1] 0.1944444
    
    • 通过breast数据演示支持向量机
    
    rm(list=ls())
    setwd("E:\\Rwork")
    
    
    loc <- "http://archive.ics.uci.edu/ml/machine-learning-databases/"
    ds <- "breast-cancer-wisconsin/breast-cancer-wisconsin.data"
    url <- paste(loc, ds, sep="")
    breast <- read.table(url, sep=",", header=FALSE, na.strings="?")
    names(breast) <- c("ID", "clumpThickness", "sizeUniformity",
                       "shapeUniformity", "maginalAdhesion",
                       "singleEpithelialCellSize", "bareNuclei",
                       "blandChromatin", "normalNucleoli", "mitosis", "class")
    
    write.csv(breast,"breast.csv")
    df <- breast[-1]
    df$class <- factor(df$class, levels=c(2,4),
                       labels=c("benign", "malignant"))
    set.seed(1234)
    index <- sample(nrow(df), 0.7*nrow(df))
    df.train <- df[index,]
    df.validate <- df[-index,]
    table(df.train$class)
    table(df.validate$class)
    
    
    # linear SVM
    svmfit <- svm(class ~ ., data = df.train, kernel = "linear", 
                  cost = 10, scale = FALSE) # linear svm, scaling turned OFF
    print(svmfit)
    
    
    svm.pred <- predict(svmfit, na.omit(df.validate))
    svm.perf <- table(na.omit(df.validate)$class,
                      svm.pred, dnn=c("Actual", "Predicted"))
    
    svm.perf 
    
    
    
    
    # radial SVM
    svmfit <- svm(response ~ ., data = inputData, 
                  kernel = "radial", cost = 10, 
                  scale = FALSE) # radial svm, scaling turned OFF
    print(svmfit)
    
    svm.pred <- predict(svmfit, na.omit(df.validate))
    svm.perf <- table(na.omit(df.validate)$class,
                      svm.pred, dnn=c("Actual", "Predicted"))
    svm.perf 
    
    
    
    
    
    ### Tuning
    # Prepare training and test data
    set.seed(1234) # for reproducing results
    rowIndices <- 1 : nrow(breast) # prepare row indices
    sampleSize <- 0.8 * length(rowIndices) # training sample size
    trainingRows <- sample (rowIndices, sampleSize) # random sampling
    trainingData <- breast[trainingRows, ] # training data
    testData <- breast[-trainingRows, ] # test data
    tuned <- tune.svm(class~., data = trainingData,
                      gamma = 10^(-6:-1), cost = 10^(1:2)) # tune
    summary (tuned) # to select best gamma and cost
    
    
    svmfit <- svm (class ~ ., 
                   data = trainingData, kernel = "radial",
                   cost = 10, gamma=0.01, 
                   scale = FALSE)
    # radial svm, scaling turned OFF
    print(svmfit)
    svm.perf <- table(na.omit(df.validate)$class,
                      svm.pred, dnn=c("Actual", "Predicted"))
    svm.perf 
    ···

    相关文章

      网友评论

        本文标题:R 支持向量机②

        本文链接:https://www.haomeiwen.com/subject/qnnooxtx.html