集合知プログラミングの勉強(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))))))