最近邻算法(KNN)

本文介绍了K近邻(KNN)算法,重点讨论了在K=1时的最近邻算法。文章阐述了如何创建节点类,运用KNN算法确定测试实例的类别,并通过多数投票决定分类。针对数据集中数值属性的差异对距离计算的影响,采用了规范化处理,以消除大型数值的权重,从而提升结果精度至0.58。作者提到KNN算法的优化空间有限,主要在于属性选择和距离度量方式,但实验中尝试剔除部分属性并未带来显著改善。此外,程序执行效率较低,有进一步优化的潜力。文章最后提到了字符类属性的处理建议,并给出了优化后的代码实现。
摘要由CSDN通过智能技术生成

【算法分析】

KNN是本次实验第一个需要实现的方法,不算太难,但是要求是k=1,或者代码中根据测试集来自动识别最好的k值。本次实现只是采用了k=1的情况。

何谓K近邻算法,即K-NearestNeighbor algorithm,简称KNN算法, K个最近的邻居,当K=1时,算法便成了最近邻算法,即寻找最近的那个邻居。也即是给定一个训练数据集,对新的输入实例(或者说是给定的数据集),在训练数据集中找到与该实例(数据集)最邻近的K个实例,这K个实例的多数属于某个类,就把该输入实例分类到这个类中。

1、编写       节点类,记录k个临近数据的相关值。

 

2、KNN算法处理,获取测试元组的类别

        

3、根据所得到的k个邻近的数据,获取类别最多的那个类别

(特殊情况:本次k只能等于1,所以只有一个类别)

 

【优化处理】

         分析:前面分析得到,数据集所提供的属性都是数值型的,但是他们又不属于同一个类别,比如说有些是比例型的,有些是个数型的,这样必然会出现大型数据对数据间的欧式距离产生很大的影响(测试的结果只能达到0.55),所以为了消除这种影响,本次实验用了对所有属性值做规范化的处理,value = (value – min) / ( max – min ) ,那么得到的值也都在0~1之间,消除了大型数值的影响。最后达到0.58.

        过程:通过遍历训练集,用数组保存每一个属性的最大值和最小值,最后在统一做规范化处理。

                           

利用value = (value – min) / (max – min )做规范化处理后再计算距离:

max[0] = 19.0

min[0] = 2.0

max[1] = 8474.0

min[1] = 0.0

max[2] = 0.999999967

min[2] = 0.0

max[3] = 1.0

min[3] = 0.0

max[4] = 0.999999986

min[4] = 0.0

……

……

max[54] = 1.0

min[54] = 0.0

max[55] = 1.0

min[55] = -1.0

max[56] = 0.5

min[56] = 0.0

max[57] = 1.0

min[57] = 0.0

max[58] = 1.0

min[58] = 0.0

【实验思考和总结】

          KNN算法比较常规,优化空间不大,除了在选取欧式距离、曼哈顿距离和切比雪夫距离之间做取舍之外,也就只能在属性上做功夫。

           本次实验选取其他距离来做的话,不切实际,所以我在实验过程中,尝试了下剔除掉“最大最小”关联的属性,只保留“平均”属性,但是得到的结果是0.57,显然不能剔除这些属性,所以至今认为最大的优化空间就是对数值属性做规范化了。

          实验采用java编写,每次执行一次程序,花费了10+mins,个人认为程序跑的太慢,开销太大,在这方面可以继续优化。

          本次实验提供的属性都是数值型的,所以为统一做规范化提供了便利性,倘若属性有数值型的和字符类的,那么对字符类的属性要另加思考,如果说该属性的分类标签不多,可以不做处理,但是如果分类标签太多的话,那么可以举一反三,给相近的标签做归类处理,举个例子:

{ {(苹果),(香蕉),(桔子)};{(奶茶),(咖啡)}}

虽然都属于“食物” 的属性,但是对其还是可以做归类处理的。



下面是参考网上代码优化实现的代码:


package KNN;  
import java.io.BufferedReader;  
import java.io.File;  
import java.io.FileOutputStream;
import java.io.FileReader;  
import java.util.ArrayList;  
import java.util.List;  
/** 
 * KNN算法测试类 
 */  
public class TestKNN {  
      
    /** 
     * 从数据文件中读取数据 
     * @param datas 存储数据的集合对象 
     * @param path 数据文件的路径 
     */  
	

    
    public void read(List<List<Double>> datas, String path){  
        try {  
            BufferedReader br = new BufferedReader(new FileReader(new File(path)));  
            String data = br.readLine();  
            List<Double> l = 
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值