具体步骤:
- 计算当前要分类的点与每一个已知分类点的距离。
- 对结果进行排序。
- 选取距离最近的k个点。
- 统计这k个点不同分类出现的频次。
- 选取频次最高的分类作为当前要分类的点的分类。
以sklearn库自带的iris数据集为例。
获取iris数据集
from sklearn import datasets
import pandas as pd
from collections import Counter
iris_datas = datasets.load_iris()
iris = pd.DataFrame(iris_data.data, columns=iris_datas['feature_names'])
print(iris.head())
将种类作为新的一列添加进去
iris = pd.merge(iris, pd.DataFrame(iris_datas['target'], columns=['species']), left_index=True, right_index=True)
labels = {x: y for x, y in enumerate(iris_datas['target_names'])}
iris['species'] = iris['species'].apply(lambda x: labels[x])
print(iris.head())
进行KNN算法测试
距离选择的是标准的欧式距离公式
例如:计算点[5.6 2.5 3.9 1.1] 和 [5.9 3.2 4.8 1.8]的距离,算法如下
import random
from collections import Counter
import numpy as np
def classify(input_data, train_data, labels, k):
data_size = train_data.shape[0]
# tile函数将input_data在行上复制了data_size次
diff = np.tile(input_data, (data_size, 1)) - train_data
sqrt_diff = diff ** 2
sqrt_distance = sqrt_diff.sum(axis=1)
distance = np.sqrt(sqrt_distance)
sorted_index = distance.argsort()
class_count = Counter(labels[sorted_index[:k]])
return class_count.most_common()[0][0]
def try_once(iris):
# 打乱样本
iris = iris.sample(frac=1)
index = iris.index.values[-1]
iris = iris.reset_index(drop=True)
input_data = iris.iloc[-1, :-1]
input_label = iris.iloc[-1, -1]
data = iris.iloc[:-1, :-1]
labels = iris.iloc[:-1, -1]
print('input_index:', index)
print('true class:', input_label)
print(classify(input_data, data, labels, 5))
try_once(iris)
取6次测试结果