基于Python语言的KNN算法

import operator
import numpy as np
# 鸢尾花的数据集 load_iris
from sklearn.datasets import load_iris

'''
对测试集中的每个对象 X,依次执行以下操作:
(1)计算训练集中的所有对象与 X 之间的距离;
(2)按照距离递增的次序对训练集中的所有对象进行排序;
(3)选取与 X 距离最小的 K个对象;
(4)确定前 K 个对象所属类别的出现频率;
(5)返回前 K 个对象出现频率最高的类别,作为X的预测分类。
'''
######## 测试集  训练集  训练集对应的标签 几个最小的值
def knn(x_test, x_train, y_train, k):
    #存储测试集预测出来的结果
    predict_result_set=[]
    # 训练集的长度
    train_set_size = len(x_train)

    # 创建一个全零的矩阵,长度为130
    distances = np.array(np.zeros(train_set_size))
    # 计算每一个测试集与每一个训练集的距离
    for i in x_test:
        for indx in range(train_set_size):
            # 计算数据之间的距离 欧式距离公式 来求测试数据到训练数据的距离
            distances[indx] = np.sqrt(sum((i - x_train[indx]) ** 2))
        sorted_dist = np.argsort(distances)
        class_count = {}
        # 取出k个最短距离
        for i in range(k):
            # 获得下标所对应的标签值
            sort_label = y_train[sorted_dist[i]]
            #print(i,sort_label,)
            # get()函数返回指定键的值。
            # 字典形式:key:判断之后的类别-value:有几个
            class_count[sort_label]=class_count.get(sort_label, 0) + 1
        # 对标签进行排序
        sorted_class_count = sorted(class_count.items(), key=operator.itemgetter(1), reverse=True)
        # print(sorted_class_count)
        predict_result_set.append(sorted_class_count[0][0])
    # 返回预测结果列表
    return predict_result_set
##########################################
#简单的数据集进行试验
# 训练集 [打架次数,接吻次数]
trainData = np.array([[3, 104], [2, 100], [1, 81], [101, 10], [99, 5], [98, 2]])
# 标签 代表的类别
labels = ['Romance', 'Romance', 'Romance', 'Action','Action','Action']
# 测试集
testData = [18, 90]
############################################
# KNN算法是最近邻算法的一个延伸。基本思路:选择未知样本一定范围内的K个近邻样本,如果该K个近邻大多数属于某一类型,则未知样本就判定为该类型。
# KNN 可以说是一种最直接的用来分类未知数据的方法。
# 采用少数服从多数的原则,给新数据归类.

if __name__ == "__main__":
    # 加载数据集数据
    iris = load_iris()
    # 样本数据150*4二维数据,代表150个样本,每个样本4个属性分别为花瓣和花萼的长、宽
    iris_x = iris.data
    # permutation接收一个数作为参数(150),产生一个0-149一维数组,只不过是随机打乱的,当然她也可以接收一个一维数组作为参数,结果是直接对这个数组打乱
    indices = np.random.permutation(len(iris_x))
    # 样本数据的标签
    iris_y = iris.target
    # x 数据
    # y 对应的标签
    x_train, x_test, y_train, y_test = iris_x[indices[:-20]],iris_x[indices[-20:]],iris_y[indices[:-20]],iris_y[indices[-20:]]
    # 调用前面定义的knn函数   6代表距离最近的6个 按照少数服从多数的原则进行“定义“
    result = knn(x_test,x_train, y_train, 6)
    print("原有标签:", y_test)
    # 为了方便对比查看,此处将预测结果转化为array,可直接打印结果
    print("预测结果:", np.array(result))

'''
优点
(1)算法思路较为简单,易于实现;
(2)当有新样本要加入训练集时,无需重新训练(即重新训练的代价低);
(3)算法的时间复杂度和空间复杂度与训练集的规模呈线性关系(在一些场合不算太大)。
不足
(1)分类速度慢;
整个算法的时间复杂度可以用O(m*n)表示,其中m是训练集的属性(特征)个数,而n是训练集的对象个数
(2) 各属性的权重相同,影响了准确率;
(3) 各类样本的数量不平衡时,也会影响预测准确率;
(4)K值不好确定;
'''
'''
KNN的一些改进策略
如果在使用KNN算法之前对样本的属性进行约简,删除那些对分类结果影响较小(不重要)的属性,则可以用KNN算法快速地预测待分类样本的类别,从而可以得到更好的计算效果。
缩小不相关的训练样本
'''

结果:

 

posted @ 2021-11-10 12:55  我太想努力了  阅读(124)  评论(0)    收藏  举报