You are here

protected function CFRecommender::computePrediction in Recommender API 7.6

1 call to CFRecommender::computePrediction()
CFRecommender::execute in classes/Recommender.php
Do all computation here.

File

classes/Recommender.php, line 115

Class

CFRecommender
This is the classical collaborative filtering implementation.

Code

protected function computePrediction() {

  // we do the computation based on $this->preferenceMatrix loaded in memory
  $this->userVectors = $this->preferenceMatrix
    ->row_vectors();

  // regardless of whether preferenceMatrix is a sparse matrix or not, predictionMatrix is always a sparseMatrix.
  $this->predictionMatrix = Matrix::create('SparseMatrix', $this->userNum, $this->itemNum);

  // calculate prediction for each user-item pair
  foreach ($this->userMap as $user_real_id => $user_matrix_index) {
    foreach ($this->itemMap as $item_real_id => $item_matrix_index) {

      // skip predictions on already existed preference ratings.
      if (!$this->isBooleanRecommender && !is_nan($this->preferenceMatrix
        ->get($user_matrix_index, $item_matrix_index)) || $this->isBooleanRecommender && $this->preferenceMatrix
        ->get($user_matrix_index, $item_matrix_index) != 0) {
        continue;
      }

      // $user_matrix_index is the current user's matrix index to computing. $j is the "similar users"
      $numerator = 0;
      $denominator = 0;
      for ($j = 0; $j < $this->userNum; $j++) {
        if ($j == $user_matrix_index) {
          continue;
        }

        // skip myself.
        if (is_nan($this->userVectors[$j]
          ->get($item_matrix_index))) {
          continue;
        }

        // if no rating from j, skip.
        $similarity_value = $this->similarityMatrix
          ->get($j, $user_matrix_index);
        if (is_nan($similarity_value)) {
          continue;
        }

        // skip if there is no similarity between $user_matrix_index and $j.
        $mean_j = $this->isBooleanRecommender ? $this->userVectors[$j]
          ->mean(TRUE) : $this->userVectors[$j]
          ->intersect_mean($this->userVectors[$user_matrix_index]);
        $normalized_j_score = $this->preferenceMatrix
          ->get($j, $item_matrix_index) - $mean_j;
        $numerator += $normalized_j_score * $similarity_value;
        $denominator += abs($similarity_value);
      }
      if ($denominator != 0) {
        $prediction = $this->userVectors[$user_matrix_index]
          ->mean(TRUE) + $numerator / $denominator;
        $this->predictionMatrix
          ->set($user_matrix_index, $item_matrix_index, $prediction);
      }
    }
  }
}