KNN算法
本教程将介绍 k 最近邻 (kNN) 算法的概念、工作流程和示例。这是一种用于分类和回归的流行监督模型,是理解距离函数、投票系统和超参数优化的有用方法。
为了充分利用本教程,您应该具备 Python 的基本知识和使用 DataFrame 的经验。拥有一些 scikit-learn 语法的经验也会有所帮助。kNN 经常与无监督方法 k 均值聚类相混淆。如果您对此感兴趣,请使用 scikit-learn 查看 Python 中的 k 均值聚类。您还可以立即开始注册我们的 Python 机器学习课程,其中更详细地介绍了 kNN。
通过这个实践练习练习(KNN) 分类。
虽然 kNN 可用于分类和回归,但本文将重点关注构建分类模型。机器学习中的分类是一种监督学习任务,涉及预测给定输入数据点的分类标签。该算法在带标签的数据集上进行训练,并使用输入特征来学习输入与相应类标签之间的映射。我们可以使用经过训练的模型来预测新的、未见过的数据。您还可以通过打开此 DataCamp 工作区来运行本教程的代码。
K 最近邻概述
kNN 算法可以被认为是一个投票系统,其中多数类标签决定了特征空间中最近的“k”(其中 k 是整数)邻居中新数据点的类标签。想象一个只有几百居民的小村庄,你必须决定应该投票给哪个政党。为此,您可以去最近的邻居询问他们支持哪个政党。如果你的“k”个最近邻居中的大多数支持 A 方,那么你很可能也会投票给 A 方。这类似于 kNN 算法的工作原理,其中多数类标签决定了新数据点的类标签它的 k 个最近邻居。
让我们通过另一个例子来更深入地了解一下。想象一下您有关于水果的数据,特别是葡萄和梨。您可以对水果的圆度和直径进行评分。您决定将它们绘制在图表上。如果有人递给你一个新水果,你也可以将其绘制在图表上,然后测量到 k 个(数字)最近点的距离来确定它是什么水果。在下面的例子中,如果我们选择测量三个点,我们可以说最近的三个点是梨,所以我 100% 确定这是一个梨。如果我们选择测量最近的四个点,其中三个是梨,一个是葡萄,所以我们可以说我们有 75% 的把握这是梨。我们将在本文后面介绍如何找到 k 的最佳值以及测量距离的不同方法。
数据集
为了进一步说明 kNN 算法,让我们研究一下您作为数据科学家时可能会发现的案例研究。假设您是一家在线零售商的数据科学家,您的任务是检测欺诈交易。此阶段您拥有的唯一功能是:
dist_from_home
:用户的家庭位置与交易地点之间的距离。purchase_price_ratio
:本次交易中购买商品的价格与该用户购买价格中位数之间的比率。
该数据有 39 个观察值,均为单独交易。在本教程中,我们为数据集提供了变量df
,它看起来像这样:
距家的距离 | 购买价格比率 | 欺诈罪 | |
---|---|---|---|
0 | 2.1 | 6.4 | 1 |
1 | 3.8 | 2.2 | 1 |
2 | 15.7 | 4.4 | 1 |
3 | 26.7 | 4.6 | 1 |
4 | 10.7 | 4.9 | 1 |
k-最近邻工作流程
为了拟合和训练这个模型,我们将遵循机器学习工作流程信息图。
机器学习工作流程信息图
然而,由于我们的数据非常干净,我们不会执行每一步。我们将做以下工作:
- 特征工程
- 分割数据
- 训练模型
- 超参数调整
- 评估模型性能
可视化数据
让我们首先使用 Matplotlib 可视化我们的数据;我们可以在散点图中绘制我们的两个特征。
sns.scatterplot(x=df['dist_from_home'],y=df['purchase_price_ratio'], hue=df['fraud'])
这个有帮助吗?
正如您所看到的,这些交易之间存在明显的差异,与客户的中位订单相比,欺诈交易的价值要高得多。离家距离的趋势有些难以解释,非欺诈性交易通常离家较近,但也有一些异常值。
规范化和分割数据
在训练任何机器学习模型时,将数据分为训练数据和测试数据非常重要。训练数据用于拟合模型。该算法使用训练数据来学习特征与目标之间的关系。它试图在训练数据中找到一种模式,可用于对新的、未见过的数据进行预测。测试数据用于评估模型的性能。通过使用测试数据进行预测并将这些预测与实际目标值进行比较,对模型进行测试。
训练 kNN 分类器时,必须对特征进行归一化。这是因为 kNN 测量点之间的距离。默认情况下使用欧几里得距离,它是两点之间的平方差之和的平方根。在我们的例子中,purchase_price_ratio 在 0 到 8 之间,而 dist_from_home 要大得多。如果我们没有对此进行标准化,我们的计算将受到 dist_from_home 的严重影响,因为数字更大。
我们应该在将数据分为训练集和测试集后对其进行标准化。这是为了防止“数据泄漏”,因为如果我们一次对所有数据进行标准化,标准化将为模型提供有关测试集的附加信息。
以下代码将数据拆分为训练/测试部分,然后使用scikit-learn 的标准缩放器进行标准化。我们首先在训练数据上调用 .fit_transform() ,这使得我们的缩放器适合训练数据的平均值和标准差。然后,我们可以通过调用 .transform() 将其应用到测试数据,该方法使用之前学习的值。
# Split the data into features (X) and target (y)
X = df.drop('fraud', axis=1)
y = df['fraud']
# Split the data into training and test sets
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
# Scale the features using StandardScaler
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)
拟合和评估模型
我们现在准备好训练模型了。为此,我们将使用 k 的固定值 3,但稍后我们需要对其进行优化。我们首先创建 kNN 模型的一个实例,然后将其拟合到我们的训练数据中。我们传递特征和目标变量,以便模型可以学习。
knn = KNeighborsClassifier(n_neighbors=3)
knn.fit(X_train, y_train)
模型现已训练完成!我们可以对测试数据集进行预测,稍后可以使用它来对模型进行评分。
y_pred = knn.predict(X_test)
评估该模型的最简单方法是使用准确性。我们根据测试集中的实际值检查预测,并计算模型正确的数量。
accuracy = accuracy_score(y_test, y_pred)
print("Accuracy:", accuracy)
Accuracy: 0.875
这已经是一个相当不错的成绩了!然而,我们可以通过优化 k 值来做得更好。
使用交叉验证获得 k 的最佳值
不幸的是,没有神奇的方法可以找到 k 的最佳值。我们必须循环遍历许多不同的值,然后使用我们的最佳判断。
在下面的代码中,我们选择 k 的值范围并创建一个空列表来存储我们的结果。我们使用交叉验证来查找准确性分数,这意味着我们不需要创建训练和测试拆分,但我们确实需要扩展数据。然后我们循环这些值并将分数添加到我们的列表中。
为了实现交叉验证,我们使用scikit-learn 的 cross_val_score。我们传递 kNN 模型的一个实例,以及我们的数据和要进行的多次分割。在下面的代码中,我们使用五次拆分,这意味着模型将数据分为五个大小相等的组,并使用 4 进行训练,使用 1 测试结果。它将循环遍历每个组并给出准确度分数,我们将其平均以找到最佳模型。
k_values = [i for i in range (1,31)]
scores = []
scaler = StandardScaler()
X = scaler.fit_transform(X)
for k in k_values:
knn = KNeighborsClassifier(n_neighbors=k)
score = cross_val_score(knn, X, y, cv=5)
scores.append(np.mean(score))
我们可以使用以下代码绘制结果
sns.lineplot(x = k_values, y = scores, marker = 'o')
plt.xlabel("K Values")
plt.ylabel("Accuracy Score")
从图表中我们可以看到,k = 9、10、11、12 和 13 的准确度分数都略低于 95%。由于这些都与最佳分数相关,因此建议使用较小的 k 值。这是因为当使用较高的 k 值时,模型将使用更多距离原始数据更远的数据点。另一种选择是探索其他评估指标。
更多评估指标
现在,我们可以使用以下代码使用最佳 k 值来训练我们的模型。
best_index = np.argmax(scores)
best_k = k_values[best_index]
knn = KNeighborsClassifier(n_neighbors=best_k)
knn.fit(X_train, y_train)
然后评估准确度、精确度和召回率(请注意,您的结果可能因随机化而有所不同)
y_pred = knn.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
precision = precision_score(y_test, y_pred)
recall = recall_score(y_test, y_pred)
print("Accuracy:", accuracy)
print("Precision:", precision)
print("Recall:", recall)
Accuracy: 0.875
Precision: 0.75
Recall: 1.0
将其提升到新的水平
- scikit-learn监督学习课程是 DataCamp 的 Python 机器学习课程的切入点,涵盖 k-近邻。
- Python 中的异常检测、Python中的缺失数据处理和Python 中的金融机器学习课程都展示了使用 k-近邻的示例。
- Python 教程中的决策树分类涵盖了另一种用于对数据进行分类的机器学习模型。
- scikit -learn 备忘单为流行的机器学习功能提供了方便的参考。
版权声明:
作者:建模忠哥
链接:http://jianmozhongge.cn/2023/12/02/knn%e7%ae%97%e6%b3%95/
来源:建模忠哥
文章版权归作者所有,未经允许请勿转载。