文章目录
- KNN(K-Nearest Neighbor,K最近邻)算法
- 概述
- 1. 定义
- 2. 性质
- 3. 计算过程
- 4. 例子和例题
- 5. Julia实现
- KNN算法的详细过程
- 算法
- 例子
- 手动实现KNN算法
- 使用现有库实现KNN
- 加权KNN(加权K最近邻)
- 1. 基本原理
- 2. 权重计算方法
- 3. 算法步骤
- 4. 优点与缺点
- 5. 应用场景
- 参考文献
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 Distancesfunction 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_indiceslabel = y_train[index]class_votes[label] = get(class_votes, label, 0) + 1end# 返回票数最多的类别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的距离: ( 3.0 − 1.0 ) 2 + ( 3.0 − 2.0 ) 2 = 5 \sqrt{(3.0-1.0)^2 + (3.0-2.0)^2} = \sqrt{5} (3.0−1.0)2+(3.0−2.0)2=5
- 与样本2的距离: ( 3.0 − 1.5 ) 2 + ( 3.0 − 1.8 ) 2 ≈ 2.61 \sqrt{(3.0-1.5)^2 + (3.0-1.8)^2} \approx \sqrt{2.61} (3.0−1.5)2+(3.0−1.8)2≈2.61
- 与样本3的距离: ( 3.0 − 5.0 ) 2 + ( 3.0 − 7.0 ) 2 = 20 \sqrt{(3.0-5.0)^2 + (3.0-7.0)^2} = \sqrt{20} (3.0−5.0)2+(3.0−7.0)2=20
- 与样本4的距离: ( 3.0 − 6.0 ) 2 + ( 3.0 − 8.0 ) 2 = 29 \sqrt{(3.0-6.0)^2 + (3.0-8.0)^2} = \sqrt{29} (3.0−6.0)2+(3.0−8.0)2=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 pointfor 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 neighborssorted_distances = sort(distances, by = x -> x[1])nearest_neighbors = sorted_distances[1:k]# Count the labels of the nearest neighborslabel_counts = Dict()for (_, label) in nearest_neighborsif label in keys(label_counts)label_counts[label] += 1elselabel_counts[label] = 1endend# Find the most common labelmost_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 = 3predicted_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
的接口可能会随着版本的更新而发生变化,因此请查阅最新的文档以获取准确的信息。
加权KNN(加权K最近邻)
是K最近邻(KNN)算法的一种改进版本,它在计算最近邻时考虑了邻居样本之间的距离权重。以下是关于加权KNN的详细介绍:
1. 基本原理
在传统的KNN算法中,所有的邻居样本对最终分类结果的贡献是一样的,即使它们离待分类样本更远。而在加权KNN中,距离待分类样本更近的邻居样本将会被赋予更大的权重,距离更远的邻居样本将被赋予更小的权重,这样可以更好地反映邻居样本对待分类样本的影响。
2. 权重计算方法
加权KNN通常使用距离的倒数作为权重,距离越近的邻居样本权重越大,距离越远的邻居样本权重越小。这种方法直观且易于实现,其公式如下:
w i = 1 d i w_i = \frac{1}{d_i} wi=di1
其中, w i w_i wi 是第 i i i 个近邻点的权重, d i d_i di 是第 i i i 个近邻点到查询点的距离。
除了距离的倒数,还可以使用其他函数来计算权重,如高斯函数等。高斯函数能够更平滑地处理权重分配,避免在距离非常接近时权重变得过大,其公式如下:
w i = exp ( − ( d i − μ ) 2 2 σ 2 ) w_i = \exp\left(-\frac{(d_i - \mu)^2}{2\sigma^2}\right) wi=exp(−2σ2(di−μ)2)
其中, μ \mu μ 是均值(通常设为0,表示以查询点为中心), σ \sigma σ是标准差,控制权重随距离变化的衰减速度。
3. 算法步骤
加权KNN算法的基本步骤如下:
- 计算距离:计算待分类样本与训练集中所有样本之间的距离。
- 排序选择:根据距离对训练集样本进行排序,选择距离最近的k个样本作为邻居。
- 计算权重:根据选定的权重计算方法(如距离的倒数或高斯函数),计算每个邻居样本的权重。
- 加权投票/平均:根据邻居样本的类别和权重,进行加权投票或加权平均,得到待分类样本的预测类别或数值。
4. 优点与缺点
优点:
- 能够更准确地捕捉到邻居样本对待分类样本的影响,提高了分类的准确性。
- 可以通过调整距离权重的计算方法来适应不同的数据情况。
缺点:
- 如果权重分配过于集中,可能会对噪声数据变得更加敏感。
- 权重计算方法的选择和参数调整可能需要较多的实验和调优。
5. 应用场景
加权KNN算法广泛应用于分类和回归任务中,特别是在处理具有复杂样本分布的数据集时,其性能通常优于传统的KNN算法。例如,在文本分类、图像识别、时间序列预测等领域中,加权KNN算法都展现出了良好的应用效果。
综上所述,加权KNN算法通过考虑邻居样本之间的距离权重,能够更准确地进行分类和回归,是K最近邻算法的一种重要改进。在实际应用中,需要根据具体问题的特性和数据的特点选择合适的权重计算方法和参数设置。
参考文献
- 文心一言