暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

R语言机器学习|KNN算法

1616
点击关注了解更新哦

KNN(K Nearest Neighbors)算法是有监督机器学习算法的一种。该算法简单有效,训练速度快,是广泛使用的一种分类算法。KNN算法主要通过对距离的度量及选择合适的K值来对样本进行分类。下图是一个简单KNN算法的示意图,以食物的甜度(sweet)和脆度(crunchy)两个特征为基础,计算西红柿与其他水果在特征值上的距离,选择合适的K值,进而判断西红柿所属类别。本文主要内容参考LantzMachine Learning With R[1]

1、数据准备

使用书中提供的breast cancer的数据集。该数据集除去ID标识外,共包含31个特征,其中1个为breast cancer的诊断结果,分为BenignMalignant两种类别,其余30个特征为对应的测量结果,为数值型变量。使用KNN算法来根据breast cancer各特征测量结果自动识别癌细胞。

library(class)
library(gmodels)
setwd("C://Users//Acer//Desktop")
wbcd <- read.csv("wisc_bc_data.csv")

2、数据探索

在进行KNN算法前,首先需要对数据进行基本探索。关于该部分内容详细介绍可参考R数据分析基础|理解数据

View(wbcd) #查看完整表格
head(wbcd) #查看数据前几行
str(wbcd) #数据类型
summary(wbcd) #描述性概述
wbcd <- wbcd[-1] #去除首列(ID列)
table(wbcd$diagnosis#结果变量频次
#  B   M 
#357 212 
round(prop.table(table(wbcd$diagnosis)) * 100, digits = 2) #结果变量频率
#    B     M 
#62.74 37.26 
wbcd$diagnosis <- factor(wbcd$diagnosis, levels = c("B""M"), labels = c("Benign""Malignant")) #标签因子化,并修改标签名称
round(prop.table(table(wbcd$diagnosis)) * 100, digits = 2) #结果变量频率
#   Benign Malignant 
#    62.74     37.26 
summary(wbcd[c("radius_mean""area_mean""compactness_mean")]) #查看变量数值分布
#  radius_mean       area_mean      compactness_mean 
# Min.   : 6.981   Min.   : 143.5   Min.   :0.01938  
# 1st Qu.:11.700   1st Qu.: 420.3   1st Qu.:0.06492  
# Median :13.370   Median : 551.1   Median :0.09263  
# Mean   :14.127   Mean   : 654.9   Mean   :0.10434  
# 3rd Qu.:15.780   3rd Qu.: 782.7   3rd Qu.:0.13040  
# Max.   :28.110   Max.   :2501.0   Max.   :0.34540  

3、数据标准化

数据探索发现,各特征之间数值差异较大,由于KNN算法在距离计算上很大程度依赖于属性特征的测量尺度,测量尺度不一最终会导致分类结果出现问题。因此需要对数据进行标准化或者规范化处理,首先以min-max规范化方法为例,对数据进行重新调整。关于数据处理可参考R数据分析|数据的标准化、规范化与对数化。

#定义min-max规范化函数
normalize <- function(x) {
  return((x - min(x)) / (max(x) - min(x)))
}
wbcd_n <- as.data.frame(apply(wbcd[-1], 2, normalize))
summary(wbcd_n[c("radius_mean""area_mean""compactness_mean")]) #查看变量数值分布
#  radius_mean       area_mean      compactness_mean
# Min.   :0.0000   Min.   :0.0000   Min.   :0.0000  
# 1st Qu.:0.2233   1st Qu.:0.1174   1st Qu.:0.1397  
# Median :0.3024   Median :0.1729   Median :0.2247  
# Mean   :0.3382   Mean   :0.2169   Mean   :0.2606  
# 3rd Qu.:0.4164   3rd Qu.:0.2711   3rd Qu.:0.3405  
# Max.   :1.0000   Max.   :1.0000   Max.   :1.0000  

4、模型准备

通过规范化方法,使得所有数值都落在了0~1之间。接下来进行模型准备,创建测试集和测试集,以及对应的标签向量。由于该数据集在顺序上已被打乱,因此可按顺序选择数据,但如果数据是按照结果变量顺序排列,则需要进行随机抽样,可使用sample() 函数进行随机抽样。

#创建训练集与测试集
wbcd_train <- wbcd_n[1:469, ]
wbcd_test <- wbcd_n[470:569, ]
#训练集与测试集标签
wbcd_train_labels <- wbcd[1:469, 1]
wbcd_test_labels <- wbcd[470:569, 1]

5、模型训练

使用class包中的knn() 函数来实现KNN算法。同时,需要先指定具体的k值,k值一般从选取训练样本数的平方根开始。在本案例中,训练集中的样本数为469,则k约等于取21或者22。

sqrt(469) #训练集有469个样本,取平方根
#[1] 21.65641
wbcd_z_test_pred <- knn(train = wbcd_z_train, test = wbcd_z_test, cl = wbcd_z_train_labels, k =21)
wbcd_test_pred #返回一个向量因子,为预测集
str(wbcd_test_pred)
# Factor w/ 2 levels "Benign","Malignant": 1 1 1 1 2 1 2 1 2 1 ...
table(wbcd_test_pred)
#wbcd_test_pred
#   Benign Malignant 
#       63        37 

6、模型评估

使用table() 函数或者CrossTable() 函数对模型的训练结果进行评估。

方法一:根据table() 函数返回的结果来看,有2个Malignant预测为了Benign,模型整体准确率为98%。

table(wbcd_test_labels,wbcd_test_pred)
#                wbcd_test_pred
#wbcd_test_labels Benign Malignant
#       Benign        61         0
#       Malignant      2        37

方法二:使用CrossTable() 函数,关于CrossTable() 的使用可参考R数据分析基础|理解数据。

CrossTable(x = wbcd_test_labels, y = wbcd_test_pred, 
           prop.chisq = FALSE, prop.r = FALSE, prop.c = FALSE)

训练结果

   Cell Contents
|-------------------------|
|                       N |
|         N / Table Total |
|-------------------------|
Total Observations in Table:  100 
                 | wbcd_test_pred 
wbcd_test_labels |    Benign | Malignant | Row Total | 
-----------------|-----------|-----------|-----------|
          Benign |        61 |         0 |        61 | 
                 |     0.610 |     0.000 |           | 
-----------------|-----------|-----------|-----------|
       Malignant |         2 |        37 |        39 | 
                 |     0.020 |     0.370 |           | 
-----------------|-----------|-----------|-----------|
    Column Total |        63 |        37 |       100 | 
-----------------|-----------|-----------|-----------|

7、模型改进

方法一:使用z-score标准化

模型准备

wbcd_z <- as.data.frame(scale(wbcd[-1])) #数据标准化
wbcd_z_train <- wbcd_z[1:469, ] #训练集
wbcd_z_test <- wbcd_z[470:569, ] #测试集
wbcd_z_train_labels <- wbcd[1:469, 1] #训练集标签
wbcd_z_test_labels <- wbcd[470:569, 1] #测试集标签
wbcd_z_test_pred <- knn(train = wbcd_z_train, test = wbcd_z_test, cl = wbcd_z_train_labels, k =21) #模型训练
CrossTable(x = wbcd_z_test_labels, y = wbcd_z_test_pred, 
           prop.chisq = FALSE, prop.r = FALSE, prop.c = FALSE) #查看结果

训练结果。模型准确率为95%。

   Cell Contents
|-------------------------|
|                       N |
|         N / Table Total |
|-------------------------|
Total Observations in Table:  100 
                   | wbcd_z_test_pred 
wbcd_z_test_labels |    Benign | Malignant | Row Total | 
-------------------|-----------|-----------|-----------|
            Benign |        61 |         0 |        61 | 
                   |     0.610 |     0.000 |           | 
-------------------|-----------|-----------|-----------|
         Malignant |         5 |        34 |        39 | 
                   |     0.050 |     0.340 |           | 
-------------------|-----------|-----------|-----------|
      Column Total |        66 |        34 |       100 | 
-------------------|-----------|-----------|-----------|

方法二:使用不同的k值

模型准备。以min-max规范化的数据为例,替换K值。

wbcd_test_pred_15 <- knn(train = wbcd_train, test = wbcd_test, cl = wbcd_train_labels, k = 15)
CrossTable(x = wbcd_test_labels, y = wbcd_test_pred_15, 
           prop.chisq = FALSE, prop.r = FALSE, prop.c = FALSE)

训练结果。模型准确率为97%。

   Cell Contents
|-------------------------|
|                       N |
|         N / Table Total |
|-------------------------|
Total Observations in Table:  100 
                 | wbcd_test_pred_15 
wbcd_test_labels |    Benign | Malignant | Row Total | 
-----------------|-----------|-----------|-----------|
          Benign |        61 |         0 |        61 | 
                 |     0.610 |     0.000 |           | 
-----------------|-----------|-----------|-----------|
       Malignant |         3 |        36 |        39 | 
                 |     0.030 |     0.360 |           | 
-----------------|-----------|-----------|-----------|
    Column Total |        64 |        36 |       100 | 
-----------------|-----------|-----------|-----------|

其他

关于KNN算法的原理部分可进一步阅读LantzMachine Learning With R及相关文献资料。本文数据可在后台回复【20220226】获得。


如有帮助请多多点赞哦!

参考资料

[1]

Lantz B, Machine Learning With R: https://www.packtpub.com/product/machine-learning-with-r-third-edition/9781788295864.


文章转载自日常分享的小懒猫,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论