Blog

  • I have integrated mahout in one of my projects in grails so I wanted to share some thoughts on how we can create recommendation engine using Apache Mahout.

    First of all What is Apache Mahout ?

    The Apache Mahout is an open source machine learning library from Apache. It's goal is to build scalable machine learning libraries. The Algorithms Mahout implements fall under of machine learning or collective intelligence. Mahout has Collaborative Filtering, User and Item based recommender

    In This blog i am sharing thoughts about Mahout recommendations and various recommendation Algorithm.

    What is recommendation engine ?

    Recommender engines are the most recognizable machine learning technique used today. you have seen various services or sites that attempt to recommend Books or Movies based on your past actions. They try to infer tastes and preferences and identify unknown items that are of interest.

    Mahout provides various Algorithms to give better item recommendation to various user according to their taste.

    • 1. User-based recommender
    • 2. Item-based recommender
    • 3. Slope-one recommander

    The brief description about these algorithms are as follows-

    User-based recommender algorithm-

    The user-based recommender algorithm comes out of this intuition .It's a process of recommending items to some user, denoted by u, as seen below:

    for every item i that u has no preference for yet
        for every other user v that has a preference for i
        compute a similarity s between u and v
          incorporate v's preference for i, weighted by s, into a running average
    return the top items, ranked by weighted average.

    it would be terribly slow to examine every item. In reality a neighborhood of most similar users to computed first, and only items known to those users are considered:

    for every other user w
       compute a similarity s between u and w
      retain the top users , ranked by similarity , as a neighborhood n
         for every item i that some user in n has a preference for i
       compute a similarity s between u and v
         incorporate v's preference for i ,weighed by s, into a running average.

    The primary difference is that similar users are found first ,before seeing what those most-similar users are interested in.Those items becomes the candidates for recommendation. the rest are same.

    This is the standard user-based recommender algorithm and the way it's implemented in Mahout.

    Item-based recommender algorithm-

    Item-based recommendation is derived from how similar items are to items . instead of users to users.In Mahout this means they are based on an ItemSimilarity implemeention instead of UserSimilarity

    for every item i that u has no preference for yet
       for every item j that u has a preference for
      compute a similarity s between i and j
      add u's preference for j , weighted by s, to a running average
      return the top items ,ranked by weighted average.

    The third line in above algorithms shows how it's based on item-item similarities,not user-user similarities as before.

    Slope-one recommender algorithm-

    The Slope-one name comes from the fact that the recommender algorithm starts with the assumption that there's some linear relationship between preference values for one item and another,that it's valid to estimate the preferences for some item Y based on the preferences for item X ,via some linear function like Y=mX+b. Then the slope-one recommender makes the additional simplifying assumption that m=1 : slope one .It just remains to find b=Y-X, the (average) difference in preference value , for every pair of items.

    This means the algorithm consists of a significant preprocessing phase, in which all item-item preference value differences are computed:

    for every item i
      for every other item j
        for every user u expressing preference for both i and j
      add the difference in u's preference for i and j to an average.

    And then ,the recommendation algorithm looks like this:

    for every item i the user u expresses no preference for
       for every item j that user u expresses a preference for
      find the average preference difference between j and i
         add this diff to u's preference value for j
         add this to a running average
      return the top items ranked by these averages.

    Its performance does not depend upon the number of users in the data model. So Slope one is attractive and fast like an Item-based recommender.

    Now i am using Mahout-recommender plugin in grails to create a recommender.

    Hope you have integrated mahout in grails if not please follow steps from Mahout Integration with Grails

    After integrating mahout recommender plugin in grails app and configure data model with mysql using

         mahout.recommender.data.model='mysql'
    	

    in config.groovy

    Then create a TastePreferences domain class in your mysql database with userId , itemId and preference field something like that

    package mahoutrecommander
    import org.apache.commons.lang.builder.HashCodeBuilder
    
    class TastePreferences implements Serializable {
      long userId
      long itemId
      float preference
      static constraints = {
      	userId()
      	itemId()
     	preference range: 0.0f..5.0f
      }
    
      boolean equals(other) {
          if(!(other instanceof TastePreferences)) {
             return false
          }
          log.debug "other"
      	other.userId == userId && other.itemId == itemId
      }
    
      int hashCode() {
          def builder = new HashCodeBuilder()
          builder.append userId
          builder.append itemId
          builder.toHashCode()
      }
    
      static mapping = {
         id composite: ['userId', 'itemId']
         version false
      }
    }
        

    Bydefault plugin uses TastePreferences named domain class if you want to use any other table for mahout recommender you can configure it in config.groovy

    mahout.recommender.preference.table='tableName'
    mahout.recommender.preference.userIdColumn='userIdColumn'
    mahout.recommender.preference.itemIdColumn='itemIdColumn'
    mahout.recommender.preference.valueColumn='preference value'
        

    you can use mahout-recommender plugin via three mode

    • 1 input
    • 2 config
    • 3 class
    mahout.recommender.mode = 'input'  // 'input', 'config' or 'class' in config.groovy
    	

    if mode is 'input' then user can pass parameters to recommender controller something as follows-

    params.userID-user id of that user whom we are providing recommendation

    params.howMany- how many recommendation we want to show to the user otherwise it takes default value.

    params.hasPreference-it is boolean value it can be true or false.

    params.r- recommender selected like user-based recommender ,item-based recommender or slope-one recommender.

    params.s- similarity that can be pearson correlation, Euclidian distance ,Log-likelihood ,Tanimoto coefficient these are different approach to find out similarity.

    params.n-it contains neighborhood.

    params.w- it is a boolean value that give withWeighting or not.

    You can provide these values from config.groovy also as follows:

    mahout.recommender.mode="config" //in config of project. give these values in config.groovy.
    mahout.recommender.selected=' '
    mahout.recommender.hasPreference=' '
    mahout.recommender.similarity=' '
    mahout.recommender.withWeighting=' '
    mahout.recommender.neighborhood=' '
        

    and just pass userId and howMany in parameters to recommender controller all other recommender configuration it will pick from config file.

    And now last is class mode ,it is used to create custom recommender if you want to use this part then change

    mahout.recommander.mode="class"
    

    and also give name of that class in which you are building recommender.

    mahout.recommender.builderClass='className'
        

    You can use test data in TastePreferences table as follows to check recommender engine working.

    +---------+---------+------------+
    | user_id | item_id | preference |
    +---------+---------+------------+
    |       1 |     101 |          5 |
    |       1 |     102 |          3 |
    |       1 |     103 |          2 |
    |       2 |     101 |          2 |
    |       2 |     102 |        2.5 |
    |       2 |     103 |          5 |
    |       2 |     104 |          2 |
    |       3 |     101 |        2.5 |
    |       3 |     104 |          4 |
    |       3 |     105 |        4.5 |
    |       3 |     107 |          5 |
    |       4 |     101 |          5 |
    |       4 |     103 |          3 |
    |       4 |     104 |        4.5 |
    |       4 |     106 |          4 |
    |       5 |     101 |          4 |
    |       5 |     102 |          3 |
    |       5 |     103 |          2 |
    |       5 |     104 |          4 |
    |       5 |     105 |        3.5 |
    |       5 |     106 |          0 |
    +---------+---------+------------+

    Suppose our recommender mode is input in config when we start our project in grails it will show recommender controller in home page select that it will show an input form in which you can pass parameters as discussed above and click on submit button.

    Suppose we are using userId 1 in input field and want to give recommendation to user 1 then it will show result

     

    Now you are getting recommendation. Well that working fine.

    hope it helps ! to create recommendation in grails app.

    Arun kumar

Tags: bigdata , grails , mahout