/** * The total number of users. * The number of row in matrix. */ publicint numUsers;
/** * The total number of items. * The number of column in matrix. */ publicint numItems;
/** * The total number of ratings (non-zero values) * The number of Rating in matrix. */ publicint numRatings;
/** * The predictions. */ publicdouble[] predictions;
/** * Compressed rating matrix. User-item-rating triples. * Just list 0:0:1 = user0:movie0:rating1. * In the variable maybe not continuous. */ publicint[][] compressedRatingMatrix;
/** * The degree of users (how many item he has rated). * if userDegrees[0] = 10, so user0 has 10 item what rated. */ publicint[] userDegrees;
/** * The average rating of the current user. */ publicdouble[] userAverageRatings;
/** * The degree of items (how many item has rated). */ publicint[] itemDegrees;
/** * The average rating of the current item. */ publicdouble[] itemAverageRatings;
/** * The first user start from 0. Let the first user has x ratings, the second * user will start from x. Also, we can use userDegrees to add. */ publicint[] userStartingIndices;
/** * Number of non-neighbor objects. */ privateint numNonNeighbors;
/** * The radius (delta) for determining the neighborhood. */ privatedouble radius;
/** * ************************ * Construct the rating matrix. * * @param paraFilename the rating filename. * @param paraNumUsers number of users * @param paraNumItems number of items * @param paraNumRatings number of ratings * ************************ */ publicMBR(String paraFilename, int paraNumUsers, int paraNumItems, int paraNumRatings)throws Exception { // Step 1. Initialize these arrays numItems = paraNumItems; numUsers = paraNumUsers; numRatings = paraNumRatings;
userDegrees = newint[numUsers]; userAverageRatings = newdouble[numUsers]; // The last one in userStartingIndices record the border index of the matrix. userStartingIndices = newint[numUsers + 1];
// use all ratings predictions = newdouble[numRatings];
System.out.println("Reading " + paraFilename);
// Step 2. Read the data file. FiletempFile=newFile(paraFilename); if (!tempFile.exists()) { System.out.println("File " + paraFilename + " does not exists."); System.exit(0); } // Of if BufferedReadertempBufReader=newBufferedReader(newFileReader(tempFile));
while ((tempString = tempBufReader.readLine()) != null) { // Each line has three values tempStrArray = tempString.split(","); compressedRatingMatrix[tempIndex][0] = Integer.parseInt(tempStrArray[0]); compressedRatingMatrix[tempIndex][1] = Integer.parseInt(tempStrArray[1]); compressedRatingMatrix[tempIndex][2] = Integer.parseInt(tempStrArray[2]);
if (tempIndex > 0) { // Starting to read the data of a new user. if (compressedRatingMatrix[tempIndex][0] != compressedRatingMatrix[tempIndex - 1][0]) { userStartingIndices[compressedRatingMatrix[tempIndex][0]] = tempIndex; } // Of if } // Of if tempIndex++; } // Of while tempBufReader.close();
double[] tempUserTotalScore = newdouble[numUsers]; double[] tempItemTotalScore = newdouble[numItems]; for (inti=0; i < numRatings; i++) { tempUserTotalScore[compressedRatingMatrix[i][0]] += compressedRatingMatrix[i][2]; tempItemTotalScore[compressedRatingMatrix[i][1]] += compressedRatingMatrix[i][2]; } // Of for i
for (inti=0; i < numUsers; i++) { userAverageRatings[i] = tempUserTotalScore[i] / userDegrees[i]; } // Of for i for (inti=0; i < numItems; i++) { itemAverageRatings[i] = tempItemTotalScore[i] / itemDegrees[i]; } // Of for i }// Of the first constructor
/** * ************************ * Set the radius (delta). * * @param paraRadius The given radius. * ************************ */ publicvoidsetRadius(double paraRadius) { if (paraRadius > 0) { radius = paraRadius; } else { radius = 0.1; } // Of if }// Of setRadius
/** * ************************ * Leave-one-out prediction. The predicted values are stored in predictions. * * @see #predictions * ************************ */ publicvoidleaveOneOutPrediction() { double tempItemAverageRating; // Make each line of the code shorter. int tempUser, tempItem, tempRating; System.out.println("\r\nLeaveOneOutPrediction for radius " + radius);
numNonNeighbors = 0; for (inti=0; i < numRatings; i++) { tempUser = compressedRatingMatrix[i][0]; tempItem = compressedRatingMatrix[i][1]; tempRating = compressedRatingMatrix[i][2];
// Step 1. Recompute average rating of the current item. // Use one for test, so we should cut the one. tempItemAverageRating = (itemAverageRatings[tempItem] * itemDegrees[tempItem] - tempRating) / (itemDegrees[tempItem] - 1);
// Step 2. Recompute neighbors, at the same time obtain the ratings of neighbors. // The same user with his different movies. inttempNeighbors=0; doubletempTotal=0; int tempComparedItem; for (intj= userStartingIndices[tempUser]; j < userStartingIndices[tempUser + 1]; j++) { tempComparedItem = compressedRatingMatrix[j][1]; if (tempItem == tempComparedItem) { continue;// Ignore itself. } // Of if
if (Math.abs(tempItemAverageRating - itemAverageRatings[tempComparedItem]) < radius) { tempTotal += compressedRatingMatrix[j][2]; tempNeighbors++; } // Of if } // Of for j
// Step 3. Predict as the average value of neighbors. if (tempNeighbors > 0) { predictions[i] = tempTotal / tempNeighbors; } else { predictions[i] = DEFAULT_RATING; numNonNeighbors++; } // Of if } // Of for i }// Of leaveOneOutPrediction
/** * ************************ * Compute the MAE based on the deviation of each leave-one-out. * * @author Shi-Huai Wen * ************************ */ publicdoublecomputeMAE() { doubletempTotalError=0; for (inti=0; i < predictions.length; i++) { tempTotalError += Math.abs(predictions[i] - compressedRatingMatrix[i][2]); } // Of for i
return tempTotalError / predictions.length; }// Of computeMAE
/** * ************************ * Compute the MAE based on the deviation of each leave-one-out. * * @author Shi-Huai Wen * ************************ */ publicdoublecomputeRSME() { doubletempTotalError=0; for (inti=0; i < predictions.length; i++) { tempTotalError += (predictions[i] - compressedRatingMatrix[i][2]) * (predictions[i] - compressedRatingMatrix[i][2]); } // Of for i