利用scikit-learn库的函数以及自定义函数分别实现K近邻分类器

老师要求使用两种方法实现k近邻分类器,并给我们发了乳腺癌的部分数据集,数据集大概的样子如图:

 我在百度上查阅了资料,我这份数据的最后一列是乳腺癌的类型,其中2代表良性,4代表恶性。所以这一列Class相当于就是我们机器学习中的标签。

对于k近邻分类,遵守几个原则,简单点来说就是:在待测点邻域范围内,少数服从多数。具体理解如图:

提醒:k不是半径!!!

黄色邻域内有两种类型,蓝色的点代表B类型,紫色的点代表C类型,要确定待测点A的类型。当k=1时,所代表的意思就是求出周围所有点与待测点的距离,然后找到一个与待测点距离最近的点,由于k=1,只找一个点,所以A一定会被分为这个点所属的类型。

绿色邻域内也有两种类型的点,当k=3时的意思就是求出周围所有已知类型点与该点的距离,然后选取前三个与待测点距离最近的点。待测点就属于这三个点中属于同一类型较多的类型。

在k近邻分类中,选择不同的方法求距离,以及不同的k都会对结果造成很大的影响。

在我使用的方法中,我用的是欧氏距离,k的取值是我自定义的,并没有求k的最佳值。

欧式距离:D=\sqrt{x^{2}+y^{2}}

第一种,利用sklearn库实现k近邻分类:

#利用scikit-learn库函数实现K近邻分类器
from sklearn.neighbors import KNeighborsClassifier
import pandas as pd
from sklearn.model_selection import train_test_split
x=pd.read_csv(r'D:\Python\python大三上实验作业\breastCancer.csv',usecols=(1,2,3,4,5,6,7,8,9))  
#usecols的意思是选取1-9列,第0列的编号是不需要用于计算的,最后一列属于标签,也不应该被分到数据集x中
x=x.values  #将表格形式转为矩阵形式,方便后面分割训练集和测试集的时候不报错
print(x)
y=pd.read_csv(r'D:\Python\python大三上实验作业\breastCancer.csv',usecols=[10])
y=y.values
x_train,x_test,y_train,y_test = train_test_split(x,y,test_size=0.2)
clf=KNeighborsClassifier(n_neighbors=5)  #这里的n_neighbors就是k
#进行训练
clf.fit(x_train,y_train)
#测试集的准确率
print('导入的函数的准确率为:',clf.score(x_test,y_test))

代码结果如图:

 第二种方法,是自定义函数实现k近邻分类,由于每次划分测试集和训练集都不一样,所以每次结果不同:

import numpy as np
import pandas as pd
from collections import Counter
from sklearn.metrics import accuracy_score
from sklearn.model_selection import train_test_split
x=pd.read_csv(r'D:\Python\python大三上实验作业\breastCancer.csv',usecols=(1,2,3,4,5,6,7,8,9))  
x=x.values  #将表格形式转为矩阵形式,方便后面分割训练集和测试集的时候不报错
y=pd.read_csv(r'D:\Python\python大三上实验作业\breastCancer.csv',usecols=[10])
y=y.values
x_train,x_test,y_train,y_test = train_test_split(x,y,test_size=0.2)  #划分训练集和测试,test_size的意思是测试集的数量占总数量的0.2,即训练集与测试集的划分比为8:2
def knn(x_train,x_test,y_train,y_test,k):
    row_train=x_train.shape[0]  #计算训练集的行数
    row_test=x_test.shape[0]  #计算测试集的行数
    y_predict=[]
    for i in range(0,row_test):  #为测试集的每一行预测一个标签值,再与实际的标签值做对比
        diff=np.tile(x_test[i],(row_train,1))-x_train  #将每一行测试集复制为row行,每一行和训练集对应行做差;此处tile函数的意思就是将这次循环中的测试集纵向复制为row行,横向赋值为1次
        distance=((diff**2).sum(axis=1))**0.5  #计算欧氏距离根号下xi的平方的和
        sortdis=distance.argsort()  #argsort函数,将求出来的欧式距离按照从小到大排列,其输出值为对应数的索引值
        a=[]
        for j in range(k):
            vote=y_train[sortdis[j]]  #取前k个距离最短的训练集所对应的标签值
            a.append(vote[0])
            count=Counter(a)
            max_value=max(count,key=count.get)  #返回一个count.get(item)的值最大的项。即对应于最大值的键
        y_predict.append(max_value)  #汇总输入到列表中,成为预测值
    print("测试集的预测值为:",y_predict)
    y_real=y_test.T  #由于一列转为矩阵后为n行1列,为了便于观察,将他进行转置
    y_real=y_real.tolist()  #将矩阵转为列表,但此处并没有转为真实的列表,转成了一行一列的矩阵,所以下面我在求准确率时才会写y_real[0]
    print("测试集的真实值为:",y_real)
    acc=accuracy_score(y_predict , y_real[0])  #用sklearn库中的函数
    print("自定义的函数准确率为:",acc)
b=knn(x_train,x_test,y_train,y_test,5)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值