最近在看《集体智慧编程》,相比其他机器学习的书籍,这本书有许多案例,更贴近实际,而且也很适合我们这种准备学习machinelearning的小白。
这本书我觉得不足之处在于,里面没有对算法的公式作讲解,而是直接用代码去实现,所以给想具体了解该算法带来了不便,所以想写几篇文章来做具体的说明。以下是第一篇,对皮尔逊相关系数作讲解,并采用了自己比较熟悉的java语言做实现。
皮尔逊数学公式如下,来自*。
其中,e是数学期望,cov表示协方差,\sigma_x和\sigma_y是标准差。
化简后得:
皮尔逊相似度计算的算法还是很简单的,实现起来也不难。只要求变量x、y、乘积xy,x的平方,y的平方的和。我的代码所使用的数据测试集来自《集体智慧编程》一书。代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
|
package pearsoncorrelationscore;
import java.util.arraylist;
import java.util.hashmap;
import java.util.list;
import java.util.map;
import java.util.map.entry;
/**
* @author shenchao
*
* 皮尔逊相关度评价
*
* 以《集体智慧编程》一书用户评价相似度数据集做测试
*/
public class pearsoncorrelationscore {
private map<string, map<string, double >> dataset = null ;
public pearsoncorrelationscore() {
initdataset();
}
/**
* 初始化数据集
*/
private void initdataset() {
dataset = new hashmap<string, map<string, double >>();
// 初始化lisa rose 数据集
map<string, double > rosemap = new hashmap<string, double >();
rosemap.put( "lady in the water" , 2.5 );
rosemap.put( "snakes on a plane" , 3.5 );
rosemap.put( "just my luck" , 3.0 );
rosemap.put( "superman returns" , 3.5 );
rosemap.put( "you, me and dupree" , 2.5 );
rosemap.put( "the night listener" , 3.0 );
dataset.put( "lisa rose" , rosemap);
// 初始化jack matthews 数据集
map<string, double > jackmap = new hashmap<string, double >();
jackmap.put( "lady in the water" , 3.0 );
jackmap.put( "snakes on a plane" , 4.0 );
jackmap.put( "superman returns" , 5.0 );
jackmap.put( "you, me and dupree" , 3.5 );
jackmap.put( "the night listener" , 3.0 );
dataset.put( "jack matthews" , jackmap);
// 初始化jack matthews 数据集
map<string, double > genemap = new hashmap<string, double >();
genemap.put( "lady in the water" , 3.0 );
genemap.put( "snakes on a plane" , 3.5 );
genemap.put( "just my luck" , 1.5 );
genemap.put( "superman returns" , 5.0 );
genemap.put( "you, me and dupree" , 3.5 );
genemap.put( "the night listener" , 3.0 );
dataset.put( "gene seymour" , genemap);
}
public map<string, map<string, double >> getdataset() {
return dataset;
}
/**
* @param person1
* name
* @param person2
* name
* @return 皮尔逊相关度值
*/
public double sim_pearson(string person1, string person2) {
// 找出双方都评论过的电影,(皮尔逊算法要求)
list<string> list = new arraylist<string>();
for (entry<string, double > p1 : dataset.get(person1).entryset()) {
if (dataset.get(person2).containskey(p1.getkey())) {
list.add(p1.getkey());
}
}
double sumx = 0.0 ;
double sumy = 0.0 ;
double sumx_sq = 0.0 ;
double sumy_sq = 0.0 ;
double sumxy = 0.0 ;
int n = list.size();
for (string name : list) {
map<string, double > p1map = dataset.get(person1);
map<string, double > p2map = dataset.get(person2);
sumx += p1map.get(name);
sumy += p2map.get(name);
sumx_sq += math.pow(p1map.get(name), 2 );
sumy_sq += math.pow(p2map.get(name), 2 );
sumxy += p1map.get(name) * p2map.get(name);
}
double numerator = sumxy - sumx * sumy / n;
double denominator = math.sqrt((sumx_sq - sumx * sumx / n)
* (sumy_sq - sumy * sumy / n));
// 分母不能为0
if (denominator == 0 ) {
return 0 ;
}
return numerator / denominator;
}
public static void main(string[] args) {
pearsoncorrelationscore pearsoncorrelationscore = new pearsoncorrelationscore();
system.out.println(pearsoncorrelationscore.sim_pearson( "lisa rose" ,
"jack matthews" ));
}
}
|
将各个测试集的数据反映到二维坐标面中,如下所示:
上述程序求得的值实际上就为该直线的斜率。其斜率的区间在[-1,1]之间,其绝对值的大小反映了两者相似度大小,斜率越大,相似度越大,当相似度为1时,该直线为一条对角线。
总结
以上就是本文关于java实现基于皮尔逊相关系数的相似度详解的全部内容,希望对大家有所帮助。如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!
原文链接:http://blog.csdn.net/panjiao119/article/details/78442152