Spark机器学习HelloWorld系列(一)音乐推荐

来源:互联网 发布:淘宝网入驻费用 编辑:程序博客网 时间:2024/06/06 11:02

Spark机器学习HelloWorld系列(一)个性化推荐

一、数据集准备

本教程使用的是数据集是LAST.FM的音乐推荐数据,数据集包括2个文件:

1.用户文件:usersha1-profile.tsv
数据列为:

user-mboxsha1 \t gender ('m'|'f'|empty) \t age (int|empty) \t country (str|empty) \t signup (date|empty)

示例数据:

用户ID                                    性别 年龄  国籍          注册日期000063d3fe1cf2ba248b9e3c3f0334845a27a6bf    m    19    Mexico    Apr 28, 2008

2.用户播放记录:usersha1-artmbid-artname-plays.tsv:

数据列为:

 user-mboxsha1 \t musicbrainz-artist-id \t artist-name \t plays

示例数据:

用户ID  艺术家ID 艺术家名称 播放次数000063d3fe1cf2ba248b9e3c3f0334845a27a6bf    af8e4cc5-ef54-458d-a194-7b210acf638f    cannibal corpse    48

数据集下载地址:

http://www.dtic.upf.edu/~ocelma/MusicRecommendationDataset/lastfm-360K.html

二、数据集上传到HDFS

解压文件后,上传数据文件到HDFS

cd lastfm-dataset-360Khadoop fs -put * /user/mldata/lastfm360k/

三、准备训练数据集

将现有数据文件做成3个部分,用于机器学习:
1.用户文件
2.用户评分
3.艺术家文件

本教程使用spark2,使用spark1的话,程序在使用累加器(Accumulator)的语法上,需要进行相应修改
打开spark-shell,开始编码吧

1、制作艺术家文件

我们现在没有艺术家文件,所以从用户评分文件中抽取信息,做成艺术家文件

首先我们观察用户评分文件:

usersha1-artmbid-artname-plays.tsv:  user-mboxsha1 \t musicbrainz-artist-id \t artist-name \t plays

可以通过抽取文件的第二列作为艺术家ID,第三列作为艺术家名称

    //定义累加值,生成艺术家id    val acc=sc.longAccumulator("index")    val rdd = sc.textFile("hdfs://master1.hdp.com:8020/user/mldata/lastfm360k/usersha1-artmbid-artname-plays.tsv").map(o => {      val arr = o.split("\t")      (arr(1),arr(2))   //抽取第二,三列作为艺术家id和名称    }).map(o => (o._1,o)).reduceByKey((x,y)=>x).map(o=>{      acc.add(1)   //艺术家id+1      (o._1,o._2._2,acc.value).productIterator.mkString("\t")    })    //存储文件到本地    rdd.saveAsTextFile("file:///home/hdfs/artist/")

数据转换的结果为:

46674d41-c650-43e7-8b35-0373ebe3daac    racing ape      1

上传艺术家文件到hdfs

cd /home/hdfs/artist/cat part*>artist.tsvhadoop fs -put artist.tsv /user/mldata/lastfm360k/

2、转换数据ID

Spark中的ALS算法描述如下:

 def trainImplicit(ratings: RDD[Rating], rank: Int, iterations: Int, lambda: Double, alpha: Double): MatrixFactorizationModel = {trainImplicit(ratings, rank, iterations, lambda, -1, alpha)

}
Rating对象描述如下:

case class Rating @Since("0.8.0") (@Since("0.8.0") user: Int,@Since("0.8.0") product: Int,@Since("0.8.0") rating: Double)

我们将把用户ID,艺术家ID传入,用户播放次数作为rating
Rating对象需要的参数为Int类型,而我们的用户ID和艺术家ID是这样的:

000063d3fe1cf2ba248b9e3c3f0334845a27a6bf    af8e4cc5-ef54-458d-a194-7b210acf638f    cannibal corpse

,所以先要把现有的GUID转换为INT类型。

3、转换用户ID

首先我们观察用户文件:

