
org.reco4j.dataset.UserItemDataset Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of reco4j-core Show documentation
Show all versions of reco4j-core Show documentation
Reco4j is an open source project aims at developing a recommendation framework based on graph data sources. We choose graph databases for several reasons. They are NoSQL databases, so "schemaless". This means that it is possible to extend the basic data structure with intermediate information, i.e. similarity value between item and so on. Moreover, since every information is expressed with properties, nodes and relations, the recommendation process can be customized to work on every graph.
Reco4j can be used on every graph where "user" and "item" is represented by node and the preferences are modelled as relationship between them.
Current implementation leverage on Neo4j as first graph database integrated in our framework.
The newest version!
/*
* UserItemDataset.java
*
* Copyright (C) 2013 Alessandro Negro
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package org.reco4j.dataset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.mahout.cf.taste.impl.common.FastIDSet;
import org.reco4j.graph.IEdge;
import org.reco4j.graph.IEdgeType;
import org.reco4j.graph.IGraph;
import org.reco4j.graph.INode;
import org.reco4j.model.NodeRatingStatistics;
/**
*
* @author Luigi Giuri < luigi.giuri at reco4j.org >
*/
public class UserItemDataset
{
protected IGraph graph;
protected String itemType;
protected String userType;
//
protected IEdgeType ratingEdgeType;
protected String ratingValueEdgePropertyName;
protected ConcurrentHashMap> itemsRatedByUser;
//
protected ConcurrentHashMap itemList;
protected ConcurrentHashMap userList;
protected FastIDSet itemIdList;
protected List ratingList;
protected List userIds;
protected List itemIds;
protected HashMap userIndexes;
protected HashMap itemIndexes;
//
public void init(IGraph graph, String itemType, String userType, IEdgeType ratingEdgeType, String ratingValueEdgePropertyName)
{
this.graph = graph;
this.itemType = itemType;
this.userType = userType;
this.ratingEdgeType = ratingEdgeType;
this.ratingValueEdgePropertyName = ratingValueEdgePropertyName;
}
private void initRatingStatistics()
{
initNodeListRatingStatistics(getUserList());
initNodeListRatingStatistics(getItemList());
}
private static void initNodeListRatingStatistics(final ConcurrentHashMap nodeList)
{
for (INode node : nodeList.values())
initNodeRatingStatistics(node);
}
private static void initNodeRatingStatistics(INode node)
{
if (node.getExtendedInfos() == null)
node.setExtendedInfos(new NodeRatingStatistics());
}
public void setNodeRatingStatistics()
{
initRatingStatistics();
for (IEdge rating : getRatingList())
{
double realValue = getRating(rating);
INode item = getItemList().get(rating.getDestination().getId());
((NodeRatingStatistics) item.getExtendedInfos()).addRating(realValue);
INode user = getUserList().get(rating.getSource().getId());
((NodeRatingStatistics) user.getExtendedInfos()).addRating(realValue);
}
for (INode item : getItemList().values())
{
((NodeRatingStatistics) item.getExtendedInfos()).setStatistics();
}
}
/**
* @return the itemList
*/
public ConcurrentHashMap getItemList()
{
if (itemList == null)
itemList = graph.getNodesMapByType(itemType);
return itemList;
}
/**
* @return the userList
*/
public ConcurrentHashMap getUserList()
{
if (userList == null)
userList = graph.getNodesMapByType(userType);
return userList;
}
public ConcurrentHashMap getItemListForRecommendation()
{
if (itemList == null)
itemList = graph.getNodesMapByType(itemType);
return itemList;
}
/**
* @return the userList
*/
public ConcurrentHashMap getUserListForRecommendation()
{
if (userList == null)
userList = graph.getNodesMapByType(userType);
return userList;
}
/**
* @return the ratingList
*/
public List getRatingList()
{
if (ratingList == null)
ratingList = graph.getEdgesByType(ratingEdgeType);
return ratingList;
}
public IEdge getRatingEdge(INode user, INode item)
{
return user.getEdge(item, ratingEdgeType);
}
public double getRating(IEdge rating) throws NumberFormatException
{
String propertyValue = rating.getPermissiveProperty(ratingValueEdgePropertyName);
if (propertyValue == null)
{
propertyValue = "1.0";
//throw new RuntimeException("Properties : " + ratingValueEdgePropertyName + " not found on edge of id: " + rating.getId());
}
double realValue = Double.parseDouble(propertyValue);
return realValue;
}
public FastIDSet getItemIdList()
{
if (itemIdList == null)
itemIdList = graph.getNodesIdByType(itemType);
return itemIdList;
}
public INode getItemNodeById(long itemId)
{
return graph.getItemNodeById(itemId);
}
public FastIDSet getCommonNodeIds(INode item)
{
return item.getCommonNodeIds(ratingEdgeType);
}
public ConcurrentHashMap getCommonNodes(INode item, String identifier)
{
return item.getCommonNodes(ratingEdgeType, identifier);
}
public int getRatingCountByUser(long id)
{
//TODO: optimize
return getUserList().get(id).getOutEdge(ratingEdgeType).size();
}
public int getRatingCountByItem(long id)
{
//TODO: optimize
return getItemList().get(id).getInEdge(ratingEdgeType).size();
}
public List getRatingsByUser(long id)
{
//TODO: optimize
return getUserList().get(id).getOutEdge(ratingEdgeType);
}
public List getRatingsByItem(long id)
{
//TODO: optimize
return getItemList().get(id).getInEdge(ratingEdgeType);
}
public ConcurrentHashMap> itemsRatedByUser()
{
if (itemsRatedByUser != null)
return itemsRatedByUser;
itemsRatedByUser = new ConcurrentHashMap>();
ConcurrentHashMap users = getUserList();
for (INode user : users.values())
{
List itemsRated = new ArrayList();
List ratings = user.getOutEdge(ratingEdgeType);
for (IEdge rating : ratings)
itemsRated.add(rating.getDestination().getId());
itemsRatedByUser.put(user.getId(), itemsRated);
}
return itemsRatedByUser;
}
/*public ConcurrentHashMap itemFeedbackCounts()
{
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}*/
public double getAverageRating()
{
double total = 0.0;
for (IEdge rating : getRatingList())
{
total += getRating(rating);
}
return total / getRatingList().size();
}
public int getUserIndex(long userId)
{
if (getUserIndexVector().containsKey(userId))
return getUserIndexVector().get(userId);
else
return -1;
}
public int getItemIndex(long itemId)
{
if (getItemIndexVector().containsKey(itemId))
return getItemIndexVector().get(itemId);
else
return -1;
}
public HashMap getUserIndexVector()
{
if (userIndexes == null)
buildUserIndexVector();
return userIndexes;
}
public HashMap getItemIndexVector()
{
if (itemIndexes == null)
buildItemIndexVector();
return itemIndexes;
}
private void buildUserIndexVector()
{
userIndexes = new HashMap();
userIds = new ArrayList();
int i = 0;
for (INode user : getUserList().values())
{
userIds.add(i, user.getId());
userIndexes.put(user.getId(), i);
i++;
}
}
private void buildItemIndexVector()
{
itemIndexes = new HashMap();
itemIds = new ArrayList();
int i = 0;
for (INode item : getItemList().values())
{
itemIds.add(i,item.getId());
itemIndexes.put(item.getId(), i);
i++;
}
}
public long getUserId(int index)
{
return userIds.get(index);
}
public long getItemId(int index)
{
return itemIds.get(index);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy