// Copyright (C) Chris Newell // // This file is part of MyMediaLite. // // MyMediaLite 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. // // MyMediaLite 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 MyMediaLite. If not, see <http://www.gnu.org/licenses/>. package org.mymedialite.examples; import java.util.Iterator; import org.apache.mahout.cf.taste.common.TasteException; import org.apache.mahout.cf.taste.impl.common.LongPrimitiveIterator; import org.apache.mahout.cf.taste.impl.recommender.svd.AbstractFactorizer; import org.apache.mahout.cf.taste.impl.recommender.svd.Factorization; import org.apache.mahout.cf.taste.model.DataModel; import org.apache.mahout.cf.taste.model.Preference; import org.apache.mahout.cf.taste.model.PreferenceArray; import org.mymedialite.data.PosOnlyFeedback; import org.mymedialite.datatype.SparseBooleanMatrix; import org.mymedialite.itemrec.MF; /** * Adaptor class between MyMediaLite and Mahout. * Allows a subclass of org.mymedialite.itemrec.MF to be used to create a * org.apache.mahout.cf.taste.impl.recommender.svd.Factorization * @version 2.03 */ public class TasteFactorizer extends AbstractFactorizer { private final DataModel dataModel; private final MF mf; /** * Create a factorizer from the supplied data model and MyMediaLite matrix factorization. * * See also org.apache.mahout.cf.taste.impl.recommender.svd.SVDRecommender * * @param dataModel the data model * @param mf the matrix factorization * @throws TasteException */ public TasteFactorizer(DataModel dataModel, MF mf) throws TasteException { super(dataModel); this.dataModel = dataModel; this.mf = mf; } @Override public Factorization factorize() throws TasteException { //System.out.println("TasteFactorizer.factorize(): Load data"); PosOnlyFeedback<SparseBooleanMatrix> posOnlyFeedback = null; try { posOnlyFeedback = new PosOnlyFeedback<SparseBooleanMatrix>(SparseBooleanMatrix.class); } catch (Exception e) { } if(dataModel == null) System.out.println("dataModel is null."); LongPrimitiveIterator itemIterator = dataModel.getItemIDs(); if(itemIterator == null) System.out.println("itemIterator model is null."); while (itemIterator.hasNext()) { long itemID = itemIterator.nextLong(); System.out.println("itemID = " + itemID); PreferenceArray preferenceArray = dataModel.getPreferencesForItem(itemID); if(preferenceArray == null) System.out.println("preferenceArray is null."); Iterator<Preference> preferenceIterator = preferenceArray.iterator(); while (preferenceIterator.hasNext()) { int userIndex = userIndex(preferenceIterator.next().getUserID()); int itemIndex = itemIndex(itemID); posOnlyFeedback.add(userIndex, itemIndex); } } mf.setFeedback(posOnlyFeedback); //System.out.println("TasteFactorizer.factorize(): train"); mf.train(); //System.out.println("TasteFactorizer.factorize(): Create user and item features arrays"); double[][] userFeatures = new double[mf.getUserFactors().numberOfRows()][mf.getUserFactors().numberOfColumns()]; for (int i = 0; i < mf.getUserFactors().numberOfRows(); i++) { for (int j = 0; j < mf.getUserFactors().numberOfColumns(); j++) { userFeatures[i][j] = mf.getUserFactors().get(i, j); } } double[][] itemFeatures = new double[mf.getItemFactors().numberOfRows()][mf.getItemFactors().numberOfColumns()]; for (int i = 0; i < mf.getItemFactors().numberOfRows(); i++) { for (int j = 0; j < mf.getItemFactors().numberOfColumns(); j++) { itemFeatures[i][j] = mf.getItemFactors().get(i, j); } } //System.out.println("TasteFactorizer: TasteFactorizer.factorize(): Create factorization"); return createFactorization(userFeatures, itemFeatures); } }