实现KNN算法

一、作业题目:

原生Python实现KNN分类算法,用鸢尾花数据集。

二、算法原理:

   KNN算法是选择与输入样本在特征空间内最近邻k个训练样本并根据一定的决策规则,给出输出结果 。

决策规则:

分类任务:输出结果为k个训练样本中占大多数的类 。

回归任务:输出结果为k个训练样本值的平均值 。

三、算法设计:

   (1).数据准备

      选择鸢尾花数据集(lris)每个样本x包含花萼长度(sepal length)、花萼宽度(sepal width)、花瓣长度(petal length)、花瓣宽度(petal width)四个特征。样本标签y共有三类,分别是Setosa,Versicolor和Virginica。Iris数据集总共包含150个样本,每个类别由50个样本。

       数据data应用网上下载数据集。

data = pd.read_csv('iris.data', header=None)
data.columns = [
'sepal length', 'sepal width', 'petal length', 'petal width', 'species'

将三个类别的数据分别提取出来,setosa、versicolor、virginica分别用0、1、2来表示。将每个类别的所有样本分成训练样本(training set)、验证集(validation set)和测试样本(test set),各占所有样本的比例分别为60%,20%,20%。

表示两种类别不同特征的空间分布。选择sepal length和petal length两个特征,在二维平面上作图。

(2) kNN训练函数和预测函数

kNN的训练过程实际上是一种数据标类、数据存储的过程,不包含机器学习算法。首先我们需要定义一个类(class)来实现KNN算法模块。

   kNN距离衡量一般有两种方式:L1距离和L2距离。

K值的选择:k值太小会使模型过于复杂,造成过拟合(overfitting);k值太大会使模型分类模糊,造成欠拟合(underfitting)。在KNearestNeighbor类中定义预测函数通过验证集来验证从而决定K值大小。

   (3)训练和预测

创建KNearestNeighbor实例对象通过测试发现K=3时,验证集准确率最高。最后,把预测结果绘图表示。依然选择sepal length和petal length两个特征,在二维平面上作图。

四、源代码

import numpy as np

import pandas as pd

import matplotlib.pyplot as plt



data = pd.read_csv('iris.data', header=None)

data.columns = ['sepal length', 'sepal width', 'petal length', 'petal width', 'species']    # 特征及类别名称

X = data.iloc[0:150, 0:4].values

y = data.iloc[0:150, 4].values

y[y == 'Iris-setosa'] = 0                                 # Iris-setosa 输出label用0表示

y[y == 'Iris-versicolor'] = 1                             # Iris-versicolor 输出label用1表示

y[y == 'Iris-virginica'] = 2                              # Iris-virginica 输出label用2表示

X_setosa, y_setosa = X[0:50], y[0:50]                     # Iris-setosa 4个特征

X_versicolor, y_versicolor = X[50:100], y[50:100]         # Iris-versicolor 4个特征

X_virginica, y_virginica = X[100:150], y[100:150]         # Iris-virginica 4个特征

plt.scatter(X_setosa[:, 0], X_setosa[:, 2], color='red', marker='o', label='setosa')

plt.scatter(X_versicolor[:, 0], X_versicolor[:, 2], color='blue', marker='^', label='versicolor')

plt.scatter(X_virginica[:, 0], X_virginica[:, 2], color='green', marker='s', label='virginica')

#绘制图像
 
plt.xlabel('sepal length')

plt.ylabel('petal length')

plt.legend(loc = 'upper left')

plt.show()



# training set

X_setosa_train = X_setosa[:30, :]

y_setosa_train = y_setosa[:30]

X_versicolor_train = X_versicolor[:30, :]

y_versicolor_train = y_versicolor[:30]

X_virginica_train = X_virginica[:30, :]

y_virginica_train = y_virginica[:30]

X_train = np.vstack([X_setosa_train, X_versicolor_train, X_virginica_train])

y_train = np.hstack([y_setosa_train, y_versicolor_train, y_virginica_train])



# validation set

X_setosa_val = X_setosa[30:40, :]

y_setosa_val = y_setosa[30:40]

X_versicolor_val = X_versicolor[30:40, :]

y_versicolor_val = y_versicolor[30:40]

X_virginica_val = X_virginica[30:40, :]

y_virginica_val = y_virginica[30:40]

X_val = np.vstack([X_setosa_val, X_versicolor_val, X_virginica_val])

y_val = np.hstack([y_setosa_val, y_versicolor_val, y_virginica_val])



# test set

X_setosa_test = X_setosa[40:50, :]

y_setosa_test = y_setosa[40:50]

X_versicolor_test = X_versicolor[40:50, :]

y_versicolor_test = y_versicolor[40:50]

X_virginica_test = X_virginica[40:50, :]

y_virginica_test = y_virginica[40:50]

X_test = np.vstack([X_setosa_test, X_versicolor_test, X_virginica_test])

y_test = np.hstack([y_setosa_test, y_versicolor_test, y_virginica_test])

#实现knn算法模块,定义训练函数

class KNearestNeighbor(object):

   def __init__(self):

       pass



   # 训练函数

   def train(self, X, y):

       self.X_train = X

       self.y_train = y



   # 预测函数

   def predict(self, X, k=1):

       # 计算L2距离

       num_test = X.shape[0]

       num_train = self.X_train.shape[0]

       dists = np.zeros((num_test, num_train))    # 初始化距离函数

       # because(X - X_train)*(X - X_train) = -2X*X_train + X*X + X_train*X_train, so

       d1 = -2 * np.dot(X, self.X_train.T)    # shape (num_test, num_train)

       d2 = np.sum(np.square(X), axis=1, keepdims=True)    # shape (num_test, 1)

       d3 = np.sum(np.square(self.X_train), axis=1)    # shape (1, num_train)

       dist = np.sqrt(d1 + d2 + d3)

       # 根据K值,选择最可能属于的类别

       y_pred = np.zeros(num_test)

       for i in range(num_test):

           dist_k_min = np.argsort(dist[i])[:k]    # 最近邻k个实例位置

           y_kclose = self.y_train[dist_k_min]     # 最近邻k个实例对应的标签

           y_pred[i] = np.argmax(np.bincount(y_kclose.tolist()))    # 找出k个标签中从属类别最多的作为预测类别



       return y_pred

KNN=KNearestNeighbor()

KNN.train(X_train, y_train)

y_pred = KNN.predict(X_test, k=6)

accuracy = np.mean(y_pred == y_test)

print('测试集预测准确率:%f' % accuracy)



# 训练集

plt.scatter(X_setosa_train[:, 0], X_setosa_train[:, 2], color='red', marker='o', label='setosa_train')

plt.scatter(X_versicolor_train[:, 0], X_versicolor_train[:, 2], color='blue', marker='^', label='versicolor_train')

plt.scatter(X_virginica_train[:, 0], X_virginica_train[:, 2], color='green', marker='s', label='virginica_train')

# 测试集

plt.scatter(X_setosa_test[:, 0], X_setosa_test[:, 2], color='y', marker='o', label='setosa_test')

plt.scatter(X_versicolor_test[:, 0], X_versicolor_test[:, 2], color='y', marker='^', label='versicolor_test')

plt.scatter(X_virginica_test[:, 0], X_virginica_test[:, 2], color='y', marker='s', label='virginica_test')



#绘制图像

plt.xlabel('sepal length')
plt.ylabel(
'petal length')
plt.legend(
loc = 4)
plt.show()

五:调试运行过程:

  1. 三种类别不同特征的空间分布:

 

 

 

2)K=3验证集的准确率最高,选择k值后对测试集进行预测分析  ,测试准确率很高。

 

  1. 将测试结果绘制出来

 

 

六:总结:

k近邻算法是一种最简单最直观的分类算法,也很简单。kNN算法的本质是在训练过程中,它将所有训练样本的输入和输出标签(label)都存储起来。可以说KNN算法实际上是一种识记类算法。机器学习算法包括两个过程:训练过程和测试过程。训练过程通过使用机器学习算法在训练样本上迭代训练,得到较好的机器学习模型;测试过程是使用测试数据来验证模型的好坏,通过正确率来呈现。

我在网上学习过程中,学习到了用训练集,预测集以及测试集来来取得更好的k值,让算法正确率更高。

参考:https://zhuanlan.zhihu.com/p/55960501

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值