Creating a simple recommendation engine using Apache Mahout in Grails app

Posted By : Arun Kumar | 27-Nov-2012

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

About Author

Author Image
Arun Kumar

Arun is a creative UI Developer

Request for Proposal

Name is required

Comment is required

Sending message..