最近在看《集體智慧編程》 ,相比其他機器學習的書籍,這本書有許多案例,更貼近實際,而且也很適合我們這種準備學習machinelearning的小白。
這本書我覺得不足之處在於,裡面沒有對算法的公式作講解,而是直接用代碼去實現,所以給想具體了解該算法帶來了不便,所以想寫幾篇文章來做具體的說明。以下是第一篇,對皮爾遜相關係數作講解,並採用了自己比較熟悉的java語言做實現。
皮爾遜數學公式如下,來自維基百科。
其中,E是數學期望,cov表示協方差,/sigma_X和/sigma_Y是標準差。
化簡後得:
皮爾遜相似度計算的算法還是很簡單的,實現起來也不難。只要求變量X、Y、乘積XY,X的平方,Y的平方的和。我的代碼所使用的數據測試集來自《集體智慧編程》一書。代碼如下:
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));// 分母不能為0if (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實現基於皮爾遜相關係數的相似度詳解的全部內容,希望對大家有所幫助。如有不足之處,歡迎留言指出。感謝朋友們對本站的支持!