how to get user preference in mahout datamodel - mahout

I am trying out mahout and wondering about the input datamodel
for non-distributed version
file datamodel has to follow: userid, itemid, userPreference
the problem is i dont have this user preference values, have to precompute it
does mahout have any method to do it?
I found an article http://www.codeproject.com/Articles/620717/Building-A-Recommendation-Engine-Machine-Learning
the author seems did not really have user perference values, but he used org.apache.mahout.cf.taste.hadoop.item.RecommenderJob -s SIMILARITY_COOCCURRENCE
to compute from {userid, questionid}
from what I can tell, mahout seems compute perference values from data then compute recommendation, am I correct in this case?

If you don't have user preference values, maybe you don't need them. Mahout offers an implementation for recommending items for users without having preference values. This is called Boolean preferences. Basically you just know that some user likes some item, but you don't know how much. Sometimes this is fine.
Bellow is a sample code how this can be done. Basically only the first line differs, where you tell that your data model is of type BooleanPrefDataModel. Then with boolean data you can use two types of similarity measures: LogLikelihoodSimilarity, TanimotoCoefficientSimilarity. Both can be used for compute user-based and item-based recommendations.
DataModel model = new GenericBooleanPrefDataModel( GenericBooleanPrefDataModel.toDataMap( new FileDataModel(new File("FILE_NAME"))));
UserSimilarity similarity = new LogLikelihoodSimilarity(model);
UserNeighborhood neighborhood = new NearestNUserNeighborhood(10, similarity, model);
Reecommender recommender = new GenericUserBasedRecommender(model, neighborhood, similarity);
List<RecommendedItem> recommendations = recommender.recommend(1, 10);
for (RecommendedItem recommendation : recommendations) {
System.out.println(recommendation);
}
The other alternative is to compute the preference values outside mahout and feed the data model in some other user or item-based algorithms. But as far as I know, mahout does not offer implementation for computing preference values.

You can define preference value for your data model (but, it depends on your data model). For example, your data model items are tracks which are listened by users. The preferences value can be defined that user1 listens trackA x times. Thus, preferences value for data model should be defined for every userid-itemid unique pair.
The example of data model :
userid,itemid,preferences
1,1,3 -
1,2,5 -
.... -
5,1,2... so on.

Related

Creating an Item-based Recommender using Apache Mahout

I'm trying to use Apache Mahout to create an Item-based recommender that recommends back items based off of similar items that other users also have in common.
I start by creating a DataModel and then I've tried passing it into various different ItemSimilarity objects:
// Create data model
DataModel datamodel = new FileDataModel(new File("input.csv"));
// ItemSimilarity object
// ItemSimilarity similarity = new EuclideanDistanceSimilarity(datamodel);
// ItemSimilarity similarity = new PearsonCorrelationSimilarity(datamodel);
ItemSimilarity similarity = new CityBlockSimilarity(datamodel);
Then I pass the DataModel and ItemSimilarity into a GenericItemBasedRecommender and call the mostSimilarItems() function and pass it into a list.
ItemBasedRecommender irecommender = new GenericItemBasedRecommender(datamodel, similarity);
List<RecommendedItem> irecommendations = irecommender.mostSimilarItems(item, amount);
The CityBlockSimilarity() class worked great on a small data set, but as soon as I switched to a large data set it was no longer reliable.
Is there a different class I need to implement to return recommendations for an item based off of other items that users also have in common?
So it turns out the class I needed to implement was the TanimotoCoefficientSimilarity class. Once I changed this, I was seeing the results I wanted to see.
ItemSimilarity similarity = new TanimotoCoefficientSimilarity(datamodel);
I was able to leave everything else the same and it worked great! Here is a link to the TanimotoCoefficientSimilarity class if you want to read more about it.

Apache Mahout Training on Sample Data vs Implementing on Actual Data

