机器学习实验:KNN算法—K-近邻算法

机器学习实验:KNN算法—K-近邻算法

定义:k-近邻算法(k-NearestNeighbor,kNN),顾名思义,即由某样本k个邻居的类别来推断出该样本的类别。给定测试样本,基于特定的某种距离度量方式找到与训练集中最接近的k个样本,然后基于这k个样本的类别进行预测。
实验内容:

  1. 编写代码,实现对iris数据集的KNN算法分类及预测,要求:
    (1)数据集划分为测试集占20%;
    (2)n_neighbors=5;
    (3)评价模型的准确率;
    (4)使用模型预测未知种类的鸢尾花。
  2. 改进模型,要求:
    (1)数据集划分采用10折交叉验证;
    (2)寻找最优的n_neighbors值(在5-10之间);
    (3)使用新的模型预测未知种类的鸢尾花。

待预测未知数据:
X1=[[1.5 , 3 , 5.8 , 2.2], [6.2 , 2.9 , 4.3 , 1.3]]

实现代码:

  1. 编写代码,实现对iris数据集的KNN算法分类及预测
    (1)导入库
import numpy as np
import operator
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.metrics import *
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.neighbors import KNeighborsClassifier  #neighbors有两个类,一个是分类器,一个是回归器

(2)加载数据集

iris = load_iris()  #加载数据集
X = iris.data   #X
Y = iris.target #Y
# print(X.shape)    #查看维度
# print(Y.shape)
plt.figure()
plt.scatter(X[:,1],X[:,3], c=Y,s=40,cmap=plt.cm.Spectral)   #展示iris一三列数据集
plt.show()

机器学习实验:KNN算法—K-近邻算法_第1张图片
(3)划分数据集

#划分数据集,数据集划分为测试集占20%;
x_train, x_test, y_train, y_test = train_test_split(
        iris.data, iris.target,test_size=0.2)

两种方法: 1.自己写KNN算法 2.调用Sklearn中的KNeighborsClassifier直接得到KNN分类模型
方法一:
(4)手写KNN算法

# 手写kNN算法,返回k个邻居的类别和得到的测试数据的类别
def KNN(x_train,y_train,x_test,n_neighbors=5):

    # 计算欧氏距离
    numSamples = x_train.shape[0]    # shape[0] 表示行数

    distances = []  #存放欧式距离的集合
    for i in range(len(x_test)):     #  多个样本,对每个test样本进行计算,也即x_test中的每一行计算
        diff = tile(x_test[i], (numSamples, 1)) - x_train # 计算元素属性值的差,这里利用numpy的属性,直接将x_test的每一个样本直接计算减去x_train得到x_test[i]与x_train中每个样本的差
        #注意 x_test[i]维度为[1,4],x_train维度为[120,4],利用tile函数将x_test[i]扩大为维度为[120,4]的数组,然后才能和x_train做减运算
        squaredDiff = diff ** 2 #计算差值平方和
        squaredDist = sum(squaredDiff, axis = 1) # 按行求和 
        distance = squaredDist ** 0.5  #开方
        distances.append(distance)  #得出每一个样本即x_test[i]的distance
    
    # 对距离进行排序  
    # argsort() 返回按照升序排列的数组的索引
    sortedDistIndiceses = argsort(distances)    #得到升序的数组索引序列

    classCounts = []    #统计所有样本的前k个最短距离的字典,注意里面的每一项是一个x_test样本的字典
    for sortedDistIndices in sortedDistIndiceses: 
        classCount = {} # 定义字典,字典里面包含了前k个最短距离,y值的分布
        voteLabels = {} #定义字典,存储前k个最短距离中y的值
        for i in range(n_neighbors):  
            # 选择前k个最短距离 
            voteLabel = y_train[sortedDistIndices[i]]  #记录y值
            voteLabels[i] = voteLabel   #存入字典中,可以输出查看
            # 累计标签出现的次数  
            # 如果在标签在字典中没有出现的话, get()会返回0  
            classCount[voteLabel] = classCount.get(voteLabel, 0) + 1 
        #print("k个邻居的类别分别为:"+str(voteLabels))
        classCounts.append(classCount)  #每个样本的统计
    #print(classCounts)

    # 返回得到的投票数最多的分类
    result = [] #存放最终返回的结果,即每个样本的预测值
    for classCount in classCounts:  #每个样本
        maxCount = 0  #出现的最大次数
        for key, value in classCount.items():  
            if value > maxCount:  #找出出现最多的那个y,即找出离样本最近最多的y值是哪个
                maxCount = value  
                maxIndex = key  
        result.append(maxIndex)
    return result   #返回结果

(5)计算准确率函数

def KNN_acuracy(result,y_test):
    Accuracy_score = list(np.array(result)-y_test).count(0)/len(result) #计算准确率
    return Accuracy_score
    

(6)通过测试集评价模型的准确率

