import numpy as np
# k-临近,K-Nearest Neighbor,也称knn
# 原理:有n个样本的数据集,现给定一个新的样本s,s与n个样本进行比较,选取k个与s相近的样本,查看k个样本属于哪个类型,
# 个数最多的那个类型为s的类型
''' knn封装类 '''
class KNN(object):
def __init__(self, k_value, s_data, s_label, t_data):
self.k_value = k_value # 设置的前k个样本的值
self.s_data = s_data
self.s_label = s_label
self.t_data= t_data
def calculate_distance(self, one, two, cal_type):
result = 0.0
if cal_type == 'ED': # 欧式距离(Euclidean Distance)
result = np.linalg.norm(one - two)
elif cal_type == 'MD': # 曼哈顿距离(Manhattan Distance)
result = np.sum(np.abs(one - two))
elif cal_type == 'CD': # 切比雪夫距离(Chebyshev Distance)
result = np.max(np.abs(one - two))
elif cal_type == 'MKD': # 闵可夫斯基距离(MinkowskiDistance)
result = np.sqrt(np.sum(np.square(one - two)))
elif cal_type == 'SED': # 标准化欧氏距离(Standardized Euclidean distance)
X = np.vstack([one, two])
sk = np.var(X, axis=0, ddof=1)
result = np.sqrt(((one - two) ** 2 /sk).sum())
return result
def calculate_value(self, cal_type):
result_ed1 = list([])
for s_one in self.s_data:
dist = self.calculate_distance(self.t_data, s_one, cal_type)
result_ed1.append(dist)
result_ed1 = np.array(result_ed1)
# print('result_ed1=', result_ed1)
result_ed2 = 1 / (1 + result_ed1)
# print('result_ed2:', result_ed2)
result_ed3 = np.argsort(result_ed2, axis=0) # 得到正序索引值
result_ed3 = result_ed3[::-1] # 得到倒序索引值
# 注:这里做了1 / (1 + result_ed1) 的处理,距离越近这个值越大
index1 = result_ed3[0: self.k_value]
result_label = self.s_label[index1] # 得到距离最近的前k个类别数据
# print('result_label=', result_label)
keep = np.unique(result_label, return_counts=True, return_inverse=True) # 去重
k_arr1 = keep[0] # 去重后的数据
k_arr3 = keep[2] # 去重后的数据,每个元素出现的次数
max_value = np.max(k_arr3)
index2 = np.where(k_arr3 == max_value)
index2 = index2[0]
result = k_arr1[index2]
print('result=', result)
return result
''' 使用例子 '''
# 创建数据集
def create_data_set():
group = np.array([[1.0, 1.1], [1.0, 1.0], [0, 0], [0, 1.1]])
labels = np.array(["A", "A", "B", "B"])
return group, labels
# 使用KNN分类
def classify():
group, labels = create_data_set()
t_data = np.array([0.1, 0.2])
k_value = 2
# knn的类初始化
knn = KNN(k_value, group, labels, t_data)
knn.calculate_value('ED')
return
classify()