Skip to content

Instantly share code, notes, and snippets.

@Mohamed-Code-309
Last active June 10, 2023 18:24
Show Gist options
  • Save Mohamed-Code-309/ae335b2c009a8d69a6473d1f9d9755e2 to your computer and use it in GitHub Desktop.
Save Mohamed-Code-309/ae335b2c009a8d69a6473d1f9d9755e2 to your computer and use it in GitHub Desktop.

Applying KNN algorithm πŸ€– to build a recommendation system based on users behavior πŸ€”πŸ›’

  1. What is K-Nearest Neighbor (KNN) Algorithm
  2. Use Case : Recommend the right products to a customer
  3. Steps Needed To Implement KNN Algorithm
  4. Full Code Demonstration
  5. Code Breakdown and Analysis
  6. Conclusion

KNN is one of the simplest forms of machine learning algorithms mostly used for classification. KNN algorithm assumes the similarity between the new case/data and available cases/dataset and put the new case into the category that is most similar to the available categories.

For example, if we have a dataset of tomatoes and bananas. KNN will store similar measures like shape and color. When a new object comes it will check its similarity with the color (red or yellow) and shape features and based on the most similar features it will put it in either tomatoes or bananas category.

Table of contents ☝️


We will use The KNN algorithm to recommend products to users based on their purchase history. It works by finding other users who have similar purchase histories to the current user, and then recommending products that those similar users have bought, but the current user has not.

In order to find similar users, the algorithm looks at the purchase histories of all users and calculates how similar each user is to the current user. The more similar a user is, the more weight their purchase history is given when recommending products.

For example, if User A has bought a certain set of products, and Users B, C, and D have also bought those same products and other different products, the KNN algorithm will recommend the other different products to User A. This is because Users B, C, and D are similar to User A based on their purchase history.

Overall, the KNN algorithm recommends products to a user based on the purchasing behavior of other users who have similar purchase histories.

Table of contents ☝️


To implement KNN algorithm to recommend products for a certain user, you would need the following inputs:

1. The purchase history of the user you want to recommend products for.

2. The purchase history of all other users.

3. A value of k that determines the number of nearest neighbors to consider when making recommendations.

4. A similarity measure to determine the similarity between the purchase histories of users. This can be based on various factors, such as shared purchases.

With these inputs, you can use the KNN algorithm to find the k nearest neighbors (similar users) to the user based on their purchase history, and then recommend products that those neighbors (users) have purchased but the user has not.

Table of contents ☝️


I'm going to demonstrate the full code for the KNN algorithm in JavaScript and then break it down step by step to analyze how it works.

Here's a full example of KNN algorithm in JavaScript :

//[1] Define the user purchase history as an array of purchased products
const userPurchases = ['A', 'B'];

//[2] Define the purchase histories of other users as arrays of purchased products
const userHistories = [
    {
        name: 'User1',
        purchases: ['A', 'B', 'C'],
    },
    {
        name: 'User2',
        purchases: ['B', 'C'],
    },
    {
        name: 'User3',
        purchases: ['A', 'C', 'D'],
    },
    {
        name: 'User4',
        purchases: ['A', 'B', 'C', 'E'],
    }
];

//[3] Define the number of nearest neighbors to consider (similar users)
const k = 2;

//[4] Calculate the similarity between the current user and each other user
function getSimilarities(userPurchases, userHistories) {
    const result = [];
    userHistories.map((history) => {
        let similarity = 0;

        // Iterate over each product in the user's purchase history
        for (const product of history.purchases) {
            // If the user purchased this product
            if (userPurchases.includes(product)) {
                similarity++;
            }
        }
        // Return the similarity score and the user's name
        result.push({ similarity, name: history.name });
    });
    return result;
}

//[4-1] store the result of the similarity measure
const similarities = getSimilarities(userPurchases, userHistories);

//[4-2] Sort the similarities in descending order
similarities.sort((a, b) => b.similarity - a.similarity);

//[5] Get the names of the k nearest neighbors based on k value and the result of step [4] 
const nearestNeighbors = similarities.slice(0, k).map((similarity) => similarity.name);

//[6] Iterate over each of the nearest neighbors
function recommendProducts(userPurchases, userHistories, nearestNeighbors) {
    // Define an array of recommended products
    const recommendedProducts = [];

    nearestNeighbors.forEach((neighbor) => {
        // Iterate over each product in the neighbor's purchase history
        for (const product of userHistories.find((user) => user.name === neighbor).purchases) {
            // If the neighbor has purchased this product and the current user has not
            if (userPurchases.indexOf(product) === -1) {
                // Add this product to the recommended products array
                recommendedProducts.push(product);
            }
        }
    });
    return recommendedProducts;
}



const productsToTRecommend = recommendProducts(userPurchases, userHistories, nearestNeighbors);
// Print the recommended products
console.log(productsToTRecommend);  //Output: [ 'C', 'C', 'E' ]

Table of contents ☝️