results = KNN(x_train,y_train,x_test)
print(results)
accuracy_score = KNN_acuracy(results,y_test)
print("KNN算法的准确率为:"+str(accuracy_score))
#[0, 0, 2, 2, 1, 1, 1, 2, 0, 0, 0, 1, 0, 2, 2, 0, 2, 2, 1, 2, 0, 1, 1, 2, 1, 1, 2, 0, 1, 0]
#KNN算法的准确率为:1.0

(7)预测结果

X1 = [[1.5, 3, 5.8, 2.2], [6.2, 2.9, 4.3, 1.3]]
predict = KNN(x_train,y_train,X1)
X1_classes = [load_iris().target_names[idx] for idx in predict]
print("两个鸢尾花的预测结果为:[1.5, 3, 5.8, 2.2] :{0}, [6.2, 2.9, 4.3, 1.3] :{1}".format(*X1_classes))
#两个鸢尾花的预测结果为:[1.5, 3, 5.8, 2.2] :virginica, [6.2, 2.9, 4.3, 1.3] :versicolor

方法二:
(8)通过sklearn库中的KNeighborsClassifier直接得到KNN分类模型

#通过sklearn库中的KNeighborsClassifier验证一下结果

X, y = load_iris(return_X_y=True)
# 按照训练集: 测试集 = 8: 2划分数据集
X_train, X_test, y_train, y_test = train_test_split(X,y,test_size=0.2)
# 定义模型
model = KNeighborsClassifier(n_neighbors=5)
# 用训练集拟合模型
model.fit(X_train,y_train)
# 得到测试集的准确率
test_accuracy_score = model.score(X_test,y_test)
print("鸢尾花测试集中,模型Accuracy 为: %f" % (test_accuracy_score))
# 加载预测的数据X1
X1 = [[1.5, 3, 5.8, 2.2], [6.2, 2.9, 4.3, 1.3]]
# 用模型进行预测并得到预测结果
predict = model.predict(X1)
# 获得X1中两个鸢尾花预测得到的索引所对应的类别
X1_classes = [load_iris().target_names[idx] for idx in predict]
print("两个鸢尾花的预测结果为:[1.5, 3, 5.8, 2.2] :{0}, [6.2, 2.9, 4.3, 1.3] :{1}".format(*X1_classes))
#鸢尾花测试集中,模型Accuracy 为: 1.000000
#两个鸢尾花的预测结果为:[1.5, 3, 5.8, 2.2] :virginica, [6.2, 2.9, 4.3, 1.3] :versicolor

2.改进模型,数据集划分采用10折交叉验证,并寻找最优的K值(在5-10之间)
(1)导入库

from  sklearn.model_selection import  cross_val_score     #导入K折交叉验证模块     
from  sklearn.datasets  import  load_iris                            #导入iris数据集
from  sklearn.neighbors  import  KNeighborsClassifier     #导入K近邻分类算法

(2)加载数据集

iris = load_iris()  #加载数据集
# 加载鸢尾花数据集的数据和标签
X = iris.data
y = iris.target

(3)数据集划分采用10折交叉验证,寻找最优的K值

# 定义迭代次数和超参数n_neighbors
epochs = 6
n_neighbors = 5

# 定义用于记录最佳准确率、最佳模型和最佳n_neighbors的参数
best_score = 0
best_model = None
best_n = 5
# 进行迭代
for iter in range(epochs):
    # 定义当前的KNN模型
    cur_model = KNeighborsClassifier(n_neighbors=n_neighbors)
    # 训练模型
    model = cur_model.fit(X,y)
    cur_score = cross_val_score(cur_model, X, y, cv=10).mean()

    # 判断得分是否超过最佳得分, 如果是则替换最佳模型
    if cur_score > best_score:
        best_n = n_neighbors
        best_model = cur_model
        best_score = cur_score
    print("n_neighbors {0}, 10折交叉验证的平均准确率为{1}".format(n_neighbors, cur_score))
    # 每次迭代n_neighbors += 1
    n_neighbors += 1
print("最佳模型的n_neighbors 为 {0}, 10折交叉验证的平均准确率为 {1}".format(best_n,best_score))

机器学习实验:KNN算法—K-近邻算法_第2张图片

(4)进行预测

# 定义用于测试的数据
X1 = [[1.5, 3, 5.8, 2.2], [6.2, 2.9, 4.3, 1.3]]
# 用最佳模型进行预测并得到预测结果
predict = best_model.predict(X1)
# 获得X1中两个鸢尾花预测得到的索引所对应的类别
X1_classes = [load_iris().target_names[idx] for idx in predict]
print("两个鸢尾花的预测结果为:[1.5, 3, 5.8, 2.2] :{0}, [6.2, 2.9, 4.3, 1.3] :{1}".format(*X1_classes))
#两个鸢尾花的预测结果为:[1.5, 3, 5.8, 2.2] :virginica, [6.2, 2.9, 4.3, 1.3] :versicolor

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