Package de.apaxo.bedcon

Source Code of de.apaxo.bedcon.FacebookRecommender

/*M///////////////////////////////////////////////////////////////////////////////////////
//
//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
//  By downloading, copying, installing or using the software you agree to this license.
//  If you do not agree to this license, do not download, install,
//  copy or use the software.
//
//
//                           License Agreement
//                For de.apaxo.bedcon.FacebookRecommender Bean
//
// Copyright (C) 2012, Apaxo GmbH, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistribution's of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//
//   * Redistribution's in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//
//   * The name of the copyright holders may not be used to endorse or promote products
//     derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Apaxo GmbH or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/

package de.apaxo.bedcon;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.annotation.PostConstruct;
import javax.ejb.Singleton;

import org.apache.commons.csv.CSVParser;
import org.apache.mahout.cf.taste.common.TasteException;
import org.apache.mahout.cf.taste.impl.common.FastByIDMap;
import org.apache.mahout.cf.taste.impl.model.GenericDataModel;
import org.apache.mahout.cf.taste.impl.model.GenericPreference;
import org.apache.mahout.cf.taste.impl.model.GenericUserPreferenceArray;
import org.apache.mahout.cf.taste.impl.model.MemoryIDMigrator;
import org.apache.mahout.cf.taste.impl.recommender.GenericBooleanPrefItemBasedRecommender;
import org.apache.mahout.cf.taste.impl.similarity.LogLikelihoodSimilarity;
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.apache.mahout.cf.taste.recommender.RecommendedItem;
import org.apache.mahout.cf.taste.recommender.Recommender;

/**
* This class implements the most simple recommender
* which is directly bundles as a war and can be used
* as a basis for doing recommendations.
*
* It is implemented as a singleton because keeping the
* data model in memory can be memory consuming.
* If you require parallel access or a pool of
* beans please consider using a static variable
* for a session bean or using the
* @javax.ejb.ConcurrencyManagement(javax.ejb.ConcurrencyManagementType)
*
* @author Manuel Blechschmidt <blechschmidt@apaxo.de>
*
*/
@Singleton
public class FacebookRecommender {

  /**
   * Log class which is used for sophisticated error
   * logging.
   */
  private Logger log = Logger.getLogger(FacebookRecommender.class.getName());
 
  /**
   * Recommender which will be hold by this
   * session bean.
   */
  private Recommender recommender = null;
 
  /**
   * An MemoryIDMigrator which is able to create for every string
   * a long representation. Further it can store the string which
   * were put in and it is possible to do the mapping back.
   */
  private MemoryIDMigrator thing2long = new MemoryIDMigrator();
 
  /**
   * The name of the file used for loading.
   */
  private static String DATA_FILE_NAME = "DemoFriendsLikes.csv";
 
  /**
   * A data model which is needed for the recommender implementation.
   * It provides a standardized interface for using the recommender.
   * The data model can be become quite memory consuming.
   * In our case it will be around 2 mb.
   */
  private static DataModel dataModel;
 
  /**
   * This function will init the recommender
   * it will load the CSV file from the resource folder,
   * parse it and create the necessary data structures
   * to create a recommender.
   * The
   */
  @PostConstruct
  public void initRecommender() {
    
    try {
      // get the file which is part of the WAR as
      URL url = getClass().getClassLoader().getResource(DATA_FILE_NAME);
     
      // create a file out of the resource
      File data = new File(url.toURI());
     
      // create a map for saving the preferences (likes) for
      // a certain person
      Map<Long,List<Preference>> preferecesOfUsers = new HashMap<Long,List<Preference>>();
     
      // use a CSV parser for reading the file
      // use UTF-8 as character set
      CSVParser parser = new CSVParser(new InputStreamReader(new FileInputStream(data), "UTF-8"));
     
      // parse out the header
      // we are not using the header
      String[] header = parser.getLine();
     
      // should output person name
      log.fine(header[0]+" "+header[1]);
     
     
      String[] line;
     
      // go through every line
      while((line = parser.getLine()) != null) {
     
        String person = line[0];
        String likeName = line[1];
       
        // other lines contained but not used
        // String category = line[2];
        // String id = line[3];
        // String created_time = line[4];
       
        // create a long from the person name
        long userLong = thing2long.toLongID(person);
       
        // store the mapping for the user
        thing2long.storeMapping(userLong, person);
       
        // create a long from the like name
        long itemLong = thing2long.toLongID(likeName);
       
        // store the mapping for the item
        thing2long.storeMapping(itemLong, likeName);
       
        List<Preference> userPrefList;
       
        // if we already have a userPrefList use it
        // otherwise create a new one.
        if((userPrefList = preferecesOfUsers.get(userLong)) == null) {
          userPrefList = new ArrayList<Preference>();
          preferecesOfUsers.put(userLong, userPrefList);
        }
        // add the like that we just found to this user
        userPrefList.add(new GenericPreference(userLong, itemLong, 1));
        log.fine("Adding "+person+"("+userLong+") to "+likeName+"("+itemLong+")");
      }
     
      // create the corresponding mahout data structure from the map
      FastByIDMap<PreferenceArray> preferecesOfUsersFastMap = new FastByIDMap<PreferenceArray>();
      for(Entry<Long, List<Preference>> entry : preferecesOfUsers.entrySet()) {
        preferecesOfUsersFastMap.put(entry.getKey(), new GenericUserPreferenceArray(entry.getValue()));
      }

      // create a data model
      dataModel = new GenericDataModel(preferecesOfUsersFastMap);
     
      // Instantiate the recommender
      recommender = new GenericBooleanPrefItemBasedRecommender(dataModel, new LogLikelihoodSimilarity(dataModel));
    } catch (URISyntaxException e) {
      log.log(Level.SEVERE, "Problem with the file URL", e);
    } catch (FileNotFoundException e) {
      log.log(Level.SEVERE, DATA_FILE_NAME+" was not found", e);
    } catch (IOException e) {
      log.log(Level.SEVERE, "Error during reading line of file", e);
    }
  }
 
  /**
   * Returns up to 10 recommendations for a certain person
   * as a string array. If less then 10 things are found
   * the array will contain less elements.
   * If no recommendations are found the array will contain 0
   * elements.
   * @param personName The Facebook name of the person
   * @return a string array with recommendations
   * @throws TasteException If anything goes wrong a TasteException is thrown
   */
  public String[] recommendThings(String personName) throws TasteException {
    List<String> recommendations = new ArrayList<String>();
    try {
      List<RecommendedItem> items = recommender.recommend(thing2long.toLongID(personName), 10);
      for(RecommendedItem item : items) {
        recommendations.add(thing2long.toStringID(item.getItemID()));
      }
    } catch (TasteException e) {
      log.log(Level.SEVERE, "Error during retrieving recommendations", e);
      throw e;
    }
    return recommendations.toArray(new String[recommendations.size()]);
  }
}
TOP

Related Classes of de.apaxo.bedcon.FacebookRecommender

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.