人工智能与机器学习原理精解【20】
文章目录
- KNN(K-Nearest Neighbor,K最近邻)算法
- 概述
- 1. 定义
- 2. 性质
- 3. 计算过程
- 4. 例子和例题
- 5. Julia实现
- KNN算法的详细过程
- 算法
- 例子
- 手动实现KNN算法
- 使用现有库实现KNN
- 参考文献
KNN(K-Nearest Neighbor,K最近邻)算法
是数据挖掘分类技术中最简单的方法之一,它既可以用于分类问题,也可以用于回归问题,但更常用于分类问题。下面将按照要求详细介绍KNN算法的定义、性质、计算过程、例子和例题,以及Julia语言的实现(由于Julia实现部分较为具体且可能涉及特定库,这里将提供一般性指导)。
概述
1. 定义
KNN算法是一种基于实例的学习,或者说是懒惰学习,它不需要显式地训练模型,而是将输入样本与训练集中的每个样本进行比较,找到最近的K个邻居,然后根据这些邻居的类别来预测输入样本的类别。
2. 性质
- 简单直观:算法思想简单,易于理解和实现。
- 无需显式训练:不需要像其他算法那样进行显式地模型训练,而是直接使用训练集进行分类。
- 监督学习:需要有标签的数据集进行训练。
- 对样本分布敏感:当样本分布不平衡时,分类结果可能偏向样本数量较多的类别。
3. 计算过程
KNN算法的计算过程主要包括以下几个步骤:
-
准备数据:包括收集、清洗和预处理数据。预处理可能包括归一化或标准化特征,以确保所有特征在计算距离时具有相等的权重。
-
选择距离度量方法:确定用于比较样本之间相似性的度量方法,常用的有欧氏距离、曼哈顿距离等。
-
确定K值:选择一个K值,即在分类时应考虑的邻居数量。这是一个超参数,可以通过交叉验证等方法来选择最优的K值。
-
计算距离:计算待分类样本与训练集中每个样本之间的距离。
-
选择邻居:根据计算得到的距离,选择与待分类样本距离最近的K个邻居。
-
投票或权重计算:对于分类问题,根据K个邻居的类别进行投票,选择票数最多的类别作为待分类样本的类别。对于回归问题,可以根据K个邻居的距离和标签进行加权计算,得到待分类样本的预测值。
-
评估和优化:使用适当的评价指标评估模型的性能,并根据需要调整参数以优化性能。
4. 例子和例题
例子:假设有一个二维平面上的点集,每个点都有一个类别标签(红或蓝)。现在有一个新的点需要分类,KNN算法会计算这个新点到所有已知点的距离,然后选择距离最近的K个点,看这些点中哪个类别的点最多,就将新点归为该类别。
例题:具体实现时,可以设定一个具体的K值(如K=3),然后计算待分类点到所有已知点的欧氏距离,选择距离最小的3个点,如果这3个点中有2个是红色,1个是蓝色,则待分类点被归类为红色。
5. Julia实现
由于Julia语言的实现细节可能因库和版本而异,这里只提供一个大致的框架性指导。在Julia中,可以使用Distances.jl
库来计算距离,使用自定义函数或循环来实现KNN算法的核心逻辑。以下是一个简化的伪代码示例:
using Distances
function knn(x_test, x_train, y_train, k)
# 初始化距离和索引数组
distances = zeros(length(x_train))
nearest_indices = zeros(Int, k)
# 计算测试样本到每个训练样本的距离
for (i, x_train_point) in enumerate(x_train)
distances[i] = euclidean(x_test, x_train_point) # 使用欧氏距离
end
# 选择距离最近的K个邻居的索引
sorted_indices = sortperm(distances)[1:k]
nearest_indices = sorted_indices
# 根据邻居的类别进行投票
class_votes = Dict{eltype(y_train), Int}()
for index in nearest_indices
label = y_train[index]
class_votes[label] = get(class_votes, label, 0) + 1
end
# 返回票数最多的类别
max_vote = maximum(values(class_votes))
most_common_class = first(filter(x -> class_votes[x] == max_vote, keys(class_votes)))
return most_common_class
end
请注意,上述代码是一个简化的示例,并未处理所有可能的边缘情况,且可能需要根据实际情况进行调整。在实际应用中,还需要考虑数据的预处理、性能优化(如使用KD树等数据结构加速邻居搜索)等因素。
K最近邻(K-Nearest Neighbors, KNN)算法是一种基本的分类与回归方法,通常用于监督学习。在这里,我们主要讨论KNN用于分类的情况。KNN算法的核心思想是:一个样本的标签大多数情况下与它最近邻的k个样本的标签相同。
KNN算法的详细过程
算法
-
收集数据:
收集训练数据集,包括样本的特征和对应的标签。 -
处理数据:
- 如果数据集中的特征量纲不同,需要进行归一化或标准化处理,以确保每个特征对距离计算的影响是相同的。
- 确定K值,即最近邻的个数。K值的选择通常需要通过交叉验证等方法来优化。
-
计算距离:
对于待分类的样本,计算它与训练集中每个样本之间的距离。常用的距离度量方法包括欧氏距离、曼哈顿距离、切比雪夫距离等。 -
选择最近邻:
根据计算出的距离,选择距离待分类样本最近的K个训练样本。 -
投票表决:
统计这K个最近邻样本的标签,选择出现次数最多的标签作为待分类样本的预测标签。 -
评估模型:
使用测试数据集来评估KNN模型的性能,如准确率、召回率、F1分数等。
例子
假设我们有一个简单的二维数据集,包含以下样本和对应的标签:
样本编号 | 特征1 | 特征2 | 标签 |
---|---|---|---|
1 | 1.0 | 2.0 | A |
2 | 1.5 | 1.8 | A |
3 | 5.0 | 7.0 | B |
4 | 6.0 | 8.0 | B |
现在,我们有一个待分类的样本,其特征为(3.0, 3.0),我们需要确定这个样本的标签。
-
处理数据:
在这个例子中,特征量纲相同,因此不需要进行归一化处理。我们假设K=3。 -
计算距离:
使用欧氏距离公式,计算待分类样本与每个训练样本之间的距离:- 与样本1的距离:(\sqrt{(3.0-1.0)^2 + (3.0-2.0)^2} = \sqrt{5})
- 与样本2的距离:(\sqrt{(3.0-1.5)^2 + (3.0-1.8)^2} \approx \sqrt{2.61})
- 与样本3的距离:(\sqrt{(3.0-5.0)^2 + (3.0-7.0)^2} = \sqrt{20})
- 与样本4的距离:(\sqrt{(3.0-6.0)^2 + (3.0-8.0)^2} = \sqrt{29})
-
选择最近邻:
根据计算出的距离,选择距离最小的3个样本,即样本1、样本2和样本3。 -
投票表决:
统计这3个样本的标签,发现样本1和样本2的标签为A,样本3的标签为B。因此,选择出现次数最多的标签A作为待分类样本的预测标签。 -
得出结论:
待分类样本(3.0, 3.0)的预测标签为A。
这个简单的例子展示了KNN算法的基本流程。在实际应用中,KNN算法的性能受到K值选择、距离度量方法、数据预处理等多种因素的影响,需要通过实验来优化这些参数。
在Julia中实现K最近邻(K-Nearest Neighbors, KNN)算法可以从两个角度进行:一是手动编写算法,二是使用现有的库。下面我将分别展示这两种方法。
手动实现KNN算法
首先,我们手动实现一个简单的KNN算法。这个实现将包括计算欧氏距离、找到最近的K个邻居,并进行投票表决。
using LinearAlgebra # for Euclidean distance calculation
# Define a function to calculate the Euclidean distance between two vectors
function euclidean_distance(a, b)
return sqrt(sum((a - b) .^ 2))
end
# Define the KNN function
function knn(train_data, train_labels, test_point, k)
distances = []
# Calculate the distance between the test point and each training point
for i in 1:size(train_data, 1)
push!(distances, (euclidean_distance(train_data[i, :], test_point), train_labels[i]))
end
# Sort the distances and select the k nearest neighbors
sorted_distances = sort(distances, by = x -> x[1])
nearest_neighbors = sorted_distances[1:k]
# Count the labels of the nearest neighbors
label_counts = Dict()
for (_, label) in nearest_neighbors
if label in keys(label_counts)
label_counts[label] += 1
else
label_counts[label] = 1
end
end
# Find the most common label
most_common_label = max(label_counts, by = x -> x[2])[1]
return most_common_label
end
# Example usage
train_data = [1.0 2.0; 1.5 1.8; 5.0 7.0; 6.0 8.0]
train_labels = ["A", "A", "B", "B"]
test_point = [3.0, 3.0]
k = 3
predicted_label = knn(train_data, train_labels, test_point, k)
println("Predicted label: ", predicted_label)
使用现有库实现KNN
在Julia中,你可以使用scikit-learn
的Julia接口ScikitLearn.jl
来轻松实现KNN。首先,你需要安装这个包:
(julia) pkg> add ScikitLearn
然后,你可以使用以下代码来调用KNN算法:
using ScikitLearn
using ScikitLearn.CrossValidation: train_test_split
using ScikitLearn.Neighbors: KNeighborsClassifier
using ScikitLearn.Metrics: accuracy_score
# Prepare the data
train_data = [1.0 2.0; 1.5 1.8; 5.0 7.0; 6.0 8.0]
train_labels = ["A", "A", "B", "B"]
# Convert labels to numerical format for scikit-learn
label_mapping = {"A" => 0, "B" => 1}
train_labels_numeric = [label_mapping[label] for label in train_labels]
# Split data into training and testing sets (in this case, we'll just use the whole dataset for training)
X_train, X_test, y_train, y_test = train_test_split(train_data, train_labels_numeric, test_size=0.0) # no test set
# Create the KNN classifier
knn = KNeighborsClassifier(n_neighbors=3)
# Fit the model
fit!(knn, X_train, y_train)
# Predict the label for the test point
test_point = [[3.0, 3.0]]
predicted_label_numeric = predict(knn, test_point)
# Convert the predicted label back to the original format
predicted_label = (for (key, value) in label_mapping if value == predicted_label_numeric[1] key end).next()
println("Predicted label: ", predicted_label)
注意:
ScikitLearn.jl
是对 Python 的scikit-learn
库的封装,因此它依赖于 Python 和scikit-learn
的安装。- 在上面的例子中,由于我们的数据集很小,我们没有划分训练集和测试集。在实际应用中,你应该划分数据集来评估模型的性能。
ScikitLearn.jl
的接口可能会随着版本的更新而发生变化,因此请查阅最新的文档以获取准确的信息。
参考文献
- 文心一言