Recommending Something Before Knowing the Reader
Botie has a shelf of guides and a record of which were opened. Begin with a popularity baseline, then examine what those records actually tell us.
13 sections · 4 questions · 2 coding challenges
The arrow keys move between sections too.
Giving Recommendations a Reference Point
BOTIE
A popularity list is a useful reference because it can operate without an individual history. Our library examples expose its main limitation: the system’s past display choices affect which interactions it gets to count.
Sources for this history
Which Guide Should Botie Put First?
A reader arrives at Botie’s library for the first time. We have no history for that reader, but we do know which guides previous visitors opened.
Counting those interactions gives a simple first ranking. Before calling it a preference model, we need to ask whether everyone had an equal chance to see each guide.
The small reader-guide table contains invented interactions.
Step 1 of 3
Record interactions
Rows identify readers; columns identify guides. Zero means no recorded open.
| Reader | Guide 0 | Guide 1 | Guide 2 |
|---|---|---|---|
| Reader A | 1 | 1 | 0 |
| Reader B | 1 | 0 | 0 |
Reader A
- Guide 0
- 1
- Guide 1
- 1
- Guide 2
- 0
Reader B
- Guide 0
- 1
- Guide 1
- 0
- Guide 2
- 0
Step 2 of 3
Count by guide
Sum down the reader dimension.
| Guide | Open counts |
|---|---|
| Guide 0 | 2 |
| Guide 1 | 1 |
| Guide 2 | 0 |
Guide 0
- Open counts
- 2
Guide 1
- Open counts
- 1
Guide 2
- Open counts
- 0
Step 3 of 3
Rank candidates
Larger counts come first; equal counts keep catalogue order.
| Most opened first | Guide indices |
|---|---|
| Rank 1 | 0 |
| Rank 2 | 1 |
| Rank 3 | 2 |
Rank 1
- Guide indices
- 0
Rank 2
- Guide indices
- 1
Rank 3
- Guide indices
- 2
Popularity supplies a useful but shared starting recommendation
The reduction preserves a separate popularity count for each guide.
Which guide gets recommended before we know this reader?
A popularity rule adds opens across readers while keeping each guide separate. Change one reader's row and inspect which guide counts actually change.
BOTIE
Guide indices ordered by popularity
- 00
- 11
- 22
Follow the operations
1. Reader-by-guide interaction matrix
1 1 0 1 0 0 2. Add each column
- 02
- 11
- 20
3. Rank indices by descending score
- 00
- 11
- 22
4. Result
- 00
- 11
- 22
Zero is unobserved interaction, not proof of dislike. Ties use catalogue order.
1. Define What One Interaction Means
What should count as an interaction? Opening a guide is different from rating it or finishing it. In this example, one means that a reader opened the guide during a specified window. Repeated refreshes do not add more ones.
Zero means that no open was recorded. Perhaps the reader disliked the guide, but perhaps it was never shown to them. The table alone cannot distinguish those explanations, so we should not treat every zero as a negative review.
Our matrix is an interaction record, not a table of explicit likes and dislikes.
2. Build a Reproducible Baseline
Sum interactions down rows to obtain one count per guide. Sort descending and define a tie rule. Filter unavailable guides before showing recommendations, and exclude already-consumed items when the task requires novelty.
Interactions = [[1,1,0], [1,0,0]]
Counts = [2,1,0]
Descending guide order = [0,1,2]The baseline gives all new readers the same order.
3. Examine Exposure and Time
A guide shown on the front page can receive more opens simply because more readers encountered it. Longer availability also creates more opportunity to accumulate interactions.
An exposure-normalised click rate answers a different question from raw popularity. It can be unstable with few impressions, so retain sample counts and compare uncertainty rather than celebrate a perfect rate from one display.
Popularity is partly a record of how the service presented its catalogue.
Count the opens of one guide first
One column records whether each reader opened this guide. Its total measures popularity across these readers, without yet deciding the order of the whole catalogue.
import numpy as np
opened_this_guide = np.array([1, 0, 1, 1])
print(int(opened_this_guide.sum()))3Three readers opened it. Practice applies the reduction to every guide column, then uses the counts to obtain a stable ranking.
4. Test the Task We Care About
Fit counts only from the training period, then ask which later relevant guides appear in the recommendation list. Define the candidate set and availability at that time.
New readers can use this fallback, but entirely new guides have no interaction evidence. Content descriptions or deliberate exploration can help them enter the list. A feedback loop that never displays them cannot learn much about them.
Botie’s next lesson adds guide descriptions so the ranking can respond to a reader’s stated interests.
5. Ten Opens May Come from One Reader
A guide opened ten times by one reader has ten events but only one distinct reader. A popularity rule must decide which support it counts. Reloads, automated requests and repeated visits can dominate a raw event count.
Keep event identity, reader identity when available, and timestamps long enough to apply the chosen counting rule. On an anonymous site, do not claim to know distinct people from events alone. The measurement limits what the baseline can mean.
6. Remove Ineligible Guides before Taking the First Few
A reader may have already completed a guide, or a guide may be unavailable in the selected language. Rank among the candidates that can actually be shown. Taking the top entries first and removing ineligible ones afterward can leave an unnecessarily short list.
Use a deterministic tie convention so a replay produces the same recommendation. Stable ordering is a reproducibility choice; it does not establish that one tied guide is better.
Rank the available unread guides
The counts are fixed historical inputs, not updated from the evaluation interaction.
import numpy as np
count = np.array([20,12,12,5])
eligible = np.array([False,True,True,True])
candidates = np.flatnonzero(eligible)
ranked = candidates[np.argsort(-count[candidates], kind='stable')]
print(ranked[:2].tolist())[1, 2]The most popular guide is excluded before ranking because it is not eligible for this request.
7. What Was Shown Affects What Was Opened
A prominent guide has more opportunities to receive interactions. Popularity can therefore reinforce earlier display choices. A low count may mean low interest, little exposure or a newly published guide.
Evaluate a temporal baseline on later eligible requests and inspect new guides separately. Keep exposure records when available. Interaction counts are useful for a starting rule, but they are not direct measurements of each guide's intrinsic quality.
Check yourself
Questions on Parts 1 to 7
Question 1 of 4
Which guide has most opens?
Use the information below.
Interactions [[1,1,0],[1,0,0]], columns are guides.Try it with Botie
Build with Botie
Write and run Python