人工智能与机器学习原理精解【20】

文章目录

KNN(K-Nearest Neighbor,K最近邻)算法

是数据挖掘分类技术中最简单的方法之一,它既可以用于分类问题,也可以用于回归问题,但更常用于分类问题。下面将按照要求详细介绍KNN算法的定义、性质、计算过程、例子和例题,以及Julia语言的实现(由于Julia实现部分较为具体且可能涉及特定库,这里将提供一般性指导)。

概述

1. 定义

KNN算法是一种基于实例的学习,或者说是懒惰学习,它不需要显式地训练模型,而是将输入样本与训练集中的每个样本进行比较,找到最近的K个邻居,然后根据这些邻居的类别来预测输入样本的类别。

2. 性质

  • 简单直观:算法思想简单,易于理解和实现。
  • 无需显式训练:不需要像其他算法那样进行显式地模型训练,而是直接使用训练集进行分类。
  • 监督学习:需要有标签的数据集进行训练。
  • 对样本分布敏感:当样本分布不平衡时,分类结果可能偏向样本数量较多的类别。

3. 计算过程

KNN算法的计算过程主要包括以下几个步骤:

  1. 准备数据:包括收集、清洗和预处理数据。预处理可能包括归一化或标准化特征,以确保所有特征在计算距离时具有相等的权重。

  2. 选择距离度量方法:确定用于比较样本之间相似性的度量方法,常用的有欧氏距离、曼哈顿距离等。

  3. 确定K值:选择一个K值,即在分类时应考虑的邻居数量。这是一个超参数,可以通过交叉验证等方法来选择最优的K值。

  4. 计算距离:计算待分类样本与训练集中每个样本之间的距离。

  5. 选择邻居:根据计算得到的距离,选择与待分类样本距离最近的K个邻居。

  6. 投票或权重计算:对于分类问题,根据K个邻居的类别进行投票,选择票数最多的类别作为待分类样本的类别。对于回归问题,可以根据K个邻居的距离和标签进行加权计算,得到待分类样本的预测值。

  7. 评估和优化:使用适当的评价指标评估模型的性能,并根据需要调整参数以优化性能。

4. 例子和例题

例子:假设有一个二维平面上的点集,每个点都有一个类别标签(红或蓝)。现在有一个新的点需要分类,KNN算法会计算这个新点到所有已知点的距离,然后选择距离最近的K个点,看这些点中哪个类别的点最多,就将新点归为该类别。

例题:具体实现时,可以设定一个具体的K值(如K=3),然后计算待分类点到所有已知点的欧氏距离,选择距离最小的3个点,如果这3个点中有2个是红色,1个是蓝色,则待分类点被归类为红色。

5. Julia实现

由于Julia语言的实现细节可能因库和版本而异,这里只提供一个大致的框架性指导。在Julia中,可以使用Distances.jl库来计算距离,使用自定义函数或循环来实现KNN算法的核心逻辑。以下是一个简化的伪代码示例:

julia 复制代码
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算法的详细过程

算法

  1. 收集数据

    收集训练数据集,包括样本的特征和对应的标签。

  2. 处理数据

    • 如果数据集中的特征量纲不同,需要进行归一化或标准化处理,以确保每个特征对距离计算的影响是相同的。
    • 确定K值,即最近邻的个数。K值的选择通常需要通过交叉验证等方法来优化。
  3. 计算距离

    对于待分类的样本,计算它与训练集中每个样本之间的距离。常用的距离度量方法包括欧氏距离、曼哈顿距离、切比雪夫距离等。

  4. 选择最近邻

    根据计算出的距离,选择距离待分类样本最近的K个训练样本。

  5. 投票表决

    统计这K个最近邻样本的标签,选择出现次数最多的标签作为待分类样本的预测标签。

  6. 评估模型

    使用测试数据集来评估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),我们需要确定这个样本的标签。

  1. 处理数据

    在这个例子中,特征量纲相同,因此不需要进行归一化处理。我们假设K=3。

  2. 计算距离

    使用欧氏距离公式,计算待分类样本与每个训练样本之间的距离:

    • 与样本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. 选择最近邻

    根据计算出的距离,选择距离最小的3个样本,即样本1、样本2和样本3。

  4. 投票表决

    统计这3个样本的标签,发现样本1和样本2的标签为A,样本3的标签为B。因此,选择出现次数最多的标签A作为待分类样本的预测标签。

  5. 得出结论

    待分类样本(3.0, 3.0)的预测标签为A。

这个简单的例子展示了KNN算法的基本流程。在实际应用中,KNN算法的性能受到K值选择、距离度量方法、数据预处理等多种因素的影响,需要通过实验来优化这些参数。

在Julia中实现K最近邻(K-Nearest Neighbors, KNN)算法可以从两个角度进行:一是手动编写算法,二是使用现有的库。下面我将分别展示这两种方法。

手动实现KNN算法

首先,我们手动实现一个简单的KNN算法。这个实现将包括计算欧氏距离、找到最近的K个邻居,并进行投票表决。

julia 复制代码
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。首先,你需要安装这个包:

bash 复制代码
(julia) pkg> add ScikitLearn

然后,你可以使用以下代码来调用KNN算法:

julia 复制代码
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)

注意

  1. ScikitLearn.jl 是对 Python 的 scikit-learn 库的封装,因此它依赖于 Python 和 scikit-learn 的安装。
  2. 在上面的例子中,由于我们的数据集很小,我们没有划分训练集和测试集。在实际应用中,你应该划分数据集来评估模型的性能。
  3. ScikitLearn.jl 的接口可能会随着版本的更新而发生变化,因此请查阅最新的文档以获取准确的信息。

参考文献

  1. 文心一言
相关推荐
初级炼丹师(爱说实话版)6 分钟前
nn.MultiheadAttention返回的注意力权重和标准的计算注意力权重的区别
人工智能·深度学习·机器学习
roman_日积跬步-终至千里7 分钟前
【人工智能基础】计算机视觉
人工智能·计算机视觉
終不似少年遊*29 分钟前
数据分析-机器学习-第三方库使用基础
python·机器学习·数据挖掘·数据分析·numpy
Francek Chen1 小时前
【大数据分析&深度学习】在Hadoop上实现分布式深度学习
人工智能·hadoop·分布式·深度学习·数据分析
明朝百晓生1 小时前
【PyTorch][chapter 228][李宏毅深度学习][Diffusion Model-1]
人工智能
骑猪玩狗1 小时前
第N8周:使用Word2vec实现文本分类
人工智能·分类·word2vec
狗窝超厉害1 小时前
研0找实习【学nlp】15---我的后续,总结(暂时性完结)
人工智能·pytorch·python·自然语言处理·bert
企业通用软件开发1 小时前
大语言模型提示词工程学习--写小说系列(文心一言&豆包&通义千问):1~创作前的准备工作
人工智能·学习·语言模型
龙的爹23331 小时前
论文翻译 | BERTese: Learning to Speak to BERT
人工智能·深度学习·自然语言处理·prompt·bert
神奇的布欧1 小时前
BERT的工作原理
人工智能·深度学习·bert