KNN算法原理及代码实现

目录


一、KNN是什么?

KNN算法(K-最近邻算法,K-Nearest Neighbor)是一种基本且经典的监督学习算法,广泛应用于分类和回归任务中。

二、KNN核心思想

1.计算距离

当给定一个新的数据点,需要确定它的类别时,KNN算法会计算这个点与训练集中所有其他数据点之间的距离(例如欧氏距离)。
​​​​​​

2.决策类别

然后,从训练集中选取距离最近的K个数据点(即邻居),并基于这K个数据点的类别信息进行决策。

三、KNN的优缺点:

优点

1.简单易理解,易于实现。

2.无需训练过程,适用于少量数据和实时预测任务。

3.可以处理多类别问题。

缺点

1.计算开销较大,特别是在数据量较大时,需要计算每个样本与所有训练样本之间的距离。

2.对噪声和异常值敏感。

3.存储开销大,因为需要保存所有训练样本。

四、数据可视化展示

通过不同的散点图展示“FlightMiles”、“GameTime”、“IceCream”与目标标签(“Label”)之间的联系:

具体代码实现:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

#读取数据集
file_path = r"C:XXXXXXX\datingTestSet.txt"
df = pd.read_csv(file_path, sep="\t", header=None)
df.columns = ["FlightMiles", "GameTime", "IceCream", "Label"]

#标签编码
label_encoder = {"didntLike": 0, "smallDoses": 1, "largeDoses": 2}
df["Label"] = df["Label"].map(label_encoder)

#颜色映射
colors = {0: "black", 1: "orange", 2: "red"}

#创建可视化图
fig, axes = plt.subplots(2, 2, figsize=(12, 10))
fig.suptitle("Data Visualization", fontsize=16)

#FlightMiles vs GameTime
axes[0, 0].scatter(df["FlightMiles"], df["GameTime"], c=df["Label"].map(colors))
axes[0, 0].set_title("FlightMiles vs GameTime")

#FlightMiles vs IceCream
axes[0, 1].scatter(df["FlightMiles"], df["IceCream"], c=df["Label"].map(colors))
axes[0, 1].set_title("FlightMiles vs IceCream")

#GameTime vs IceCream
axes[1, 0].scatter(df["GameTime"], df["IceCream"], c=df["Label"].map(colors))
axes[1, 0].set_title("GameTime vs IceCream")

#移除空的子图
fig.delaxes(axes[1, 1])

#显示图表
plt.tight_layout()
plt.savefig("knn_visualization.png")
plt.show()

五、利用KNN算法设计分类器一般流程

使用分类器的大致流程图如下:

1.数据准备:

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

我使用的归一化方法如下:

#归一化
scaler = MinMaxScaler()
df.iloc[:, :-1] = scaler.fit_transform(df.iloc[:, :-1])
df.iloc[:, -1] = df.iloc[:, -1].astype(int)

公式如下:

2.选择K值:

选择一个正整数K,表示在预测时选取最近的K个邻居。

1、如果K为1,则选择距离最近的一个样本进行分类;如果K较大,则根据更多的邻居做决策。

2、K值的选择通常通过交叉验证来优化,K过小可能会导致模型过拟合,K过大可能会导致模型过于简化。

k=1:

k=10:

k=20:

k=50:

k=100:

k=200:

我使用的k值为5(较小k值和较大k值都会使训练出来的模型不如意,即:准确度较低):

    def __init__(self, k=5):#k选择5
        self.k = k

3.计算距离

对于待分类的样本,计算它与训练集中的所有样本之间的距离,常用的距离度量方法有:

1、欧氏距离:最常用的距离度量,适用于连续数值特征。

2、曼哈顿距离:适用于某些特定的情况,如网格数据。

欧氏距离公式:

#计算所有训练数据与 x 之间的距离
distances = [np.linalg.norm(x - x_train) for x_train in self.X_train]
#找到最近的 k 个点
k_indices = np.argsort(distances)[:self.k]

4.分类

分类任务:根据K个邻居的类别标签进行投票,选择类别频率最高的类别作为最终预测结果

#获取这 k 个点的分类
k_nearest_labels = [self.y_train[i] for i in k_indices]

