基于Mahout的图书推荐系统

一、 用Maven搭建Mahout的开发环境

package com.panguoyuan.mahout.itemcf;

import java.io.File;
import java.io.IOException;
import java.util.List;

import org.apache.mahout.cf.taste.common.TasteException;
import org.apache.mahout.cf.taste.impl.common.LongPrimitiveIterator;
import org.apache.mahout.cf.taste.impl.model.file.FileDataModel;
import org.apache.mahout.cf.taste.impl.neighborhood.NearestNUserNeighborhood;
import org.apache.mahout.cf.taste.impl.recommender.GenericUserBasedRecommender;
import org.apache.mahout.cf.taste.impl.similarity.EuclideanDistanceSimilarity;
import org.apache.mahout.cf.taste.model.DataModel;
import org.apache.mahout.cf.taste.recommender.RecommendedItem;
import org.apache.mahout.cf.taste.recommender.Recommender;
import org.apache.mahout.cf.taste.similarity.UserSimilarity;
public class UserCF {
    final static int NEIGHBORHOOD_NUM = 2;
    final static int RECOMMENDER_NUM = 3;
    public static void main(String[] args) throws IOException, TasteException {
        String file = "inputdata/item.csv";
        DataModel model = new FileDataModel(new File(file));
        UserSimilarity user = new EuclideanDistanceSimilarity(model);
        NearestNUserNeighborhood neighbor = new NearestNUserNeighborhood(NEIGHBORHOOD_NUM, user, model);
        Recommender r = new GenericUserBasedRecommender(model, neighbor, user);
        LongPrimitiveIterator iter = model.getUserIDs();
        while (iter.hasNext()) {
            long uid = iter.nextLong();
            List<RecommendedItem> list = r.recommend(uid, RECOMMENDER_NUM);
            System.out.printf("uid:%s", uid);
            for (RecommendedItem ritem : list) {
                System.out.printf("(%s,%f)", ritem.getItemID(), ritem.getValue());
            }
            System.out.println();
        }
    }
}

(8)在eclipse里运行结果如下

二、用案例的数据集,基于Mahout,任选一种算法,对任意一个女性用户进行协同过滤推荐,并解释推荐结果是否合理,解释过程可以写成一文档说明。

1、选择基于用户的协同过滤算法:UserCF

2、算法模型:DataModel+UserSimilarity+UserNeighborhood+UserBasedRecommender

package com.panguoyuan.mahout.itemcf;

import java.io.File;
import java.util.List;

import org.apache.mahout.cf.taste.impl.model.file.FileDataModel;
import org.apache.mahout.cf.taste.impl.neighborhood.NearestNUserNeighborhood;
import org.apache.mahout.cf.taste.impl.recommender.GenericUserBasedRecommender;
import org.apache.mahout.cf.taste.impl.similarity.PearsonCorrelationSimilarity;
import org.apache.mahout.cf.taste.model.DataModel;
import org.apache.mahout.cf.taste.neighborhood.UserNeighborhood;
import org.apache.mahout.cf.taste.recommender.RecommendedItem;
import org.apache.mahout.cf.taste.recommender.UserBasedRecommender;
import org.apache.mahout.cf.taste.similarity.UserSimilarity;

public class BasedUserBookRecommender2 {

    public static void main(String[] args) throws Exception {
        long userId = 188;
        //构建数据模型
        DataModel model = new FileDataModel(new File("inputdata/rating.csv"));
        //创建相似度
        UserSimilarity itemSimilarity = new PearsonCorrelationSimilarity(model);
        //UserSimilarity itemSimilarity = new EuclideanDistanceSimilarity(model);
        //GenericUserSimilarity genericItemSimilarity = new GenericUserSimilarity(itemSimilarity, model);
        //构建近邻算法
        UserNeighborhood neighborhood = new NearestNUserNeighborhood(3, itemSimilarity, model);
        //构建推荐模型
        UserBasedRecommender userBasedRecommender = new GenericUserBasedRecommender(model, neighborhood, itemSimilarity);
        //计算并返回图书推荐结果
        List<RecommendedItem> recommendations = userBasedRecommender.recommend(188, 5);
        //打印推荐结果
        showItems(userId, recommendations, true);

    }

    public static void showItems(long uid,
            List<RecommendedItem> recommendations, boolean skip) {
        if (skip || recommendations.size() > 0) {
            System.out.printf("userId:%s,", uid);
            for (RecommendedItem r : recommendations) {
                System.out.printf("(%s,%f)", r.getItemID(), r.getValue());
            }
            System.out.println();
        }
    }
}

