0
点赞
收藏
分享

微信扫一扫

机器学习-KNN(K近邻算法)

爱薇Ivy趣闻 2022-04-19 阅读 189

机器学习–K近邻算法

基本概念

k k k 近邻法 ( k k k-nearest neighbor, k k k-NN) 是一种基于分类与回归的方法。

原理:对于一个实例,根据其 k k k 个最近邻的训练实例的类别,通过多数表决等方式来决定这个实例的类别。

输入:实例的特征向量
输出:实例的类别

三个基本要素: k k k 值的选择、距离度量以及分类决策规划

k k k 近邻算法

输入:训练数据集
T = { ( x 1 , y 1 ) , ( x 2 , y 2 ) , ⋯   , ( x n , y n ) } T = \{(x_1,y_1),(x_2,y_2), \cdots,(x_n,y_n)\} T={(x1,y1),(x2,y2),,(xn,yn)}
其中, x i x_i xi是实例特征向量, y i y_i yi 是实例的类别。
输出:实例 x x x 所属的类别 y y y

  1. 根据指定的度量,在训练集 T T T 中找出与 x x x 最邻近的 k k k 个点,包含在 N k ( x ) N_k(x) Nk(x) 中。
  2. N k ( x ) N_k(x) Nk(x) 中根据分类决策规则(如多数表决)决定 x x x 的类别 y y y

即: y = a r g   m a x x j ∑ x i ∈ N k ( x ) I ( y i = c j ) , i = 1 , 2 , ⋯   , N ; j = 1 , 2 , ⋯   , K y=arg\ \mathop{max}\limits_{x_j} \sum_{x_i \in N_k(x)}I(y_i=c_j),i=1,2,\cdots,N;j=1,2,\cdots,K y=arg xjmaxxiNk(x)I(yi=cj),i=1,2,,N;j=1,2,,K
其中, I I I 表示指示函数,当 y i = c j y_i=c_j yi=cj I = 1 I=1 I=1,否则为0。

k k k 近邻模型

模型由三个基本要素----距离度量、 k k k 值选择和分类决策规则决定。

距离度量

特征空间中两个实例之间的距离可以反映两个实例之间的相似程度。在 k k k 近邻中,一般使用过欧式距离,也可以使用曼哈顿距离或者更一般的 L p L_p Lp 距离。

对于实例 x i , x j   R n x_i, x_j \ R^n xi,xj Rn L p L_p Lp 距离可以定义为:
L p ( x i , x j ) = ( ∑ l = 1 n ∣ x i ( l ) − x j ( l ) ∣ p ) 1 p L_p(x_i,x_j)=(\sum_{l=1}^n\vert x_i^{(l)}-x_j^{(l)}\vert^p)^{\frac{1}{p}} Lp(xi,xj)=(l=1nxi(l)xj(l)p)p1
当 p = 2 时称为欧式距离,当 p = 1 时称为曼哈顿距离。

k k k 值的选择

k k k 值的选择会对 k k k 近邻算法的结果产生巨大的影响。
如果 k k k 值过小,训练误差会减小,但测试误差会增大。意味着整体模型变得复杂,容易发生过拟合。
如果 k k k 值过大,模型变得更加简单,测试误差会减小,但训练误差会增加。
通常我们使用交叉验证法来选取最优的 k k k 值。

分类决策规则

k k k 近邻法中的分类决策规则往往是多数表决,即由周围 k k k 个实例中的类别最多的点来决定输入实例的类别。

实现案例

本章节使用 sklearn 库内置函数实现了基于 k k k 近邻算法的分类(鸢尾花分类和手写数字识别)与回归(波斯顿房价预测)。

k k k 近邻算法实现鸢尾花数据集分类

# coding=utf-8

from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.neighbors import KNeighborsClassifier

if __name__ == '__main__':

    # 导入数据
    iris = datasets.load_iris()

    # 划分数据集
    x_train, x_test, y_train, y_test = train_test_split(iris.data, iris.target, test_size=0.3)

    # 标准化处理
    std = StandardScaler()
    x_train = std.fit_transform(x_train)
    x_test = std.transform(x_test)

    # 创建KNN模型

    knn = KNeighborsClassifier(n_neighbors=5, weights="uniform")

    # 进行训练
    knn.fit(x_train, y_train)

    # 进行预测
    y_predict = knn.predict(x_test)

    print(f"predict accuracy = {knn.score(x_test, y_test)}")
	# predict accuracy = 0.9333333333333333

k k k 近邻算法实现手写数字识别

# coding=utf-8

from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.neighbors import KNeighborsClassifier

if __name__ == '__main__':

    # 导入数据
    digits = datasets.load_digits()

    # 数据集划分
    x_train, x_test, y_train, y_test = train_test_split(digits.data, digits.target, test_size=0.3)
    
	# 标准化处理
    std = StandardScaler()
    x_train = std.fit_transform(x_train)
    x_test = std.transform(x_test)

    # 创建模型
    knn = KNeighborsClassifier(n_neighbors=5)

    # 训练模型
    knn.fit(x_train, y_train)

    # 测试模型
    knn.predict(x_test)

    print(f"prediction accuracy = {knn.score(x_test, y_test)}")
	# predict accuracy = 0.9888888888888889

k k k 近邻算法实现波斯顿房价预测

# coding=utf-8

from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import r2_score, mean_squared_error, mean_absolute_error

if __name__ == '__main__':

    # 导入数据
    boston = datasets.load_boston()

    # # 数据集划分
    x_train, x_test, y_train, y_test = train_test_split(boston.data, boston.target, test_size=0.3)

    # 输入要为二维数组
    y_train = y_train.reshape(-1, 1)
    y_test = y_test.reshape(-1, 1)

    # 标准化处理
    std = StandardScaler()
    x_train = std.fit_transform(x_train)
    x_test = std.transform(x_test)
    y_train = std.fit_transform(y_train)
    y_test = std.transform(y_test)

    # 创建模型
    knn = KNeighborsClassifier(n_neighbors=3)

    # 训练模型
    knn.fit(x_train, y_train.astype(int).astype(float))
    # Tips: y_train.astype(int).astype(float) 如果不这样会出现: 
    # ValueError: Unknown label type: 'continuous'
    # 测试模型
    prediction = knn.predict(x_test)

    # 模型评估
    print(f"default evolution value = {knn.score(x_test, y_test.astype(int).astype(float))}")
    print(f"R_squared value = {r2_score(std.inverse_transform(y_test), std.inverse_transform(prediction))}")
    print(f"mean_squared_error value = {mean_squared_error(std.inverse_transform(y_test), std.inverse_transform(prediction))}")
    print(f"mean_absolute_error value = {mean_absolute_error(std.inverse_transform(y_test), std.inverse_transform(prediction))}")
	# default evolution value = 0.756578947368421
	# R_squared value = 0.3205080076834249
	# mean_squared_error value = 74.66965266743814
	# mean_absolute_error value = 5.753533302051314
举报

相关推荐

0 条评论