5.输出预测结果

输出预测的分类标签或回归值作为KNN算法的最终结果

#返回最多的分类
most_common = Counter(k_nearest_labels).most_common(1)
return most_common[0][0]

注:给的数据中未分训练集和测试集,我将设置训练集和测试集4:1

#确定训练集和测试集4:1
X = df.iloc[:, :-1].values
y = df.iloc[:, -1].values
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

六、利用训练出来模型对用户输入进行预测

代码展示:

#用户输入数据
flight_miles = float(input("请输入每年飞行里程数: "))
game_time = float(input("请输入玩游戏的时间比例: "))
ice_cream = float(input("请输入每周吃的冰淇淋公升数: "))

#归一化输入数据
input_data = np.array([[flight_miles, game_time, ice_cream]])
input_data = scaler.transform(input_data)

#预测用户输入数据
prediction = knn.predict(input_data)
predicted_label = label_encoder.inverse_transform(prediction)

print(f"Prediction: {predicted_label[0]}")

代码运行效果展示(输入的是数据集的第一个数据(仅作预测展示,无法确定模型效果)):

七、完整代码展示

import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder, MinMaxScaler
from collections import Counter

#读取数据
file_path = r"C:XXXXXX\datingTestSet.txt"
df = pd.read_csv(file_path, sep="\t", header=None)

#定义列名
df.columns = ["FlightMiles", "GameTime", "IceCream","Label"]

#预处理标签
label_encoder = LabelEncoder()
df["Label"] = label_encoder.fit_transform(df["Label"])

df.iloc[:, :-1] = df.iloc[:, :-1].astype(float)

#归一化
scaler = MinMaxScaler()
df.iloc[:, :-1] = scaler.fit_transform(df.iloc[:, :-1])
df.iloc[:, -1] = df.iloc[:, -1].astype(int)

#确定训练集和测试集4:1
X = df.iloc[:, :-1].values
y = df.iloc[:, -1].values
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

#KNN
class KNN:
    def __init__(self, k=5):#k选择5
        self.k = k

    def fit(self, X_train, y_train):
        self.X_train = np.array(X_train)
        self.y_train = np.array(y_train)

    def predict(self, X_test):
        return np.array([self._predict(x) for x in np.array(X_test)])

    def _predict(self, x):
        #计算所有训练数据与 x 之间的距离
        distances = [np.linalg.norm(x - x_train) for x_train in self.X_train]
        #找到最近的 k 个点
        k_indices = np.argsort(distances)[:self.k]
        #获取这 k 个点的分类
        k_nearest_labels = [self.y_train[i] for i in k_indices]
        #返回最多的分类
        most_common = Counter(k_nearest_labels).most_common(1)
        return most_common[0][0]

#训练模型
knn = KNN(k=5)
knn.fit(X_train, y_train)

#预测
y_pred = knn.predict(X_test)

#计算准确率
accuracy = np.mean(y_pred == y_test)

print(f"Accuracy: {accuracy:.2f}")

#用户输入数据
flight_miles = float(input("请输入每年飞行里程数: "))
game_time = float(input("请输入玩游戏的时间比例: "))
ice_cream = float(input("请输入每周吃的冰淇淋公升数: "))

#归一化输入数据
input_data = np.array([[flight_miles, game_time, ice_cream]])
input_data = scaler.transform(input_data)

#预测用户输入数据
prediction = knn.predict(input_data)
predicted_label = label_encoder.inverse_transform(prediction)

print(f"Prediction: {predicted_label[0]}")

总结

        K最近邻(KNN)算法是一种简单且直观的监督学习算法,广泛应用于分类和回归问题。它的基本原理是通过计算待预测样本与训练集中其他样本的距离,选择最近的K个邻居,并根据这些邻居的标签(分类任务)或数值(回归任务)进行预测。KNN算法的优点是无需训练过程、易于实现且灵活适应多类别问题,但它在大规模数据集上计算开销大,且对噪声和高维数据敏感。选择合适的K值对于模型的性能至关重要,通常通过交叉验证来优化。KNN广泛应用于图像分类、推荐系统和医学诊断等领域。

声明:本博客仅为个人理解,如有错误,敬请谅解并指出

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值