Ok, sorry for being unclear.
I wrote at the end there in mail 1 "Running recommendations from
Account (User) doesn't return any
recommendations at all.". That's the userbased recommender. It didn't
throw any exceptions like the item-based recommender, but it also
didn't (and doesn't) return anything. I did flip the values in the
DataModel for the item-based recommender like you suggested, and it
now works. The DataModel for the user-based recommender is unchanged.
So in total for the user-based recommender the code now is:
The DataModel.
--------------------
public class WorkDataModel implements DataModel {
org.apache.mahout.cf.taste.model.DataModel delegate;
public WorkDataModel(ArrangementDAO arrangementDAO,
ReviewDAO reviewDAO, List<Arrangement> arrangements) {
super();
this.arrangementDAO = arrangementDAO;
this.reviewDAO = reviewDAO;
this.arrangements = arrangements;
refresh();
FastByIDMap<PreferenceArray> users = readUsers();
delegate = new GenericDataModel(users);
}
private FastByIDMap<PreferenceArray> readUsers() {
FastByIDMap<Collection<Preference>> userIDPrefMap = new
FastByIDMap<Collection<Preference>>();
for (Review r : reviews) {
Collection<Preference> userPrefs =
userIDPrefMap.get(r.getReviewer().getId());
if (userPrefs == null) {
userPrefs = new ArrayList<Preference>(2);
userIDPrefMap.put(r.getReviewer().getId(),
userPrefs);
}
userPrefs.add(new GenericPreference(
r.getReviewer().getId(),
r.getArrangement().getId(),
r.getValue()));
}
return GenericDataModel.toDataMap(userIDPrefMap, true);
}
@Override
public LongPrimitiveIterator getUserIDs() throws TasteException {
LongPrimitiveIterator userIDs = delegate.getUserIDs();
return userIDs;
}
@Override
public PreferenceArray getPreferencesFromUser(long id) throws
TasteException {
PreferenceArray preferencesFromUser =
delegate.getPreferencesFromUser(id);
return preferencesFromUser;
}
@Override
public FastIDSet getItemIDsFromUser(long userID) throws TasteException {
FastIDSet itemIDsFromUser = delegate.getItemIDsFromUser(userID);
return itemIDsFromUser;
}
@Override
public LongPrimitiveIterator getItemIDs() throws TasteException {
LongPrimitiveIterator itemIDs = delegate.getItemIDs();
return itemIDs;
}
@Override
public PreferenceArray getPreferencesForItem(long itemID)
throws TasteException {
PreferenceArray preferencesForItem =
delegate.getPreferencesForItem(itemID);
return preferencesForItem;
}
@Override
public Float getPreferenceValue(long userID, long itemID)
throws TasteException {
Float preferenceValue = delegate.getPreferenceValue(userID,
itemID);
return preferenceValue;
}
@Override
public int getNumItems() throws TasteException {
int numItems = delegate.getNumItems();
return numItems;
}
@Override
public int getNumUsers() throws TasteException {
int numUsers = delegate.getNumUsers();
return numUsers;
}
@Override
public int getNumUsersWithPreferenceFor(long... itemIDs)
throws TasteException {
int numUsersWithPreferenceFor =
delegate.getNumUsersWithPreferenceFor(itemIDs);
return numUsersWithPreferenceFor;
}
@Override
public void setPreference(long userID, long itemID, float value) {
throw new UnsupportedOperationException();
}
@Override
public void removePreference(long userID, long itemID) {
throw new UnsupportedOperationException();
}
@Override
public void refresh(Collection<Refreshable> alreadyRefreshed) {
// do nothing
}
private ReviewDAO reviewDAO;
private ArrangementDAO arrangementDAO;
private List<Arrangement> arrangements;
private List<Review> reviews;
public void refresh() {
if (arrangements == null) {
arrangements = arrangementDAO.getAll();
}
reviews = reviewDAO.getAll();
}
}
--------------
I have debugged it and the WorkDataModel seems to return valid data.
The call and the test code is in my last mail. I removed the
AveragingPreferenceInferrer, but it didnt change that I get no results
back.
I hope that's clearer.
Thank you!
Johan
On Fri, Nov 27, 2009 at 1:57 AM, Sean Owen <[email protected]> wrote:
> I'm not clear what you mean. There are user-based and item-based
> recommenders. Both recommend items to users. You had expressed
> interest in recommending users to items. That could be done with a
> user-based or item-based recommender, by flipping user and item IDs.
>
> Which one(s) are and aren't working exactly? You show a user-based
> recommender below, but can't tell whether you mean this works or
> doesn't.
>
> Also I am not sure what's going on in WorkDataModel. Have you
> 'flipped' user and item IDs there or no?
>
> Last you say you are trying to recommend items to users, and that's an
> issue, but I thought you had that working.
>
> Back up a bit and clarify what the situation is.
>
> (PS I wouldn't use a preference inferrer unless you know for sure it's
> beneficial. It usually isn't.)
>
> On Fri, Nov 27, 2009 at 12:51 AM, Johan Fredholm
> <[email protected]> wrote:
>> Thanks for the help.
>> I got the recommender based on items to work, but I cant seem to get
>> the recommender based on users to work.
>> I don't get any errors, I just don't get any results.
>>
>> My call>
>> -----------------
>> WorkDataModel model = new WorkDataModel(accountDAO, arrangementDAO,
>> reviewDAO, arrangements);
>> UserSimilarity userSimilarity = new PearsonCorrelationSimilarity(model);
>> userSimilarity.setPreferenceInferrer(new AveragingPreferenceInferrer(model));
>> NearestNUserNeighborhood neighborhood = new NearestNUserNeighborhood
>> (3, userSimilarity, model);
>> GenericUserBasedRecommender recommender = new
>> GenericUserBasedRecommender(model, neighborhood, userSimilarity);
>> List<RecommendedItem> recommendations =
>> recommender.recommend(account.getId(), amount);
>> ------------------
>>
>> It looks like WorkDataModel returns everything correctly.
>> This is my test:
>>
>> ------------------
>> List<Arrangement> allReady = arrangementDAO.getAllReady();
>>
>> Account ac1 = accountDAO.get(22L);
>> Account ac2 = accountDAO.get(21L);
>> Account ac3 = accountDAO.get(23L);
>>
>> int i = 0;
>> Arrangement aSearch = null;
>>
>> for (Arrangement a : allReady) {
>>
>> if (i < 8) {
>> reviewDAO.save(new Review(a, ac1, 4F, Reviewtype.HUMAN));
>> }
>> if (i > 3) {
>> reviewDAO.save(new Review(a, ac2, 2F, Reviewtype.HUMAN));
>> }
>> if (i > 6 && i < 16) {
>> reviewDAO.save(new Review(a, ac3, 5F, Reviewtype.HUMAN));
>> }
>>
>> if (i == 5) {
>> aSearch = a;
>> }
>>
>> if (i > 15) {
>> break;
>> }
>>
>> i++;
>> }
>>
>> List<Arrangement> recommendations =
>> arrangementService.getRecommendations(ac1, allReady, 10);
>> -------------------
>>
>> I'm not really sure what I am sending in there, I'm just trying to mix
>> it up a bit :-)
>> I have tried to get recommendations from for all three of the accounts
>> (users), but I don't get anything.
>> Do I need more preferences, or is something else wrong?? The
>> preferences are not overlapping, so shouldn't I get some kind of
>> result back?
>>
>> Thanks!
>> Johan
>>
>>
>> On Thu, Nov 26, 2009 at 12:02 PM, Sean Owen <[email protected]> wrote:
>>> Yes everything looks fine here, but with one key issue.
>>> It seems you are trying to recommender "users" to "items" in the
>>> second case. That is not what an item-based recommender does -- it
>>> still recommenders items to users.
>>>
>>> To do what you want, you need to transpose user and item IDs in your
>>> DataModel, then use any algorithm you like. It's a two-line change to
>>> the line where you make a GenericPreference. Maybe create a flag in
>>> the constructor that controls this so you can reuse the model in both
>>> cases.
>>>
>>> It does mean you need a separate model, yes.
>>>
>>> PS I think your model-building will use a lot of memory at peak --
>>> that map of Collection<Preference> will be a lot bigger than the final
>>> data set. You can instead build PreferenceArray directly, note.
>>>
>>> On Thu, Nov 26, 2009 at 9:38 AM, Johan Fredholm
>>> <[email protected]> wrote:
>>>> Hi,
>>>> I have been trying to configure Mahout for using hibernate. I haven't
>>>> been able to find any examples of such a configuration. Its probably
>>>> the wrong way to do it but I cant even get this simple model to work.
>>>> It would be great if you could tell me what I'm doing wrong here, and
>>>> maybe some pointers on how it should be done.
>>>>
>>>
>>
>