机器学习之监督学习-分类模型K近邻(KNN)算法实现

Posted nuist__NJUPT

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了机器学习之监督学习-分类模型K近邻(KNN)算法实现相关的知识,希望对你有一定的参考价值。

机器学习之监督学习-分类模型K近邻(KNN)算法实现

监督学习中常用的分类分类模型有k近邻,逻辑斯谛回归,决策树。今天我们主要学习,K近邻模型。

最简单,最初级的分类器就是将全部的训练数据所对应的类别都记录下来,当测试对象的属性和某个训练对象的属性完全匹配时,便可以进行分类。

K近邻(KNN)

K近邻是一种基本分类方法,通过测量不同特征值之间的距离进行分类,它的思路是:如果一个样本在特征有k个最相似的大多数属于某一类别,则该样本也属于某一类别,其中K通常是不大于20的整数,KNN算法中所选择的邻居都是已经正确分类的对象。

简单的说KNN就是K个最接近的邻居,它们属于哪一类,我就属于哪一类。

下面我们看一个KNN示例:如下图所示,绿色的圆形需要被判断赋予哪个类,是红色三角形还是蓝色四边形呢?
如果取K=3,需要寻找和它最接近的三个邻居去判断分类,那么红色三角形所占比例为三分之二,就要把绿色圆形赋予红色三角形类,当然,如果取K=5,则蓝色四边形所占比例为五分之三,则应该把绿色圆形赋予给蓝色四边形类。
由此,我们可以看出,KNN算法很大程度上取决于K的选择。

KNN算法中,通过计算各个对象之间的距离作为各个对象的非相似性指标,避免了对象之间的匹配问题,一般使用欧式距离或者曼哈顿距离,同时,KNN通过依据k个对象中占优的类别进行决策,而不是单一的对象类别决策。

在训练集中数据和标签已知的情况下,输入测试数据,将测试数据的特征与训练集中的特征进行比较,找到训练集中与之最为相似的K个数据,则该测试数据对应的类别就是K个数据中出现次数最小的那个分类。

KNN算法的具体描述:

1-计算测试数据与各个训练数据之间的距离

2-按照距离递增的关系进行排序

3-选取距离最小的K个点

4-确定前K个点出现类别的频率

5-返回前K个点中出现频率最高的类别作为该测试数据的预测分类

注意:我们在此次实验中使用了sklearn库中的鸢尾花数据集,sklearn库中常用的数据集如下:

python代码实现如下:
我使用的pychram实现的,需要在该软件中下载安装机器学习库到本地,才能引入依赖并使用,相应的demo同步上传到了github,github链接如下:https://github.com/wgdwg/-K-KNN-


#引入依赖
import  numpy as np
import pandas as pd

#数据的加载和预处理,这里直接引入sklearn的数据集
from sklearn.datasets import load_iris #导入鸢尾花数据集
from sklearn.model_selection import  train_test_split #切分数据集与训练集与数据集
from sklearn.metrics import  accuracy_score #计算分类预测准确度的

iris = load_iris() #加载数据集,data数据相当于x,target相当于y,取得离散值0,1,2表示每个样本点对应的类别,
df = pd.DataFrame(data=iris.data, columns=iris.feature_names)
df['class'] = iris.target #增加一列类别class
#将对应的0,1,2改成对应的分类的花名
df['class'] = df['class'].map(0:iris.target_names[0], 1:iris.target_names[1], 2:iris.target_names[2])
x = iris.data
y = iris.target.reshape(-1,1) #转换成二维列向量

#划分训练集与测试集
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.3, random_state=35, stratify=y) #测试集占比30%,按照y等比例分层,x随机

#核心算法实现
#定义距离函数
def l1_distance(a, b):
    return np.sum(np.abs(a-b), axis=1)
def l2_distance(a,b):
    return np.sqrt(np.sum((a-b)**2,axis=1))

#分类器的实现
class KNN(object):
    #定义类的构造方法
    def __init__(self, n_neighbors=1, dis_fun=l1_distance):
        self.n_neighbors = n_neighbors
        self.dis_fun = dis_fun

    #训练模型的方法
    def fit(self, x, y):
        self.x_train =  x
        self.y_train = y

    #预测模型的方法
    def predict(self, x):
        #初始化预测分类数组
        y_pred = np.zeros((x.shape[0],1), dtype=self.y_train.dtype)
        #遍历输入的x个测试点,取出每个数据点的序号i和数据x_test
        for i, x_test in enumerate(x):
            #1.x_test要跟所有训练数据计算距离
            distance = self.dis_fun(self.x_train, x_test)
            #2.得到的距离按照由近到远排序,从近到远对应的索引
            nn_index = np.argsort(distance)
            #3.选取距离最近的k个点,保存它们的对应类别
            nn_y = self.y_train[nn_index[:self.n_neighbors]].ravel()
            #4.统计类别中出现频率最高的,赋给y_pred
            y_pred[i] = np.argmax(np.bincount(nn_y))
        return y_pred

#测试

'''knn = KNN(n_neighbors=3)
#训练模型
knn.fit(x_train, y_train)
#模型预测
y_pred = knn.predict(x_test)
#求出预测准确率
accuracy = accuracy_score(y_test, y_pred)
print("预测准确率:", accuracy)'''

knn = KNN()
#训练模型
knn.fit(x_train, y_train)
#保存结果
result_list = []
#针对不同的参数选取,做预测,两个不同的距离计算
for p in [1, 2]:
    knn.dis_fun = l1_distance if p==1 else l2_distance
    #考虑到不同的k值,尽量选奇数,所以步长为2
    for k in range(1,10,2):
        knn.n_neighbors = k
        #预测
        y_pred = knn.predict(x_test)
        #计算准确率
        accuracy = accuracy_score(y_test, y_pred)
        result_list.append([k, 'l1_distance' if p==1 else '2_distance', accuracy])
df = pd.DataFrame(result_list, columns=['k', '距离函数', '准确率'])
print(df)

我选择了奇数个K值,使用了欧氏距离和哈曼顿距离公式,并做了对比分析,运行结果如下,由此可以看出并不是K值越大越好,当K=5时,此模型的预测能力最好。

以上是关于机器学习之监督学习-分类模型K近邻(KNN)算法实现的主要内容,如果未能解决你的问题,请参考以下文章

机器学习之K近邻算法

机器学习之分类方法K近邻(KNN)

机器学习之K-近邻算法

机器学习之K-近邻(KNN)算法

机器学习之Knn(K-近邻算法)

监督学习算法_k-近邻(kNN)分类算法_源代码