赞
踩
老师要求使用两种方法实现k近邻分类器,并给我们发了乳腺癌的部分数据集,数据集大概的样子如图:
我在百度上查阅了资料,我这份数据的最后一列是乳腺癌的类型,其中2代表良性,4代表恶性。所以这一列Class相当于就是我们机器学习中的标签。
对于k近邻分类,遵守几个原则,简单点来说就是:在待测点邻域范围内,少数服从多数。具体理解如图:
提醒:k不是半径!!!
黄色邻域内有两种类型,蓝色的点代表B类型,紫色的点代表C类型,要确定待测点A的类型。当k=1时,所代表的意思就是求出周围所有点与待测点的距离,然后找到一个与待测点距离最近的点,由于k=1,只找一个点,所以A一定会被分为这个点所属的类型。
绿色邻域内也有两种类型的点,当k=3时的意思就是求出周围所有已知类型点与该点的距离,然后选取前三个与待测点距离最近的点。待测点就属于这三个点中属于同一类型较多的类型。
在k近邻分类中,选择不同的方法求距离,以及不同的k都会对结果造成很大的影响。
在我使用的方法中,我用的是欧氏距离,k的取值是我自定义的,并没有求k的最佳值。
欧式距离:
第一种,利用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)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。