This approach not only computes the common behavior based on the same set of items associated with different users, but also on how each user rates those items. For a given user, U, this technique finds all the users who have rated the items similar to U. Then, it recommends items based on the items rated by the users that displayed similar behavior.
The Algorithm:
For a given user, find the top similar users by:
-
Find all users that rated at least one (or N) common item(s) as the user, and use them as candidates.
-
For each candidate, calculate a score using the Root Mean Square (RMS) of the difference between their mutual item ratings.
-
Store the top similar users for each individual user.
Find the top recommended item:
-
Find all the items that were rated by users similar to the original user, but that have not yet been rated by the individual user.
-
Calculate the average rating for each item.
-
Store the top items.
Step 1 Insert rating events
Maintain a Sorted Set for each user to store all the items rated by that user.
ZADD user:<user id>:items <rating> <item id>
Have a Sorted Set for each item; track all the users who rated that item.
ZADD item:<item id>:scores <rating> <user id>
Step 2 Get candidates with the same item ratings
This is a two-step process. In the first step, fetch all the users who have rated the same items. Secondly, find how similar each user computed in the previous step is with respect to user U, whom we need to recommend.
- Find items rated by <user id>
ZRANGE user:<user id>:items 0 -1
- Find users who have rated the same items
ZUNIONSTORE user:<user id>:same_items 3 item:I1:scores item:I2:scores item:I3:scores
Step 3 Calculate similarity for each candidate
Find the difference between <user id> and others in the list. This example uses ZMEMBERS assuming a small dataset. Use ZSCAN when working with a large dataset.
ZRANGE user:<user id>:same_items 0 -1
ZINTERSTORE rms:<user id1>:<user id2> 2 user:<user id1>:items user:<user id2>:items WEIGHTS 1 -1
The absolute value gives the root mean square between two users. After this step, implement your own logic to identify who is close enough to a given user based on the root mean square between the users.
Step 4 Getting the candidate items
Now that we have a sorted set of users similar to U1, we can extract the items associated with those users and their ratings. We’ll do this with ZUNIONSTORE with all U1’s similar users, but then we need to make sure we exclude all the items U1 has already rated.
We’ll use weights again, this time with the AGGREGATE option and ZRANGEBYSCORE command. Multiplying U1’s items by -1 and all the others by 1, and specifying the AGGREGATE MIN option will yield a sorted set that is easy to cut: All U1’s item scores will be negative, while the other user’s item scores will be positive. With ZRANGEBYSCORE, we can fetch the items with a score greater than 0, returning only those items that U1 has not rated.
Assuming <user id 1> with similar users <user id 3>, <user id 5>, <user id 6>:
ZUNIONSTORE recommendations:<user id 1> 4 user:<user id 1>:items user:<user id 3>:items user:<user id 5>:items user:<user id 6>:items WEIGHTS -1 1 1 1 AGGREGATE MIN
Sample Scenario: The local grocery store’s mobile app for recommendations
The grocery chain now decides to add yet another feature within its application. It allows the customers to rate the items on a scale from 1 to 5. The customers who purchase similar items and rate them in a similar fashion would be more closely related as the store starts promoting items based not just based on their purchasing behavior, but also on how they rate those items.
The data structures would look like:
userid:U1:items = {(milk, 4), (bananas, 5)}
userid:U2:items = {(milk, 3), (carrots, 4), (bananas, 5)}
userid:U3:items = {(milk, 5)}
item:milk:scores = {(U1, 4), (U2, 3), (U3, 5)}
item:bananas:scores = {(U1, 5), (U2, 5)}
item:carrots:scores = {(U2, 4)}
ZRANGE user:U1:items 0 -1
= {(milk, 4), (bananas, 5)}
ZUNIONSTORE user:U1:same_items 2 item:milk:scores item:bananas:scores
user:U1:same_items = {(U1, 9), (U2, 8), (U3, 5)}
ZINTERSTORE rms:U1:U2 2 user:U1:items user:U2:items WEIGHTS 1 -1
ZINTERSTORE rms:U1:U3 2 user:U1:items user:U3:items WEIGHTS 1 -1
rms:U1:U2 = {(bananas, 0), (milk, 1)};
rms:U1:U3 = {(milk, -1)};
RMS of rms:U1:U2 = 0.7
RMS of rms:U1:U3 = 1
From the above calculation, we can conclude that U2 is closer to U1, than U3 is to U1. However, for our calculations, we will choose RMS values less than or equal to 1. Therefore, we will consider the ratings of both U2 and U3.
ZUNIONSTORE recommendations:U1 3 user:U1:items user:U2:items user:U3:items WEIGHTS -1 1 1 AGGREGATE MIN
recommendations:U1 = {(bananas, -5), (milk, -4), (carrots, 4)}
The item that has the highest score is recommended to U1. In our example, the store recommends carrots to U1.
{{ parent.title || parent.header.title}}
{{ parent.tldr }}
{{ parent.linkDescription }}
{{ parent.urlSource.name }}