K-近邻算法(KNN算法)的python代码实现(基于sklearn的鸢尾花iris数据集为例)

利用sklearn内置的鸢尾花数据集为例,使用KNN算法进行鸢尾花的品种分类,其中包含了数据集获取,数据集分析,测试数据和训练数据切分,网格搜索最佳超参数等具体代码实现用例。

1.数据集获取
sklearn模块提供了丰富的数据集供开发者学习和试验,本文使用的是分类算法经典用例——鸢尾花案例,
sklearn数据集中datasets.load_digits也是一个学习分类算法不错的案例,大家可以尝试一下 
2. 数据集结构分析
通过iris.keys()方法能够清晰了解到此数据集包括哪些内容,同时也可以直接print(iris),但不建议这样做,
数据集大的话根本看不过来,可以通过numpy提供的shape方法去了解数据结构。
主要需要了解的信息有:
样本数量(data矩阵多少行)
样本维度(data矩阵多少列)
标签分类(target取值枚举数)
3. 数据集分布分析
主要通过画图的方式,分析各个样本的特征值与标签的关系,判断特征值与标签分类结果是否相关
4.切分数据集
将数据集分为两份,一份用来训练,一份用来测试
一般情况下按二八分类,80%数据训练,20%数据测试
5. 归一化处理
无论是训练数据集还是测试数据集,都需要归一化处理,推荐均值方差归一化处理,这样有效避免极值对样本整体的影响
sklearn同时也提供最值归一化:MinMaxScaler()
值得注意的是,测试样本使用的归一化参数由训练样本计算而得
这样真实的模拟了实际生产环境,因为实际生产数据集无法求得归一化参数,
训练样本求得的归一化参数也是算法的一部分
6. 网格搜索
使用KNN算法,虽然算法本身没有模型参数,不需要训练模型参数。
但算法具备超参数,需要通过训练集数据确定最佳超参数,
这里使用sklearn提供的网格搜索方法进行最佳超参数搜索
7. 测试结果
使用网格搜索得到的最佳超参数进行测试数据验证,查看起得分是否满足业务需求
# -*- coding: UTF-8 -*-
import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets
from sklearn.metrics import accuracy_score
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.neighbors import KNeighborsClassifier
from sklearn.preprocessing import StandardScaler

"""
1.数据集获取
sklearn模块提供了丰富的数据集供开发者学习和试验,本文使用的是分类算法经典用例——鸢尾花案例,
sklearn数据集中datasets.load_digits也是一个学习分类算法不错的案例,大家可以尝试一下
"""
iris = datasets.load_iris()
print(iris.keys())  # 数据集包括 dict_keys(['data', 'target', 'frame', 'target_names', 'DESCR', 'feature_names', 'filename'])
data = iris.data  # 特征数据
feature_names = iris.feature_names  # 特征名称
target = iris.target  # 标签数据
target_names = iris.target_names  # 标签名称

"""
2. 数据集 结构 分析
通过iris.keys()方法能够清晰了解到此数据集包括哪些内容,同时也可以直接print(iris),但不建议这样做,
数据集大的话根本看不过来,可以通过numpy提供的shape方法去了解数据结构。
主要需要了解的信息有:
样本数量(data矩阵多少行)
样本维度(data矩阵多少列)
标签分类(target取值枚举数)
"""
print(iris.keys())
print(np.shape(data))  # (150, 4) 150个样本 4个维度的特征值
print(feature_names)  # 四个特征值名称分别是['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)']
print(np.shape(target))  # 对应150个样本的标签数据
print(target_names)  # 标签分为三类,分别是['setosa' 'versicolor' 'virginica']

