All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.librec.recommender.cf.rating.AspectModelRecommender Maven / Gradle / Ivy

/**
 * Copyright (C) 2016 LibRec
 * 

* This file is part of LibRec. * LibRec is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. *

* LibRec is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. *

* You should have received a copy of the GNU General Public License * along with LibRec. If not, see . */ package net.librec.recommender.cf.rating; import com.google.common.collect.HashBasedTable; import com.google.common.collect.Table; import net.librec.common.LibrecException; import net.librec.math.algorithm.Gaussian; import net.librec.math.algorithm.Randoms; import net.librec.math.structure.DenseMatrix; import net.librec.math.structure.DenseVector; import net.librec.math.structure.MatrixEntry; import net.librec.recommender.ProbabilisticGraphicalRecommender; import java.util.HashMap; import java.util.Map; /** *

Latent class models for collaborative filtering

*

* This implementation refers to the method proposed by Thomas et al. at IJCAI 1999. *

* Tempered EM: Thomas Hofmann, Latent class models for collaborative filtering * , IJCAI. 1999, 99: 688-693. * * @author guoguibin and Haidong Zhang */ public class AspectModelRecommender extends ProbabilisticGraphicalRecommender { /* * Conditional distribution: P(u|z) */ protected DenseMatrix topicUserProbs, topicUserProbsSum; /* * Conditional distribution: P(i|z) */ protected DenseMatrix topicItemProbs, topicItemProbsSum; /* * topic distribution: P(z) */ protected DenseVector topicProbs, topicProbsSum; /* * */ protected DenseVector topicProbsMean, topicProbsMeanSum; /* * */ protected DenseVector topicProbsVariance, topicProbsVarianceSum; /* * number of topics */ protected int numTopics; /* * small value */ protected static double smallValue = 0.0000001; /* * {user, item, {topic z, probability}} */ protected Table> Q; @Override protected void setup() throws LibrecException { super.setup(); numTopics = conf.getInt("rec.factory.number", 10); // Initialize topic distribution topicProbs = new DenseVector(numTopics); topicProbsSum = new DenseVector(numTopics); double[] probs = Randoms.randProbs(numTopics); for (int z = 0; z < numTopics; z++) { topicProbs.set(z, probs[z]); } // intialize conditional distribution P(u|z) topicUserProbs = new DenseMatrix(numTopics, numUsers); topicUserProbsSum = new DenseMatrix(numTopics, numUsers); for (int z = 0; z < numTopics; z++) { probs = Randoms.randProbs(numUsers); for (int u = 0; u < numUsers; u++) { topicUserProbs.set(z, u, probs[u]); } } // initialize conditional distribution P(i|z) topicItemProbs = new DenseMatrix(numTopics, numItems); topicItemProbsSum = new DenseMatrix(numTopics, numItems); for (int z = 0; z < numTopics; z++) { probs = Randoms.randProbs(numItems); for (int i = 0; i < numItems; i++) { topicItemProbs.set(z, i, probs[i]); } } // initialize Q Q = HashBasedTable.create(); for (MatrixEntry me : trainMatrix) { int u = me.row(); int i = me.column(); Q.put(u, i, new HashMap()); } // double globalMean = trainMatrix.mean(); topicProbsMean = new DenseVector(numTopics); topicProbsVariance = new DenseVector(numTopics); topicProbsMeanSum = new DenseVector(numTopics); topicProbsVarianceSum = new DenseVector(numTopics); for (int z = 0; z < numTopics; z++) { topicProbsMean.set(z, globalMean); topicProbsVariance.set(z, 2); } } @Override protected void trainModel() throws LibrecException { super.trainModel(); } @Override protected void eStep() { // variational inference to compute Q for (MatrixEntry me : trainMatrix) { int u = me.row(); int i = me.column(); double r = me.get(); double denominator = 0; double[] numerator = new double[numTopics]; for (int z = 0; z < numTopics; z++) { double val = topicProbs.get(z) * topicUserProbs.get(z, u) * topicItemProbs.get(z, i) * Gaussian.pdf(r, topicProbsMean.get(z), topicProbsVariance.get(z)); numerator[z] = val; denominator += val; } Map QTopicProbs = Q.get(u, i); for (int z = 0; z < numTopics; z++) { double prob = (denominator > 0 ? numerator[z] / denominator : 0.0d); QTopicProbs.put(z, prob); } } } @Override protected void mStep() { topicProbsSum.setAll(0.0); topicUserProbsSum.setAll(0.0); topicItemProbsSum.setAll(0.0); topicProbsMeanSum.setAll(0.0); topicProbsVarianceSum.setAll(0.0); for (int z = 0; z < numTopics; z++) { for (MatrixEntry me : trainMatrix) { int u = me.row(); int i = me.column(); double r = me.get(); double val = Q.get(u, i).get(z); topicProbsSum.add(z, val); topicUserProbsSum.add(z, u, val); topicItemProbsSum.add(z, i, val); topicProbsMeanSum.add(z, r * val); } topicProbsSum.add(z, smallValue); topicProbs.set(z, topicProbsSum.get(z) / numRates); for (int u = 0; u < numUsers; u++) { topicUserProbs.set(z, u, topicUserProbsSum.get(z, u) / topicProbsSum.get(z)); } for (int i = 0; i < numItems; i++) { topicItemProbs.set(z, i, topicItemProbsSum.get(z, i) / topicProbsSum.get(z)); } double mean = topicProbsMeanSum.get(z) / topicProbsSum.get(z); for (MatrixEntry me : trainMatrix) { int u = me.row(); int i = me.column(); double r = me.get(); double val = Q.get(u, i).get(z); topicProbsVarianceSum.add(z, (r - mean) * (r - mean) * val); } topicProbsMean.set(z, mean); topicProbsVariance.set(z, (topicProbsVarianceSum.get(z) + smallValue) / topicProbsSum.get(z)); } } @Override protected void readoutParams() { } @Override protected void estimateParams() { } @Override protected double predict(int userIdx, int itemIdx) throws LibrecException { double predictRating = 0.0d; double denominator = 0.0d; for (int z = 0; z < numTopics; z++) { double weight = topicProbs.get(z) * topicUserProbs.get(z, userIdx) * topicItemProbs.get(z, itemIdx); denominator += weight; predictRating += weight * topicProbsMean.get(z); } predictRating = predictRating / denominator; return predictRating; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy