大数据商品推荐系统

  1. 引言

1.1 目的

Hadoop是一个开发和运行处理大规模数据的软件平台,是Appach的一个用java语言实现开源软件框架,实现在大量计算机组成的集群中对海量数据进行分布式计算,同时它也是当前最流行的云计算平台。本次课程设计通过Hadoop云计算平台实现一个商品推荐系统,希望通过编写本次课程设计,能够对Hadoop有一个基本的了解。

1.2 背景

随着科技与信息技术的迅猛发展,社会进入了一个全新的高度信息化的时代,互联网无处不在,影响了人类生活的方方面面,并彻底改变了人们的生活方式。在面对庞大且复杂的互联网信息时往往感到无从下手,使得在互联网中找寻有用信息的成本巨大,产生了所谓的“信息过载”问题。搜索引擎和推荐系统的产生为解决“信息过载”问题提供了非常重要的技术手段。推荐系统不需要用户提供明确的需求,而是通过分析用户的历史行为来对用户的兴趣进行建模,从而主动给用户推荐可能满足他们兴趣和需求的信息。

近年来,在电商领域中各种各样的网购平台发展迅速,网上购物已成为许多人选购商品的基本途径。同时随着C2C经营模式的普及,越来越多的人纷纷在网上开店,网购平台上每时每刻都有新商家入驻,商品上下架,伴随着海量的商品信息更新。如何实时准确地收集并更新大量数据,怎样让消费者在网购平台快速找到自己心目中的商品,这些问题使网购平台所使用的商品搜索引擎面临着巨大挑战。

面对海量购物数据,单机运行处理的模式不论从效率或处理能力上来讲,都已经满足不了如今数据挖掘的需求以及不便于用户购物。为了方便用户在购物过程中购物,通过其购买信息与购买物品对其推荐相关物品。

2 需求分析

商品推荐系统是对用户的历史行为进行挖掘,对用户兴趣信息进行建模,并对用户未来行为进行预测,从而建立用户和内容的关系,满足用户对商品的推荐需求的一种智能系统。通过对主要的推荐算法进行比较分析,模拟实现了基于用户行为的智能推荐系统,提高了推荐算法的有效性。商品推荐系统是为了更精准的为用户推荐他们想要的内容,如果一个用户在浏览商品信息的时候,通过对用户数据的记录,和已经存在的其他的用户记录进行分析,从而为用户推荐相应的数据。

用户行为数据的处理。商品推荐系统用户、商品行为主要是用户的购买行为。

购买行为包含了丰富的用户购买商品,如何处理这些购买商品是推荐系统实现的关键。

推荐系统的推荐质量。推荐系统的最终目的是推荐,所以推荐质量是整个系统设计的最终目的。

3 系统设计

3.1系统架构设计

系统总体架构如图3.1所示,包括客户端、服务器、数据库和Hadoop集群。客户端面向用户,通过购物软件HTTP请求发送给服务器,并解析来自服务器的响应,用直观的方式展现给客户。

服务器是系统后台的“出入口”,大部分的业务逻辑都在服务器中实现。服务器会和数据库交互,将需要持久化的数据存储到数据库,客户端传来的查询任务也由服务器去完成。数据库和文件系统一样,是数据持久化的地方。用户的推荐商品指数会保存到数据库,服务器和Hadoop集群都会访问数据库。Hadoop集群会将原始数据文件拷贝到HDFS中,方便MapReduce访问,执行的结果保存到数据库中,供服务器使用。

图3.1系统架构设计

3.2系统层次架构设计

为保证系统的扩展性以及可维护性,基于Hadoop的商品推荐系统采用分层架构设计。分层架构设计可以很好的将业务逻辑区分开,使开发人员专注每层的开发从而降低系统的开发风险。其主要分为5层:界面表示层、应用功能层、服务提供层、数据访问层和数据资源层。系统层次架构如图3.2所示。

图3.2系统层次架构设计

3.3系统功能模块设计

基于Hadoop的商品推荐系统,以商品推荐为基础,采集分析和分析用户、商品行为数据,以推荐为最终目标。为用户提供智能的个性化推荐服务。本项目采用hadoop上HDFS集群,通过MapReduce程序以作业的方式对数据进行处理和分析,其主要的功能如图3.3所示。

图3.3系统功能模块设计

3.4系统数据库设计

数据库是数据持久化的重要方式,本次课程设计的系统中需要持久化的数据是推荐运算结果。本次采用MySQL数据库。数据表结构results 表用于保存推荐运算的最终结果数据,由MapReduce负责插入到数据库中。

图3.4系统数据库设计

字段名称

数据类型

说明

id

int(11)

id

uid

varchar(20)

用户id

gid

varchar(20)

商品id

expect

int(10)

推荐指数

表3.4系统数据库设计

4.系统开发

4.1源程序清单

4.11 计算用户购买商品的列表:

文件名

类名

UserByList.java

UserByList

UserByListMapper

UserByListReducer

由原始数据提供计算

 4.12 计算商品的共现关系:

