k近邻法(KNN)的Python代码

k近邻法(KNN)的Python代码:

import numpy as np #数值计算包
import pandas as pd #数据分析包
import matplotlib.pyplot as plt #画图工具包
from sklearn.datasets import load_iris #导入load_iris数据集
from sklearn.model_selection import train_test_split #划分数据的训练集与测试集包
from collections import Counter #计数

iris=load_iris() #导入数据
df = pd.DataFrame(iris.data, columns=iris.feature_names)
#将iris中的四个特征数据放入df矩阵中
#DataFrame介绍:https://www.jianshu.com/p/8024ceef4fe2
df['label']=iris.target
#在df矩阵的最后插入一列label即样本类别
df.columns=['sepal length','sepal width','petal length','petal width','label']
#输入print(df)即可查看
plt.figure(figsize=(15, 8))
#figsize:指定figure的宽和高
#plt.figure()的使用:https://blog.youkuaiyun.com/m0_37362454/article/details/81511427
plt.subplot(121)
#subplot绘制多个子图介绍:https://www.cnblogs.com/xiaoboge/p/9683056.html
plt.scatter(df[:50]['sepal length'], df[:50]['sepal width'], label='0')
#画散点图
plt.scatter(df[50:100]['sepal length'], df[50:100]['sepal width'], label='1')
plt.xlabel('sepal length')
plt.ylabel('sepal width')
plt.title('original data')
plt.legend() #给图像加上图例
#legend介绍:https://blog.youkuaiyun.com/lanluyug/article/details/80002273

data = np.array(df.iloc[:100, [0, 1, -1]])
#读取df的前100行,第一、二、五列('sepal length','sepal width','label')
#array:计算机为数组分配一段连续的内存,从而支持对数组随机访问
#要选取连续多列就该使用df.iloc
#iloc的用法示例:https://blog.youkuaiyun.com/qq_39697564/article/details/87855167
X, y = data[:,:-1], data[:,-1]
#令X等于'sepal length','sepal width'的100个二维数据(不包括写的那个索引值),令y等于100个类别(只有0,1)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
#train_test_split介绍:https://blog.youkuaiyun.com/qq_36523839/article/details/80280771
#随机数种子的含义:其取值不变时划分得到的结果一模一样,其值改变时,划分得到的结果不同

'''
下面KNN类中predict函数的基本思想:
因为是需要在训练集中找出k个距离测试点最近的点,此处采用先求出k个距离作为基准,
将后面的距离(相比之下较小的距离)不断替代前面的最大的距离,这样就会得出几个最近的距离
(此处还可以先将所有的欧式距离计算出来,然后将每一个欧式距离与对应的标签分类进行绑定,
通过将欧式距离从小到大排序,然后选取前k个,即可得到最近的k个点)
'''

class KNN:
    def __init__(self,X_train,y_train,n_neighbors=3,p=2):
        self.n = n_neighbors
        self.p = p
        self.X_train = X_train
        self.y_train = y_train
        #n_neighbors表示临近点的个数,p表示距离度量
        #__init__左右两边为两个下划线
        #函数定义时不能将没有默认值的参数放在有默认值的参数的后面

    def predict(self,X):
        knn_list = []
        for i in range(self.n):
            dist = np.linalg.norm(X - self.X_train[i],ord = self.p)
            knn_list.append((dist,self.y_train[i]))
    #np.linalg.norm的介绍:https://blog.youkuaiyun.com/weixin_37763870/article/details/103434397
    #append用于在列表末尾添加新的对象,range不包括后面的索引值
    #二范数和欧式距离:https://www.cnblogs.com/cainiaoxuexi2017-ZYA/p/12683444.html
    #Python 中矩阵或者数组相减的法则:https://blog.youkuaiyun.com/dake13/article/details/80917932

        for i in range(self.n,len(self.X_train)):
            max_index = knn_list.index(max(knn_list,key = lambda x:x[0]))
            dist = np.linalg.norm(X - self.X_train[i],ord = self.p)
            if knn_list[max_index][0] > dist:
                knn_list[max_index] = (dist,self.y_train[i])
    #knn_list为测试点到k个欧式距离最小的训练集的列表,第一列为欧氏距离,第二列为对应的标签分类
    #max()函数中key参数介绍:https://blog.youkuaiyun.com/u011675334/article/details/104838083
    #lambda用于简化函数定义的书写形式

        knn = [k[-1] for k in knn_list]
        count_pairs = Counter(knn)
        max_count = sorted(count_pairs.items(),key=lambda x:x[1])[-1][0]
        return max_count
    #sorted介绍:https://www.runoob.com/python3/python3-func-sorted.html
    #sorted与key连用https://www.cnblogs.com/yiyaxuan/p/12991842.html
    #items() 函数以列表返回可遍历的(键, 值) 元组数组
    
    def score(self, X_test, y_test):
        right_count = 0
        n = 10
        for X, y in zip(X_test, y_test):
            label = self.predict(X)
            if label == y:
                right_count += 1
        return right_count / len(X_test)

clf = KNN(X_train, y_train)
print('Test_score: {}'.format(clf.score(X_test, y_test)))
test_point = [6.0, 3.0]
print('Test Point: {}'.format(clf.predict(test_point)))

plt.subplot(122)
plt.scatter(df[:50]['sepal length'], df[:50]['sepal width'], label='0')
plt.scatter(df[50:100]['sepal length'], df[50:100]['sepal width'], label='1')
plt.plot(test_point[0], test_point[1], 'bo', label='test_point')
plt.xlabel('sepal length')
plt.ylabel('sepal width')
plt.legend()
plt.title('classification by KNN(n=3, p=2)')
plt.subplots_adjust(top=0.92, bottom=0.08, left=0.10, right=0.95, hspace=0.25,wspace=0.35)
plt.savefig("demo.jpg")
plt.show()

KNN中predict最后部分计算k个最近邻点中标签分类个数最多的那个标签的代码部分目前没理解,代码参考第3章 k近邻法(KNearestNeighbors)代码实现

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值