knn训练的时候在画点,预测的时候用已经存在的点和输入的点计算距离 。

KNN数学公式完整计算(以电影数据为例)

目标:预测新电影 [23, 3, 17] 的类型
特征:搞笑镜头数、拥抱镜头数、打斗镜头数
类别:0=喜剧片、1=动作片、2=爱情片
参数:K=3(取3个最近邻居)

数据表格化

样本搞笑镜头(x₁)拥抱镜头(x₂)打斗镜头(x₃)标签(y)类型
1390310喜剧片
232651动作片
323552爱情片
493822爱情片
5834172爱情片
652571动作片
7211750喜剧片
845290喜剧片

待预测:Q = [23, 3, 17]

数学公式体系

1. 距离公式(欧氏距离)

d(x, y) = √[(x₁ - y₁)² + (x₂ - y₂)² + (x₃ - y₃)²]

2. K近邻集合

Nₖ(q) = {(x⁽ⁱ⁾, y⁽ⁱ⁾) | 距离d(q, x⁽ⁱ⁾) 最小的K个样本}

3. 投票决策

ŷ = argmax_{c∈{0,1,2}} ∑_{(x⁽ⁱ⁾,y⁽ⁱ⁾)∈Nₖ(q)} I(y⁽ⁱ⁾ = c)

其中 I(条件) 是指示函数(条件成立=1,否则=0)

逐步计算过程

第1步:计算所有距离

通用公式:d_i = √[(23 - x₁_i)² + (3 - x₂_i)² + (17 - x₃_i)²]

计算样本1(喜剧片):
d₁ = √[(23-39)² + (3-0)² + (17-31)²]
   = √[(-16)² + 3² + (-14)²]
   = √[256 + 9 + 196]
   = √461 ≈ 21.47
计算样本2(动作片):
d₂ = √[(23-3)² + (3-2)² + (17-65)²]
   = √[20² + 1² + (-48)²]
   = √[400 + 1 + 2304]
   = √2705 ≈ 52.01
计算样本3(爱情片):
d₃ = √[(23-2)² + (3-3)² + (17-55)²]
   = √[21² + 0² + (-38)²]
   = √[441 + 0 + 1444]
   = √1885 ≈ 43.42
计算样本4(爱情片):
d₄ = √[(23-9)² + (3-38)² + (17-2)²]
   = √[14² + (-35)² + 15²]
   = √[196 + 1225 + 225]
   = √1646 ≈ 40.57
计算样本5(爱情片):
d₅ = √[(23-8)² + (3-34)² + (17-17)²]
   = √[15² + (-31)² + 0²]
   = √[225 + 961 + 0]
   = √1186 ≈ 34.44
计算样本6(动作片):
d₆ = √[(23-5)² + (3-2)² + (17-57)²]
   = √[18² + 1² + (-40)²]
   = √[324 + 1 + 1600]
   = √1925 ≈ 43.87
计算样本7(喜剧片):
d₇ = √[(23-21)² + (3-17)² + (17-5)²]
   = √[2² + (-14)² + 12²]
   = √[4 + 196 + 144]
   = √344 ≈ 18.55
计算样本8(喜剧片):
d₈ = √[(23-45)² + (3-2)² + (17-9)²]
   = √[(-22)² + 1² + 8²]
   = √[484 + 1 + 64]
   = √549 ≈ 23.43

第2步:距离排序表

排名样本特征向量标签距离类型
17[21, 17, 5]018.55喜剧片
21[39, 0, 31]021.47喜剧片
38[45, 2, 9]023.43喜剧片
45[8, 34, 17]234.44爱情片
54[9, 38, 2]240.57爱情片
63[2, 3, 55]243.42爱情片
76[5, 2, 57]143.87动作片
82[3, 2, 65]152.01动作片

第3步:选取K=3个最近邻

根据排序,最近的3个邻居是:

N₃(q) = { (样本7, 标签0), (样本1, 标签0), (样本8, 标签0) }

用数学集合表示:

N₃(q) = {(x⁽⁷⁾,0), (x⁽¹⁾,0), (x⁽⁸⁾,0)}
      = {([21,17,5],0), ([39,0,31],0), ([45,2,9],0)}

第4步:多数投票

投票公式:对于每个类别c,计算:v_c = ∑_{(x,y)∈N₃(q)} I(y = c)

计算各类别票数:
v₀ = I(0=0) + I(0=0) + I(0=0) = 1 + 1 + 1 = 3
v₁ = I(0=1) + I(0=1) + I(0=1) = 0 + 0 + 0 = 0
v₂ = I(0=2) + I(0=2) + I(0=2) = 0 + 0 + 0 = 0

票数统计

类别0(喜剧片):3票
类别1(动作片):0票
类别2(爱情片):0票

第5步:决策结果

决策公式

ŷ = argmax_{c∈{0,1,2}} {v₀=3, v₁=0, v₂=0}

计算最大值:

max(3, 0, 0) = 3
argmax = 对应的类别 = 0

最终预测:ŷ = 0 (喜剧片)

实现代码

例一

def dm01_knn_clas():
    # 1 导入依赖包
    from sklearn.neighbors import KNeighborsClassifier

    # 2 准备数据  # 0-喜剧片 1-动作片 2-爱情片
    x = [[39, 0, 31],  # 0
         [3, 2, 65],  # 1
         [2, 3, 55],  # 2
         [9, 38, 2],  # 2
         [8, 34, 17],  # 2
         [5, 2, 57],  # 1
         [21, 17, 5],  # 0
         [45, 2, 9]]  # 0
    y = [0, 1, 2, 2, 2, 1, 0, 0]

    # 3 实例化模型
    estimator = KNeighborsClassifier(n_neighbors=3)
    print('estimator-->', estimator)

    # 4 模型训练 .fit()
    estimator.fit(x, y)

    # 5 模型预测 .predict() 搞笑镜头23 拥抱镜头3 打动镜头17
    pred = estimator.predict([[23, 3, 17]])
    print('pred-->', pred)

列二

def dm02_knn_clas():
    # 1.导入依赖包
    from sklearn.neighbors import KNeighborsClassifier

    # 2.准备数据  # 0-喜剧片 1-动作片 2-爱情片
    x = [[39, 0, 31],  # 0
         [3, 2, 65],  # 1
         [2, 3, 55],  # 2
         [9, 38, 2],  # 2
         [8, 34, 17],  # 2
         [5, 2, 57],  # 1
         [21, 17, 5],  # 0
         [45, 2, 9]]  # 0
    y = [0, 1, 2, 2, 2, 1, 0, 0]

    # 分为3类
    estimator = KNeighborsClassifier(n_neighbors=3)
    print('estimator-->', estimator)

    # 4.模型训练
    estimator.fit(x, y)
    score = estimator.score(x, y)
    print('score-->', score)

    # 5 模型预测 .predict() 搞笑镜头23 拥抱镜头3 打动镜头17
    pred = estimator.predict([[23, 3, 17]])
    print('pred-->', pred)

    pred = estimator.predict([[23, 3, 17], [8, 34, 17]])
    print('pred-->', pred)

    # 6. 保存模型
    import joblib
    joblib.dump(estimator, './model/knn_model.bin')
    print('\n模型已保存为: ./model/knn_model.bin')

    # 9. 验证模型加载和预测
    loaded_model = joblib.load('./model/knn_model.bin')
    test_pred = loaded_model.predict([[23, 3, 17], [8, 34, 17]])
    print(f'加载模型后的预测验证: {test_pred}')

更多推荐