文件名

类名

CommonCount.java

CommonCount

CommonCountMapper

CommonCountReducer

根据第一步的计算结果计算

4.13 计算用户的购买向量:

文件名

类名

GoodByList.java

GoodByList

GoodByListMapper

GoodByListReducer

第1步的结果或者最原始数据。

4.14 推荐结果:

文件名

类名

MultiplyMatrix.java

MultiplyMatrixMapper1

MultiplyMatrixMapper2

MultiplyMatrixReducer

算法模型:推荐矩阵=(相似度矩阵*用户购买向量)

商品共现矩阵乘以用户购买向量,形成临时的推荐结果。

4.15 数据去重:

文件名

类名

CutRepeat.java

CutRepeat

CutRepeatMapper

CutRepeatReducer

数据去重,在推荐结果中去掉用户已购买的商品信息

4.16推荐结果存储于数据库中:

文件名

类名

ConnMysql.java

ConnMysqlMapper<LW,Text,Text,Text>

ConnMysqlReducer<Text,Text,Key,NullWritable>

CREATE TABLE `results`

将计算后的推荐结果储存于数据库中

MySQL数据库,grms.result

4.17构建对象:

文件名

类名

JobControl.java

JobControl

运行推荐结果

4.2功能实现

4.21计算用户购买商品的列表:

public class UserByList extends Configured implements Tool{

    //mapper

    public static class UserByListMapper

            extends Mapper<LongWritable,Text,Text,Text>{

        @Override

        protected void map(LongWritable key,Text value,Context context) throws IOException, InterruptedException {

            String[] strs = value.toString().split("\t");

            context.write(new Text(strs[0].trim()),new Text(strs[1].trim()));

        }

    }

    //reduce

    public static class UserByListReduce extends Reducer<Text,Text,Text,Text> {

        @Override

        protected void reduce(Text key,Iterable<Text> values,Context context) throws IOException, InterruptedException {

            StringBuilder sb = new StringBuilder();

            for (Text value:values){

                sb.append(value.toString()).append(",");

            }

            String result = sb.substring(0,sb.length()-1);

            context.write(key,new Text(result));

        }

    }

        job.setMapperClass(UserByListMapper.class);

        job.setMapOutputKeyClass(Text.class);

        job.setMapOutputValueClass(Text.class);

        job.setInputFormatClass(TextInputFormat.class);

        TextInputFormat.addInputPath(job,input);

        job.setReducerClass(UserByListReduce.class);

        job.setOutputKeyClass(Text.class);

        job.setOutputValueClass(Text.class);

        job.setOutputFormatClass(TextOutputFormat.class);

        TextOutputFormat.setOutputPath(job,output);

        return job.waitForCompletion(true)?0:1;

4.22计算商品的共现关系:

        job.setMapperClass(CommonCountMapper.class);

        job.setMapOutputKeyClass(Text.class);

        job.setMapOutputValueClass(IntWritable.class);

        job.setInputFormatClass(TextInputFormat.class);

        TextInputFormat.addInputPath(job,input);

        job.setReducerClass(CommonCountReduce.class);

        job.setOutputKeyClass(Text.class);

        job.setOutputValueClass(IntWritable.class);

        job.setOutputFormatClass(TextOutputFormat.class);

        TextOutputFormat.setOutputPath(job,output);

        return job.waitForCompletion(true)?0:1;

4.23计算用户的购买向量:

        job.setMapperClass(GoodLikeMatrixMapper.class);

        job.setMapOutputKeyClass(Text.class);

        job.setMapOutputValueClass(Text.class);

        job.setInputFormatClass(TextInputFormat.class);

        TextInputFormat.addInputPath(job,input);

        job.setReducerClass(GoodLikeMatrixReduce.class);

        job.setOutputKeyClass(Text.class);

        job.setOutputValueClass(Text.class);

        job.setOutputFormatClass(TextOutputFormat.class);

        TextOutputFormat.setOutputPath(job,output);

        return job.waitForCompletion(true)?0:1;

4.24计算用户的购买向量:

        job.setMapperClass(GoodByListMapper.class);

        job.setMapOutputKeyClass(Text.class);

        job.setMapOutputValueClass(Text.class);

        job.setInputFormatClass(TextInputFormat.class);

        TextInputFormat.addInputPath(job,input);

        job.setReducerClass(GoodByListReduce.class);

        job.setOutputKeyClass(Text.class);

        job.setOutputValueClass(Text.class);

        job.setOutputFormatClass(TextOutputFormat.class);

        TextOutputFormat.setOutputPath(job,output);

        return job.waitForCompletion(true)?0:1;

4.25推荐结果:

   public static class MultiplyMatrixReduce extends Reducer<Text,Text,Text,IntWritable>{

        @Override

