机器学习一:KNN算法

一、KNN学习

  K近邻学习是一种常用的监督学习方法,是“懒惰学习”的代表,仅在训练阶段把样本保存起来,训练时间开销为零,待收到测试样本后再进行处理。工作机制很简单:
  1.分类任务:可使用“投票法”,即选择这K个样本中出现的最多的类别作为预测结果;
  2.回归任务:可使用“平均法”,即将K个样本出现的实值输出的标记的平均值作为预测结果;也可以基于距离远近加权平均或加权投票,距离越近的样本权重越大。
  在K近邻算法中,当训练集、距离度量(如欧氏距离)、K值的选择及分类决策规则(如“投票法”)确定后,对于任何一个新的输入实例,它所属的类也会唯一的确定。
  K值选择过小:
  (a)容易受到噪声影响 ;
  (b)模型变得复杂,容易过拟合。
  K值选择过大:
  (a)模型变得简单,欠拟合。
  一般使用交叉验证的方法来选取最优的K值。
交叉验证的步骤:
  1.将数据集分为n段(如:1,3,5…),每一段再分为训练集和测试集;
  2.对这n段的数据进行KNN的训练;
  3.将得到的准确率相加再除以n,得到KNN模型训练之后的准确率;
  4.比较所有的n(如:1,3,5…),准确率最高的KNN最终的K值选择。

二、代码实现

代码如下

import numpy as np
import pandas as pd

def txt2mat(path):
    '''
        将txt文件中的数据变为features和label
    '''
    label = []
    with open(path, 'r', encoding = "utf-8") as f:
        lines = f.readlines()
    feature = np.zeros((len(lines), 3))
    for index, it in enumerate(lines):
        it = it.strip().split('\t')
        feature[index, :] = it[:3]
        label.append(it[-1])
    assert len(feature) == len(label)
    return feature, label

def autoNorm(feature):
    '''
        标准化
    '''
    minval = feature.min(0) # 每列的最小值
    maxval = feature.max(0) # 每列的最大值
    norm_df = np.zeros((len(feature), len(feature)))
    norm_df = feature - np.tile(minval, (len(feature), 1))
    norm_df = norm_df / np.tile(maxval - minval, (len(feature), 1))
    return norm_df

def train(feature, label):
    errornum = 0.0
    number = int(0.1 * len(feature))
    #前number个数据作为测试集,后len(feature)-number个数据作为训练集
    for i in range(number):
        pri_number = knn(feature[i, :], feature[number:len(feature), :], label[number:len(feature)], 3)
        print(f"the classifier came back with:{pri_number},the real answer is:{label[i]}")       
        if pri_number != label[i]: 
            errornum += 1.0
    print(f"the total error rate is:{errornum / float(number)}")


def knn(inx, features, labels, k):
    '''
        inx: 需要预测的数组,用的是欧氏距离
    '''
    datasize = features.shape[0] # 多少行数据,也就是有多少条数据
    # np.title(inx, (a, b)) 数组inx在沿行方向复制a次,沿列方向复制b次
    # 将数组inx复制和features一样的矩阵,并求出他们之间的差值
    # 这一步的意义也就是将数组inx和features中的每条数据求差值
    diffmat = np.tile(inx, (datasize, 1)) - features
    sqdiffmat = diffmat ** 2
    distances = (sqdiffmat.sum(axis = 1)) ** 0.5 # 求和
    index_ = distances.argsort() # 将distances的值按照从小到大的顺序将对应的索引输出
    
    
    # 输出前k个数据的标签以及各个标签占据的总个数
    classcount = {}
    for i in range(k):
        votelabel = labels[index_[i]]
        classcount[votelabel] = classcount.get(votelabel, 0) + 1

    # 按照value值从大到小进行排序
    result = sorted(
        classcount.items(),
        key = lambda x: x[1],
        reverse = True
    )

    return result[0][0]
        


if __name__ == "__main__":
    feature, label =txt2mat('knn/datingTestSet.txt')
    norm_df = autoNorm(feature)
    train(norm_df, label)

三、数据链接

代码以及数据链接

四、参考资料

  1. 《机器学习》,周志华
  2. 《统计学习方法(第二版)》,李航
  3. 《机器学习实战》,Peter Harrington
  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值