机器学习与R语言学习笔记01:kNN

通过将《机器学习与R语言》一书中的代码tidyverse化,来学习这本书。

书中第一个例子是利用kNN算法来诊断乳腺癌。

首先载入需要用到的包:

library(tidyverse) # 清洗数据
library(here) # 设置数据文件路径
library(knitr) # 呈现更好看的表格
library(kableExtra) # 同上
library(class) # 使用包中的knn()函数
library(gmodels) # 使用包中的CrossTable()函数

然后导入数据并清洗:

wbcd <- read_csv(here('data', '01-wisc_bc_data.csv')) %>% 
  select(-id) %>% 
  mutate(diagnosis = factor(diagnosis, levels = c('B', 'M'),
                            labels = c('Benign', 'Malignant'))) %>% 
  mutate_if(is.numeric, ~ (.x - min(.x)) / (max(.x) - min(.x)))

首先使用here函数找到数据文件的路径,然后使用read_csv函数将其读入R中;随后通过select函数将id变量去掉;然后利用mutate函数将diagnosis变量改为因子型;最后利用mutate_if函数,将所有数值型的变量进行min-max标准化,这里用到了公式化的匿名函数,可以使代码更为简练。此时的数据是这样的:

wbcd %>% head()

## # A tibble: 6 x 31
##   diagnosis radius_mean texture_mean perimeter_mean area_mean
##   <fct>           <dbl>        <dbl>          <dbl>     <dbl>
## 1 Malignant       0.521       0.0227          0.546     0.364
## 2 Malignant       0.643       0.273           0.616     0.502
## 3 Malignant       0.601       0.390           0.596     0.449
## 4 Malignant       0.210       0.361           0.234     0.103
## 5 Malignant       0.630       0.157           0.631     0.489
## 6 Malignant       0.259       0.203           0.268     0.142
## # ... with 26 more variables: smoothness_mean <dbl>,
## #   compactness_mean <dbl>, concavity_mean <dbl>, `concave
## #   points_mean` <dbl>, symmetry_mean <dbl>, fractal_dimension_mean <dbl>,
## #   radius_se <dbl>, texture_se <dbl>, perimeter_se <dbl>, area_se <dbl>,
## #   smoothness_se <dbl>, compactness_se <dbl>, concavity_se <dbl>,
## #   `concave points_se` <dbl>, symmetry_se <dbl>,
## #   fractal_dimension_se <dbl>, radius_worst <dbl>, texture_worst <dbl>,
## #   perimeter_worst <dbl>, area_worst <dbl>, smoothness_worst <dbl>,
## #   compactness_worst <dbl>, concavity_worst <dbl>, `concave
## #   points_worst` <dbl>, symmetry_worst <dbl>,
## #   fractal_dimension_worst <dbl>

书中还提到了Z分数标准化,因为有现成的scale函数,所以代码会稍微简单:

wbcd <- read_csv(here('data', '01-wisc_bc_data.csv')) %>% 
  select(-id) %>% 
  mutate(diagnosis = factor(diagnosis, levels = c('B', 'M'),
                            labels = c('Benign', 'Malignant'))) %>% 
  mutate_if(is.numeric, scale)

下一步是创建训练数据集和测试数据集。首先先设定一个随机种子,保证结果可以复现,然后利用sample_n函数从完整数据中随机选择469行作为训练数据集,并利用setdiff函数筛选出训练数据集的补集作为测试数据集;最后利用pull函数把标签提取出来:

set.seed(0412)
wbcd_train <- wbcd %>% sample_n(469)
wbcd_test <- wbcd %>% setdiff(wbcd_train)
wbcd_train_labels <- wbcd_train %>% pull(1)
wbcd_test_labels <- wbcd_test %>% pull(1)

数据已经整理好,可以建模了,但是在书中没有看到将数据集中的标签变量去掉的过程,所以在这里的模型中,我把两个数据集的标签变量都去掉了:

wbcd_test_pred <- knn(train = wbcd_train[, -1], test = wbcd_test[, -1], 
                      cl = wbcd_train_labels, k = 21)

看一下模型的性能:

CrossTable(wbcd_test_labels, wbcd_test_pred, prop.chisq = FALSE)