        protected void reduce(Text key,Iterable<Text> values,Context context) throws IOException, InterruptedException {

            String[] str1 = null;

            String[] str2 = null;

            for (Text value:values){

                String flag = value.toString().substring(0,1);

                String result = value.toString().substring(1);

                if (flag.equals("s")){

                    str1 = result.split(",");

                }else if (flag.equals("t")){

                    str2 = result.split(",");

                }

            }

            for (int i=0;i<str1.length;i++){

                for (int j=0;j<str2.length;j++){

                    String u = str1[i].split(":")[0];

                    int uV = Integer.valueOf(str1[i].split(":")[1]);

                    String g = str2[j].split(":")[0];

                    int gV = Integer.valueOf(str2[j].split(":")[1]);

                    context.write(new Text(g+","+u),new IntWritable(uV*gV));

                }

            }

        }

    }

        job.setMapperClass(MultiplyMatrixMapper1.class);

        job.setMapOutputKeyClass(Text.class);

        job.setMapOutputValueClass(Text.class);

        MultipleInputs.addInputPath(job,input1,TextInputFormat.class,

                MultiplyMatrixMapper1.class);

        MultipleInputs.addInputPath(job,input2,TextInputFormat.class,

                MultiplyMatrixMapper2.class);

        job.setReducerClass(MultiplyMatrixReduce.class);

        job.setOutputKeyClass(Text.class);

        job.setOutputValueClass(IntWritable.class);

        job.setOutputFormatClass(TextOutputFormat.class);

        TextOutputFormat.setOutputPath(job,output);

        return job.waitForCompletion(true)?0:1;

4.26数据去重:

public static class CutRepeatMapper1 extends Mapper<LongWritable,Text,Text,Text>{

        @Override

        protected void map(LongWritable key,Text value,Context context)

            throws IOException, InterruptedException {

            //原数据

            String[] strs = value.toString().split("\t");

            context.write(new Text(strs[0]+"\t"+strs[1]),

                          new Text("*"));

        }

    }

    public static class CutRepeatMapper2 extends Mapper<LongWritable,Text,Text,Text>{

        @Override

        protected void map(LongWritable key,Text value,Context context)

            throws IOException, InterruptedException {

            //推荐数据

            String[] strs = value.toString().split("\t");

            String[] strs1 = strs[0].split(",");

            context.write(new Text(strs1[0]+"\t"+strs1[1]),

                          new Text(strs[1]));

        }

    }

    //reduce

    public class CutRepeatReduce extends Reducer<Text,Text,Text,Text>{

        @Override

        protected void reduce(Text key,Iterable<Text> values,Context context)

            throws IOException, InterruptedException {

            Iterator<Text> iterator = values.iterator();

            Text next = iterator.next();

            if(!iterator.hasNext()){

                context.write(key,new Text(next));

            }

        }

    }

        job.setMapperClass(CutRepeatMapper1.class);

        job.setMapOutputKeyClass(Text.class);

        job.setMapOutputValueClass(Text.class);

        MultipleInputs.addInputPath(job,input1,TextInputFormat.class,

                CutRepeatMapper1.class);

        MultipleInputs.addInputPath(job,input2,TextInputFormat.class,

                CutRepeatMapper2.class);

        job.setReducerClass(CutRepeatReduce.class);

        job.setOutputKeyClass(Text.class);

        job.setOutputValueClass(Text.class);

        job.setOutputFormatClass(TextOutputFormat.class);

        TextOutputFormat.setOutputPath(job,output);

        return job.waitForCompletion(true)?0:1;

4.27推荐结果存储于数据库中:

//重写DBWriter

    public static class TblsWritable implements Writable,DBWritable{

        String uid;

        String gid;

        Integer expect;

        public TblsWritable(){

        }

        public TblsWritable(String uid, String gid, Integer expect) {

            this.uid = uid;

            this.gid = gid;

            this.expect = expect;

        }

        @Override

        public void write(DataOutput dataOutput) throws IOException {

            dataOutput.writeUTF(this.uid);

            dataOutput.writeUTF(this.gid);

            dataOutput.write(this.expect);

        }

        @Override

        public void readFields(DataInput dataInput) throws IOException {

            this.uid=dataInput.readUTF();

            this.gid=dataInput.readUTF();

            this.expect=dataInput.readInt();

        }

        @Override

        public void write(PreparedStatement prep) throws SQLException {

            prep.setString(1,this.uid);

            prep.setString(2,this.gid);

            prep.setInt(3,this.expect);

        }

        @Override

        public void readFields(ResultSet rs) throws SQLException {

            this.uid=rs.getString(1);

            this.gid=rs.getString(2);

            this.expect=rs.getInt(3);

        }

}

        DBConfiguration.configureDB(conf,

                "com.mysql.jdbc.Driver",

                "jdbc:mysql://60.205.212.196:3306/grms",

                "root",

                "123456");

5.系统测试

5.1测试方法

收集数据后进行代码测试

5.2测试结果

5.21计算用户购买商品的列表

5.22计算商品的共现次数(共现矩阵)

5.23计算用户的购买向量

5.24推荐结果:

5.25数据去重:

     

5.25推荐结果入库

  • 18
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值