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

net.librec.recommender.cf.ranking.FISMaucRecommender 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.ranking; import com.google.common.cache.LoadingCache; import net.librec.annotation.ModelData; import net.librec.common.LibrecException; import net.librec.math.algorithm.Randoms; import net.librec.math.structure.DenseMatrix; import net.librec.math.structure.DenseVector; import net.librec.math.structure.SparseVector; import net.librec.recommender.MatrixFactorizationRecommender; import java.util.List; import java.util.concurrent.ExecutionException; /** * Kabbur et al., FISM: Factored Item Similarity Models for Top-N Recommender Systems, KDD 2013. * * @author SunYatong */ @ModelData({"isRanking", "fismrmse", "P", "Q", "itemBiases", "userBiases"}) public class FISMaucRecommender extends MatrixFactorizationRecommender { private float rho,alpha,beta,gamma; /** * bias regularization */ private double lRate; /** * items and users biases vector */ private DenseVector itemBiases; /** * two low-rank item matrices, an item-item similarity was learned as a product of these two matrices */ private DenseMatrix P, Q; /** * user-items cache, item-users cache */ protected LoadingCache> userItemsCache; /** * Guava cache configuration */ protected static String cacheSpec; @Override protected void setup() throws LibrecException { super.setup(); P = new DenseMatrix(numItems, numFactors); Q = new DenseMatrix(numItems, numFactors); P.init(0,0.01); Q.init(0,0.01); itemBiases = new DenseVector(numItems); itemBiases.init(0,0.01); rho = conf.getFloat("rec.fismauc.rho");//3-15 alpha = conf.getFloat("rec.fismauc.alpha",0.5f); beta = conf.getFloat("rec.fismauc.beta",0.6f); gamma=conf.getFloat("rec.fismauc.gamma",0.1f); lRate=conf.getDouble("rec.iteration.learnrate",0.0001); cacheSpec = conf.get("guava.cache.spec", "maximumSize=200,expireAfterAccess=2m"); userItemsCache = trainMatrix.rowColumnsCache(cacheSpec); userItemsCache = trainMatrix.rowColumnsCache(cacheSpec); } @Override protected void trainModel() throws LibrecException{ for (int iter = 1; iter <= numIterations; iter++) { loss = 0; // for all u in C for (int u = 0; u < numUsers; u++) { SparseVector Ru = trainMatrix.row(u); int Ru_p_size = Ru.size(); if(Ru_p_size == 0 || Ru_p_size == 1) { Ru_p_size = 2; } // for all i in Ru+ for (int i : Ru.getIndex()) { // x <- 0 DenseVector x = new DenseVector(numFactors); x.init(0); // t <- (n - 1)^(-alpha) Σ pj (j!=i) DenseVector t = new DenseVector(numFactors); t.init(0); for (int j : Ru.getIndex()) { if(i != j){ t = t.add(P.row(j)); } } t = t.scale(Math.pow(Ru_p_size - 1, -alpha)); for (int tindex = 0; tindex < numFactors; tindex ++) { if (Double.isNaN(t.get(tindex))) { LOG.info("user:" + u + ", item:" + i + ", Ru_p_size:" + Ru_p_size); } } // Z <- SampleZeros(rho) int sampleSize = (int)(rho * Ru_p_size); // make a random sample of negative feedback for Ru- List negative_indices = null; try { negative_indices = Randoms.randInts(sampleSize, 0, numItems); for (int list_idx = 0; list_idx < negative_indices.size(); list_idx++) { int index = negative_indices.get(list_idx); // if negative_indices contains positive index, remove it if (Ru.get(index) > 0.1) { negative_indices.remove(list_idx); } } } catch (Exception e) { e.printStackTrace(); } // for all j in Z for (int j : negative_indices) { double bi = itemBiases.get(i); double bj = itemBiases.get(j); // update pui puj rui ruj double rui = Ru.get(i); double pui = bi + Q.row(i).inner(t); double puj = bj + Q.row(j).inner(t); double ruj = 0.0; double e = (rui - ruj) - (pui - puj); loss += e*e; // update bi bj itemBiases.add(i, lRate * (e - gamma * bi)); itemBiases.add(j, lRate * (e - gamma * bj)); // update qi qj DenseVector delta_qi=t.scale(e).minus(Q.row(i).scale(beta)); DenseVector qi = Q.row(i).add(delta_qi.scale(lRate)); Q.setRow(i, qi); DenseVector delta_qj=t.scale(e).minus(Q.row(j).scale(beta)); DenseVector qj = Q.row(j).add(delta_qj.scale(lRate)); Q.setRow(j, qj); // update x x = x.add(qi.minus(qj).scale(e)); } // for all j in Ru+\{i} for (int j : Ru.getIndex()) { if (j != i) { // update pj DenseVector delta_pj = x.scale(Math.pow(rho, -1) * Math.pow(Ru_p_size - 1, -alpha)).minus(P.row(j).scale(beta)); P.setRow(j, P.row(j).add(delta_pj.scale(lRate))); } } } } for (int i = 0; i ratedItems = null; try { ratedItems = userItemsCache.get(u); } catch (ExecutionException e) { e.printStackTrace(); } for (int i : ratedItems) { // for test, i and j will be always unequal as j is unrated if (i != j) { sum += DenseMatrix.rowMult(P, i, Q, j); count++; } } double wu = count > 0 ? Math.pow(count, -alpha) : 0; return pred + wu * sum; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy