"""
Created on Tue Oct 19 19:26:28 2021
直接近邻
@author: lj
"""
import numpy as np
import random
random.seed(2)
class k_near:
def __init__(self):
self.feature=[]
self.dist=[]
self.all_label=[]
self.label=0
def com_dist(self,data):
[row,col]=data.shape
diff=np.zeros_like(data)
for i in range(len(data)):
diff[i,:]=(self.feature[:]-data[i,:])**2
self.dist.append(np.sqrt(sum(diff[i,:]))/col)
def find_label(self,label,k):
self.dist[np.argmin(self.dist)]=2#0*abs(np.max(self.dist))
for i in range(k):
self.all_label.append(label[np.argmin(self.dist)])
self.dist[np.argmin(self.dist)]=2#0*abs(np.max(self.dist))
num=np.zeros([3])
num[0]=(self.all_label.count(1))
num[1]=(self.all_label.count(2))
num[2]=(self.all_label.count(3))
self.label=np.argmax(num)+1
data = np.loadtxt('sonar.txt', delimiter=',')
[row,col]=data.shape
#全部数据集特征
feature=(data[:,0:-1]-np.min(data[:,0:-1]))/(np.max(data[:,0:-1],axis=0)-np.min(data[:,0:-1]))
label=data[:,-1]
list_test=range(data.shape[0])
test=random.sample(list_test, 100)
#test=range(0,200)
k=25#近邻数
x=k_near()
#x.feature=np.zeros([col-1])
#输入x的特征值
inputfeature=feature[test,:]
test_label=[]
right_label=label[test]
for i in range(inputfeature.shape[0]):
x.feature=inputfeature[i,:]
x.dist=[]
x.all_label=[]
x.com_dist(feature)
x.find_label(label,k)
test_label.append(x.label)
print("数据" + str(test[i])+ "的类别为:",x.label)
right_rate=1-np.sum(np.abs(test_label-right_label))/len(test_label)
print("数据正确率:",right_rate)
本文中作者使用了最为基础的K近邻算法对数据进行分类,其基本思路可以简单总结成以下流程图:
但是,这种分类方法常常对于分布不均匀的数据有着较差的分类能力,如某些数据临近范围内仅有3、4个点,某些点临近范围内却有着更多的样本,这种情况下,我们需要对不同的点分别进行处理,于是采用了一种新的办法:尝试对搜索临近数据的邻域半径进行限制,将部分超出半径的临近数据剔除,从而有效保证K近邻算法的思想不因为数据分布不均而缺乏体现。
以下是邻域限制时K近邻的代码:
"""
Created on Tue Oct 19 19:26:28 2021
附加邻域k近邻
@author: lj
"""
import numpy as np
import random
random.seed(2)
class k_near:
def __init__(self):
self.feature=[]
self.dist=[]
self.all_label=[]
self.label=0
def com_dist(self,data):
[row,col]=data.shape
diff=np.zeros_like(data)
for i in range(len(data)):
diff[i,:]=(self.feature[:]-data[i,:])**2
self.dist.append(np.sqrt(sum(diff[i,:]))/col)
def find_label(self,label,k):
self.dist[np.argmin(self.dist)]=20*abs(np.max(self.dist))
limit=0.04*1
for i in range(k):
if np.min(self.dist)<limit:
self.all_label.append(label[np.argmin(self.dist)])
self.dist[np.argmin(self.dist)]=2#0*abs(np.max(self.dist))
else:
self.all_label.append(3)
self.dist[np.argmin(self.dist)]=2#0*abs(np.max(self.dist))
num=np.zeros([2])
num[0]=(self.all_label.count(1))
num[1]=(self.all_label.count(2))
self.label=np.argmax(num)+1
data = np.loadtxt('sonar.txt', delimiter=',')
[row,col]=data.shape
#全部数据集特征
feature=(data[:,0:-1]-np.min(data[:,0:-1]))/(np.max(data[:,0:-1],axis=0)-np.min(data[:,0:-1]))
label=data[:,-1]
list_test=range(data.shape[0])
test=random.sample(list_test, 100)
#test=range(0,200)
k=25
#近邻数
x=k_near()
#x.feature=np.zeros([col-1])
#输入x的特征值
inputfeature=feature[test,:]
test_label=[]
right_label=label[test]
for i in range(inputfeature.shape[0]):
x.feature=inputfeature[i,:]
x.dist=[]
x.all_label=[]
x.com_dist(feature)
x.find_label(label,k)
test_label.append(x.label)
print("数据" + str(test[i])+ "的类别为:",x.label)
right_rate=1-np.sum(np.abs(test_label-right_label))/len(test_label)
print("数据正确率:",right_rate)
由于采用的数据分布较为均匀,两种算法的差距并不是特别明显。不过当K取值25时,附加邻域法的正确率要高出普通K近邻5%以上。