这里给大家展示和讲解有关于KNN分类算法的代码,通过代码让大家更直观的了解其工作原理,关于KNN算法的详细原理,大家可以自行搜索了解。
ps.这里将讲解的内容以注释的方法写到了代码中,希望大家更直观的了解其中的代码精髓。
import numpy as np
from sklearn import datasets
from scipy.stats import mode
from sklearn.metrics.pairwise import euclidean_distances
from sklearn.model_selection import train_test_split
'''
好好好,让我写到真代码了吧。
该说不说感谢人工智能感谢GPT,给我提供了完整详细的代码,并在代码风格上,语言逻辑上都做的非常好。
我非常觉得这是一个非常高效的代码学习方式,但就是不知道会不会影响个人的代码编写能力。
'''
class SimpleKNN:
# 类的初始化方法,设置默认的邻居数为5,权重方案为uniform(均匀权重)
def __init__(self, n_neighbors=5, weights="uniform"):
self.n_neighbors = n_neighbors
self.weights = weights
self.trained = False # 这个变量是一个标志位,用来检验模型是否训练
# 训练模型,接受训练数据集X和标签y,所以大家要注意的是重点还是分类器而不是fit这个方法
def fit(self, X, y):
self.X_train = X
self.y_train = y
self.trained = True # 这个变量是一个标志位,训练完成后置True,表示模型已经训练完成。
# 这是一个对于新数据集x进行预测的方法
def predict(self, X):
# 如果没有训练,这里语法就很简单了
if not self.trained:
# 抛出异常
raise NotImplementedError("The model must be fitted before it can be used to predict.")
# 如果没有异常,就调用私有方法_predice这个编程习惯也蛮重要的,确实需要在这方面上多学习
# 这里呢predictions是一个数组类型,python对于这些数据操作做的还是很不错的,节省了很多,也直观起来了
# 采用循环,对每个测试数据集中的数据进行逐个操作
predictions = [self._predict(x) for x in X]
# 这里呢使用numpy库对predictions数组进行输出
return np.array(predictions)
# 这就是一个核心方法了,这个方法展示了knn算法最核心的内容,需要着重了解
def _predict(self, x):
# 这里也是使用了numpy库中对于数组的操作,计算了训练样本之间欧氏距离-类似于两点之间的直线距离,只不过是在多个维度下。
distances = euclidean_distances(x.reshape(1, -1), self.X_train)
# 这里呢是获取最近的n_neighbors个邻居的索引,这里要注意使用了numpy中的argsort方法。
# 这玩意很简单的,就是对计算后的distances进行一个排序,然后找前0:n_neighbors个数据的索引值,注意是索引值,是可以根据这个索引值去得到这个元素的其他数据
nearest_indices = np.argsort(distances[0])[:self.n_neighbors]
# 这里来看是不是就获得了这些索引值对应的y_train,这里其实就是获得了关于这些数据的标签
nearest_labels = self.y_train[nearest_indices]
# 检查权重方案是否为“uniform”
if self.weights == "uniform":
# 使用众数来作为预测的类别,这个怎么理解呢就是你在一堆豆子里选了占比最多的品种
prediction = mode(nearest_labels)[0]
# 检查权重方案是否为“distance"
elif self.weights == "distance":
# 这里就使用到了加权众数来更加详细的分类计算,获取最近邻居的数据,注意这里的nearest_indices是上面已经求过的索引值的数组
distances = distances[0][nearest_indices]
# 这里计算每个邻居的权重,采用了使用倒数,即距离越近的数据样本权重越大
weights = 1 / distances
# 使用加权众数来获得预测结果
weighted_mode = mode(nearest_labels, weights=weights)
# 这里返回预测值
prediction = weighted_mode[0]
# 如果两种权重方案都没有的话,那就要抛出异常
else:
raise ValueError("Unsupported weighting scheme.")
# 最后返回这个数组
return prediction
# 用法示例:
if __name__ == "__main__":
# 从sklearn中获取iris数据集
iris_dataset = datasets.load_iris()
# 划分训练集和测试集,这里的train_test_split用于随机划分数据集和训练集,为什么会是随机的呢,因为有些数据集的标签是排列好的,所以当你错误的没有打乱的话,就会丢到很多重要数据
x_train, x_test, y_train, y_test = train_test_split(iris_dataset['data'], iris_dataset['target'], random_state=0)
# 实例化分类器,将其拟合到训练数据,并根据测试数据进行预测
knn = SimpleKNN(n_neighbors=3, weights="uniform")
# 这里构建模型,其实就是传输训练样本
knn.fit(x_train, y_train)
# 然后输入测试集,进行模型预测
predictions = knn.predict(x_test)
print("Predictions:", predictions)
'''
到这里了关于knn的分类器就讲到这里,这里非常直观的展示了其工作原理,希望可以帮助大家更快的了解
'''