机器学习笔记(KNN算法)

情景分析

  • 现在一个二维平面上有众多点 ( x 1 , y 1 ) , ( x 2 , y 2 ) . . . ( x n , y n ) (x_1, y_1), (x_2, y_2) ... (x_n, y_n) (x1,y1),(x2,y2)...(xn,yn),我也知道它们所属哪个类别,现在给出一个点 ( x , y ) (x, y) (x,y),问这个点是属于哪个类的。
  • 这是一个典型的分类问题

重要概念

  • 相邻点的个数K

相邻点的个数K

  • knn中最重要的概念就是这个了,也是唯一需要理解的概念,knn算法的思想是给出一个点 ( x , y ) (x, y) (x,y),找到其相邻最近的K个点,统计这K个点所属的分类,统计得到的最多的分类就是点 ( x , y ) (x, y) (x,y)的分类

自定义python代码实现knn

  • 代码中用到了heapq模块,Counter,lambda表达式等稍微复杂的运用,请大家自行理解
# 要添加一个新单元,输入 '# %%'
# 要添加一个新的标记单元,输入 '# %% [markdown]'
# %%
import heapq
import numpy as np
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from collections import Counter


# %%
# 加载数据
iris = load_iris()
# 切分X和y
X = iris.data[:, :2]
y = iris.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=12)


# %%
def knn(X_train, X_test, y_train, y_test, k=3):
    count = 0
    # 遍历测试数据里面的每一行,计算最小的k个距离以及它们的y
    for i in range(X_test.shape[0]):
        # 计算每个点的欧式距离
        diff = X_train - X_test[i]
        distance_list = [np.linalg.norm(_) for _ in diff]
        # 将距离和y_train组合
        combine_list = zip(distance_list, y_train.tolist())
        # 用heapq找出最小的k个值
        top_k_list = heapq.nsmallest(k, combine_list, key=lambda x : x[0])
        # 找出最小个k个值对应的y中出现最多的
        y = Counter([c[1] for c in top_k_list]).most_common(1)[0][0]
        if y == y_test[i]:
            count = count + 1
        print("{0} 预测属于:{1},实际属于:{2}".format(X_test[i], y, y_test[i]))
    # 所有行遍历完以后,输出准确率
    print("总共{0}个测试数据,{1}个准确,正确率{2:.2f}%".format(X_test.shape[0], count, count/X_test.shape[0]*100))
knn(X_train, X_test, y_train, y_test)
# %%




[5.  3.5] 预测属于:0,实际属于:0
[6.3 2.5] 预测属于:2,实际属于:2
[4.4 3. ] 预测属于:0,实际属于:0
[5.7 2.8] 预测属于:1,实际属于:1
[6.8 3.2] 预测属于:2,实际属于:2
[6.5 3. ] 预测属于:2,实际属于:2
[6.2 3.4] 预测属于:2,实际属于:2
[5.1 3.4] 预测属于:0,实际属于:0
[7.7 3. ] 预测属于:2,实际属于:2
[5.1 3.3] 预测属于:0,实际属于:0
[5.6 3. ] 预测属于:1,实际属于:1
[5.4 3.9] 预测属于:0,实际属于:0
[5.4 3.4] 预测属于:0,实际属于:0
[5.1 3.7] 预测属于:0,实际属于:0
[7.  3.2] 预测属于:2,实际属于:1
[7.2 3.2] 预测属于:2,实际属于:2
[6.7 2.5] 预测属于:1,实际属于:2
[5.9 3. ] 预测属于:2,实际属于:1
[4.6 3.4] 预测属于:0,实际属于:0
[6.3 2.5] 预测属于:2,实际属于:1
[4.9 3. ] 预测属于:0,实际属于:0
[6.1 2.8] 预测属于:1,实际属于:1
[6.2 2.8] 预测属于:1,实际属于:2
[6.  2.9] 预测属于:1,实际属于:1
[4.8 3.4] 预测属于:0,实际属于:0
[6.7 3. ] 预测属于:2,实际属于:2
[6.7 3. ] 预测属于:2,实际属于:1
[5.5 2.6] 预测属于:1,实际属于:1
[4.8 3.4] 预测属于:0,实际属于:0
[4.5 2.3] 预测属于:1,实际属于:0
[5.1 3.5] 预测属于:0,实际属于:0
[5.5 2.4] 预测属于:1,实际属于:1
[6.3 2.9] 预测属于:1,实际属于:2
[5.5 4.2] 预测属于:0,实际属于:0
[5.8 2.7] 预测属于:1,实际属于:2
[5.7 4.4] 预测属于:0,实际属于:0
[5.6 2.9] 预测属于:1,实际属于:1
[5.5 2.4] 预测属于:1,实际属于:1
[5.8 4. ] 预测属于:0,实际属于:0
[6.  2.2] 预测属于:1,实际属于:1
[5.1 2.5] 预测属于:1,实际属于:1
[5.  3.4] 预测属于:0,实际属于:0
[4.4 2.9] 预测属于:0,实际属于:0
[5.1 3.8] 预测属于:0,实际属于:0
[4.8 3. ] 预测属于:0,实际属于:0
总共45个测试数据,36个准确,正确率80.00%

用sklearn中的KNeighborsClassifier预测鸢尾花的分类

# 要添加一个新单元,输入 '# %%'
# 要添加一个新的标记单元,输入 '# %% [markdown]'
# %%
from sklearn.neighbors import KNeighborsClassifier
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt


# %%
# 导入数据
iris = load_iris()
# 分离X和y
X = iris.data
y = iris.target


# %%
# 分割训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=10)


# %%
# 训练模型
k_neighbors_classifier = KNeighborsClassifier(n_neighbors=5)
k_neighbors_classifier.fit(X_train, y_train)


# %%
# 预测测试集准确率
print("测试集准确率:", k_neighbors_classifier.score(X_test, y_test))


# %%

测试集准确率: 0.9777777777777777

你可能感兴趣的:(机器学习,python,机器学习,算法)