4、输出结果

userId:188,(885,9.500000)(396,7.000000)(688,6.000000)

5、用R语言对推荐结果进行人工分析

(1)导入分析数据(rating.csv为评分数据,user.csv为用户信息)

ratings=read.csv("F:\workspace1\mahout\inputdata\rating.csv",FALSE)
users=read.csv("F:\workspace1\mahout\inputdata\user.csv",FALSE)

(2)修改列名

ratings=data.frame('userid'=ratings$V1,'bookid'=ratings$V2,'grade'=ratings$V3)
users=data.frame('userid'=users$V1,'sex'=users$V2,'age'=users$V3)

(3)查看用户188都看了哪些书

> ratings[c(ratings$userid==188),]
userid bookid grade
3760    188    798     6
3761    188    653     3
3762    188    426     6
3763    188    742     7
3764    188    549     2
3765    188    520     8
3766    188    312     2
3767    188    213    10
3768    188    954     5
3769    188    121    10
3770    188    204     9
3771    188    684     3
3772    188    493     4
3773    188    452     1
3774    188    622     3
3775    188    298     8

(4)图书885推荐分数最高,下面查看该图书有哪些人评过分

ratings[c(ratings$bookid==885),]
userid bookid grade
182       9    885     8
1225     60    885    10
3691    184    885     9

(5)查看这用户9,用户60,用户184,用户188的信息

> users[c(9,60,184,188),]  userid sex age
9        9   M  50
60      60   F  49
184    184   M  27
188    188   F  24

(6)查看这用户9,用户60,用户184与用户188都共同看了哪些图书

> rating188=ratings[which(ratings$userid==188),]
>  rating9=ratings[which(ratings$userid==9),]
>  rating60=ratings[which(ratings$userid==60),]
> rating184=ratings[which(ratings$userid==184),]
> intersect(rating188$bookid,rating9$bookid)
integer(0)
> intersect(rating188$bookid,rating60$bookid)
[1] 312 298
> intersect(rating188$bookid,rating184$bookid)
[1] 121 684

从上面可以看出用户188与用户60共同看了312和298这两本书,与用户184共同看了121和684这两本书,他们都有共同的偏好,所以给用户188推荐图书885是合理的。

三、增加过滤条件,排除男性,只保留对女性用户的推荐评分

选用的算法模型为:FileDataModel+EuclideanDistanceSimilarity+GenericItemBasedRecommender

package com.panguoyuan.mahout.itemcf;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.mahout.cf.taste.common.TasteException;
import org.apache.mahout.cf.taste.impl.common.LongPrimitiveIterator;
import org.apache.mahout.cf.taste.impl.model.file.FileDataModel;
import org.apache.mahout.cf.taste.impl.recommender.GenericItemBasedRecommender;
import org.apache.mahout.cf.taste.impl.similarity.EuclideanDistanceSimilarity;
import org.apache.mahout.cf.taste.impl.similarity.GenericItemSimilarity;
import org.apache.mahout.cf.taste.model.DataModel;
import org.apache.mahout.cf.taste.recommender.IDRescorer;
import org.apache.mahout.cf.taste.recommender.ItemBasedRecommender;
import org.apache.mahout.cf.taste.recommender.RecommendedItem;
import org.apache.mahout.cf.taste.similarity.ItemSimilarity;

public class BookFilterGenderRecommender3 {

    public static void main(String[] args) throws Exception {
        DataModel model = new FileDataModel(new File("inputdata/rating.csv"));
        ItemSimilarity otherSimilarity = new EuclideanDistanceSimilarity(model);
        GenericItemSimilarity similarity = new GenericItemSimilarity(otherSimilarity, model);
        ItemBasedRecommender recommender = new GenericItemBasedRecommender(model, similarity);
        filterRecommender(188, recommender, model);
    }

    public static void showItems(long uid,List<RecommendedItem> recommendations, boolean skip) {
        if (skip || recommendations.size() > 0) {
            System.out.printf("userId:%s,", uid);
            for (RecommendedItem r : recommendations) {
                System.out.printf("Item:(%s,%f)", r.getItemID(), r.getValue());
                System.out.println();
            }

        }
    }

