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

net.librec.recommender.cf.ranking.BNPPFRecommeder Maven / Gradle / Ivy

The newest version!
package net.librec.recommender.cf.ranking;

import net.librec.common.LibrecException;
import net.librec.math.algorithm.Gamma;
import net.librec.math.algorithm.Randoms;
import net.librec.math.structure.*;
import net.librec.recommender.MatrixFactorizationRecommender;


/**
 * Gopalan, P., Ruiz, F. J., Ranganath, R., & Blei, D. M.
 * Bayesian Nonparametric Poisson Factorization for Recommendation Systems, ICAIS 2014
 *
 * @author Yatong Sun
 */

public class BNPPFRecommeder extends MatrixFactorizationRecommender {

    /** user Gamma shape */
    private double alpha;

    /** user Gamma rate */
    private double c;

    /** item Gamma shape */
    private double a;

    /** item Gamma rate */
    private double b;

    /** variational sticks */
    private DenseMatrix v;

    private DenseMatrix pi;

    private DenseMatrix logpi;

    private GammaDenseMatrixGR beta;

    private GammaDenseVector s;

    private DenseVector eBetaSum;

    private DenseVector eThetaSum;

    private DenseMatrix zUsers;
    private DenseMatrix zItems;

    private DenseVector userBudget;

    double d_scalar;

