Changeset 30704

Show
Ignore:
Timestamp:
03/02/09 22:52:46 (4 years ago)
Author:
miyamuko
Message:

lang/xyzzy/pci-code (get-recommended-items): p26 2.7.2 推薦を行う

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • lang/xyzzy/pci-code/site-lisp/chapter2/recommendations.l

    r30701 r30704  
    9090       (not (zerop ($ prefs person item))))) 
    9191 
     92(defmacro aincf (value item alist) 
     93  `(if (assoc ,item ,alist :test #'string=) 
     94       (incf (cdr (assoc ,item ,alist :test #'string=)) 
     95             ,value) 
     96     (setf ,alist (acons ,item ,value ,alist)))) 
     97 
    9298;($ *critics* "Lisa Rose") 
    9399;($ *critics* "Lisa Rose" "Lady in the Water") 
     
    168174;; person 以外の全ユーザの評点の重み付き平均を使い、person への推薦を算出する 
    169175(defun get-recommendations (prefs person &key (similarity #'sim-pearson)) 
    170   (macrolet ((aincf (value item alist) 
    171                `(if (assoc ,item ,alist :test #'string=) 
    172                     (incf (cdr (assoc ,item ,alist :test #'string=)) 
    173                           ,value) 
    174                   (setf ,alist (acons ,item ,value ,alist))))) 
    175     (let (totals simsums) 
    176       ;; 自分自身とは比較しないので remove 
    177       (dolist (other (remove person (persons prefs) 
    178                              :test #'string=)) 
    179         (let ((sim (funcall similarity prefs person other))) 
    180           ;; 0 以下のスコアは無視する 
    181           (when (> sim 0) 
    182             (dolist (item (items prefs other)) 
    183               ;; まだ見ていない映画の得点のみを算出 
    184               (unless (rated prefs person item) 
    185                 (aincf (* ($ prefs other item) sim) item totals) 
    186                 (aincf sim item simsums)))))) 
    187       ;; 正規化したリストを作る 
    188       (let ((rankings (mapcar #'(lambda (item/total) 
    189                                   (let ((item (car item/total)) 
    190                                         (total (cdr item/total))) 
    191                                     (cons (/ total ($ simsums item)) item))) 
    192                               totals))) 
    193         (sort rankings #'> :key #'car))))) 
     176  (let (totals simsums) 
     177    ;; 自分自身とは比較しないので remove 
     178    (dolist (other (remove person (persons prefs) 
     179                           :test #'string=)) 
     180      (let ((sim (funcall similarity prefs person other))) 
     181        ;; 0 以下のスコアは無視する 
     182        (when (> sim 0) 
     183          (dolist (item (items prefs other)) 
     184            ;; まだ見ていない映画の得点のみを算出 
     185            (unless (rated prefs person item) 
     186              (aincf (* ($ prefs other item) sim) item totals) 
     187              (aincf sim item simsums)))))) 
     188    ;; 正規化したリストを作る 
     189    (let ((rankings (mapcar #'(lambda (item/total) 
     190                                (let ((item (car item/total)) 
     191                                      (total (cdr item/total))) 
     192                                  (cons (/ total ($ simsums item)) item))) 
     193                            totals))) 
     194      (sort rankings #'> :key #'car)))) 
    194195 
    195196;(get-recommendations *critics* "Toby") 
     
    226227 
    227228;(calculate-similar-items *critics*) 
     229 
     230 
     231;;; p26 2.7.2 推薦を行う 
     232 
     233(defun get-recommended-items (prefs item-match user) 
     234  (let ((user-ratings ($ prefs user)) 
     235        (scores) 
     236        (total-sim)) 
     237    (dolist (item/rating user-ratings) 
     238      (dolist (similarity/item ($ item-match (car item/rating))) 
     239        (unless (rated prefs user (cdr similarity/item)) 
     240          (aincf (* (cdr item/rating) 
     241                    (car similarity/item)) 
     242                 (cdr similarity/item) scores) 
     243          (aincf (car similarity/item) (cdr similarity/item) total-sim)))) 
     244    (let ((rankings (mapcar #'(lambda (item/score) 
     245                                (cons (/ (cdr item/score) 
     246                                         ($ total-sim (car item/score))) 
     247                                      (car item/score))) 
     248                            scores))) 
     249      (sort rankings #'> :key #'car)))) 
     250 
     251;(setf itemsim (calculate-similar-items *critics*)) 
     252;(get-recommended-items *critics* itemsim "Toby")