     /**
     * 对用户性别进行过滤
     */
    public static void filterRecommender(long uid, ItemBasedRecommender recommender, DataModel dataModel) throws TasteException, IOException {
        Set<Long> userids = getMale("datafile/book/user.csv");

        //计算男性用户打分过的图书
        Set<Long> bookids = new HashSet<Long>();
        for (long uids : userids) {
            LongPrimitiveIterator iter = dataModel.getItemIDsFromUser(uids).iterator();
            while (iter.hasNext()) {
                long bookid = iter.next();
                bookids.add(bookid);
            }
        }

        IDRescorer rescorer = new FilterRescorer(bookids);
        List<RecommendedItem> list = recommender.recommend(uid, 10, rescorer);
        showItems(uid, list, false);
    }

    /**
     * 返回所有男性id
     */
    public static Set<Long> getMale(String file) throws IOException {
        BufferedReader br = new BufferedReader(new FileReader(new File(file)));
        Set<Long> userids = new HashSet<Long>();
        String s = null;
        while ((s = br.readLine()) != null) {
            String[] cols = s.split(",");
            if (cols[1].equals("M")) {
                userids.add(Long.parseLong(cols[0]));
            }
        }
        br.close();
        return userids;
    }
}

/**
* 对结果重计算
*/
class FilterRescorer implements IDRescorer {
    final private Set<Long> userids;

    public FilterRescorer(Set<Long> userids) {
        this.userids = userids;
    }

    @Override
    public double rescore(long id, double originalScore) {
        return isFiltered(id) ? Double.NaN : originalScore;
    }

    @Override
    public boolean isFiltered(long id) {
        return userids.contains(id);
    }
}

3、打印推荐结果

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
userId:188,Item:(365,8.800000)
Item:(725,8.583333)
Item:(427,8.000000)
Item:(403,7.987013)
Item:(734,7.676371)
Item:(256,7.533333)
Item:(300,7.428571)
Item:(743,7.333333)
Item:(356,6.875000)
Item:(579,6.777778)

4、人工对数据进行分析

(1)查看图书365都有哪些用户评过分

> ratings[c(ratings$bookid==365),]
     userid bookid grade
1046     51    365     9
2206    111    365     9
2632    134    365     4
> users[c(51,111,134),]
    userid sex age
51      51   F  18
111    111   F  40
134    134   F  74

(2)利用intersect函数把用户188与25,45,65这三个用户共同评分过的图书汇集出来

说明:intersect(A,B)是一个数据框都在A和B这些行

>rating188=ratings[which(ratings$userid==188),]
>rating51=ratings[which(ratings$userid==51),]
>rating111=ratings[which(ratings$userid==111),]
>rating134=ratings[which(ratings$userid==134),]
> intersect(rating188$bookid,rating51$bookid)
integer(0)> intersect(rating188$bookid,rating134$bookid)
[1] 204
> intersect(rating188$bookid,rating111$bookid)
[1] 742

(3)从上面可以看出用户188与用户134共同看了204图书,与111共同看了742图书

> rating188
     userid bookid grade
3760    188    798     6
3761    188    653     3
3762    188    426     6
3763    188    742     7
3764    188    549     2
3765    188    520     8
3766    188    312     2
3767    188    213    10
3768    188    954     5
3769    188    121    10
3770    188    204     9
3771    188    684     3
3772    188    493     4
3773    188    452     1
3774    188    622     3
3775    188    298     8

综上所述把图书365推荐给用户188是合理的。

时间: 2024-08-04 13:13:19

基于Mahout的图书推荐系统的相关文章

Mahout构建图书推荐系统

阅读导读: 1.Mahout中推荐过滤算法支持哪两种算法? 2.用java代码如何计算男性用户打分过的图书? 3.itemEuclidean,userEuclideanNoPref分别是什么算法? 1. 项目背景 Amazon是最早的电子商务网站之一,以网上图书起家,最后发展成为音像,电子消费品,游戏,生活用品等的综合性电子商务平台.Amazon的推荐系统,是互联网上最早的商品推荐系统,它为Amazon带来了至少30%的流量,和可观的销售利润. 如今推荐系统已经成为电子商务网站的标配,如果还没有

基于大数据技术推荐系统算法案例实战视频教程(项目实战)

38套大数据,云计算,架构,数据分析师,Hadoop,Spark,Storm,Kafka,人工智能,机器学习,深度学习,项目实战视频教程 视频课程包含: 38套大数据和人工智能精品高级课包含:大数据,云计算,架构,数据挖掘实战,实时推荐系统实战,电视收视率项目实战,实时流统计项目实战,离线电商分析项目实战,Spark大型项目实战用户分析,智能客户系统项目实战,Linux基础,Hadoop,Spark,Storm,Docker,Mapreduce,Kafka,Flume,OpenStack,Hiv