## 
##  
##    Cell Contents
## |-------------------------|
## |                       N |
## |           N / Row Total |
## |           N / Col Total |
## |         N / Table Total |
## |-------------------------|
## 
##  
## Total Observations in Table:  100 
## 
##  
##                  | wbcd_test_pred 
## wbcd_test_labels |    Benign | Malignant | Row Total | 
## -----------------|-----------|-----------|-----------|
##           Benign |        68 |         0 |        68 | 
##                  |     1.000 |     0.000 |     0.680 | 
##                  |     0.986 |     0.000 |           | 
##                  |     0.680 |     0.000 |           | 
## -----------------|-----------|-----------|-----------|
##        Malignant |         1 |        31 |        32 | 
##                  |     0.031 |     0.969 |     0.320 | 
##                  |     0.014 |     1.000 |           | 
##                  |     0.010 |     0.310 |           | 
## -----------------|-----------|-----------|-----------|
##     Column Total |        69 |        31 |       100 | 
##                  |     0.690 |     0.310 |           | 
## -----------------|-----------|-----------|-----------|
## 
## 

跟书中的结果不一样,但也不错。

最后,书中还使用不同的k值对模型进行了评估,但没有给出相应的代码,我这里补充了一下:

k <- map(1:30, ~ knn(train = wbcd_train[, -1], test = wbcd_test[, -1], 
         cl = wbcd_train_labels, k = .x)) %>% 
  enframe(name = 'k', value = 'prediction') %>% 
  unnest() %>% 
  mutate(label = rep(wbcd_test_labels, 30),
         FN = prediction == 'Malignant' & label == 'Benign',
         FP = prediction == 'Benign' & label == 'Malignant') %>% 
  group_by(k) %>% 
  summarise(FN = sum(FN), 
            FP = sum(FP),
            total = FN + FP)

首先利用map函数将1到30分别映射到模型的k参数上,此时得到了会是一个长度为30的列表;随后利用enframe函数将列表变为行数为30的数据框,这时value变量下的每一个元素都包含100个字符;随后利用unnest将value变量中的字符解放出来,使数据框的行数变为3000;剩余的代码就比较简单,不多描述。

这时的数据是这样的:

print(k, n = nrow(k))

## # A tibble: 30 x 4
##        k    FN    FP total
##    <int> <int> <int> <int>
##  1     1     2     1     3
##  2     2     4     0     4
##  3     3     2     0     2
##  4     4     4     0     4
##  5     5     2     0     2
##  6     6     2     0     2
##  7     7     3     0     3
##  8     8     3     0     3
##  9     9     2     0     2
## 10    10     3     1     4
## 11    11     0     0     0
## 12    12     0     0     0
## 13    13     0     0     0
## 14    14     0     0     0
## 15    15     0     0     0
## 16    16     0     0     0
## 17    17     0     0     0
## 18    18     0     1     1
## 19    19     0     1     1
## 20    20     0     1     1
## 21    21     0     1     1
## 22    22     1     1     2
## 23    23     1     1     2
## 24    24     1     1     2
## 25    25     1     1     2
## 26    26     1     1     2
## 27    27     1     0     1
## 28    28     1     1     2
## 29    29     1     1     2
## 30    30     1     0     1

可以看到,k值从11到17时的结果都很“完美”。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 首页 资讯 文章 资源 小组 相亲 登录 注册 首页 最新文章 IT 职场 前端 后端 移动端 数据库 运维 其他...
    Helen_Cat阅读 4,159评论 1 10
  • 以西瓜书为主线,以其他书籍作为参考进行补充,例如《统计学习方法》,《PRML》等 第一章 绪论 1.2 基本术语 ...
    danielAck阅读 4,930评论 0 5
  • https://developers.google.com/machine-learning/crash-cour...
    iOSDevLog阅读 2,921评论 1 11
  • 机器学习术语表 本术语表中列出了一般的机器学习术语和 TensorFlow 专用术语的定义。 A A/B 测试 (...
    yalesaleng阅读 2,150评论 0 11
  • 之前,总觉得自己的生活太平平淡淡,没有一丝惊喜,没有大的改变,我其实很焦虑,害怕自己就这样一事无成的过下去,总觉...
    苏南安阅读 190评论 0 0

友情链接更多精彩内容