# 基于Mapreduce的KNN实现
## 项目介绍
- 该项目实现了KNN算法在Hadoop平台基于***欧拉距离***,***加权欧拉距离***,***高斯函数***的MapReduce实现。
- 特色或创意:在网上KNN实现的例子上添加了基于***欧拉距离***,***加权欧拉距离***,***高斯函数***的实现。
- 解决的问题来自[http://archive.ics.uci.edu/ml/datasets/Iris](http://archive.ics.uci.edu/ml/datasets/Iris)。
使用的是著名的鸢尾花数据集。据集内包含 3 类共 150 条记录,每类各 50 个数据,每条记录都有 4 项特征:花萼长度、花萼宽度、花瓣长度、花瓣宽度,可以通过这4个特征预测鸢尾花卉属于(iris-setosa, iris-versicolour, iris-virginica)中的哪一品种。
训练集中数据为:属性值1,属性值2,.......,标签
测试集中数据为:属性值1,属性值2,......., 正确标签
## 运行方法
- 运行程序时需要输入 **hadoop jar KNN.jar KNN train/iris_train.csv output**
- 执行普通KNN需要把加权KNN和高斯函数注释掉
- 执行加权KNN请把KNN和高斯函数注释掉
- Reduce里也要相应地注释掉
## 部署文件
部署hadoop只需按照实验二再过一遍就行了,此处我直接采用超算习堂的环境进行实验。
## 代码描述
### mapper
mapper的任务是读取测试集并计算测试样本与训练集样本的相似度。
- setup负责将测试集数据读入进来,每一行存为一个list,再将这些list存入一个测试集list中(即ArrayList<ArrayList<Float>>)
```java
protected void setup(org.apache.hadoop.mapreduce.Mapper<Object, Text, Text, Text>.Context context) throws java.io.IOException, InterruptedException {
// load the test vectors
FileSystem fs = FileSystem.get(context.getConfiguration());
BufferedReader br = new BufferedReader(new InputStreamReader(fs.open(new Path(context.getConfiguration().get(
"org.niubility.learning.test", "./test/iris_test_data.csv")))));//读取该路径下的测试集
String line = br.readLine();
int count = 0;
while (line != null) {//按行读取
String[] s = line.split(",");//以,分割
ArrayList<Float> testcase = new ArrayList<Float>();
for (int i = 0; i < s.length-1; i++){
testcase.add(Float.parseFloat(s[i]));//存储到list中
}
test.add(testcase);//将存储每一行的list放到另一个list中
line = br.readLine();
count++;
}
br.close();
}
```
- map负责计算测试样本与训练集样本距离
```java
public void map(Object key, Text value, Context context) throws IOException, InterruptedException
{
//key是训练数据行号
context.setStatus(key.toString()); //设置
String[] s = value.toString().split(",");//将value按‘,’分开
String label = s[s.length - 1]; //标签存储在行的最后一个
for (int i=0; i<test.size(); i++){//遍历test
ArrayList<Float> curr_test = test.get(i);//读取每一行的list
double tmp = 0;
for(int j=0; j<curr_test.size(); j++){
//计算所有训练集距离 x^2+y^2+...
tmp += (curr_test.get(j) - Float.parseFloat(s[j]))*(curr_test.get(j) - Float.parseFloat(s[j]));
}
context.write(new Text(Integer.toString(i)), new Text(Double.toString(tmp)+","+label)); //测试样例编号,所有训练集距离&标签
}
}
```
### combiner
combiner中设定k值,即排序选择前k个,并取其中最多的作为结果。然后分别根据欧拉距离,加权欧拉距离,高斯函数得到结果。
```java
public static class KNNCombiner extends Reducer<Text, Text, Text, Text>
{
public void reduce(Text key, Iterable<Text> values, Context context) throws IOException, InterruptedException
{
ArrayList<Dis_Label> dis_Label_set = new ArrayList<Dis_Label>();
for (Text value : values){
String[] s = value.toString().split(","); //拆开所有 距离+标签
Dis_Label tmp = new Dis_Label();
tmp.label = s[1];
tmp.dis = Float.parseFloat(s[0]);//转为float
dis_Label_set.add(tmp);//加入list中
}
//排序
Collections.sort(dis_Label_set, new Comparator<Dis_Label>(){
@Override
public int compare(Dis_Label a, Dis_Label b){
if (a.dis > b.dis){
return 1; //小的在前
}
return -1;
}
});
final int k = 5; //K值
········
}
}
```
其中三种计算方法对应的操作如下:
```java
//统计前K个最近样例的标签 KNN
for (int i=0; i<dis_Label_set.size() && i<k; i++){
context.write(key, new Text(dis_Label_set.get(i).label));
}
//KNN end
```
```java
//加权KNN
HashMap<String, Double> label_dis = new HashMap<String, Double>(); //label , confidence
for (int i=0; i<dis_Label_set.size() && i<k; i++){
String cur_l = dis_Label_set.get(i).label;
if (!label_dis.containsKey(cur_l)) label_dis.put(cur_l, 0.0);
label_dis.put(cur_l, label_dis.get(cur_l) + 1.0/(0.5+dis_Label_set.get(i).dis));
}
for (String l:label_dis.keySet()){
context.write(key, new Text(Double.toString(label_dis.get(l))+","+l));
}
//加权KNN End
```
```java
//高斯函数
HashMap<String, Double> label_dis = new HashMap<String, Double>(); //label , confidence
for (int i=0; i<dis_Label_set.size() && i<k; i++){
String cur_l = dis_Label_set.get(i).label;
if (!label_dis.containsKey(cur_l)) label_dis.put(cur_l, 0.0);
label_dis.put(cur_l, label_dis.get(cur_l) + Math.exp(Math.pow(dis_Label_set.get(i).dis,2)/0.5));
}
for (String l:label_dis.keySet()){
context.write(key, new Text(Double.toString(label_dis.get(l))+","+l));
}
//高斯函数 End
```
实际运行时,需要注释掉其他两种计算。
### reducer
reducer就是将结果进行输出,获取其对应的标签输出出来。
```java
public static class KNNReducer extends Reducer<Text, Text, Text, Text>
{
public void reduce(Text key, Iterable<Text> values, Context context) throws IOException, InterruptedException
{
//KNN部分
// HashMap<String, Integer> ans = new HashMap<String, Integer>();
// for(Text val:values)
// {
// if (!ans.containsKey(val)){
// ans.put(val.toString(), 0);
// }
// ans.put(val.toString(), ans.get(val.toString())+1);
// }
// //确定标签
// int mx = -1;
// String ansLabel = "";
// for (String l:ans.keySet()){
// if (mx < ans.get(l)){
// mx = ans.get(l);
// ansLabel = l;
// }
// }
// context.write(key, new Text(ansLabel));
//KNN End
//加权KNN & 高斯函数
double mx = -1;
String ansLabel = "";
for (Text val: values){
String[] s = val.toString().split(",");
if (Double.parseDouble(s[0]) > mx){
mx = Double.parseDouble(s[0]);
ansLabel = s[1];
}
}
context.write(key, new Text(ansLabel));
//加权KNN & 高斯 End
}
}
```
同样地,实际运行时需要注释掉其余两种。
## 文件组成
```
Hadoop_knn
├── img //运行结果截图
├── result //存放结果输出文件夹
| ├── part-r-00000(1) //基于欧拉距离计算结果
| ├── part-r-00000(2) //基于加权欧拉距离计算结果
| ├── part-r-00000(3) //基于高斯函数计算结果
├── test //测试集文件夹
| ├── iris_test_data.csv
类型
├── train //测试集文件夹
| ├── iris_train.csv
├── KNN.jar
├── KNN.java //源代码文件
├── README.MD
├── REPORT.MD //报告文件
```
妄北y
- 粉丝: 2w+
- 资源: 1万+
最新资源
- 数独游戏app,for安卓
- 我的编程作品:《声音、光和运动》
- SQlServer2005编程入门经典-触发器和存储过程教程pdf最新版本
- 车辆树木检测21-YOLO(v5至v9)、COCO、CreateML、Darknet、Paligemma、TFRecord、VOC数据集合集.rar
- SQL经典语句大全及技巧汇集chm版最新版本
- SQLServer入门到精通HTML版最新版本
- 医疗领域数据相关的标准清单.xlsx
- xilinx FPGA利用can IP实现can总线通信verilog源码,直接可用,注释清晰 vivado实现,代码7系列以上都兼容
- SQL2005教程PPT讲义(初级入门基础)最新版本
- CC2530无线点对点传输协议zigbee BasicRF代码实现一发一收无线控制LED灯亮灭.zip
- CC2530无线点对点传输协议zigbee BasicRF代码实现一发一收无线通讯质量检测(误包率、RSSI 值和接收数据包个数等).zip
- comsol仿真,磁屏蔽 铁氧体做磁屏蔽和没有屏蔽时的接受端磁密大小,及屏蔽上的磁密分布
- 四足机器人设计原理与应用探索
- 车辆检测1-YOLO(v5至v9)、COCO、CreateML、Darknet、Paligemma、TFRecord、VOC数据集合集.rar
- 食品数据相关标准清单.xlsx
- SQLServer入门基础15天掌握最新版本
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