在模式识别领域中,最近邻居法(KNN算法,又译K-近邻算法)是一种用于分类和回归的非参数统计方法。[1]在这两种情况下,输入包含特征空间中的k个最接近的训练样本。 KNN可分为分类和回归:
在k-NN分类中,输出是一个分类族群。一个对象的分类是由其邻居的“多数表决”确定的,k个最近邻居(k为正整数,通常较小)中最常见的分类决定了赋予该对象的类别。若k = 1,则该对象的类别直接由最近的一个节点赋予。
在k-NN回归中,输出是该对象的属性值。该值是其k个最近邻居的值的平均值。
KNN的思想非常的简单,没有什么理论公式。看官看完上面的介绍我这里就直接上代码了~
from sklearn.datasets import make_multilabel_classification import numpy as np import matplotlib.pyplot as plt import operator _color_table = ['#99CC99', '#FFCC00', '#006699', '#33CC99', '#66CCCC', '#CC6600', '#333399', '#99CC00', '#FF6600', '#FFCC99', '#FF9900', '#009999', '#CC3366', '#FFFFFF', '#99CCFF', '#FFFF00', '#FFCC33', '#FF9933', '#FFFF33', '#CCCCFF', '#FFCCCC', '#FF0033', '#CC0033', '#003399', '#666699', '#CCFF99', '#FFFFCC', '#CCCC00', '#99CC33', '#FF9966', '#336699', '#CCFFCC', '#99CCCC', '#CCCC44', '#0099CC', '#CCFFFF', '#0066CC', '#FFFF99', '#CC3333', '#CCCCCC', '#6699CC', '#FF6666', '#66CCFF', '#663399', '#339933'] def get_color(i): return _color_table[i % len(_color_table)] def knn(x, y, k, predict_x): """ knn算法实现,使用欧氏距离 :param x: 样本值 :param y: 标签 :param k: 个数 :return: """ assert isinstance(y, np.ndarray) y = y.flatten('F') def cal_distance(a, b): return np.sqrt(np.sum(np.power(a - b, 2), axis=0)) dists = { } for (index, sample) in enumerate(x): dists[index] = cal_distance(sample, predict_x) k_sample = sorted(dists.items(), key=operator.itemgetter(1))[:k] # 排序选出前面n个 k_labels = y[[key for (key, value) in k_sample]] # 选出距离较小的前面n个的label counters = { } for k in k_labels: if k not in counters.keys(): counters[k] = 1 else: counters[k] += 1 return sorted(counters.items(), key=operator.itemgetter(1))[0] # 选个数最多的~ # 生成数据 sample_num = 30 x, y = make_multilabel_classification(n_samples=sample_num, n_features=2, n_classes=1, n_labels=1, random_state=2) c_1 = x[np.where(y == 0)[0]] # 类别1 c_2 = x[np.where(y == 1)[0]] # 类别2 predict_x = np.array([30, 30]) result = knn(x, y, 5, predict_x) ## 绘图 plt.figure() plt.subplot(111) s_c1 = plt.scatter(c_1[:, 0], c_1[:, 1], c=get_color(0), ) s_c2 = plt.scatter(c_2[:, 0], c_2[:, 1], c=get_color(1)) s_c3 = plt.scatter(predict_x[0], predict_x[1], c=get_color(2)) plt.legend((s_c1, s_c2, s_c3), ('label 0', 'label 1', 'pre points'), scatterpoints=1, loc='lower left', fontsize=8) plt.annotate("belong to '{}'".format(result[0]), xy=(predict_x[0], predict_x[1]), xytext=(-20, 20), textcoords='offset points', ha='right', va='bottom', bbox=dict(boxstyle='round,pad=0.5', fc='yellow', alpha=0.5), arrowprops=dict(arrowstyle='->', connectionstyle='arc3,rad=0')) plt.show()最后一步,上图~鄙人对图还是有点满意的、