ISLR实验:分类 - K最近邻

目录

本文源自《统计学习导论:基于R语言应用》(ISLR) 中《4.6 R实验:逻辑斯谛回归、LDA、QDA和KNN》章节

library(ISLR)
library(class)

数据

股票市场数据

data(Smarket)
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

训练集和测试集

训练集:2001 至 2004 年

测试集:2005 年

train <- (Year < 2005)

构建测试集和训练集

train_X <- cbind(Lag1, Lag2)[train,]
test_X <- cbind(Lag1, Lag2)[!train,]
train_direction <- Direction[train]
test_direction <- Direction[!train]

方法

class 包中的 knn() 函数

训练 k=1 的模型

set.seed(1)
knn_predict <- knn(
  train_X,
  test_X,
  train_direction,
  k=1
)

列联表

table(test_direction, knn_predict)
              knn_predict
test_direction Down Up
          Down   43 68
          Up     58 83

正确率

(83+43)/252
[1] 0.5

训练 k=3 的模型

set.seed(1)
knn_predict <- knn(
  train_X,
  test_X,
  train_direction,
  k=3
)

列联表

table(test_direction, knn_predict)
              knn_predict
test_direction Down Up
          Down   48 63
          Up     55 86

正确率

(86+48)/252
[1] 0.531746

应用

大篷车保险数据集

数据集

attach(Caravan)
dim(Caravan)
[1] 5822   86
summary(Purchase)
  No  Yes 
5474  348 
348/(5474+348)
[1] 0.05977327

只有 6% 的人购买了大篷车保险

标准化

scale() 函数将每列标准化为均值为 0,方差为 1 的数据

standardized_X = scale(Caravan[,-86])
c(var(Caravan[,1]), var(standardized_X[,1]))
[1] 165.0378   1.0000
c(var(Caravan[,2]), var(standardized_X[,2]))
[1] 0.1647078 1.0000000

测试集和训练集

test <- 1:1000
train_X <- standardized_X[-test,]
test_X <- standardized_X[test,]
train_Y <- Purchase[-test]
test_Y <- Purchase[test]

K最近邻

set.seed(1)
knn_predict <- knn(
  train_X,
  test_X,
  train_Y,
  k=1
)
mean(test_Y != knn_predict)
[1] 0.118

错误率为 12%

mean(test_Y != "No")
[1] 0.059

只有 6% 的顾客购买了保险

预测阳性率

精确率

真阳性值 / (真阳性值 + 假阳性值)

保险公司更愿意向有购买倾向性的客户销售保险,对总错误率不感兴趣,而对精确率感兴趣

k=1

table(knn_predict, test_Y)
           test_Y
knn_predict  No Yes
        No  873  50
        Yes  68   9
9/(68+9)
[1] 0.1168831

k=3

knn_predict_3 <- knn(
  train_X,
  test_X,
  train_Y,
  k=3
)
table(knn_predict_3, test_Y)
             test_Y
knn_predict_3  No Yes
          No  920  54
          Yes  21   5
5/(5 + 21)
[1] 0.1923077

k=5

knn_predict_5 <- knn(
  train_X,
  test_X,
  train_Y,
  k=5
)
table(knn_predict_5, test_Y)
             test_Y
knn_predict_5  No Yes
          No  930  55
          Yes  11   4
4/(11 + 4)
[1] 0.2666667

逻辑斯谛回归

glm_fit <- glm(
  Purchase ~ .,
  data=Caravan,
  family=binomial,
  subset=-test
)
glm_probs <- predict(
  glm_fit,
  Caravan[test,],
  type="response"
)

以 0.5 作为阈值

glm_predict <- rep("No", 1000)
glm_predict[glm_probs > .5] = "Yes"
table(glm_predict, test_Y)
           test_Y
glm_predict  No Yes
        No  934  59
        Yes   7   0
0/(7 + 0)
[1] 0

没有一个预测对

以 0.25 为阈值

glm_predict <- rep("No", 1000)
glm_predict[glm_probs > .25] = "Yes"
table(glm_predict, test_Y)
           test_Y
glm_predict  No Yes
        No  919  48
        Yes  22  11
11/(22 + 11)
[1] 0.3333333

33% 比随机猜想的五倍还多

参考

https://github.com/perillaroc/islr-study

ISLR实验系列文章

线性回归

分类

重抽样方法

线性模型选择与正则化