No I want both, (both user and item based recommendation) and the
item-based recommender now works, but the user-based recommender
returns nothing.
I remade the DataModel for the _user-based_ recommender. Here it is>
----------------------
public class WorkDataModel implements DataModel {
FastByIDMap<PreferenceArray> usersArray;
FastByIDMap<PreferenceArray> itemsArray;
public WorkDataModel(ArrangementDAO arrangementDAO, ReviewDAO
reviewDAO, List<Arrangement> arrangements) {
super();
this.arrangementDAO = arrangementDAO;
this.reviewDAO = reviewDAO;
this.arrangements = arrangements;
refresh();
usersArray = readUsers();
itemsArray = readItems();
}
private FastByIDMap<PreferenceArray> readItems() {
FastByIDMap<Collection<Preference>> userIDPrefMap = new
FastByIDMap<Collection<Preference>>();
for (Review r : reviews) {
Collection<Preference> userPrefs =
userIDPrefMap.get(r.getArrangement().getId());
if (userPrefs == null) {
userPrefs = new ArrayList<Preference>(2);
userIDPrefMap.put(r.getArrangement().getId(), userPrefs);
}
userPrefs.add(new GenericPreference(
r.getReviewer().getId(),
r.getArrangement().getId(),
r.getValue()));
}
return GenericDataModel.toDataMap(userIDPrefMap, true);
}
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 keySetIterator = usersArray.keySetIterator();
return keySetIterator;
}
@Override
public PreferenceArray getPreferencesFromUser(long id) throws TasteException {
return usersArray.get(id);
}
@Override
public FastIDSet getItemIDsFromUser(long userID) throws TasteException {
FastIDSet itemIDsFromUser = new FastIDSet();
for (Preference pref : usersArray.get(userID)) {
itemIDsFromUser.add(pref.getItemID());
}
return itemIDsFromUser;
}
@Override
public LongPrimitiveIterator getItemIDs() throws TasteException {
throw new UnsupportedOperationException();
}
@Override
public PreferenceArray getPreferencesForItem(long id)
throws TasteException {
return itemsArray.get(id);
}
@Override
public Float getPreferenceValue(long userID, long itemID)
throws TasteException {
throw new UnsupportedOperationException();
}
@Override
public int getNumItems() throws TasteException {
return itemsArray.size();
}
@Override
public int getNumUsers() throws TasteException {
return usersArray.size();
}
@Override
public int getNumUsersWithPreferenceFor(long... itemIDs) throws
TasteException {
throw new UnsupportedOperationException();
}
@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();
}
}
-------------------
here is the call
------------------
WorkDataModel model = new WorkDataModel(arrangementDAO, reviewDAO,
arrangements);
UserSimilarity userSimilarity = new PearsonCorrelationSimilarity(model);
NearestNUserNeighborhood neighborhood = new
NearestNUserNeighborhood (3, userSimilarity, model);
GenericUserBasedRecommender recommender = new
GenericUserBasedRecommender(model, neighborhood, userSimilarity);
List<RecommendedItem> recommendations =
recommender.recommend(account.getId(), amount);
-----------------
and the unittest
-----------------
List<Arrangement> allReady = arrangementDAO.getAllReady();
reviewDAO.emptyTable();
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 < 15) {
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);
----------------------------
This gives me nothing.
Thanks!
/Johan
On Fri, Nov 27, 2009 at 2:24 AM, Sean Owen <srowen@gmail.com> wrote:
> Yes, in order to recommend users to items, you just have to flip user
> IDs and item IDs. Then use whatever algorithm you want. Then you pass
> in item IDs, not user IDs, to recommend(). If you were passing item
> IDs, without flipping the two, that would be why things don't work.
>
> You are saying you flipped the values, and it works now. What is not
> working then -- are you just wondering why you saw no results in that
> one case?
>
> On Fri, Nov 27, 2009 at 1:19 AM, Johan Fredholm
> <johan.fredholm@gmail.com> wrote:
>> 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:
>>
>
|