目录
一、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广泛应用于图像分类、推荐系统和医学诊断等领域。
声明:本博客仅为个人理解,如有错误,敬请谅解并指出