"""
3. 数据集 分布 分析
主要通过画图的方式,分析各个样本的特征值与标签的关系,判断特征值与标签分类结果是否相关
"""
plt.scatter(data[target == 0, 0], data[target == 0, 1], color='b', marker='o')  # 标签为0的样本数据 前两列特征值的数据分布
plt.scatter(data[target == 1, 0], data[target == 1, 1], color='g', marker='*')  # 标签为1的样本数据 前两列特征值的数据分布
plt.scatter(data[target == 2, 0], data[target == 2, 1], color='r', marker='+')  # 标签为2的样本数据 前两列特征值的数据分布
plt.xlabel("sepal length (cm)", fontsize=15, color='b')  # 设置x轴标签
plt.ylabel("sepal width (cm)", fontsize=15, color='b')  # 设置y轴标签
plt.legend(['setosa', 'versicolor', 'virginica'])  # 设置图例
plt.show()
plt.scatter(data[target == 0, 2], data[target == 0, 3], color='b', marker='o')  # 标签为0的样本数据 后两列特征值的数据分布
plt.scatter(data[target == 1, 2], data[target == 1, 3], color='g', marker='*')  # 标签为1的样本数据 后两列特征值的数据分布
plt.scatter(data[target == 2, 2], data[target == 2, 3], color='r', marker='+')  # 标签为2的样本数据 后两列特征值的数据分布
plt.xlabel("petal length (cm)", fontsize=15, color='b')  # 设置x轴标签
plt.ylabel("petal width (cm)", fontsize=15, color='b')  # 设置y轴标签
plt.legend(['setosa', 'versicolor', 'virginica'])  # 设置图例
plt.show()

"""
4.切分数据集
将数据集分为两份,一份用来训练,一份用来测试
一般情况下按二八分类,80%数据训练,20%数据测试
"""
X_train, X_test, y_train, y_test = train_test_split(data, target, test_size=0.2, random_state=666)

"""
5. 归一化处理
无论是训练数据集还是测试数据集,都需要归一化处理,推荐均值方差归一化处理,这样有效避免极值对样本整体的影响
sklearn同时也提供最值归一化:MinMaxScaler()
值得注意的是,测试样本使用的归一化参数由训练样本计算而得
这样真实的模拟了实际生产环境,因为实际生产数据集无法求得归一化参数,
训练样本求得的归一化参数也是算法的一部分
"""
standardscaler = StandardScaler()
standardscaler.fit(X_train)  # 使用测试集数据训练归一化参数
print(standardscaler.mean_)  # 训练数据求得的归一化参数:均值[5.83416667, 3.08666667, 3.70833333, 1.17]
print(standardscaler.scale_)  # 训练数据求得的归一化参数:方差[0.81019502, 0.44327067, 1.76401924, 0.75317107]
X_train_standard = standardscaler.transform(X_train)  # 使用上诉归一化参数对训练数据归一化
X_test_standard = standardscaler.transform(X_test)  # 使用上诉归一化参数对测试数据归一化

"""
6. 网格搜索
使用KNN算法,虽然算法本身没有模型参数,不需要训练模型参数。
但算法具备超参数,需要通过训练集数据确定最佳超参数,
这里使用sklearn提供的网格搜索方法进行最佳超参数搜索
"""
param_grid = [
    {
        'weights': ['uniform'],  # 不考虑距离权重的模式
        'n_neighbors': [i for i in range(1, 11)]  # 邻近点的个数
    },
    {
        'weights': ['distance'],  # 考虑距离权重的模式
        'n_neighbors': [i for i in range(1, 11)],
        'p': [i for i in range(1, 6)]  # 明可夫斯基距离参数 p = (0:曼哈顿距离, 1:欧拉距离)
    }
]
knn_clf = KNeighborsClassifier()  # 实例化 KNN 算法
grid_search = GridSearchCV(knn_clf, param_grid, n_jobs=-1, verbose=2)  # n_jobs=-1 最大并行训练
grid_search.fit(X_train_standard, y_train)  # 针对训练数据进行最佳超参数搜索
best_estimator = grid_search.best_estimator_  # 这就是最终得到的最佳参数
best_score = grid_search.best_score_  # 使用上诉训练到的最佳参数得到的分类得分

"""
7. 测试结果
使用网格搜索得到的最佳超参数进行测试数据验证,查看起得分是否满足业务需求
"""
knn_clf = grid_search.best_estimator_
test_score_1 = knn_clf.score(X_test_standard, y_test)  # 可以直接通过KNeighborsClassifier内置函数得到分类得分
print("test_score_1 = {}".format(test_score_1))  # test_score_1 = 1.0

y_predict = knn_clf.predict(X_test_standard)  # 通过KNeighborsClassifier函数求得预测值
test_score_2 = accuracy_score(y_test, y_predict)  # 使用accuracy_score函数对比y_test,y_predict得到分类得分
print("test_score_2 = {}".format(test_score_2))  # test_score_2 = 1.0

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