usersha1-profile.tsvuser-mboxsha1 \t gender ('m'|'f'|empty) \t age (int|empty) \t country (str|empty) \t signup (date|empty)000063d3fe1cf2ba248b9e3c3f0334845a27a6bf    m    19    Mexico    Apr 28, 2008

可以通过抽取文件的第一列作为用户ID,生成整数值作为用户ID2

//定义累加值,生成用户idval acc=sc.longAccumulator("index")val rdd = sc.textFile("hdfs://master1.hdp.com:8020/user/mldata/lastfm360k/usersha1-profile.tsv").map(o => {  val arr = o.split("\t")  val userid=arr(0)  acc.add(1)  (arr(0),acc.value).productIterator.mkString("\t")})//存储文件到本地rdd.saveAsTextFile("file:///home/hdfs/user/")

上传文件到hdfs

cd /home/hdfs/user/cat part*>user.tsvhadoop fs -put user.tsv /user/mldata/lastfm360k/

4、转换用户评分文件

首先我们观察用户文件:

 usersha1-artmbid-artname-plays.tsv:  000063d3fe1cf2ba248b9e3c3f0334845a27a6bf    af8e4cc5-ef54-458d-a194-7b210acf638f    cannibal corpse    48  000063d3fe1cf2ba248b9e3c3f0334845a27a6bf    eaaee2c2-0851-43a2-84c8-0198135bc3a8    elis    31

转换第一,二列为整数型的ID

 //生成map,存储用户信息val rddUser = sc.textFile("hdfs://master1.hdp.com:8020/user/mldata/lastfm360k/user.tsv").map(s => {  val arr = s.split("\t")  (arr(0), arr(1))}).collectAsMap()//生成map,存储艺术家val rddArtist = sc.textFile("hdfs://master1.hdp.com:8020/user/mldata/lastfm360k/artist.tsv").map(s => {  val arr = s.split("\t")  (arr(0), arr(2))   //艺术家guid,艺术家整型id}).collectAsMap//发送变量到节点sc.broadcast(rddUser)sc.broadcast(rddArtist)val rddData = sc.textFile("hdfs://master1.hdp.com:8020/user/mldata/lastfm360k/usersha1-artmbid-artname-plays.tsv").map(s => {  val arr = s.split("\t")  val userid=rddUser.get(arr(0)).getOrElse(-1)  val artistid=rddArtist.get(arr(1)).getOrElse(-1)  (userid,artistid,arr(3)).productIterator.mkString("\t")})rddData.saveAsTextFile("file:///home/hdfs/data/")

文件转换结果为:

用户ID 艺术家ID 播放次数1       449     2137

上传文件到hdfs

cd /home/hdfs/data/cat part*>data.tsvhadoop fs -put data.tsv /user/mldata/lastfm360k/

至此,数据准备完成

四、生成模型

import org.apache.spark.mllib.recommendation.{ALS, Rating}    //生成Rating    val rddData = sc.textFile("hdfs://master1.hdp.com:8020/user/mldata/lastfm360k/data.tsv").map(o=>{      val arr=o.split("\t")      Rating(arr(0).toInt,arr(1).toInt,arr(2).toDouble)    }).cache()    //生成数据模型,特征值10,迭代次数5    val model=ALS.trainImplicit(rddData,10,5)    //生成map,存储艺术家    val rddArtist = sc.textFile("hdfs://master1.hdp.com:8020/user/mldata/lastfm360k/artist.tsv").map(s => {      val arr = s.split("\t")      (arr(2),arr(1))   //艺术家id,艺术家名称    }).collectAsMap    //发送变量到节点    sc.broadcast(rddArtist)    //给ID为1的用户推荐5个艺术家    val recom= model.recommendProducts(1,5)    recom.foreach(o=>{      val i=o.productIterator.mkString("\t")+"\t"+rddArtist.get(o.product.toString).getOrElse(None)      println(i)    })

给出的推荐结果为:

1       7652    1.1916553012363487      leona machálková1       6811    1.1661875108481186      asphyx1       3875    1.1555434408409613      penn state blue band1       7205    1.1465708495326612      magical strings1       9867    1.127803543649008       sandra dahlberg
原创粉丝点击