Here's a step-by-step breakdown of the code:

  1. First, we define an array userPurchases that represents the products purchased by the user we want to recommend new products to.

    const userPurchases = ['A', 'B'];
  2. We define an array of objects userHistories that represents the purchase history of all users. Each object has a name property and a purchases property, which is an array of products purchased by that user.

    const userHistories = [
        {
            name: 'User1',
            purchases: ['A', 'B', 'C'],
        },
        {
            name: 'User2',
            purchases: ['B', 'C'],
        },
        {
            name: 'User3',
            purchases: ['A', 'C', 'D'],
        },
        {
            name: 'User4',
            purchases: ['A', 'B', 'C', 'E'],
        }
    ];

  1. We define a variable k that represents the number of nearest neighbors (similar users) we want to consider when recommending products.

    const k = 2;

  1. We define a function getSimilarities that calculates the similarity score between the user we want to recommend products to and all other users.

    function getSimilarities(userPurchases, userHistories) {
        const result = [];
        userHistories.map((history) => {
            let similarity = 0;
            // Iterate over each product in the user's purchase history
            for (const product of history.purchases) {
                // If the user purchased this product
                if (userPurchases.includes(product)) {
                    similarity++;
                }
            }
            // Return the similarity score and the user's name
            result.push({ similarity, name: history.name });
        });
        return result;
    }
    
    const similarities = getSimilarities(userPurchases, userHistories);
  • This code defines a function getSimilarities() that takes two arguments: userPurchases and userHistories. It then creates an empty array result to store the similarity scores and user names for each user in userHistories.

  • The map method is called on userHistories, which iterates over each element in userHistories and applies a function to each element. The function calculates the similarity score between each user's purchase history and userPurchases.

  • To calculate the similarity score, the function first initializes a variable similarity to 0. Then, it iterates over each product in the user's purchase history using a for-of loop. For each product, it checks if userPurchases includes the product. If it does, the similarity score is incremented by 1.

  • After calculating the similarity score, the function pushes an object with the user's name and similarity score to the result array.

  • Finally, the function returns the result array.


  1. We store the result of calling getSimilarities() function in a variable similarities.

    const similarities = getSimilarities(userPurchases, userHistories);
  • The result of calling getSimilarities() function will be :
    [
    { similarity: 2, name: 'User1' },
    { similarity: 1, name: 'User2' },
    { similarity: 1, name: 'User3' },
    { similarity: 2, name: 'User4' }
    ]

  1. We sort the similarities array in descending order based on the similarity score.
    similarities.sort((a, b) => b.similarity - a.similarity);
  • By sorting the array in descending order, we can easily select the top k similar users using the slice method as we will do in the next step.

  1. We extract the top k similar users from the similarities array and store their names in an array nearestNeighbors.

    const nearestNeighbors = similarities.slice(0, k).map((similarity) => similarity.name);
  • The result of logging nearestNeighbors variable will be :
    [ 'User1', 'User4' ]

  1. We define a function recommendProducts() that recommends products based on the purchase history of the k nearest neighbors. The function returns an array of recommended products.

    function recommendProducts(userPurchases, userHistories, nearestNeighbors) {
        // Define an array of recommended products
        const recommendedProducts = [];
    
        nearestNeighbors.forEach((neighbor) => {
            // Iterate over each product in the neighbor's purchase history
            for (const product of userHistories.find((user) => user.name === neighbor).purchases) {
                // If the neighbor has purchased this product and the current user has not
                if (userPurchases.indexOf(product) === -1) {
                    // Add this product to the recommended products array
                    recommendedProducts.push(product);
                }
            }
        });
        return recommendedProducts;
    }
  • The function starts by defining an empty array called recommendedProducts, which will eventually contain the products that we recommend to the user.

  • The function then iterates over each neighbor in the nearestNeighbors array using the forEach method. For each neighbor, the function finds their purchase history using the find method to search the userHistories array for the object with a name property equal to the neighbor's name.

  • For each product in the neighbor's purchase history, the function checks if the current user has not already purchased the product (using the indexOf method to search the userPurchases array).

  • If the product has not been purchased by the current user, the function adds it to the recommendedProducts array using the push method.

  • Finally, the function returns the recommendedProducts array, which contains the products that we recommend to the user based on the purchase histories of their nearest neighbors

  • The result of calling recommendProducts() function will be :

    [ 'C', 'C', 'E' ]
  • To make sure that the recommendProducts() function return array contains only unique products, we can use a Set data structure to store the recommended products.

  • A Set automatically removes duplicates, so you can simply add all the recommended products to the set and then convert the set back to an array

  • Here's an updated version of the recommendProducts() function that uses a Set to store the recommended products:

    function recommendProducts() {
        // Define a Set of recommended products
        const recommendedProductsSet = new Set();
    
        nearestNeighbors.forEach((neighbor) => {
            // Iterate over each product in the neighbor's purchase history
            for (const product of userHistories.find((user) => user.name === neighbor).purchases) {
                // If the neighbor has purchased this product and the current user has not
                if (userPurchases.indexOf(product) === -1) {
                    // Add this product to the recommended products Set
                    recommendedProductsSet.add(product);
                }
            }
        });
        // Convert the recommended products Set to an array
        const recommendedProducts = Array.from(recommendedProductsSet);
        return recommendedProducts;
    }
    
    
    const productsToTRecommend = recommendProducts();
    // Print the recommended products
    console.log(productsToTRecommend);  //Output: [ 'C', 'E' ] instead of [ 'C', 'C', 'E' ]

Table of contents ☝️


The KNN algorithm is one of the simplest classification algorithms. It’s easy to implement and understand, but has a major drawback of becoming significantly slows as the size of that dataset in use grows. Finally, we looked at an example of how the KNN algorithm could be used to recommend the right products or services to customers using javascript.

Table of contents ☝️


Links:

πŸ•΄οΈ Linkedin: Dragon Slayer 🐲
πŸ“ Articles: All Articles written by D.S

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment