统计学习方法之k近邻法

    科技2024-07-19  67

    统计学习方法之k近邻法

    1. k近邻算法

    I n p u t : Input: Input:

    T = { ( x 1 , y 1 ) , ( x 2 , y 2 ) , ⋯   , ( x N , y N ) } 其 中 , x i ∈ X ⊆ R n 为 实 例 的 特 征 向 量 T=\left\{\left(x_{1}, y_{1}\right),\left(x_{2}, y_{2}\right), \cdots,\left(x_{N}, y_{N}\right)\right\} 其中, x_{i} \in \mathcal{X} \subseteq \mathbf{R}^{n} 为实例的特征向量 T={(x1,y1),(x2,y2),,(xN,yN)}xiXRn y i ∈ Y = { c 1 , c 2 , ⋯   , c K } 为 实 例 的 别 , i = 1 , 2 , ⋯   , N y_{i} \in \mathcal{Y}=\left\{c_{1}, c_{2}, \cdots, c_{K}\right\} 为实例的别, i=1,2, \cdots, N yiY={c1,c2,,cK}i=1,2,,N 实 例 特 征 向 量 x 实例特征向量 x x

    O u t p u t : Output: Output:

    实 例 x 所 属 的 类 y 实例x所属的类y xy

    A l g o r i t h m : Algorithm: Algorithm:

    根据给定的距离度量,在训练集 T T T中找出与 x x x最近邻的 k k k个点,涵盖这 k k k个点的 x x x的邻域记作 N k ( x ) N_k(x) Nk(x) N k ( x ) N_k(x) Nk(x)中根据分类决策规则决定 x x x的类别 y y y

    y = arg ⁡ max ⁡ c j ∑ x i ∈ N k ( x ) I ( y i = c j ) , i = 1 , 2 , ⋯   , N ; j = 1 , 2 , ⋯   , K y=\arg \max _{c_{j}} \sum_{x_{i} \in N_{k}(x)} I\left(y_{i}=c_{j}\right), \quad i=1,2, \cdots, N ; j=1,2, \cdots, K y=argcjmaxxiNk(x)I(yi=cj),i=1,2,,N;j=1,2,,K

    2. k近邻模型

    2.1 距离度量

    特征空间中两个实例点的距离是两个实例点相似程度的反映。

    闵可夫斯基距离距离:

    L p ( x i , x j ) = ( ∑ l = 1 n ∣ x i ( l ) − x j ( l ) ∣ p ) 1 p L_{p}\left(x_{i}, x_{j}\right)=\left(\sum_{l=1}^{n}\left|x_{i}^{(l)}-x_{j}^{(l)}\right|^{p}\right)^{\frac{1}{p}} Lp(xi,xj)=(l=1nxi(l)xj(l)p)p1

    欧式距离:

    L p 2 ( x i , x j ) = ( ∑ l = 1 n ∣ x i ( l ) − x j ( l ) ∣ 2 ) 1 2 L_{p2}\left(x_{i}, x_{j}\right)=\left(\sum_{l=1}^{n}\left|x_{i}^{(l)}-x_{j}^{(l)}\right|^{2}\right)^{\frac{1}{2}} Lp2(xi,xj)=(l=1nxi(l)xj(l)2)21

    曼哈顿距离:

    L 1 ( x i , x j ) = ∑ l = 1 n ∣ x i ( l ) − x j ( l ) ∣ L_{1}\left(x_{i}, x_{j}\right)=\sum_{l=1}^{n}\left|x_{i}^{(l)}-x_{j}^{(l)}\right| L1(xi,xj)=l=1nxi(l)xj(l)

    切比雪夫距离:

    L ∞ ( x i , x j ) = max ⁡ l ∣ x i ( l ) − x j ( l ) ∣ L_{\infty}\left(x_{i}, x_{j}\right)=\max _{l}\left|x_{i}^{(l)}-x_{j}^{(l)}\right| L(xi,xj)=lmaxxi(l)xj(l)

    2.2 k值的选择

    k值的选择会对k近邻法的结果产生重大影响

    k值的减小就意味着整体模型变得复杂,容易发生过拟合。k值的增大就意味着整体的模型变得简单,容易使预测发生错误。在应用中,一般取一个比较小的数值。通常采用交叉验证法来选取最优的k值
    2.3 分类决策规则

    k近邻法中的分类决策规则一般为多数表决。

    分类函数为: f : R n → { c 1 , c 2 , . . . , c k } f:R^n \rightarrow\{c_1,c_2,...,c_k\} f:Rn{c1,c2,...,ck}

    误分类概率: P ( Y ≠ f ( X ) ) = 1 − P ( Y = f ( X ) ) P(Y \not= f(X)) = 1 - P(Y=f(X)) P(Y=f(X))=1P(Y=f(X))

    实例 x ∈ X x \in \mathcal{X} xX;最近邻的k个训练实例点构成集合 N k ( x ) N_k(x) Nk(x)。如果涵盖 N k ( x ) N_k(x) Nk(x)区域的类别为 c j c_j cj,那么误分类率为: 1 k ∑ x i ∈ N k ( x ) I ( y i ≠ c j ) = 1 − 1 k ∑ x i ∈ N k ( x ) I ( y i = c j ) \frac{1}{k} \sum_{x_{i} \in N_{k}(x)} I\left(y_{i} \neq c_{j}\right)=1-\frac{1}{k} \sum_{x_{i} \in N_{k}(x)} I\left(y_{i}=c_{j}\right) k1xiNk(x)I(yi=cj)=1k1xiNk(x)I(yi=cj)

    要使误分类率最小即经验风险最小,就要使 1 k ∑ x i ∈ N k ( x ) I ( y i = c j ) \frac{1}{k} \sum_{x_{i} \in N_{k}(x)} I\left(y_{i}=c_{j}\right) k1xiNk(x)I(yi=cj)最大,也就是多数表决。

    3. 算法实现

    # 导入所需的库 import numpy as np import pandas as pd import matplotlib.pyplot as plt from sklearn.datasets import load_iris from sklearn.model_selection import train_test_split # 加载数据 iris = load_iris() df = pd.DataFrame(iris.data, columns=iris.feature_names) df['label'] = iris.target df sepal length (cm)sepal width (cm)petal length (cm)petal width (cm)label05.13.51.40.2014.93.01.40.2024.73.21.30.2034.63.11.50.2045.03.61.40.20..................1456.73.05.22.321466.32.55.01.921476.53.05.22.021486.23.45.42.321495.93.05.11.82

    150 rows × 5 columns

    # 展示数据 x_idx = iris.feature_names[0] y_idx = iris.feature_names[1] plt.scatter(df[:50][x_idx], df[:50][y_idx], label='0') plt.scatter(df[50:100][x_idx], df[50:100][y_idx], label='1') plt.xlabel('sepal length') plt.ylabel('sepal width') plt.legend() plt.show()

    # 准备数据 data = np.array(df.iloc[:100, [0, 1, -1]]) X, y = data[:,:-1], data[:,-1] X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2) test_point = [[6, 3]] plt.scatter(df[:50][x_idx], df[:50][y_idx], label='0') plt.scatter(df[50:100][x_idx], df[50:100][y_idx], label='1') plt.plot(test_point[0][0], test_point[0][1], 'bo', label='test_point') plt.xlabel('sepal length') plt.ylabel('sepal width') plt.legend() plt.show()

    from sklearn.neighbors import KNeighborsClassifier clf = KNeighborsClassifier() clf.fit(X_train, y_train) clf.predict(test_point) array([1.])
    Processed: 0.009, SQL: 8