mahout入门指南之基于mahout的itembased算法

基于mahout的itembased算法 其实mahout分布式上只是实现了部分算法.比如推荐算法中Item-based和slopone都有hadoop实现和单机版实现,User-based没有分布式实现. Mahout已实现的算法(单机版和分布式版) https://mahout.apache.org/users/basics/algorithms.html 大多数情况下,我们只是调用mahout的算法,要么单机版,要么分布式版. 那么mahout的分布式算法怎么调用呢? 其实mahout分布

基于矩阵分解的推荐系统应用

使用MATLAB尝试了随机梯度下降的矩阵分解方法,实现了一个比较简单的推荐系统的原理. 常用推荐系统的方法有协同过滤,    基于物品内容过滤等等. 这次是用的矩阵分解模型属于协同过滤的一种方法,大致原理是通过一定数量的因子来描述各个用户的喜好和各个物品的属性. 通过随机梯度下降法分解后得到两个矩阵,一个是用户因子矩阵,另一个是物品因子矩阵. 这两个矩阵相乘可以得到所有用户对所有电影的预测评分. 以Movie-Lens数据集举例,这包含943个用户对1682部电影的十万条评分. 第一列用户编号,

基于SSM的图书管理系统(读者管理借阅管理)-java图书管理系统图书馆管理

基于SSM的图书管理系统(读者管理借阅管理)-java图书管理系统图书馆管理 1.包含源程序,数据库脚本.代码和数据库脚本都有详细注释.2.课题设计仅供参考学习使用,可以在此基础上进行扩展完善开发环境:Eclipse ,MYSQL,JDK1.7,Tomcat 7涉及技术点:MVC模式.SpringMvc.Mybatis.Spring.HTML.JavaScript.CSS.JQUERY.DWR.Ajax等系统采用Mybatis框架实现ORM对象关系映射,前台JSP实现,后台springMvc映射

基于flask的图书管理系统-蓝图

基于flask的图书管理-- 蓝图方式 效果图, 只有基本的增删功能 目录 app 应用名 templates 存放模板, html之类的 book 用于区分html文件 index.html 主页展示 view 存放视图 __init__ 初始化蓝图 bookManage.py 视图函数 __init__ 这个是app的类 , 初始化文件 model.py 数据库模型 manage.py 启动 migrations 这个是flask-migrate生成的, 用于迁移数据库 requiremen

下载基于大数据技术推荐系统实战教程(Spark ML Spark Streaming Kafka Hadoop Mahout Flume Sqoop Redis)

地址:http://pan.baidu.com/s/1c2tOtwc  密码:yn2r 82课高清完整版,转一播放码. 互联网行业是大数据应用最前沿的阵地,目前主流的大数据技术,包括 hadoop,spark等,全部来自于一线互联网公司.从应用角度讲,大数据在互联网领域主要有三类应用:搜索引擎(比如百度,谷歌等),广告系统(比如百度凤巢,阿里妈妈等)和推荐系统(比如阿里巴巴天猫推荐,优酷视频推荐等). 本次培训以商业实战项目作为驱动来学习大数据技术在推荐系统项目中的应用.使得学员能够亲身体会大数

《推荐系统》基于标签的用户推荐系统

1:联系用户兴趣和物品的方式 2:标签系统的典型代表 3:用户如何打标签 4:基于标签的推荐系统 5:算法的改进 源代码查看地址:github查看 一:联系用户兴趣和物品的方式 推荐系统的目的是联系用户的兴趣和物品,这种联系方式需要依赖不同的媒介.目前流行的推荐系统基本上是通过三种方式联系用户兴趣和物品. 1:利用用户喜欢过的物品,给用户推荐与他喜欢过的物品相似的物品,即基于item的系统过滤推荐算法(算法分析可参考:点击阅读) 2:利用用户和兴趣用户兴趣相似的其他用户,给用户推荐哪些和他们兴趣

【形式化方法:VDM++系列】3.基于VDM++的图书管理系统需求定义

接前文:http://www.cnblogs.com/Kassadin/p/4091040.html 1.Before We Start: 在开始图书管理系统需求定义之前,需要先进行一些说明. 1.1 输入,输出定义 输入:用户需求文字说明 输出:基于VDM++的需求规格说明文档 任何问题只有明确它的输入和输出,才会有一个明确的预期,才有可能获得预期的结果.在这里明确问题的输入输出更加重要.特别需要指出的是,VDM++作为一种形式化方法语言,它主要用于需求分析,而不是代码实现.虽然它的产出是一段