| 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)))) |
| | 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") |