R 是实现 KNN 分类的强大工具,广泛用于数据科学家和统计学家在各类机器学习应用中的实践。
在本教程中,我们将学习 K-近邻(KNN)的概念、工作原理,并回顾其优缺点。此外,我们将使用 R 的 'class' 和 'caret' 包,轻松实现 KNN 分类模型。
什么是 K-近邻(KNN)?
K-近邻(KNN)是一种监督式机器学习模型,可用于回归和分类任务。该算法为非参数模型,这意味着它不对数据的底层分布作出任何假设。
KNN 算法通过在训练数据集的特征空间中,查找与测试数据集中样本最近的邻居,并根据这些邻居的标签来预测测试样本的标签。“K”是最重要的超参数,可以通过调优来优化模型性能。
KNN 是一种简单直观的算法,能在广泛的分类问题上给出良好结果。它容易实现和理解,适用于小型和大型数据集。不过,它也有一些缺点,主要在于对于大规模数据集或高维特征空间,计算代价可能较高。
KNN 广泛应用于电商推荐引擎、图像识别、欺诈检测、文本分类、异常检测等场景。在本教程中,我们将以贷款审批系统为例使用 KNN 算法。
如果您对如何开启数据科学之路仍感到困惑,可查看 Data Scientist Professional with R 职业路径课程,为数据科学职业生涯做好准备。该技能路径将帮助您掌握 R 编程、数据摄取、数据清洗、数据处理、数据可视化、机器学习、假设检验、实验设计、SQL 和 Git。
K-近邻分类如何工作?
KNN 分类算法通过在训练数据集中找到与新数据点最近的 K 个邻居(最近的数据点),然后将邻居中占多数的类别标签赋给新数据点。
让我们将算法分解为多个步骤。
首先,计算新数据点与训练集中所有数据点之间的距离,并选择距离最近的 K 个点。用于计算距离的度量会因问题而异,最常用的是欧氏距离。
在确定了 K 个最近邻之后,算法将这些邻居中占多数的类别标签赋给新数据点。比如,如果两个标签为“blue”,一个标签为“red”,算法会将“blue”赋给新数据点。
动图来源:eunsukim.me
小结:
选择 K 的取值,即用于预测的最近邻数量。
计算该点与训练集中所有点的距离。
根据距离选择最近的 K 个邻居。
将多数类的标签赋给新数据点。
对测试集中所有数据点重复步骤 2 至 4。
评估算法的准确率。
“K” 的值由用户提供,也可用于优化算法性能。K 值过小可能导致过拟合,过大则可能欠拟合。因此,找到既稳定又拟合良好的最优值至关重要。
在 R 中实现 KNN
本节中,我们将使用 贷款数据 ,并借助 class 包训练 KNN 分类模型。该数据集包含 10,000 条贷款记录,我们将根据客户数据判断贷款是否会按期还清。
加载数据
我们将导入 tidyverse 库,以访问数据加载、处理和可视化所需的 R 基础包。suppressPackageStartupMessages 将屏蔽启动信息,使输出更干净。
随后,我们使用 read_csv 加载数据集,使用 subset 函数从数据框中移除 “purpose” 列,并展示前 3 条样本。
suppressPackageStartupMessages( library( tidyverse) )
data <- read_csv( 'data/loans.csv.gz' , show_col_types = FALSE )
data <- subset( data, select = - c( purpose) )
head( data, 3 ) 技术支持
划分训练集与测试集
我们可以手动划分数据集,但使用 caTools 库会更简洁。
设置随机种子以保证可复现性。
使用 sample.split 以 75:25 的比例为训练集和测试集创建索引。
使用 subset 创建训练集与测试集,如下所示。
library( caTools)
set.seed( 255 )
split = sample.split( data$ not_fully_paid,
SplitRatio = 0.75 )
train = subset( data,
split == TRUE )
test = subset( data,
split == FALSE ) 技术支持
特征缩放
现在对训练集和测试集进行缩放。底层实现采用 (x - mean(x)) / sd(x)。我们只对特征做缩放,并从训练集与测试集中移除目标标签。
train_scaled = scale( train[ - 13 ] )
test_scaled = scale( test[ - 13 ] ) 技术支持
训练 KNN 分类器并预测
class 库在训练 KNN 分类方面非常常用,简单且快速。我们将提供缩放后的训练/测试数据集、目标列以及 “k” 超参数。
library( class)
test_pred <- knn(
train = train_scaled,
test = test_scaled,
cl = train$ not_fully_paid,
k= 10
) 技术支持
模型评估
为评估模型结果,我们将使用 table 函数展示混淆矩阵。我们向 table 函数提供了实际(测试目标)与预测标签。可以看到,对多数类的预测效果相当不错。
KNN 不擅长处理类别不平衡的数据,这也是我们在少数类上表现较差的原因。
actual <- test$ not_fully_paid
cm <- table( actual, test_pred)
cm技术支持
test_pred
actual 0 1
0 1988 23
1 373 10 技术支持
我们可以通过将混淆矩阵中的对角线(真正类)求和,并除以目标列总长度来计算准确率。
可以看到,在未调优的基础模型上,我们已获得较好的准确率。通过调优 “K” 超参数并对数据集做平衡处理,还可进一步提升准确率。
accuracy <- sum( diag( cm) ) / length( actual)
sprintf( "Accuracy: %.2f%%" , accuracy* 100 ) 技术支持
'Accuracy: 83.46%' 技术支持
使用 caret 在 R 中进行 KNN 分类
本节我们将全程使用 caret。caret 是一个用于构建和评估机器学习模型的 R 包,为主流机器学习算法提供统一接口。
我们将用它来划分与预处理数据集、执行超参数调优,并训练与评估模型。
划分训练集与测试集
我们将导入 caret 包并设置随机种子以保证可复现性。随后把目标变量从整数转换为因子。最后使用 createDataPartition 按 80:20 的比例将数据集划分为训练集和测试集。
suppressPackageStartupMessages( library( caret) )
set.seed( 255 )
data$ not_fully_paid <- factor( data$ not_fully_paid, levels = c( 0 , 1 ) )
trainIndex <- createDataPartition( data$ not_fully_paid,
times= 1 ,
p = .8 ,
list = FALSE )
train <- data[ trainIndex, ]
test <- data[ - trainIndex, ] 技术支持
数据预处理
随后我们使用 preProcess 函数对训练集与测试集进行缩放。
preProcValues <- preProcess( train, method = c( "center" , "scale" ) )
trainTransformed <- predict( preProcValues, train)
testTransformed <- predict( preProcValues, test) 技术支持
模型调优
在训练 KNN 模型之前,我们需要通过训练函数找到 “K” 的最优值。train 函数需要提供公式、缩放后的训练数据集、模型名称、训练控制方法(交叉验证)以及超参数列表。我们将评估 K 取 3、5、7 时的模型表现。
knnModel <- train(
not_fully_paid ~ .,
data = trainTransformed,
method = "knn" ,
trControl = trainControl( method = "cv" ) ,
tuneGrid = data.frame( k = c( 3 , 5 , 7 ) )
) 技术支持
训练表现最佳的模型
找到 “K” 的最佳取值后,我们将使用缩放后的训练数据集训练 KNN 分类模型。
best_model<- knn3(
not_fully_paid ~ .,
data = trainTransformed,
k = knnModel$ bestTune$ k
) 技术支持
模型评估
caret 提供了简单而强大的模型评估函数。为了展示模型表现,我们先对未见过的测试数据集进行标签预测。之后使用预测值与实际值,通过 confusionMatrix 函数评估模型性能。
predictions <- predict( best_model, testTransformed, type = "class" )
cm <- confusionMatrix( predictions, testTransformed$ not_fully_paid)
cm技术支持
结果中包含混淆矩阵、模型准确率、P 值、模型敏感性以及其他有助于判断模型稳定性和性能的重要指标。
如我们所见,模型在“Neg Pred Value”(少数类)上的表现较差,平衡准确率为 51%,与掷硬币的结果相近。
我们可以通过过采样和欠采样来平衡类别,从而改善结果。也可以进行特征工程,创建新特征并删除高度相关的特征。
Confusion Matrix and Statistics
Reference
Prediction 0 1
0 1570 288
1 39 18
Accuracy : 0.8292
95 % CI : ( 0.8116 , 0.8458 )
No Information Rate : 0.8402
P- Value [ Acc > NIR] : 0.9091
Kappa : 0.0516
Mcnemar's Test P- Value : < 2e-16
Sensitivity : 0.97576
Specificity : 0.05882
Pos Pred Value : 0.84499
Neg Pred Value : 0.31579
Prevalence : 0.84021
Detection Rate : 0.81984
Detection Prevalence : 0.97023
Balanced Accuracy : 0.51729
'Positive' Class : 0 技术支持
我们也可以将结果以数据框的形式简化展示。
data.frame( Accuracy = cm$ overall[ "Accuracy" ] ,
Sensitivity = cm$ byClass[ "Sensitivity" ] ,
Specificity = cm$ byClass[ "Specificity" ] ) 技术支持
如果您更偏爱 Python,想学习如何进行 KNN 分类,请阅读我们的 使用 scikit-learn 的 K-近邻(KNN)分类 教程,通过示例理解 KNN 的概念与流程。
使用 KNN 的优缺点
优点
算法简单,易于理解和实现。
适用性强,可用于回归与分类任务。
结果具有可解释性,易于可视化与理解,因为预测类别基于训练数据中最近邻的标签。
KNN 不对类别间的决策边界作假设,因此能够捕捉特征之间的非线性关系。
算法不对数据分布作出假设,适用于多种问题场景。
KNN 不构建显式模型,而是存储训练数据并在预测时使用。
缺点
对于大型、复杂数据集,计算与内存开销较大。
在类别不平衡的数据上性能下降,易偏向多数类,从而导致对少数类的表现较差。
不适合噪声较大的数据,因为数据点的最近邻可能并不能代表其真实类别。
不适用于高维数据,高维度可能导致各点之间的距离变得相似。
寻找最优的 K 值可能耗时。
KNN 对离群点敏感,因为其以距离度量来选择邻居。
不善于处理训练数据中的缺失值。
结论
在本教程中,我们学习了如何在 R 中使用 K-近邻(KNN)分类。我们介绍了 KNN 的基本概念与工作原理,并学习了 class 与 caret 两个库如何在真实数据集上训练与评估 KNN 分类模型。
通过 Supervised Learning in R: Classification 课程,您还可学习 R 中的其他监督学习算法。课程将通过示例与编码练习讲解朴素贝叶斯、逻辑回归与分类树。
本 R 教程涵盖了数据处理、划分与预处理、超参数调优、模型训练与结果评估等步骤。由于数据集不平衡,我们在少数类上的表现最差。
需要注意的是,KNN 并不完美,它同样存在一些缺点。在将其作为主要模型之前,我们需要综合考虑多方面因素。
R 是实现 KNN 分类的强大工具,广泛用于数据科学家和统计学家在各类机器学习应用中的实践。
在本教程中,我们将学习 K-近邻(KNN)的概念、工作原理,并回顾其优缺点。此外,我们将使用 R 的 'class' 和 'caret' 包,轻松实现 KNN 分类模型。
什么是 K-近邻(KNN)?
K-近邻(KNN)是一种监督式机器学习模型,可用于回归和分类任务。该算法为非参数模型,这意味着它不对数据的底层分布作出任何假设。
KNN 算法通过在训练数据集的特征空间中,查找与测试数据集中样本最近的邻居,并根据这些邻居的标签来预测测试样本的标签。“K”是最重要的超参数,可以通过调优来优化模型性能。
KNN 是一种简单直观的算法,能在广泛的分类问题上给出良好结果。它容易实现和理解,适用于小型和大型数据集。不过,它也有一些缺点,主要在于对于大规模数据集或高维特征空间,计算代价可能较高。
KNN 广泛应用于电商推荐引擎、图像识别、欺诈检测、文本分类、异常检测等场景。在本教程中,我们将以贷款审批系统为例使用 KNN 算法。
如果您对如何开启数据科学之路仍感到困惑,可查看 Data Scientist Professional with R 职业路径课程,为数据科学职业生涯做好准备。该技能路径将帮助您掌握 R 编程、数据摄取、数据清洗、数据处理、数据可视化、机器学习、假设检验、实验设计、SQL 和 Git。
K-近邻分类如何工作?
KNN 分类算法通过在训练数据集中找到与新数据点最近的 K 个邻居(最近的数据点),然后将邻居中占多数的类别标签赋给新数据点。
让我们将算法分解为多个步骤。
首先,计算新数据点与训练集中所有数据点之间的距离,并选择距离最近的 K 个点。用于计算距离的度量会因问题而异,最常用的是欧氏距离。
在确定了 K 个最近邻之后,算法将这些邻居中占多数的类别标签赋给新数据点。比如,如果两个标签为“blue”,一个标签为“red”,算法会将“blue”赋给新数据点。
动图来源:eunsukim.me
小结:
“K” 的值由用户提供,也可用于优化算法性能。K 值过小可能导致过拟合,过大则可能欠拟合。因此,找到既稳定又拟合良好的最优值至关重要。
在 R 中实现 KNN
本节中,我们将使用 贷款数据,并借助
class包训练 KNN 分类模型。该数据集包含 10,000 条贷款记录,我们将根据客户数据判断贷款是否会按期还清。加载数据
我们将导入
tidyverse库,以访问数据加载、处理和可视化所需的 R 基础包。suppressPackageStartupMessages将屏蔽启动信息,使输出更干净。随后,我们使用
read_csv加载数据集,使用subset函数从数据框中移除 “purpose” 列,并展示前 3 条样本。划分训练集与测试集
我们可以手动划分数据集,但使用
caTools库会更简洁。sample.split以 75:25 的比例为训练集和测试集创建索引。subset创建训练集与测试集,如下所示。特征缩放
现在对训练集和测试集进行缩放。底层实现采用
(x - mean(x)) / sd(x)。我们只对特征做缩放,并从训练集与测试集中移除目标标签。训练 KNN 分类器并预测
class库在训练 KNN 分类方面非常常用,简单且快速。我们将提供缩放后的训练/测试数据集、目标列以及 “k” 超参数。模型评估
为评估模型结果,我们将使用
table函数展示混淆矩阵。我们向table函数提供了实际(测试目标)与预测标签。可以看到,对多数类的预测效果相当不错。KNN 不擅长处理类别不平衡的数据,这也是我们在少数类上表现较差的原因。
我们可以通过将混淆矩阵中的对角线(真正类)求和,并除以目标列总长度来计算准确率。
可以看到,在未调优的基础模型上,我们已获得较好的准确率。通过调优 “K” 超参数并对数据集做平衡处理,还可进一步提升准确率。
使用 caret 在 R 中进行 KNN 分类
本节我们将全程使用
caret。caret 是一个用于构建和评估机器学习模型的 R 包,为主流机器学习算法提供统一接口。我们将用它来划分与预处理数据集、执行超参数调优,并训练与评估模型。
划分训练集与测试集
我们将导入
caret包并设置随机种子以保证可复现性。随后把目标变量从整数转换为因子。最后使用createDataPartition按 80:20 的比例将数据集划分为训练集和测试集。数据预处理
随后我们使用
preProcess函数对训练集与测试集进行缩放。模型调优
在训练 KNN 模型之前,我们需要通过训练函数找到 “K” 的最优值。train 函数需要提供公式、缩放后的训练数据集、模型名称、训练控制方法(交叉验证)以及超参数列表。我们将评估 K 取 3、5、7 时的模型表现。
训练表现最佳的模型
找到 “K” 的最佳取值后,我们将使用缩放后的训练数据集训练 KNN 分类模型。
模型评估
caret 提供了简单而强大的模型评估函数。为了展示模型表现,我们先对未见过的测试数据集进行标签预测。之后使用预测值与实际值,通过
confusionMatrix函数评估模型性能。结果中包含混淆矩阵、模型准确率、P 值、模型敏感性以及其他有助于判断模型稳定性和性能的重要指标。
如我们所见,模型在“Neg Pred Value”(少数类)上的表现较差,平衡准确率为 51%,与掷硬币的结果相近。
我们可以通过过采样和欠采样来平衡类别,从而改善结果。也可以进行特征工程,创建新特征并删除高度相关的特征。
我们也可以将结果以数据框的形式简化展示。
如果您更偏爱 Python,想学习如何进行 KNN 分类,请阅读我们的 使用 scikit-learn 的 K-近邻(KNN)分类 教程,通过示例理解 KNN 的概念与流程。
使用 KNN 的优缺点
优点
缺点
结论
在本教程中,我们学习了如何在 R 中使用 K-近邻(KNN)分类。我们介绍了 KNN 的基本概念与工作原理,并学习了
class与caret两个库如何在真实数据集上训练与评估 KNN 分类模型。通过 Supervised Learning in R: Classification 课程,您还可学习 R 中的其他监督学习算法。课程将通过示例与编码练习讲解朴素贝叶斯、逻辑回归与分类树。
本 R 教程涵盖了数据处理、划分与预处理、超参数调优、模型训练与结果评估等步骤。由于数据集不平衡,我们在少数类上的表现最差。
需要注意的是,KNN 并不完美,它同样存在一些缺点。在将其作为主要模型之前,我们需要综合考虑多方面因素。