Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jonahharris/de312ecf645523569cfc3356f1d17e2f to your computer and use it in GitHub Desktop.
Save jonahharris/de312ecf645523569cfc3356f1d17e2f to your computer and use it in GitHub Desktop.
a JavaScript implementation of A Practical Guide to Building Recommender Systems Epsilon-based Dithering
/**
* The following is a JavaScript implementation of the Spark+Scala code
* snippets for performing recommendation dithering via an epsilon-based
* post-processing step using normally distributed random noise.
*
* Source:
* Hristakeva, M. (2015, November 12). Dithering.
* A Practical Guide to Building Recommender Systems.
* https://buildingrecommenders.wordpress.com/2015/11/11/dithering/
*/
const gaussian = require('gaussian');
function ditherRecsForUser (recommendations, epsilon) {
let variance = (epsilon > 1.0) ? Math.log(epsilon) : 1e-10;
let distribution = gaussian(0, variance);
/* Sort recommendations by score descending */
recommendations.sort((a, b) => (a.score > b.score) ? -1 : 1)
/* Calculate dither score by rank */
for (let ii in recommendations) {
let recommendation = recommendations[ii];
let rank = ii;
recommendation.ditherScore = (Math.log(rank + 1) + distribution.ppf(Math.random()));
}
/* Sort recommendations by ditherScore ascending */
recommendations.sort((a, b) => (a.ditherScore > b.ditherScore) ? 1 : -1)
return recommendations;
}
// Testing
function createNormalizedRecommendations (recommendationCount) {
const recommendations = [];
let sum = 0;
for (let ii = 1; ii <= recommendationCount; ++ii) {
let score = (recommendationCount - ii);
sum += score;
recommendations.push({ id: ii, score: score });
}
for (let ii in recommendations) {
recommendations[ii].score = (recommendations[ii].score / sum);
}
return recommendations;
}
let recommendations = createNormalizedRecommendations(30);
let epsilons = [1.0, 1.25, 1.5, 2.0, 2.5, 3.0, 5.0];
let table = [];
for (let ii in epsilons) {
let eps = epsilons[ii];
table.push(ditherRecsForUser(JSON.parse(JSON.stringify(recommendations)), eps));
}
let rows = [];
for (let ii in epsilons) {
epsilons[ii] = 'eps=' + epsilons[ii];
}
rows.push(epsilons);
for (let xx in table[0]) {
let row = [];
for (let yy in table) {
row.push(table[yy][xx].id);
}
rows.push(row);
}
console.table(rows);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment