KNN分类器

来源:互联网 发布:php 5.3 is required 编辑:程序博客网 时间:2024/06/06 11:45

  转载请声明出处:http://blog.csdn.net/zhongkejingwang/article/details/44132771

   KNN即K-Nearest Neighbor,是数据挖掘中一种最简单的分类方法,即要判断某一个样本属于已知样本种类中的哪一类时,通过计算找出所有样本中与测试样本最近或者最相似的K个样本,统计这K个样本中哪一种类最多则把测试样本归位该类。如何衡量两个样本的相似度?可以用向量的p-范数来定义。

假设有两个样本X=(x1, x2, ..., xn),Y=(y1, y2, ..., yn),则他们之间的相似度可以用以下向量p-范数定义:

                

当p=2时即为计算X、Y的欧几里得距离。

  本文将介绍用Java实现KNN分类器对Iris数据进行分类。Iris数据如下:


  前面四个item是属性,最后一个是类别名,总共有三类。完整的数据集可点击这里下载

拿到原始数据后为了测试KNN分类效果,需要在原始数据中随机抽取一部分作为测试集,另一部分作为训练集。随机抽取的方法可以用下面代码实现:

/** * 将数据集划分为训练集和测试集,随机划分 *  * @param filePath *            数据集文件路径 * @param testCount *            测试集个数 * @param outputPath *            输出路径 * @throws Exception */public static void splitDataSet(String filePath, int testCount,String outputPath) throws Exception{BufferedWriter trainFile = new BufferedWriter(new FileWriter(new File(outputPath + "/train.txt")));BufferedWriter testFile = new BufferedWriter(new FileWriter(new File(outputPath + "/test.txt")));BufferedReader input = new BufferedReader(new FileReader(new File(filePath)));List<String> lines = new ArrayList<String>();String line = null;//将所有数据读取到一个List里while ((line = input.readLine()) != null)lines.add(line);//遍历一次List,每次产生一个随机序号,将该随机序号和当前序号内容进行交换for (int i = 0; i < lines.size(); i++){int ran = (int) (Math.random() * lines.size());String temp = lines.get(i);lines.set(i, lines.get(ran));lines.set(ran, temp);}int i = 0;//将指定数目的测试集写进test.txt中for (; i < testCount; i++){testFile.write(lines.get(i) + "\n");testFile.flush();}//剩余的写进train.txt中for (; i < lines.size(); i++){trainFile.write(lines.get(i) + "\n");trainFile.flush();}testFile.close();trainFile.close();}

  调用这个方法后就可以得到train.txt和test.txt两份数据了。

  接下来将数据读入:

/** * 根据文件生成训练集,注意:程序将以第一个出现的非数字的属性作为类别名称 *  * @param fileName *            文件名 * @param sep *            分隔符 * @return * @throws Exception */public List<DataNode> getDataList(String fileName, String sep)throws Exception{List<DataNode> list = new ArrayList<DataNode>();BufferedReader br = new BufferedReader(new FileReader(new File(fileName)));String line = null;while ((line = br.readLine()) != null){String splits[] = line.split(sep);//DataNode类用于保存数据属性和数据类别DataNode node = new DataNode();int i = 0;for (; i < splits.length; i++){try{node.addAttrib(Float.valueOf(splits[i]));} catch (NumberFormatException e){// 非数字,则为类别名称,将类别映射为数字if (!mTypes.containsKey(splits[i])){mTypes.put(splits[i], mTypeCount);mTypeCount++;}node.setType(mTypes.get(splits[i]));list.add(node);}}}return list;}
对于testList中的每一个样本,均与所有trainList中的样本进行计算,取出最接近的K个样本并返回:

KnnClassifier.java

package com.jingchen.knn;import java.util.List;/** * @author chenjing *  */public class KnnClassifier{//k个近邻节点private int k;private KNode[] mNearestK;private List<DataNode> mTrainData;public KnnClassifier(int k, List<DataNode> trainList){mTrainData = trainList;this.k = k;mNearestK = new KNode[k];for (int i = 0; i < k; i++)mNearestK[i] = new KNode();}public void setK(int k){this.k = k;mNearestK = new KNode[k];for (int i = 0; i < k; i++)mNearestK[i] = new KNode();}private void train(DataNode test, float p){for (int i = 0; i < mTrainData.size(); i++){putNode(getSim(test, mTrainData.get(i), p));}}/** * 将新计算出来的节点与k个近邻节点比较,如果比其中之一小则插入 * @param node */private void putNode(KNode node){for (int i = 0; i < k; i++){if (node.getD() < mNearestK[i].getD()){for (int j = k - 1; j > i; j--)mNearestK[j] = mNearestK[j - 1];mNearestK[i] = node;break;}}}/** * 获取相似度并封装成一个KNode类型返回 * @param test * @param trainNode * @param p * @return */private KNode getSim(DataNode test, DataNode trainNode, float p){List<Float> list1 = test.getAttribs();List<Float> list2 = trainNode.getAttribs();float d = 0;for (int i = 0; i < list1.size(); i++)d += Math.pow(Math.abs(list1.get(i).floatValue() - list2.get(i).floatValue()), p);d = (float) Math.pow(d, 1/p);KNode node = new KNode(d, trainNode.getType());return node;}private void reset(){for (int i = 0; i < k; i++)mNearestK[i].reset();}/** * 返回K个近邻节点 * @param test * @param p * @return */public KNode[] getKNN(DataNode test, float p){reset();train(test, p);return mNearestK;}}

  main方法:

public static void main(String[] args) throws Exception{DataUtil util = DataUtil.getInstance();//获得训练集和测试集List<DataNode> trainList = util.getDataList("E:/train.txt", ",");List<DataNode> testList = util.getDataList("E:/test.txt", ",");int K = BASE_K;KnnClassifier classifier = new KnnClassifier(K, trainList);BufferedWriter output = new BufferedWriter(new FileWriter(new File("E:/output.txt")));int typeCount = util.getTypeCount();int[] count = new int[typeCount];for (int i = 0; i < testList.size();){for (int m = 0; m < typeCount; m++)count[m] = 0;DataNode test = testList.get(i);classifier.setK(K);KNode[] nodes = classifier.getKNN(test, 2);for (int j = 0; j < nodes.length; j++)count[nodes[j].getType()]++;int type = -1;int max = -1;for (int j = 0; j < typeCount; j++){if (count[j] > max){max = count[j];type = j;} else if (count[j] == max){// 存在两个类型分个数相同,无法判断属于哪个类型,增加K的值继续从该节点开始type = -1;K++;break;}}if (type == -1)continue;else{i++;K = BASE_K;}//将分类结果写入文件List<Float> attribs = test.getAttribs();for (int n = 0; n < attribs.size(); n++){output.write(attribs.get(n) + ",");output.flush();}output.write(util.getTypeName(type) + "\n");output.flush();}output.close();}

  经测试,KNN对Iris数据集分类准确率基本都在90+%以上,此分类方法也比较直观。数据集及完整的项目代码可以从这里下载:点击下载。后面介绍的BP神经网络将会把准确率提高到接近100%。




0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 杂志社不给寄论文版面费发票怎么办 学区房因为户籍没满一年怎么办 没学历没技术的年轻人该怎么办? 二十岁没有学历没有技术该怎么办 单位派我去进修我没去怎么办 老师在教育学生学生跑出教室怎么办 孩子遇到校园暴力回来不敢说怎么办 学位网没有英文认证出国留学怎么办 4-5岁幼儿记忆不好该怎么办 2个月宝宝不拉大便怎么办 论文已查重了要下载查重报告怎么办 华为畅享7手机媒体音量小怎么办 杂志投稿投到了假的网站怎么办 支付宝骗了5万多怎么办 微信转账到银行卡被骗了怎么办 给对方转账到银行卡疑似被骗怎么办 谷歌邮箱收不到邮件了怎么办 我在微信上做兼职被骗了钱怎么办 要是微信里面做兼职被骗了怎么办 在打离婚管斯死亡赔常金怎么办 编辑部回复我文章没有被录用怎么办 父亲死后教师资格被别人顶替怎么办 刚发的论文影响因子变化了怎么办 奥鹏毕业论文过了提交时间了怎么办 手机电池被拿出来后时间不准怎么办 高中的孩子与同学相处不好怎么办 孩子在幼儿园不敢和老师说话怎么办 注册过万方医学网忘了用户名怎么办 狗咬了没破皮没出血有点疼怎么办 狗咬了没出血肿起来了怎么办 广州已经过了幼儿园报名时间怎么办 大专学费没交学校开始查了怎么办 如果申请留学的本科成绩不够怎么办 硕士读了三年无法毕业怎么办啊 孩子在美国读研读不下去怎么办? 在地割草中过失死亡法律^怎么办 高中毕业申请国外大学没录取怎么办 英国研究生老师没给写推荐信怎么办 申请悉尼大学博士奖学金被拒怎么办 硕士延迟毕业但被博士录取怎么办 考完初级职称还是不会做账怎么办