    @Override
    protected void setup() throws LibrecException {
        super.setup();
        alpha = conf.getDouble("rec.alpha", 0.3);
        c = conf.getDouble("rec.c", 0.3);
        a = conf.getDouble("rec.a", 0.3);
        b = conf.getDouble("rec.b", 0.3);

        //_beta.initialize();
        beta = new GammaDenseMatrixGR(numItems, numFactors, a, b);
        beta.init();

        //_s.initialize();
        s = new GammaDenseVector(numUsers, alpha, c);
        s.init();

        //initialize_sticks();
        v = new DenseMatrix(numUsers, numFactors);
        v.init(0.001);

        //compute_pi();
        pi = new DenseMatrix(numUsers, numFactors);
        logpi = new DenseMatrix(numUsers, numFactors);
        for (int u=0; u 0) {
                    lw += Math.log(1-v.get(u, k-1));
                }
                logpi.set(u, k, Math.log(v_value) + lw);

                double pi_value = Math.exp(v_value);
                pi.set(u, k, pi_value);
                userFactors.set(u, k, pi_value * s.value.get(u));
            }
        }

        eBetaSum = new VectorBasedDenseVector(numFactors);
        eThetaSum = new VectorBasedDenseVector(numFactors);

        zUsers = new DenseMatrix(numUsers, numFactors);
        zItems = new DenseMatrix(numItems, numFactors);
        userBudget = new VectorBasedDenseVector(numUsers);
        for (int u=0; u1) {
                        phi.times(y);
                    }

                    zUsers.set(u, zUsers.row(u).plus(phi));
                    zItems.set(itemIdx, zItems.row(itemIdx).plus(phi));
                }
            }
            updateSticks();

            update_sticks_scalar();

            updateItems();

        }

        itemFactors = new DenseMatrix(beta.value);

    }

    private void computeExpectations() {
        s.computeExpectations();
        beta.computeExpectations();
    }

    private void commputeSums() {
        computeEThetaSum();
        computeEBetaSum();
    }

    private void computeEThetaSum() {
        for (int k=0; k 0) {
                    pi.set(u, k, pi.get(u, k-1) / v.get(u, k-1) * (1-v.get(u, k-1)) * v_value);
                } else {
                    pi.set(u, k, v_value);
                }
                logpi.set(u, k, Math.log(pi.get(u, k)));
                userFactors.set(u, k, pi.get(u, k) * s.value.get(u));
            }
        }
    }

    private double[] sum_of_prod_in_range(int u, int K) {
        double sum = 0.0;
        double p = convert_oldpi_to_new(u, K-1);
        for (int k=K; k .0 && s1 <= 1.0 && s2 > .0 && s2 <= 1.0) {

            if (s1 < s2)
                return s1 + 1e-30;
            else
                return s2 + 1e-30;
        }

        if (s1 > .0 && s1 <= 1.0)
            return s1;

        if (s2 > .0 && s2 <= 1.0)
            return s2;

        // TODO
        if (Math.abs(s1 - .0) < 1e-30)
            return 1e-30;

        if (Math.abs(s1 - 1.0) < 1e-30)
            return 1 - 1e-30;

        if (Math.abs(s2 - .0) < 1e-30)
            return 1e-30;

        if (Math.abs(s2 - 1.0) < 1e-30)
            return 1 - 1e-30;

        return s1;
    }

    private void update_sticks_scalar() {
        for (int u=0; u= 0 && bv >= 0);
                if (av <= 0) {
                    a = 1e-30;
                } else {
                    a = av;
                }
                if (bv <= 0) {
                    b = 1e-30;
                } else {
                    b = bv;
                }
                value.set(i, a / b);
                logValue.set(i, Gamma.digamma(a) - Math.log(b));
            }
        }
    }

    public class GammaDenseMatrix {

        protected int numRows, numColumns;
        protected double shapePrior;
        protected double ratePrior;
        protected DenseMatrix shape;
        protected DenseMatrix rate;
        protected DenseMatrix value;
        protected DenseMatrix logValue;

        public GammaDenseMatrix(int _numRows, int _numColumns, double shapeP, double rateP) {
            shapePrior = shapeP;
            ratePrior = rateP;
            numRows = _numRows;
            numColumns = _numColumns;
            shape = new DenseMatrix(numRows, numColumns);
            rate = new DenseMatrix(numRows, numColumns);
            value = new DenseMatrix(numRows, numColumns);
            logValue = new DenseMatrix(numRows, numColumns);
        }

        public void init() {
            for (int i = 0; i < numRows; i++) {
                for (int j = 0; j < numColumns; j++) {
                    shape.set(i, j, shapePrior + 0.01 * Randoms.uniform(0.0, 1.0));

                    if (i == 0) {
                        rate.set(0, j, ratePrior + 0.1 * Randoms.uniform(0.0, 1.0));
                    } else {
                        rate.set(i, j, rate.get(0, j));
                    }
                }
            }

            for (int i = 0; i < numRows; i++) {
                for (int j = 0; j < numColumns; j++) {
                    value.set(i, j, shape.get(i, j) / rate.get(i, j));
                    logValue.set(i, j, Gamma.digamma(shape.get(i, j)) - Math.log(rate.get(i, j)));
                }
            }
        }

        public void computeExpectations() {
            double a = 0.0, b = 0.0;
            for (int i = 0; i < numRows; i++) {
                for (int j = 0; j < numColumns; j++) {
                    double av = shape.get(i, j);
                    double bv = rate.get(i, j);
                    // assert (av >= 0 && bv >= 0);
                    if (av <= 0) {
                        a = 1e-30;
                    } else {
                        a = av;
                    }
                    if (bv <= 0) {
                        b = 1e-30;
                    } else {
                        b = bv;
                    }
                    value.set(i, j, a / b);
                    logValue.set(i, j, Gamma.digamma(a) - Math.log(b));
                }
            }
        }
    }

    public class GammaDenseMatrixGR {

        protected int numRows, numColumns;
        protected double shapePrior;
        protected double ratePrior;
        protected DenseMatrix shape;
        protected DenseVector rate;
        protected DenseMatrix value;
        protected DenseMatrix logValue;

        public GammaDenseMatrixGR(int _numRows, int _numColumns, double shapeP, double rateP) {
            shapePrior = shapeP;
            ratePrior = rateP;
            numRows = _numRows;
            numColumns = _numColumns;
            shape = new DenseMatrix(numRows, numColumns);
            rate = new VectorBasedDenseVector(numColumns);
            value = new DenseMatrix(numRows, numColumns);
            logValue = new DenseMatrix(numRows, numColumns);
        }

        public void init() {
            for (int i = 0; i < numRows; i++) {
                for (int j = 0; j < numColumns; j++) {
                    shape.set(i, j, shapePrior + 0.01 * Randoms.uniform(0.0, 1.0));
                }
            }

            for (int j = 0; j < numColumns; j++) {
                rate.set(j, ratePrior + 0.1 * Randoms.uniform(0.0, 1.0));
            }

            for (int i = 0; i < numRows; i++) {
                for (int j = 0; j < numColumns; j++) {
                    value.set(i, j, shape.get(i, j) / rate.get(j));
                    logValue.set(i, j, Gamma.digamma(shape.get(i, j)) - Math.log(rate.get(j)));
                }
            }
        }

        public void computeExpectations() {
            double a = 0.0, b = 0.0;
            for (int i = 0; i < numRows; i++) {
                for (int j = 0; j < numColumns; j++) {
                    double av = shape.get(i, j);
                    double bv = rate.get(j);
                    // assert (av >= 0 && bv >= 0);
                    if (av <= 0) {
                        a = 1e-30;
                    } else {
                        a = av;
                    }
                    if (bv <= 0) {
                        b = 1e-30;
                    } else {
                        b = bv;
                    }
                    value.set(i, j, a / b);
                    logValue.set(i, j, Gamma.digamma(a) - Math.log(b));
                }
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy