machine_learning-knn算法详解(近邻算法)

近邻算法是机器学习算法中的入门算法,该算法用于针对已有数据集对未知数据进行分类


该算法核心思想是通过计算预测数据与已有数据的相似度推测结果。

举例:
假设有如下一组数据(在以下我们统一把该数据作为训练数据):

身高年龄国籍
17023中国
18021美国
18522俄国
17524中国
120 23日本

我们将该组数据的前两列作为一个特征值,最后一项作为一个待分类结果,当数据量足够大时,可以通过该数据便可得出较为精确的分类。

例如我们拿到测试数据,年龄23岁,身高172,需要预测其国籍。

一般预测的方法是通过特征值求测试数据与训练数据中各项的差异(求点与点之间的距离),当有x,y两项特征值时,则距离为


注:xA0为测试数据第一特征值(身高),xB0为训练数据第一特征值(身高),xA1为测试数据第二特征值(年龄),xB1为训练数据第二特征值(年龄)

同理,当特征项有3项时,则为(xA0 - xB0)的平方加上(xA1 - xB1)的平方再加上(xA2 - xB2)的平台,再开平方根,这个就是数学中求空间内两个点的距离


距离最近的训练数据则为特征最为相似的数据,该训练数据的分类则是分类可能性最大的结果

因为数据过少,我们简单可以看出,通过年龄和身高进行匹配,最为相似的数据就是以下这一条。

17023中国

在训练数据较大时,需要程序进行比对分类,程序的一般逻辑是通过训练数据集中的各项数据与测试数据进行距离计算,求出最为相似的数据,但是这样对数据准确性的依赖太强,所以引入了近邻的概念,则是通过最为相似的N个数据,求出这N个数据中出现概率最高的分类则是近邻算法的结果,在本文中使用python和numpy库实现近邻算法。


# train_data为训练数据集的特征值(在本次训练数据集中为[[170, 23], [180, 21], [185, 22], [175, 24], [120, 23]])

# type_set为训练数据集分类,与train_data顺序相对应的(在本次训练数据集中为[中国,美国,俄国,中国,日本])

# test_data为需要分类的测试数据([172, 23])

# k则为上面所述的N值

import numpy as np

def forecast_data_type(train_data, type_set, test_data, k):

    # 求出train_data长度,matrix类型的shape是矩阵各维度长度,例如[[1,2,3],[4,5,6]]为(2,3)

    train_data_size = train_data.shape[0]

    # 首先把test_data转换成与train_data一样的格式[[172,23], [172,23],[172,23], [172,23],[172,23]]

    test_data_set = np.tile(test_data, (train_data_size,1))

    # 求出train_data和test_data_set的差(结果为[[x1A0-x1A1,x1B0-x1B1], ......, [x4A0-x4A1,x4B0-x4B1]])

    data_diff = train_data - test_data_set

    # 对差值求平方(这个地方我用matrix来求平方不得行,所以我先转成了array)

    data_diff_pow = np.mat(np.asarray(data_diff) ** 2)

    # 将平方值相加

    data_diff_pow_sum = data_diff_pow.sum(axis=1)

    # 求平方根,a的平方根就是a的1/2次方,得出距离(类似[[1.22], [0.31], [0.444]......])

    distances = np.mat(np.asarray(data_diff_pow_sum) ** 0.5)

    # 对结果进行排序,注意,argsort的返回值是原数据索引列表

    # 例如old_data是[1, 3, 5, 2, 4],sorted_data是[1, 2, 3, 4, 5],

    # sorted_data[0]对应old_data[0]

    # sorted_data[1]对应old_data[3]

    # sorted_data[2]对应old_data[1]

    # sorted_data[3]对应old_data[4]

    # sorted_data[4]对应old_data[2]

    # 则argsort返回 [0, 3, 1, 4, 2],这个地方的axis=0是因为原来的数据不是[1, 2, 3, 4]而是[[1], [2], [3], [4]],如果不加这个参数则会返回[[0], [0], [0]]这种

    sorted_distance = distances.argsort(axis=0)

    # 通过给定的k值选择最为相似的k个数据,我这边用了collections库的Counter

    list_result = []

    for i in range(k):

        # sorted_distance 是 [[2], [1], [4]...]

        list_result.append(type_set[sorted_distance [i][0]])

    count_result = Counter(list_result)

 
 

    count_result是一个有序dict,按照count的大小进行数据排序,例如{'a': 3, 'b': 2, 'c': 2}

    count_result的第一项就是分类的结果

 

注意: 

1.该算法较为依赖训练数据集的大小,在一定范围内,训练数据量越大得到的结果最准确。

2.k值比较关键,当k值过大和过小时数据准确性都会受到影响。

3.当特征值的某一项差异太大时,例如a特征的值为1,2,3,4这样,b特征的值为1000,2000,3000这样,b特征对整体判断的影响较大,这个时候就应该对所有特征值做归一化处理,归一化方法如下

归一化值 = (数据特征值 - 最小特征值) / (最大特征值 - 最小特征值) ------这样得出的特征值会<=1

例如c特征为 1000, 2000, 3000, 4000, 5000

最小特征值为1000,最大特征值为5000

那么如果值为3000,那么归一化后的特征值为 (3000 - 1000) / (5000 - 1000) 为 0.5


参考资料:

1.<<机器学习实战>>


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值