opencf icon indicating copy to clipboard operation
opencf copied to clipboard

How to implement similarity recommendation based on goods? Can you write an example?

Open lujihong opened this issue 2 years ago • 6 comments

lujihong avatar May 09 '22 09:05 lujihong

sorry for the late reply, here is a quick example:

$dataset = [
    "Intel core i5-12400" => [
        "user1" => 1,
        "user2" => 1,
        "user3" => 0.2,
    ],
    "Intel core i5-12900k" => [
        "user1" => 0.5,
        "user3" => 0.4,
        "user4" => 0.9,
    ],
    "Ryzen 5 5600x" => [
        "user1" => 0.2,
        "user2" => 0.5,
        "user3" => 1,
        "user4" => 0.4,
    ],
    "Asus Prime B660" => [
        "user2" => 0.2,
        "user3" => 0.4,
        "user4" => 0.5,
    ],
];

$recommenderService = new RecommenderService($dataset);

$recommender = $recommenderService->weightedSlopeone(); // WeightedSlopeone recommender

Now let's say a new user enters your shop and rates the Intel core i5-12400 with 0.4, you can now predict his ratings for other goods in your shop based on what he already rated, and based on other ratings from other users.

// Predict future ratings
$results = $recommender->predict([
    "Intel core i5-12400" => 0.4
]);

[
  "Intel core i5-12900k" => 0.25,
  "Ryzen 5 5600x" => 0.23,
  "Asus Prime B660" => 0.1
];

the-dijkstra avatar Jul 26 '22 11:07 the-dijkstra

Thank you very much for your reply. Can this score only be in the range of 0.1-1? And can it be 0.01,0.15,0.001... Or something?

In addition, from which dimensions can each user's score be generated, and how many points are appropriate for each generated dimension?

Is there a real project case that can explain how scores are generated and stored? Thank you!

lujihong avatar Jul 28 '22 09:07 lujihong

@lujihong

  • The score can range from [0,1]. you can think of it as a percentage [0%, 100%].
  • This package has 3 schemes to calculate the similarity between 2 users. (Weighted Slopeone, Weighted cosine, Cosine). each similarity function has a requirements for the dimension. I believe the Slope-one function is the scheme that can operate with the least amount of data-points (u1[0.5,0.5], u2[0.7,0.8])
  • There is real project made with laravel but it's a little bit old and unmaintained. I will look for the link and attach it here.

the-dijkstra avatar Jul 28 '22 10:07 the-dijkstra

Here is a database diagram for an app that stores user ratings for visited venues. and serves recommendations based on the those ratings.

drawSQL-export-2022-07-28_12_01

And here is the function that builds the recommendation service from the ratings, assuming here that I have Model called Rating

Context: the following code snippets are taken from a Laravel app with the following models (User, Rating, Venue)

  • Venue HasMany Rating
  • User HasMany Rating
  • Rating BelongsTo Venue
  • Rating BelongsTo User
public function getRecommender() {
  foreach (Venue::with(['ratings'])->all() as $venue) {
          foreach($venue->ratings as $rating) {
                [$venue->id][$rating->user_id] = $rating->rating;
          }  
  }
  
  $recommenderService = new RecommenderService($dataset);
  return $recommender = $recommenderService->weightedSlopeone(); 
}

To get the predictions for the current user here is the function that does that:

public function getPredictions($request) {
      $currentUser = $request->user();

      $evaluations = [];
      
      foreach ($currentUser->ratings as $rating ) {
	      $evaluations[$rating->venue_id] = $rating->rating;
      }
      
      $recommender = $this->getRecommender();
      
      return $recommender->predict($evaluation);
}

If I manage to get a working laravel example I will attach it here.

the-dijkstra avatar Jul 28 '22 11:07 the-dijkstra

Thank you very much for your serious answer. I'll study it and ask you if I don't understand it.

lujihong avatar Jul 28 '22 11:07 lujihong

@lujihong great. good luck mate.

Note: I have updated the code to reflect the last version of the package.

the-dijkstra avatar Jul 28 '22 11:07 the-dijkstra