初学hadoop之一:相似度计算(余弦距离)
2016-05-28 12:40
405 查看
写这个博客的初衷还是想记录一下自己学hadoop的历程啦~,大部分的东西都是老师要我们下来写的作业,虽然自己做的确实不怎么样,但如果要转载的话,还是麻烦注明一下出处,谢谢啦~
(一)问题
老师给我们留的作业就是求一个或多个txt文件中任意两行的距离(余弦、jacard、欧式距离都行),txt文件中每一行是中文英文还是数字都不限。
下面代码的我做测试用的数据格式是这样的:1{s1 s2 s3 s4 s5 s6},前面的1为行号,后面“{”“}”里的内容为真正要计算距离的某一行至,每个值之间用空格隔开。
(二)余弦距离
网上关于余弦距离的计算的也有很多讲解的例子,我同学就举了这样一个例子,比如有这样两行A和B;A为“他喜欢你”,B为“我喜欢你”。要计算A,B的相似度,需先进行中文分词,分次后,A变成了“他”
“喜欢” “你”,B为“我”
“喜欢” “你”,先求A,B的并集,为{他
喜欢 你 我 },再将A,B转化为向量来表示,如下图所示:
那么,A对应的向量为(1,1,1,0),B为(0,1,1,1),再根据cosAB=(A,B)/|A||B|求得余弦值。
下面的计算A和B的余弦值的函数cosAB是没有考虑任何的优化直接写的,大家就随便看看吧:
(三)相似度计算
3.1 计算思想
input:
1 s1
2 s2
mapper
1,1 s1
1,2 s1
1,1 s1
2,1 s1
2,1 s2
2,2 s2
1,2 s2
2,2 s2
reducer
1,1 {s1 s1}
1,2 {s1 s2}
2,1 {s1 s2}
2,2 {s2 s2}
input中“1”“2”代表行号。
[b] 3.2 mapper函数
[/b]
3.3 reducer函数
(四)疑问
假如有以下三句话:A{他特别喜欢你};B{他非常喜欢你};C{他不喜欢你}。按照上面的余弦算法,AB和BC的余弦值是一样的,但是直观上感受明显是A比C离B更近,这种情形会怎么处理?
---------感谢将这篇博客看完啦,这是一条结束的分割线:)---------
(一)问题
老师给我们留的作业就是求一个或多个txt文件中任意两行的距离(余弦、jacard、欧式距离都行),txt文件中每一行是中文英文还是数字都不限。
下面代码的我做测试用的数据格式是这样的:1{s1 s2 s3 s4 s5 s6},前面的1为行号,后面“{”“}”里的内容为真正要计算距离的某一行至,每个值之间用空格隔开。
(二)余弦距离
网上关于余弦距离的计算的也有很多讲解的例子,我同学就举了这样一个例子,比如有这样两行A和B;A为“他喜欢你”,B为“我喜欢你”。要计算A,B的相似度,需先进行中文分词,分次后,A变成了“他”
“喜欢” “你”,B为“我”
“喜欢” “你”,先求A,B的并集,为{他
喜欢 你 我 },再将A,B转化为向量来表示,如下图所示:
他 | 喜欢 | 你 | 我 | |
A | 1 | 1 | 1 | 0 |
B | 0 | 1 | 1 | 1 |
下面的计算A和B的余弦值的函数cosAB是没有考虑任何的优化直接写的,大家就随便看看吧:
//计算string1和string2的余弦值 public static double calculate(String s1,String s2){ String[] t1=s1.split(" "); String[] t2=s2.split(" "); //以键值形式存储m1和m2的值 Map<String, Integer> m1=new HashMap<String, Integer>(); Map<String, Integer> m2=new HashMap<String, Integer>(); for(int i=0;i<t1.length;i++){ if(m1.containsKey(t1[i])) m1.put(t1[i], m1.get(t1[i])+1); else m1.put(t1[i], 1); } for(int j=0;j<t2.length;j++){ if(m2.containsKey(t2[j])) m2.put(t2[j], m2.get(t2[j])+1); else m2.put(t2[j], 1); } Set temp=new HashSet(t1.length+t2.length); //set为两个行的并集的key值 for(int i=0;i<t1.length;i++){ for(int j=0;j<t2.length;j++){ temp.add(t1[i]); temp.add(t2[j]); } } //分别计数 for(int i=0;i<temp.size();i++){ if(! m1.containsKey(temp.toArray()[i])) m1.put(temp.toArray()[i].toString(), 0); } for(int j=0;j<temp.size();j++){ if(! m2.containsKey(temp.toArray()[j])) m2.put(temp.toArray()[j].toString(), 0); } int n1=0,n2=0,nfinal=0; for(int k=0;k<temp.size();k++){ String st1=temp.toArray()[k].toString();//得到某一个具体的key值 System.out.println("m1的"+st1+"值为:"+m1.get(st1)+" m2的"+st1+"值为:"+m2.get(st1)); n1+=m1.get(st1)*m1.get(st1); n2+=m2.get(st1)*m2.get(st1); nfinal+=m1.get(st1)*m2.get(st1); System.out.println(n1); System.out.println(n2); System.out.println(nfinal); } double dis=nfinal/Math.sqrt(n1*n2); return dis; }
(三)相似度计算
3.1 计算思想
input:
1 s1
2 s2
mapper
1,1 s1
1,2 s1
1,1 s1
2,1 s1
2,1 s2
2,2 s2
1,2 s2
2,2 s2
reducer
1,1 {s1 s1}
1,2 {s1 s2}
2,1 {s1 s2}
2,2 {s2 s2}
input中“1”“2”代表行号。
[b] 3.2 mapper函数
[/b]
public static class calMapper extends Mapper<LongWritable, Text, Text, Text>{//后两个Text指的是CONTEXT的参数 public void map(LongWritable ikey, Text ivalue, Context context) throws IOException, InterruptedException { String[] temp=ivalue.toString().split(" "); for(int i=1;i<=100;i++){//偷懒了,这边可以自己确定一下一共有多少行需要计算 String id1=temp[0]+","+i; String id2=i+","+temp[0]; System.out.println("比较"+id1+"和"+id2); context.write(new Text(id1), new Text(ivalue));//重要的一点就是context可以写多行 context.write(new Text(id2), new Text(ivalue)); } } }
3.3 reducer函数
public static class calReducer extends Reducer<Text,Text,Text,Text> { public void reduce(Text key, Iterable<Text> values, Context context ) throws IOException, InterruptedException { String[] data=new String[2]; String[] k=new String[2]; String[] id1=new String[2]; String[] id2=new String[2]; //将id1,id2的两值分别存于data[0]和data[1]中 int i=0; for(Text line:values){ String[] temp=line.toString().split(" "); k[i]=temp[0]; //从values中读取行号和后面的值 data[i]=line.toString().substring(line.toString().indexOf("{")+1, line.toString().length()-1); /*若将 line.toString().length()-1改为line.toString().indexOf("}"), 就会报index out of range:-1的错误,不是很理解 */ System.out.println("第"+k[i]+"行的数据为:"+data[i]); if(i==0){ id1=data[i].split(" "); } else{ id2=data[i].split(" "); } i++; } double dis=calculate(data[0],data[1]); System.out.println(k[0]+"与"+k[1]+"的相似度为:"+dis); String t="the similarity of "+k[0]+","+k[1]+"is:"; System.out.println(t+":"+dis); context.write(new Text(t), new Text(String.valueOf(dis+"\r\n"))); System.out.println("------------------------"); } }
(四)疑问
假如有以下三句话:A{他特别喜欢你};B{他非常喜欢你};C{他不喜欢你}。按照上面的余弦算法,AB和BC的余弦值是一样的,但是直观上感受明显是A比C离B更近,这种情形会怎么处理?
---------感谢将这篇博客看完啦,这是一条结束的分割线:)---------
相关文章推荐
- 皮质颜色检测的几个问题(VS2010/OpenCV)
- Opencv源码之平面点集的最小包围圆
- 11.Spark Streaming源码解读之Driver中的ReceiverTracker架构设计以及具体实现彻底研究
- centos不能桥接上网的问题
- 11.Spark Streaming源码解读之Driver中的ReceiverTracker架构设计以及具体实现彻底研究
- CentOS 打开mysql 3306端口
- CentOS6.5中利用其自带的openjdk设置JAVA_HOME
- centos自带mysql初始处理
- tenda u1 usb wireless device install driver for kali linux kernal Debian 4.3.3-7kali2 (2016-01-27) x86_64 GNU/Linux
- linux 命令总结
- linux系统下常用文件和目录的命令
- 网格细分算法(Catmull-Clark subdivision & Loop subdivision)附源码
- PopupWindow的二级菜单的简单demo
- Tomcat下log4j设置文件路径和temp目录
- shell 脚本(menu)
- PowerShell 查询 Excel记录
- 修改tomcat的部署名称
- shell 脚本菜单menu
- docker学习笔记4.1-使用Dockerfile文件构建镜像
- tomcat常见错误及解决方案