本文为作者学习K近邻算法后的整理笔记,仅供学习使用!
K近邻算法
1、概述
意思是K个最近的邻居,也就是说对于每个样本,都可以用它最近的K个邻居来代表。
2、工作原理
(1)存在一个训练样本集,样本集中的每一个数据都有对应的标签
(2)当输入一个新的数据时,将新数据中的每个特征与训练样本集中对应的特征进行比较
(3)利用算法提取出训练样本集中与新数据最相似的K个数据
(4)将这K个数据中出现次数最多的标签作为新数据的标签
3、核心思想
如果一个样本在特征空间中k个最相邻的样本中大多数属于某一个类别,那么该样本也属于该类别,并具有该类别的样本特性。
4、公式
在KNN算法中,主要通过计算样本间的距离来判断样本是否相似。计算距离的公式主要有两种:欧式距离和曼哈顿距离。
5、举例说明
如下图,绿色圆是属于哪个类别?是蓝色正方形还是红色三角形?
(1)如果K = 3,那么在离绿色圆最近的三个形状中(最内层的圆圈),红色三角形有2个,蓝色正方形有1个,所以最终绿色圆会被判定为红色三角形类别的;
(2)如果K = 5, 那么在离绿色圆最近的5个形状中(外层的圆圈),蓝色正方形有3个,红色三角形有2个,所以最终绿色圆会被判定为蓝色正方形类别的。
6、优缺点
(1)优点:
a、简单,容易理解,容易实现,无需其他估计参数,也不需要训练
b、适合对稀有时间进行分类
c、特别适合多分类问题(对象具有多个特征标签),KNN比SVM的表现要好
(2)缺点:
a、当样本不均衡时,即样本集中某一类别的样本数据很大,而其他类别的样本集很小,那么当输入新的样本数据进行预测时,该样本中K个特征最相似的数据中大容量的数据占多数,导致预测结果很大概率为大容量样本的类别。
b、计算量较大。对于每一个新的样本数据,都需要和训练样本集中的所有数据进行比较,才能计算出其最相邻的样本数据。
c、可礼节性差,无法给出像决策树那样的规则
7、算法流程
(1)准备样本集,从文件中或其他数据源中加载数据集
(2)对数据进行预处理(方法:标准化和归一化)
(3)计算新的数据点到训练样本集的每一个数据的距离
(4)取出离新的数据最近的K个样本集
(5)用这k个最相邻的样本的标签值作为新数据的标签类别
(6)测试算法准确性
8、程序示例
import pandas as pd
import operator as opt
# 1、加载数据集
file_name = "../DataSet/KNNDataSet1.txt"
features = ["feature1", "feature2", "feature3", "result"]
dataset = pd.read_csv(file_name, sep="\t", header=None, names=features)
# 获取训练样本集和测试样本集
features_count = dataset.shape[0]
train_data = dataset.iloc[0:900, :] # 训练集
test_data = dataset.iloc[900 : features_count, :] # 测试集
train_data_X = train_data.iloc[:, 0:3] # 训练集特征
train_data_y = train_data.iloc[:, 3] # 训练集标签
test_data_X = test_data.iloc[:,0:3] # 测试集特征
test_data_y = test_data.iloc[:,3] # 测试集标签
#2、对数据进行预处理(归一化)
def normalized_data(samples):
min_value = samples.min()
max_value = samples.max()
normalized_sample = (samples - min_value) / (max_value - min_value)
return normalized_sample
train_data_X = normalized_data(train_data_X)
test_data_X = normalized_data(test_data_X)
# 训练样本集
def predict_data(test_data_row, k_count):
# 3、计算新的数据点到训练样本集的每一个数据的距离
different_data = (test_data_row - train_data_X) ** 2 # 差平方
sum_data = different_data.sum(axis=1) # 求和
distance = sum_data ** 0.5 # 开根
# 4、取出离新的数据最近的K个样本集
sort_data = distance.argsort()[:k_count]
# 5、用这k个最相邻的样本的标签值作为新数据的标签类别
label_count = {}
for index in sort_data:
label = train_data_y[index]
label_count[label] = label_count.get(label, 0) + 1
max_label_count = sorted(label_count.items(), key=opt.itemgetter(1), reverse = True)
return max_label_count[0][0]
# 用于记录预测值
list_predict = []
for index in test_data_X.index:
# print(test_data.loc[index]["predict_data"])
result = predict_data(test_data_X.loc[index].values, 5)
list_predict.append(result)
# 计算准确率
right_count = 0
for index in range(len(list_predict)):
if(test_data_y[900 + index] == list_predict[index]):
right_count = right_count + 1
rate = right_count / len(list_predict)
print(rate)