分享

KNN算法Hadoop实现及kaggle digit recognition数据测试


问题导读

1.Hadoop实现KNN算法,如何设计mapper和reducer?
2.Mapper函数包含哪三个函数?
3.Combiner是如何设计的?






软件版本:
Hadoop2.6,MyEclipse10.0 , Maven 3.3.2

源码下载地址:https://github.com/fansy1990/knn

1. KNN算法思路如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类别。KNN算法中,所选择的邻居都是已经正确分类的对象。该方法在定类决策上只依据最邻近的一个或者几个样本的类别来决定待分样本所属的类别。-- 摘自《邻近算法》,百度百科

2. KNN算法MR实现:

Hadoop实现KNN算法,最主要的就是设计Mapper和Reducer,使数据流可以套用Hadoop的MR框架,即<K1,V1>--> <K2,V2>  , <K2,List<V2>>--> <K3,V3>;

2.1.Mapper设计Mapper 有三个函数setup(),map(),cleanup(),其中setup()函数在最开始运行一次,cleanup函数在最后运行一次,map函数针对每条记录每次处理一次;这里输入文件设置为训练数据集,即如下格式:
Label,x1,x2,...,xn
第一列为样本类别,其他列为样本属性;
1)在setup()函数中读取测试数据,测试数据格式如下:
x1,x2,...,xn
同时初始化一个和测试数据容量大小一样的数组List<Type,Distance>,用于存储每个测试样本的近邻数据。近邻数据包含k个样本类别以及对应的距离;
2)接着,在map函数中读取每个训练样本,针对训练样本,来更新所有测试样本的邻近数据,即List<Type,Label>,最开始初始化Type=[-1,-1,-1,...,-1],Label=[MaxDouble,MaxDouble,...,MaxDouble].
更新具体做法:
当前训练样本数据tr_i以及类别tr_type,当前测试样本te_i,以及对应的te_i_<type[],distance[]>,
a. 计算tr_i和te_i的距离distance_tr_te;
b. 遍历te_i_<type[],distance[]>的distance[]
        find distance[]中最大的max_distance以及下标index_max_distance;
                if max_distance> distance_tr_te then
                   //替换
                   distance[index_max_distance]=distance_tr_te;
                   type[index_max_distance]=tr_type;
                end
    end
3) 最后,在cleanup()函数中,输出List<Type,Lable>中的每一条记录,这里默认test的数据是一个文件,所以这里可以直接使用List的下标代表每一个数据;即最后Mapper的输出为<id,<type[],distance[]>>,每个id代表一个测试数据,<type[],distance[]>代表当前测试数据的邻近类别以及对应的距离;

2.2.Reducer设计 Reducer 只设计reduce函数即可,reduce函数需要做的就是针对同一个测试样本id,统计汇总后的邻近类别以及对应的距离数据,同时需要再次整理这些数据,保留距离最小的k个类别值;然后同时这个k个类别的众数,即最后测试样本id的类别值,输出即可;

2.3. Combiner设计Combiner,这里可以添加一个Combiner操作,Combiner操作就是map端的reduce操作,可以先把数据汇总一次,然后再发往reducer端,减少网络IO。Combiner需要输入/输出的格式一直,即输入为<id,<type[],distance[]>>,输出也需要是这样的格式。这里可以把reducer的汇总整理代码直接拷贝过来即可,同时需要注意这里就不需要求众数了。
3. 测试数据使用Kaggle中的digit recognition的数据;数据下载:https://www.kaggle.com/c/digit-recognizer/data
在测试算法时,首先截取了较少的数据进行测试,测试数据18个样本,训练样本第一次50多个样本,第二次8.9M(约5k左右样本)的样本;
得到的结果对比:


1.png              2.png

上面的测试数据使用训练数据截取类别得到的,上面两张图左边是预测的结果,右边是实际类别。从图1中可以看到(训练数据比较少)其预测准确率很低,但是在训练数据量增加后(图2的8.9M)时就有很好的预测效果了(准确率为100%);

使用上面的算法来对kaggle的数据进行测试(训练集70M,测试集40M),数据可以从上面的url中下载;
Hadoop集群情况:


本地集群情况:
node101  (主节点,namenode,datanode,ResourceManager,NodeManager,SecondaryNamenode,3.7G,2核)
node102  (数据/计算节点,datanode,NodeManager,1G,1核)

上面两个机器是虚拟机,本机是windows7系统4核8G内存;
耗时:

3.png

得到的预测结果,提交到Kaggle官网,可以得到预测的准确率,如下:

4.png

准确率为92%左右,同时可以看到排名为557,这个很后了。


4. 总结1. knn算法由于需要计算全部训练数据集以及测试数据集的距离,所以算法比较耗时(这里可以看到一共有110M的数据耗时11小时左右),这里没有对该算法进行调优,可以参考国外的一些论文对此进行修改,比如《Efficient Parallel kNN Joins for Large Data in MapReduce》;
2. 不同数据针对的问题不一样,这里kaggle的数字识别,一般会使用随机森林来做;

分享,成长,快乐
脚踏实地,专注
转载请注明blog地址:http://blog.csdn.net/fansy1990


已有(2)人评论

跳转到指定楼层
tang 发表于 2015-7-29 09:02:06
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

推荐上一条 /2 下一条