前言
之前学习了有关java的Mohout推荐引擎,我们就可以根据它提供的类快速的进行我们的推荐算法的构建了。
导入Mahout依赖
<dependency>
<groupId>org.apache.mahout</groupId>
<artifactId>mahout</artifactId>
<version>0.11.1</version>
<type>pom</type>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.mahout/mahout-core -->
<dependency>
<groupId>org.apache.mahout</groupId>
<artifactId>mahout-core</artifactId>
<version>0.9</version>
</dependency>
导入依赖的之后,发现org.apache.mahout包中会有一个子package报错,好像是缺少了什么东西,并且在install的时候还会报错,但是却不影响代码的执行,好像那个package在项目中完全没有用到。
最后加上了<type>pom</type>
之后问题解决,好像是依赖不是从maven的中心仓库拉取的,所以出现了这样的问题。
数据源
昨天抽取到的user tag 的浏览数据和user category的浏览数据,存取csv中。
基于用户的协同过滤
/**
* 基于用户的推荐 通过用户浏览某一分类或标签的文章的数据 形成相似矩阵进行推荐
* @param userId 为那个用户推荐
* @param size 推荐几个item
* @param modelFileName 模型文件名 (是要推荐标签 还是推荐分类)
* @return
* @throws IOException
* @throws TasteException
*/
public List<RecommendedItem> userBasedRecommended(int userId,int size,String modelFileName) throws IOException, TasteException
{
//构造数据模型
DataModel dataModel = new FileDataModel(new File(modelFileName));
//计算相似度,相似度算法有很多种,欧几里得、皮尔逊等等。这里基于皮尔逊
UserSimilarity similarity = new PearsonCorrelationSimilarity(dataModel);
//计算最近邻域,邻居有两种算法,基于固定数量的邻居和基于相似度的邻居,这里使用基于固定数量的邻居 选择用户数量为
UserNeighborhood userNeighborhood = new NearestNUserNeighborhood(50, similarity, dataModel);
//构建推荐器,协同过滤推荐有两种,分别是基于用户的和基于物品的,这里使用基于用户的协同过滤推荐
Recommender recommender = new GenericUserBasedRecommender(dataModel, userNeighborhood, similarity);
//给用户id为userId的用户 推荐size个标签
List<RecommendedItem> recommendedItemList = recommender.recommend(userId, size);
return recommendedItemList;
}
这里可以传入不同的模型文件的路径,来选择是基于用户-标签还是基于用户-分类构建模型。
这里我使用了皮尔逊系数来计算相似度,并且使用固定数量的邻居,
然后使用GenericUserBasedRecommender类作为推荐器,实现基于物品的协同过滤。
最终给id为userId的用户推荐size个分类或者标签。
基于标签或分类的协同过滤算法
/**
* 基于标签的推荐 基于物品的协同过滤算法
* @param userId 为那个用户推荐
* @param size 推荐几个item
* @param modelFileName 模型文件名 (是要推荐标签 还是推荐分类)
* @return 为id为user_id的用户推荐size个item
* @throws IOException
* @throws TasteException
*/
public List<RecommendedItem> itemBaseRecommended(int userId,int size ,String modelFileName) throws IOException, TasteException
{
//构造数据模型
DataModel dataModel = new FileDataModel(new File(modelFileName));
//计算相似度,相似度算法有很多种,欧几里得、皮尔逊等等。
ItemSimilarity itemSimilarity = new PearsonCorrelationSimilarity(dataModel);
//构建推荐器,协同过滤推荐有两种,分别是基于用户的和基于物品的,这里使用基于物品的协同过滤推荐
GenericItemBasedRecommender recommender = new GenericItemBasedRecommender(dataModel, itemSimilarity);
//给用户ID等于userId的用户推荐size个标签
List<RecommendedItem> recommendedItemList = recommender.recommend(userId, size);
return recommendedItemList;
}
这里可以传入不同的模型文件的路径,来选择是基于用户-标签还是基于用户-分类构建模型。
这里我使用了皮尔逊系数来计算相似度
然后使用GenericItemBasedRecommender类作为推荐器,实现基于物品的协同过滤。
最终给id为userId的用户推荐size个分类或者标签。
当用户正在浏览某个分类或者某个标签的文章时,为其推荐对应 标签 或者分类的其他标签 或者分类
/**
* 当用户正在浏览某个分类或者某个标签的文章时,为其推荐对应 标签 或者分类的其他标签 或者分类
* @param userId 为那个用户推荐
* @param itemId 当前正在浏览的 标签id 或者分类id
* @param size 推荐多少个
* @param modelFileName 模型文件名 (是要推荐标签 还是推荐分类)
* @return
* @throws IOException
* @throws TasteException
*/
public List<RecommendedItem> itemBaseRecommendedWithItem(int userId,int itemId,int size,String modelFileName) throws IOException, TasteException {
//构造数据模型
DataModel dataModel = new FileDataModel(new File(modelFileName));
//计算相似度,相似度算法有很多种,欧几里得、皮尔逊等等。
ItemSimilarity itemSimilarity = new PearsonCorrelationSimilarity(dataModel);
//构建推荐器,协同过滤推荐有两种,分别是基于用户的和基于物品的,这里使用基于物品的协同过滤推荐
GenericItemBasedRecommender recommender = new GenericItemBasedRecommender(dataModel, itemSimilarity);
//给用户ID等于user_id的用户推荐size个与标签tag_id类似的标签
List<RecommendedItem> recommendedItemList = recommender.recommendedBecause(userId, itemId, size);
return recommendedItemList;
}
这里为浏览某个分类,或者标签的人推荐与标签或者分类相似的标签或者分类
推荐结果
可以看到,这种将用户信息提前物化到csv文件中而不是访问数据库,的推荐还是非常快速的。
但是问题就是冷启动,当一个用户刚进入系统时是无法进行推荐的,会返回空值。