せっかくなのでJavaで書いてみた。
お気に入りのPerlでも書こうと思ったけど一緒に読む人間がPerl分からないのでまずはJavaで。
ていうかPerlで書いてる方がいるんですね。あとで真似してみよう。
集合知プログラミング 2章 その1 ユークリッド距離 - ケーズメモ
ユークリッド距離とは、要するに空間上の距離ということらしい。
座標,を持つ2点のユークリッド距離は
から計算される。
この章では、類似性スコアを求めて後で重み付けに使うためにこれに1を加えて逆数を取ったものを使うようだ。
こうすることで常に0から1の間の値を返すようになり、類似性が高ければ1に近くなる。
Common.java
package chapter2; public class Common { final static String LisaRose = "Lisa Rose"; final static String GeneSeymour = "Gene Seymour"; final static String MichaelPhillips = "Michael Phillips"; final static String ClaudiaPuig = "Claudia Puig"; final static String MickLassalle = "Mick Lassalle"; final static String JackMatthews = "Jack Matthews"; final static String Toby = "Toby"; final static String LadyInTheWater = "Lady in the Water"; final static String SnakesOnAPlane = "Snakes on a plane"; final static String JustMyLuck = "Just My Luck"; final static String SupermanReturns = "Superman Returns"; final static String YouMeAndDupree = "You, Me and Dupree"; final static String TheNightListener = "The Night Listener"; }
Critics.java
package chapter2; import java.util.HashMap; import java.util.Map; public class Critics { private Map<String, Map<String, Double>> data = new HashMap<String, Map<String, Double>>(); /** * データ読み込みによる初期化 */ public Critics() { /* Lisa Rose */ HashMap<String, Double> mapLisaRose = new HashMap<String, Double>(); mapLisaRose.put(Common.LadyInTheWater, Double.valueOf(2.5)); mapLisaRose.put(Common.SnakesOnAPlane, Double.valueOf(3.5)); mapLisaRose.put(Common.JustMyLuck, Double.valueOf(3.0)); mapLisaRose.put(Common.SupermanReturns, Double.valueOf(3.5)); mapLisaRose.put(Common.YouMeAndDupree, Double.valueOf(2.5)); mapLisaRose.put(Common.TheNightListener, Double.valueOf(3.0)); data.put(Common.LisaRose, mapLisaRose); /* Gene Seymour */ HashMap<String, Double> mapGeneSeymour = new HashMap<String, Double>(); mapGeneSeymour.put(Common.LadyInTheWater, Double.valueOf(3.0)); mapGeneSeymour.put(Common.SnakesOnAPlane, Double.valueOf(3.5)); mapGeneSeymour.put(Common.JustMyLuck, Double.valueOf(1.5)); mapGeneSeymour.put(Common.SupermanReturns, Double.valueOf(5.0)); mapGeneSeymour.put(Common.TheNightListener, Double.valueOf(3.0)); mapGeneSeymour.put(Common.YouMeAndDupree, Double.valueOf(3.5)); data.put(Common.GeneSeymour, mapGeneSeymour); /* Michael Phillips */ HashMap<String, Double> mapMichaelPhillips = new HashMap<String, Double>(); mapMichaelPhillips.put(Common.LadyInTheWater, Double.valueOf(2.5)); mapMichaelPhillips.put(Common.SnakesOnAPlane, Double.valueOf(3.0)); mapMichaelPhillips.put(Common.SupermanReturns, Double.valueOf(3.5)); mapMichaelPhillips.put(Common.TheNightListener, Double.valueOf(4.0)); data.put(Common.MichaelPhillips, mapMichaelPhillips); /* Claudia Puig */ HashMap<String, Double> mapClaudiaPuig = new HashMap<String, Double>(); mapClaudiaPuig.put(Common.SnakesOnAPlane, Double.valueOf(3.5)); mapClaudiaPuig.put(Common.JustMyLuck, Double.valueOf(3.0)); mapClaudiaPuig.put(Common.TheNightListener, Double.valueOf(4.5)); mapClaudiaPuig.put(Common.SupermanReturns, Double.valueOf(4.0)); mapClaudiaPuig.put(Common.YouMeAndDupree, Double.valueOf(2.5)); data.put(Common.ClaudiaPuig, mapClaudiaPuig); /* Mick Lasalle */ HashMap<String, Double> mapMickLasalle = new HashMap<String, Double>(); mapMickLasalle.put(Common.LadyInTheWater, Double.valueOf(3.0)); mapMickLasalle.put(Common.SnakesOnAPlane, Double.valueOf(4.0)); mapMickLasalle.put(Common.JustMyLuck, Double.valueOf(2.0)); mapMickLasalle.put(Common.SupermanReturns, Double.valueOf(3.0)); mapMickLasalle.put(Common.TheNightListener, Double.valueOf(3.0)); mapMickLasalle.put(Common.YouMeAndDupree, Double.valueOf(2.0)); data.put(Common.MickLassalle, mapMickLasalle); /* Jack Matthews */ HashMap<String, Double> mapJackMatthews = new HashMap<String, Double>(); mapJackMatthews.put(Common.LadyInTheWater, Double.valueOf(3.0)); mapJackMatthews.put(Common.SnakesOnAPlane, Double.valueOf(4.0)); mapJackMatthews.put(Common.TheNightListener, Double.valueOf(3.0)); mapJackMatthews.put(Common.SupermanReturns, Double.valueOf(5.0)); mapJackMatthews.put(Common.YouMeAndDupree, Double.valueOf(3.5)); data.put(Common.JackMatthews, mapJackMatthews); /* Toby */ HashMap<String, Double> mapToby = new HashMap<String, Double>(); mapToby.put(Common.SnakesOnAPlane, Double.valueOf(4.5)); mapToby.put(Common.YouMeAndDupree, Double.valueOf(1.0)); mapToby.put(Common.SupermanReturns, Double.valueOf(4.0)); data.put(Common.Toby, mapToby); } public Map<String, Double> getMap(String key) { return data.get(key); } }
SimiralityCalculator.java
package chapter2; public abstract class SimilarityCalculator { protected Critics data = new Critics(); abstract double getSimilarity(String lhs, String rhs); }
DistanceCalculator.java
package chapter2; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; public class DistanceCalculator extends SimilarityCalculator { /* (non-Javadoc) * @see chapter2.SimilarityCalculator#getSimilarity(java.lang.String, java.lang.String) */ @Override double getSimilarity(String lhs, String rhs) { Map<String, Double> lhsMap = data.getMap(lhs); Map<String, Double> rhsMap = data.getMap(rhs); // どちらかでも存在していなければ0.0を返す if ((lhsMap == null) || (rhsMap == null)) { return 0.0; } // 共通しているものが一つもなければ0.0を返す List<String> commonKeyList = new LinkedList<String>(); Iterator<String> iterKey = lhsMap.keySet().iterator(); while (iterKey.hasNext()) { String key = iterKey.next(); if (rhsMap.containsKey(key)) { commonKeyList.add(key); } } if (commonKeyList.size() == 0) { return 0.0; } // すべての差の平方を足し合わせる double sumOfSquares = 0.0; Iterator<String> iterList = commonKeyList.iterator(); while (iterList.hasNext()) { String key = iterList.next(); double difference = lhsMap.get(key).doubleValue() - rhsMap.get(key).doubleValue(); sumOfSquares += difference * difference; } return 1.0 / (1.0 + sumOfSquares); } }
Main.java
package chapter2; public class Main { /** * @param args */ public static void main(String[] args) { SimilarityCalculator simcal = new DistanceCalculator(); System.out.println(simcal.getSimilarity(Common.LisaRose, Common.GeneSeymour)); } }
実行結果。
0.14814814814814814
うん、とりあえず本の例題と同じ結果は得られてるっぽい。