Radius Neighbors Classifier 是一种分类机器学习算法。
它是 k-nearest neighbors 算法的扩展,通过查看新示例半径内的所有示例来做出预测,而不是 k 个最近的邻居。
因此,基于半径的邻居选择方法更适用于稀疏数据,可以防止特征空间中距离较远的示例对预测做出贡献。
在本教程中,您将发现 Radius Neighbors Classifier 分类机器学习算法。
完成本教程后,您将了解:
- Nearest Radius Neighbors Classifier 是 k-nearest neighbors 分类算法的一个简单扩展。
- 如何使用 Scikit-Learn 的 Radius Neighbors Classifier 模型进行拟合、评估和预测。
- 如何在给定的数据集上调整 Radius Neighbors Classifier 算法的超参数。
让我们开始吧。

使用 Python 的半径邻居分类器算法
照片由J. Triepke拍摄,保留部分权利。
教程概述
本教程分为三个部分;它们是:
- Radius Neighbors Classifier
- Radius Neighbors Classifier with Scikit-Learn
- 调整 Radius Neighbors Classifier 超参数
Radius Neighbors Classifier
Radius Neighbors 是一种分类机器学习算法。
它基于 k-nearest neighbors 算法,或称 kNN。kNN 的过程是获取整个训练数据集并将其存储起来。然后,在预测时,为我们想要预测的每个新示例找到训练数据集中 k 个最近的示例。然后将来自 k 个邻居的模式(最常见的值)类标签分配给新示例。
有关 k-nearest neighbors 算法的更多信息,请参阅本教程
Radius Neighbors Classifier 类似之处在于训练涉及存储整个训练数据集。在预测过程中使用训练数据集的方式有所不同。
Radius Neighbors Classifier 不会找到 k 个邻居,而是找到训练数据集中与新示例在给定半径内的所有示例。然后使用半径邻居为新示例做出预测。
半径在特征空间中定义,通常假定输入变量是数值型的,并且被缩放到 0-1 的范围,例如归一化。
用于查找邻居的基于半径的方法适用于那些希望邻居的贡献与特征空间中示例的密度成比例的数据集。
给定一个固定的半径,特征空间的密集区域将贡献更多信息,稀疏区域将贡献较少信息。后者这种情况是最理想的,它可以防止特征空间中距离新示例非常远的示例对预测做出贡献。
因此,对于特征空间中存在稀疏区域的预测问题,Radius Neighbors Classifier 可能更合适。
鉴于半径在特征空间的每个维度上都是固定的,随着输入特征数量的增加,它的效果会越来越差,因为特征空间中的示例会彼此远离。这种性质被称为维度灾难。
Radius Neighbors Classifier with Scikit-Learn
Radius Neighbors Classifier 可在 scikit-learn Python 机器学习库中通过 RadiusNeighborsClassifier 类获得。
该类允许您通过“radius”参数指定进行预测时使用的半径大小,该参数默认为 1.0。
1 2 3 |
... # 创建模型 model = RadiusNeighborsClassifier(radius=1.0) |
另一个重要的超参数是“weights”参数,它控制邻居是“uniform”(均匀)地对预测做出贡献,还是根据与示例的距离“distance”(距离)的倒数进行贡献。默认使用均匀权重。
1 2 3 |
... # 创建模型 model = RadiusNeighborsClassifier(weights='uniform') |
我们可以通过一个实际示例来演示 Radius Neighbors Classifier。
首先,让我们定义一个合成分类数据集。
我们将使用 make_classification() 函数创建一个具有 1,000 个示例的数据集,每个示例有 20 个输入变量。
以下示例创建并总结了数据集。
1 2 3 4 5 6 |
# 测试分类数据集 from sklearn.datasets import make_classification # 定义数据集 X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=1) # 汇总数据集 print(X.shape, y.shape) |
运行示例创建数据集并确认数据集的行数和列数。
1 |
(1000, 20) (1000,) |
我们可以使用重复分层 K 折交叉验证通过 RepeatedStratifiedKFold 类来拟合和评估 Radius Neighbors Classifier 模型。我们将在测试框架中使用 10 折和 3 次重复。
我们将使用默认配置。
1 2 3 |
... # 创建模型 model = RadiusNeighborsClassifier() |
在准备和使用模型之前,对特征空间进行缩放非常重要。
我们可以通过使用 MinMaxScaler 来规范化输入特征,并使用 Pipeline 先应用缩放,然后使用模型来实现这一点。
1 2 3 4 5 |
... # 定义模型 model = RadiusNeighborsClassifier() # 创建管道 pipeline = Pipeline(steps=[('norm', MinMaxScaler()),('model',model)]) |
以下代码列出了针对合成二分类任务评估 Radius Neighbors Classifier 模型的完整示例。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
# 在数据集上评估 radius neighbors classifier 模型 from numpy import mean from numpy import std from sklearn.datasets import make_classification from sklearn.model_selection import cross_val_score from sklearn.model_selection import RepeatedStratifiedKFold from sklearn.pipeline import Pipeline 从 sklearn.预处理 导入 MinMaxScaler from sklearn.neighbors import RadiusNeighborsClassifier # 定义数据集 X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=1) # 定义模型 model = RadiusNeighborsClassifier() # 创建管道 pipeline = Pipeline(steps=[('norm', MinMaxScaler()),('model',model)]) # 定义模型评估方法 cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1) # 评估模型 scores = cross_val_score(pipeline, X, y, scoring='accuracy', cv=cv, n_jobs=-1) # 总结结果 print('平均准确率: %.3f (%.3f)' % (mean(scores), std(scores))) |
运行该示例将评估合成数据集上的 Radius Neighbors Classifier 算法,并报告 10 折交叉验证三次重复后的平均准确率。
鉴于学习算法的随机性,您的具体结果可能会有所不同。可以尝试运行几次示例。
在这种情况下,我们可以看到模型的平均准确率约为 75.4%。
1 |
平均准确率: 0.754 (0.042) |
我们可以决定使用 Radius Neighbors Classifier 作为我们的最终模型,并对新数据进行预测。
这可以通过在所有可用数据上拟合模型管道并调用 predict() 函数来完成,传入新的一行数据。
我们可以在下面列出的完整示例中演示这一点。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
# 在数据集上使用 radius neighbors classifier 模型进行预测 from sklearn.datasets import make_classification from sklearn.pipeline import Pipeline 从 sklearn.预处理 导入 MinMaxScaler from sklearn.neighbors import RadiusNeighborsClassifier # 定义数据集 X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=1) # 定义模型 model = RadiusNeighborsClassifier() # 创建管道 pipeline = Pipeline(steps=[('norm', MinMaxScaler()),('model',model)]) # 拟合模型 pipeline.fit(X, y) # 定义新数据 row = [2.47475454,0.40165523,1.68081787,2.88940715,0.91704519,-3.07950644,4.39961206,0.72464273,-4.86563631,-6.06338084,-1.22209949,-0.4699618,1.01222748,-0.6899355,-0.53000581,6.86966784,-3.27211075,-6.59044146,-2.21290585,-3.139579] # 进行预测 yhat = pipeline.predict([row]) # 总结预测 print('预测类别: %d' % yhat) |
运行示例后,模型将被拟合,并对新数据行进行类别标签预测。
1 |
预测类别:0 |
接下来,我们可以看看如何配置模型超参数。
调整 Radius Neighbors Classifier 超参数
Radius Neighbors Classifier 方法的超参数必须针对您的特定数据集进行配置。
也许最重要的超参数是通过“radius”参数控制的半径。测试一系列值是一个好主意,也许在 1.0 的值附近。
我们将使用 0.01 的网格在我们的合成数据集上测试 0.8 到 1.5 之间的值。
1 2 3 4 |
... # 定义网格 grid = dict() grid['model__radius'] = arange(0.8, 1.5, 0.01) |
请注意,我们在 Pipeline 中的 RadiusNeighborsClassifier 的“radius”超参数进行了网格搜索,其中模型名为“model”,因此,半径参数通过 model->radius 访问,使用双下划线 (__) 分隔,例如“model__radius”。
下面的示例使用我们定义的网格值的 GridSearchCV 类来演示这一点。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
# grid search radius for radius neighbors classifier from numpy import arange from sklearn.datasets import make_classification from sklearn.model_selection import GridSearchCV from sklearn.model_selection import RepeatedStratifiedKFold from sklearn.pipeline import Pipeline 从 sklearn.预处理 导入 MinMaxScaler from sklearn.neighbors import RadiusNeighborsClassifier # 定义数据集 X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=1) # 定义模型 model = RadiusNeighborsClassifier() # 创建管道 pipeline = Pipeline(steps=[('norm', MinMaxScaler()),('model',model)]) # 定义模型评估方法 cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1) # 定义网格 grid = dict() grid['model__radius'] = arange(0.8, 1.5, 0.01) # 定义搜索 search = GridSearchCV(pipeline, grid, scoring='accuracy', cv=cv, n_jobs=-1) # 执行搜索 results = search.fit(X, y) # 总结 print('平均准确率: %.3f' % results.best_score_) print('配置: %s' % results.best_params_) |
运行示例将使用重复交叉验证评估每种配置组合。
鉴于学习算法的随机性,您的具体结果可能会有所不同。尝试运行几次示例。
在这种情况下,我们可以看到,使用 0.8 的半径取得了比上一个示例中 1.0 的半径(准确率约为 75.4%)更好的结果,准确率约为 87.2%。
1 2 |
平均准确率: 0.872 配置: {'model__radius': 0.8} |
另一个关键的超参数是通过“weights”参数影响示例在半径内对预测的贡献方式。它可以设置为“uniform”(默认值)、“distance”(距离的倒数)或自定义函数。
我们可以测试这两种内置的加权方式,看看哪种在我们的半径为 0.8 的情况下表现更好。
1 2 3 4 |
... # 定义网格 grid = dict() grid['model__weights'] = ['uniform', 'distance'] |
完整的示例如下所示。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
# grid search weights for radius neighbors classifier from sklearn.datasets import make_classification from sklearn.model_selection import GridSearchCV from sklearn.model_selection import RepeatedStratifiedKFold from sklearn.pipeline import Pipeline 从 sklearn.预处理 导入 MinMaxScaler from sklearn.neighbors import RadiusNeighborsClassifier # 定义数据集 X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=1) # 定义模型 model = RadiusNeighborsClassifier(radius=0.8) # 创建管道 pipeline = Pipeline(steps=[('norm', MinMaxScaler()),('model',model)]) # 定义模型评估方法 cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1) # 定义网格 grid = dict() grid['model__weights'] = ['uniform', 'distance'] # 定义搜索 search = GridSearchCV(pipeline, grid, scoring='accuracy', cv=cv, n_jobs=-1) # 执行搜索 results = search.fit(X, y) # 总结 print('平均准确率: %.3f' % results.best_score_) print('配置: %s' % results.best_params_) |
运行示例会拟合模型,并通过交叉验证发现能获得最佳结果的超参数。
鉴于学习算法的随机性,您的具体结果可能会有所不同。尝试运行几次示例。
在这种情况下,我们可以看到,与上一个示例中的“uniform”权重(准确率约为 87.2%)相比,此次的“distance”权重将平均分类准确率又提高了约 89.3%。
1 2 |
平均准确率: 0.893 配置: {'model__weights': 'distance'} |
您可能希望探索的另一个指标是通过‘metric’参数使用的距离度量,该参数默认为‘minkowski’。
与‘euclidean’距离以及或许‘cityblock’进行比较可能会很有趣。
进一步阅读
如果您想深入了解,本节提供了更多关于该主题的资源。
教程
书籍
- 应用预测建模, 2013.
- 统计学习导论:R语言应用, 2014.
API
- Nearest Neighbors, Scikit-Learn 用户指南.
- sklearn.neighbors.RadiusNeighborsClassifier API.
- sklearn.pipeline.Pipeline API.
- sklearn.preprocessing.MinMaxScaler API.
文章
总结
在本教程中,您了解了 Radius Neighbors Classifier 分类机器学习算法。
具体来说,你学到了:
- Nearest Radius Neighbors Classifier 是 k-nearest neighbors 分类算法的一个简单扩展。
- 如何使用 Scikit-Learn 的 Radius Neighbors Classifier 模型进行拟合、评估和预测。
- 如何在给定的数据集上调整 Radius Neighbors Classifier 算法的超参数。
你有什么问题吗?
在下面的评论中提出你的问题,我会尽力回答。
感谢这篇文章。
此算法是否处理新的类别(未训练的新类别)?
谢谢。
不能,不是直接处理。也许您可以修改该算法以适应这种情况。