The scenario is like this:
I am trying to make a recommender using apache mahaout and i have some sample preference(user,item,preference value) data for generating the similarity matrix and determining item-item similarities. But the actual preference data is much larger than the sample preference data. The list of item IDs that are present in the actual preference data are all present in the sample preference data as well. But the User ids in sample data are much lesser than the actual data.
Now, when i try to run the recommender on the actual data, it keeps giving me error that user id does not exist because it was not present in the sample data. How can i inject new user ids and their preferences in the recommender of mahout so that it can generate recommendations for any user on the fly based on item-item similarity? Or if there is any other way possible to generated recommendations for a new user, then please suggest.
Thanks.
If you think your sample data is complete for computing the item-item similarities, why don't you precompute them and use Collection<GenericItemSimilarity.ItemItemSimilarity> corrMatrix = new ArrayList<GenericItemSimilarity.ItemItemSimilarity>(); to store your precomputed similarities. Then from this you can create your ItemSimilarity like this: ItemSimilarity similarity = new GenericItemSimilarity(correlationMatrix);
I think it is not good idea for using sample of your data for computing item-item similarities based on the preference values, because you might be missing a lot of useful data. If you think that computing it on the fly is slow, you can always precomputed it and store it in a database, and load it when needed.
If you are still getting this error, than you probably use your sample data model in the recommendation class, or you use UserSimilarity to compute the item similarities.
If you want to add new user you can either use Mahout's FileDataModel and update the file periodically by including new users (I think you can create new file with some suffix, I am not sure). You can find more about this in the book Mahout in Action. The in-memory DataModel implementations are immutable. You can extend them by implementing the methods setPreference() and removePreference().
EDIT: I have an implementation for MutableDataModel that extends the AbstractDataModel. I can share it with you if you want.

Mahout Item-based recommendation engine with no preference values

I am trying to build a recommendation engine using Mahout that gives recommendations solely based on item-to-item similarity, not taking into account user preferences (i.e. ratings). The item similarities are calculated by some other process external to mahout and saved to a file. So far, I have determined that I can use the class:
GenericBooleanPrefItemBasedRecommender
...to pick items, which the documentation says is "appropriate for use when no notion of preference value exists in the data." However, the class still takes as input:
(DataModel dataModel, ItemSimilarity similarity)
I know I can use ItemSimilarity class to supply the item-to-item similarity value, but what is my datamodel in this case? I have no preferences, which seems to be the exact thing the datamodel represents. how do I work around this, or am I looking at the wrong thing here?
Here is a simple code how you can create an instance of your DataModel that uses GenericBooleanPrefDataModel
DataModel model = new GenericBooleanPrefDataModel(GenericBooleanPrefDataModel.toDataMap(new FileDataModel(new File("YOUR_FILE_NAME"))));
However, even if you have data model with preference values, and you have custom implementation of ItemSimilarity that does not use this preference values, you will get the desired result.
Best,
Dragan
Simply use a GenericBooleanPrefDataModel.

Could I define my own method to calculate UserSimilarity in Mahout's collaborative filtering?

I am using Apache Mahout's user-based collaborative filtering for recommender systems.
I have two questions.
1) Must the UserID and ItemID be numeric?
My datamodel looks like this:
jessestay,e/4d0b55757114464eb56cdf01bf5d6842,1
where "jessestay" is userID, "e/4d0b55757114464eb56cdf01bf5d6842" is itemID, "1" is the preference value from user to this item.
How could I encode the userID and ItemID to int or long?
2) When I am using UserSimilarity, must I use the built Euclidean Distance, Pearson Correlation Coefficient, or Spearman Correlation?
Could I define my own method to estimate userSimilarity?
This is my first time to use Apache Mahout's collaborative filtering.
Thank you very much for your help.
Looking forward to your reply!
xiao shen
Yes, user and item ID must be numeric. Just hash your values to longs. The only catch is that you have to remember the mapping to map back to strings. If you also have numeric IDs, it's better to use them.
Yes, just implement UserSimilarity to define whatever similarity you want.

Mahout -- Recommend for a type of people

I am a newbie learning mahout.
I learned that there are five recommenders in mahout. User-based, Item-based,...
The datasets I used is movielens 100K
I am thinking implement a little different movie recommender from user based one. i.e., instead of taking user id as an input to recommend movies to only one user, I want to take user demographic information, e.g., age range, gender, occupation, and zip code.
But the problem is how do I create my own user similarity method (The original one is taking two long type user id as parameters) and how do I combine u.user file and u.data file together?
I understand your question now. I think the simplest thing is to temporary create a dummy user with the demographic properties you are querying for, and then recommend for that dummy user.
Yes, you would have to write a UserSimilarity that implements whatever similarity rule you want on top of the demographic data.
Maybe there is another solution.
I implement my own Rescorer to deal with u.user file and input (gender, age range, ...). If each piece of information is equal, then I put the according user id into a FastIDSet.
Then, in the rescore method, I will check if the current user id is in FastIDSet, if yes, the augment the score.
In my own Recommender, I will use PlusAnoymousUserDataModel to get a temp id, and call the method recommen(id, howMany, rescorer)
However, after I tried different dataset file, I get 0 recommended item.
I am thinking whether it is the right way to use PlusAnoymousUserDataModel.

Resources