【算法分析】
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 =