package org.shanbo.feluca.cf.stars.memory; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.util.Properties; import org.shanbo.feluca.cf.common.RatingInfo; import org.shanbo.feluca.cf.common.Recommender; import org.shanbo.feluca.cf.common.UserRatings; import org.shanbo.feluca.data2.DataEntry; import org.shanbo.feluca.data2.Vector; import org.shanbo.feluca.data2.DataStatistic; import org.shanbo.feluca.paddle.common.Utilities; public class SlopeOne implements Recommender{ DataEntry dataEntry; protected int maxiid ; protected float avgrating; private static final String modelName = "Slope One"; float[][] diffs = null; int[][] coRating = null; private void init_space(){ System.out.println(DataStatistic.MAX_FEATURE_ID + " : " + maxiid); System.out.println( modelName + " start loading~~~~~"); diffs = new float[maxiid + 1][]; coRating = new int[maxiid + 1][]; for(int i = 0 ; i <= maxiid; i++){ diffs[i] = new float[maxiid +1]; coRating[i] = new int[maxiid +1]; } System.out.println("initialize finish"); } public void loadData(DataEntry data) throws Exception { dataEntry = data; maxiid = Utilities.getIntFromProperties(this.dataEntry.getDataStatistic(), DataStatistic.MAX_FEATURE_ID); double totalWeight = Utilities.getDoubleFromProperties(this.dataEntry.getDataStatistic(),DataStatistic.SUM_WEIGHTS); int totalFeatures = Utilities.getIntFromProperties(this.dataEntry.getDataStatistic(),DataStatistic.TOTAL_FEATURES); avgrating = (float)(totalWeight / totalFeatures); } public void train() throws Exception { this.init_space(); UserRatings ur = new UserRatings(); for(Vector v = dataEntry.getNextVector(); v!= null; v = dataEntry.getNextVector()){ ur.setVector(v); int rates = ur.getItemNum(); for(int i = 0 ; i < rates-1; i++){ RatingInfo rii = ur.getRatingByIndex(i); int firstItem = rii.itemId; double firstRating = rii.rating; for(int j = i+1; j < rates; j++){ RatingInfo rij = ur.getRatingByIndex(j); //actually rii changed int secondItem = rij.itemId; double secondRating = rij.rating; diffs[firstItem][secondItem] += (float)(firstRating - secondRating); diffs[secondItem][firstItem] -= (float)(firstRating - secondRating); coRating[secondItem][firstItem] += 1; coRating[firstItem][secondItem] += 1; } } if (ur.getUid() % 2000 == 0){ System.out.print("."); } } System.out.println("finish~"); } public void setProperties(Properties prop) { } public Properties getProperties() { return null; } public double predict(UserRatings user, int itemId) throws Exception { if (user == null){ return -1; }else{ double predict = 0; int coRate = 0; for(RatingInfo ri = user.getNormalNextRating(); ri != null; ri = user.getNormalNextRating()){ predict += ri.rating * this.coRating[ri.itemId][itemId] - this.diffs[ri.itemId][itemId]; coRate += this.coRating[ri.itemId][itemId]; } return (float)(predict / coRate); } } public void saveModel(String filePath) throws Exception { BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(filePath)); ObjectOutputStream oos = new ObjectOutputStream(bos); oos.writeObject(this.diffs); oos.writeObject(this.coRating); oos.close(); bos.close(); } public void loadModel(String modelPath) throws Exception { BufferedInputStream bis = new BufferedInputStream(new FileInputStream(modelPath)); ObjectInputStream ois = new ObjectInputStream(bis); this.diffs = (float[][])ois.readObject(); this.coRating = (int[][])ois.readObject(); ois.close(); bis.close(); this.maxiid = this.diffs.length - 1; } public float[] predict(UserRatings user) throws Exception { if (user == null){ return null; }else{ float[] predicts = new float[this.maxiid + 1]; int[] coRatingsArray = new int[this.maxiid + 1]; //for each rated item for(RatingInfo ri = user.getNormalNextRating(); ri != null; ri = user.getNormalNextRating()){ float[] diffOfItem = diffs[ri.itemId]; int[] coRates = this.coRating[ri.itemId]; //get co-relation vector for(int i = 0 ; i <= this.maxiid; i++){ if (coRates[i] != 0){ predicts[i] += ri.rating * coRates[i] - diffOfItem[i]; coRatingsArray[i] += coRates[i]; } } } for(int i=0; i <= this.maxiid; i++){ if (coRatingsArray[i] != 0){ predicts[i] /= coRatingsArray[i]; } } return predicts; } } public float[] predict(UserRatings user, int[] itemIds) throws Exception { if (user == null){ return null; }else{ float[] predicts = new float[itemIds.length]; int[] coRatingsArray = new int[itemIds.length]; for(RatingInfo ri = user.getNormalNextRating(); ri != null; ri = user.getNormalNextRating()){ for( int i = 0 ; i < itemIds.length; i++){ predicts[i] += ri.rating * this.coRating[ri.itemId][itemIds[i]] - this.diffs[ri.itemId][itemIds[i]]; coRatingsArray[i] += this.coRating[ri.itemId][itemIds[i]]; } } for( int i = 0 ; i < itemIds.length; i++){ if (coRatingsArray[i] != 0){ predicts[i] /= coRatingsArray[i]; }else{ predicts[i] = avgrating; } } return predicts; } } // public Map<Integer, double[]> predict(List<UserRatings> users) // throws Exception { // Map<Integer, double[]> result = new HashMap<Integer, double[]>(); // for(UserRatings user : users){ // double[] predicts = this.predict(user); // result.put(user.getUid(), predicts); // } // return result; // } }