KNN(K-Nearest Neighbor) 算法是机器学习算法中最基础的算法之一,它既能用于分类,又能用于回归。有别于其他经典的机器学习算法,其没有显式的学习过程。
模型:利用训练数据划分特征向量空间,其结果就是最终算法模型。
基本思想是:任意 N 维输入向量对应于特征空间的一点,输出为该特征向量所对应的类别标签或者预测值。
KNN 分类
KNN 用于分类,其过程简单的说就是:
- 输入需要预测离散值的实例,
- 通过指定的距离度量找出离它最近的 k 个训练数据,
- 根据这 k 个训练数据的标签,通过一个决策规则来决定输入实例的列类别。
KNN模型的基本要素为:
- 距离度量:通常使用欧式距离(p=2),或更一般的 L p Lp Lp 距离;
- k 值的选择:通常取比较小的值(k 值单位是个,所以必须选大于 0 的整数),当 k 取 1 时就是最近邻算法。但要注意,k 值取过小会导致模型过于复杂,方差过大,导致过拟合;k 值取过大会使模型过于简单,偏差较大,导致欠拟合;
- 分类决策规则:通常使用多数表决的决策规则,即认为 k 个邻近值中最多的标签便是输入值的分类结果。
KNN分类算法的Python实现:
完整代码见 Github
# 环境:Python3.6,测试通过.
# 需要给定训练集和测试集 X_train, y_train; X_test, y_test(类型为ndarray)
import numpy as np
from collections import Counter
# 核心函数
def knn_single_predict(x, k=3, p=2):
"""
knn分类算法预测函数(单个实例):
输入 -- 单个实例 X,邻近数 k,距离度量 p
输出 -- 该输入实例的类别
"""
# 1. 初始化,用于后续更新。计算出 x 与前三个训练实例点的距离
knn_list = [] # 存放邻近点的距离和类别
for i in range(k):
dist = np.linalg.norm(x - X_train[i], ord=p)
knn_list.append((dist, y_train[i]))
# 2. linear scan(kd tree 效率更高). 找到更小的值就更新.
for i in range(k, len(X_train)):
max_index = knn_list.index(max(knn_list, key=lambda x: x[0]))
dist = np.linalg.norm(x - X_train[i], ord=p)
if knn_list[max_index][0] > dist:
knn_list[max_index] = (dist, y_train[i])
# 3. 分类决策规则:多数表决
knn = [k[-1] for k in knn_list]
count_pairs = Counter(knn) # 根据列表频数生成字典,key为类别值,values为类别值频数
# 按values升序排序后取出出现最多的类别
max_count = sorted(count_pairs.items(), key=lambda x: x[1])[-1][0]
return max_count
# 对多个实例
def knn_predict(X):
"""
knn预测函数(单个或多个实例)
"""
y_pred = [] # 初始化一个列表,存放每个输入实例的预测类
if X.ndim == 1: # 单个实例
y_pred = knn_single_predict(X)
else:
for i in range(len(X)): # 依次判断每个输入实例的类别
y_pred.append(knn_single_predict(X[i]))
return y_pred
y_pred = knn_predict(X)
print(y_pred)
def score(y_pred):
"""
评分:
计算分类正确的实例数占总数的比例
"""
y_pred = knn_predict(X_test)
right_count = (y_pred == y_test).sum()
rate = right_count / len(y_test)
return rate
y_pred = knn_predict(X_test)
rate = score(y_pred)
print(rate)
KNN分类算法的sklearn实现
class sklearn.neighbors.KNeighborsClassifier(n_neighbors=5, weights=’uniform’, algorithm=’auto’, leaf_size=30, p=2, metric=’minkowski’, metric_params=None, n_jobs=None, **kwargs)[source]
- n_neighbors:邻近的点个数,默认为 5
- weights:权重度量,默认为 “uniform”,表示所有 k 个近邻在分类时重要性选取是一样的
- ……
from sklearn.neighbors import KNeighborsClassifier
clf = KNeighborsClassifier()
clf.fit(X_train, y_train)
# clf.predict(X_test)
clf.score(X_test, y_test)
KNN回归
KNN主要用来分类,但其也能用于回归预测:
- 在训练集上寻找与输入实例最相近的 K 个近邻;
- 对这 K 个样本的因变量值取均值,作为输入实例的预测值.
参考:
[1] 李航. 《统计学习方法》.
[2] 章华燕. 《机器学习算法各个击破》.
[3] https://github.com/fengdu78/lihang-code/blob/master/code / 第 3 章 k 近邻法 (KNearestNeighbors)/KNN.ipynb