slope_one_recommender
This library predicts ratings using weighted Slope One collaborative
filtering: average rating differences between items, weighted by the
number of users who rated both. The library object imports the
recommender_common category and implements recommender_protocol
protocol. The score/4 predicate returns a predicted rating. Datasets
implement the rating_dataset_protocol protocol with atomic
identifiers, unique user/item pairs, numeric ratings, a matching
positive count, and an optional numeric ordered rating scale.
API documentation
Open the ../../apis/library_index.html#slope-one-recommender link in a web browser.
Loading
To load this library, load its loader.lgt file:
| ?- logtalk_load(slope_one_recommender(loader)).
Testing
To test this library, load its tester.lgt file:
| ?- logtalk_load(slope_one_recommender(tester)).
Examples
| ?- logtalk_load(recommender_protocols('test_datasets/movie_ratings')),
slope_one_recommender::learn(movie_ratings, Model),
slope_one_recommender::score(Model, alice, m6, Rating),
slope_one_recommender::recommend(Model, alice, 3, Recommendations).
Options
The learn/3 predicate accepts the following options:
min_support(Count)sets the minimum number of users who rated both items in a contributing pair to a positive integer. The default is1.clip_to_scale(Boolean)selectstrue(default) orfalse. When enabled, it clips estimates and fallbacks to the inclusive declared scale. Without a declared scale, it leaves estimates unchanged.
There are no similarity metric or neighborhood-size options.
The learning options can be retrieved from a learned recommender model
using the recommender_options/2 predicate.
Training and prediction
Each unordered distinct item pair is collected once per co-rating user.
The deviation d(i,j) is the mean of
rating(user,i) - rating(user,j) over users who rated both; its
support count(i,j) is their count. Canonical storage uses standard
item order with ItemLo @< ItemHi; reverse lookup negates the stored
difference, so d(j,i) = -d(i,j).
For target user u and item i, each other item j rated by
u contributes if its pair support meets min_support. The
estimate is:
sum(count(i,j) * (rating(u,j) + d(i,j))) / sum(count(i,j))
Counts are rescaled by the maximum contributing count. Weighting is by support, not equal item weights; the correction is additive, not a product of deviation and rating. An already-rated target is still estimated and excluded from its own contributions. Training does not implicitly hold out observations for evaluation.
Without evidence the fallback is the known user’s mean, otherwise the known item’s mean, otherwise the global mean. This also covers unknown identifiers and catalogs with no co-rated item pairs. Query identifiers must be instantiated atomic terms. Clipping follows either kind of estimate.
The recommend/4 predicate returns up to N unrated
training-catalog items as Item-Score pairs; N must be a positive
integer. Scores agree with direct predictions; sorting is descending by
score, with descending standard item order for ties. Every
training-catalog item is a candidate for an unknown user. If no
candidates remain, the result is [].
For u: a=1,b=3 and v: a=2,b=4,c=5, the estimate for u,c is
four. Adding w: a=1,c=3 gives d(c,a)=2.5 with support two and
d(c,b)=1 with support one. The weighted estimate is
(2*(1+2.5)+(3+1))/3 = 11/3.
Models, diagnostics, and export
The learn/2 and learn/3 predicates return models using the
following term representation:
slope_one_model(Ratings, Deviations, GlobalMean, Scale, Diagnostics)
The Ratings argument is a list of rating(User, Item, Rating)
terms. Sorted canonical deviations are
deviation(ItemLo, ItemHi, MeanDifference, PositiveCount) terms. The
Scale argument is the atom none or a scale(Min, Max) term.
The Diagnostics argument is a list containing exactly one of each
diagnostic term: model(slope_one_recommender),
rating_count(Count), options(Options), user_count(Count),
item_count(Count), and deviation_pair_count(Count).
The valid_recommender/1 predicate checks records, options, means,
scale, pair keys, orientation, counts, averages, and diagnostic
consistency without binding incomplete models. The
check_recommender/1 predicate throws for invalid models. The
diagnostics/2 predicate returns the metadata list; the
diagnostic/2 predicate enumerates it.
The export_to_clauses(Dataset, Model, Functor, Clauses) predicate
exports a single Functor(Model) fact; the export_to_file/4
predicate writes it with the common header. Restore with this library
loaded. The print_recommender/1 predicate prints the template and
complete model, including effective options and summaries.
Limitations
Training enumerates a quadratic number of pairs in each user’s profile and sorts the collected contributions. A dense catalog can produce a quadratic-size deviation table. List-based duplicate checks and pair lookup also limit large-dataset performance. Public model validation recomputes the deviation table; recommendation repeats validation for every candidate. There are no incremental updates, alternative Slope One variants, or adjustable fallback policies. Arithmetic uses backend numeric precision; count rescaling does not prevent overflow in extreme rating differences or sums.
References
Lemire, D. and Maclachlan, A. (2005). Slope One Predictors for Online Rating-Based Collaborative Filtering. Proceedings of the 2005 SIAM International Conference on Data Mining, 471-475. https://doi.org/10.1137/1.9781611972757.43