集合知プログラミングの勉強(2)
図が欲しい。では集合知プログラミングを R でもやってみよう、としたいのだが‥うーん、しばらく奮闘したがまだ全然だめだ。R をまるで使えない。
- R で読めるようにタブ区切りデータで出力
- R で読み込みデータフレーム化
- データフレームを操作してプロット(図2-1 嗜好空間、とか、図2-2,2-3 とか)
- データフレームを操作して相関係数を出す
上の最初っからもうつまづいている状態。データフレームの操作が良くわかっていないのが大問題。
とりあえず飯だ。
微妙に修正したピアソン相関係数版。loop マクロは美しい、と思うのだけどどうだろう?
(defun sim-pearson (prefs person1 person2) "pearson" (flet ((square (x) (expt x 2))) (loop with pref1 = (cdr (assoc person1 prefs :test #'equal)) with pref2 = (cdr (assoc person2 prefs :test #'equal)) for (title1 . score1) in pref1 for score2 = (cdr (find title1 pref2 :key #'car :test #'equal)) if score2 collect title1 into shared-titles and ; 互いに評価しているアイテムのリスト sum score1 into sum1 and ; 全ての嗜好を合計する sum score2 into sum2 and ; 全ての嗜好を合計する sum (square score1) into sum1sq and ; 平方を合計する sum (square score2) into sum2sq and ; 平方を合計する sum (* score1 score2) into psum ; 積を合計する finally (if (null shared-titles) (return 0) ; 共に評価しているアイテムがなければ0を返す (let* ((n (length shared-titles)) (num (- psum (/ (* sum1 sum2) n))) (den (sqrt (* (- sum1sq (/ (square sum1) n)) (- sum2sq (/ (square sum2) n)))))) (if (zerop den) ; 未定義になる場合 (return 0) (return (/ num den)))))))) (defun top-matches (prefs person &optional (n 5) (similarity #'sim-pearson)) (loop for other in (mapcar #'car prefs) if (not (equal person other)) collect (cons (funcall similarity prefs person other) other) into scores finally (return (subseq (sort (copy-seq scores) #'> :key #'car) 0 (min n (length scores))))))