Spark MLib支持ALS推荐算法,通过观察所有用户给产品的评价来推断每个用户的喜好,并向用户推荐适合的多个产品,也可以把某一个产品推荐给多个用户。
推荐算法介绍
基于关系型规则的推荐(Association Rule)
消费者购买产品A,那么他有多大机会购买产品B。
基于内容的推荐(Content-based)
分析网页内容自动分类,再将用户自动分类,将新进已分类的网页推荐给对该网页感兴趣的用户
人口统计式的推荐(Demographic)
将用户以个人属性(性别、年龄、教育背景、居住地、语言)作为分类的指标,以此作为推荐的基础
协同过滤式的推荐(Collaborative Filtering)
通过观察所有用户对产品的评分来判断用户的喜好,找出对产品评分相近的其他用户,他们喜好的产品当前用户多半也喜欢
协同过滤的优缺点
优点:可以达到个性化推荐,不需要内容分析,可以发现用户兴趣点,自动化程度高
缺点:冷启动问题,即没有历史数据就没有办法分析;新用户问题,即没有评分,就不知道喜好
ALS推荐算法介绍
Spark MLib支持的ALS推荐算法是机器学习的协同过滤算法。根据用户的评分来推断每个用户的喜好,并进行推荐。
评分
显式评分:用户直接对产品的评分
隐式评分:根据用户选择的产品记录,但不知道评分等级
稀疏矩阵(Sparse Matrix)问题
当用户与产品评分成千上万时,矩阵会很大,而且很多会是空白的,使用计算机处理这样的矩阵会很浪费内存,且花费很多时间。
矩阵分解
解决稀疏矩阵问题,需要采用矩阵分解
准备数据
数据集可以用MovieLens网站的数据集来进行训练
网址:https://grouplens.org/datasets/movielens/
我这里选用ml-100k(4.7M)
wget http://files.grouplens.org/datasets/movielens/ml-100k.zip
解压
unzip -j ml-100k.zip
u.data文件
用户评分数据,包括user id、item id、rating、timestamp四个字段
u.item文件
电影数据
文件上传到hadoop集群
hadoop fs -put ../data /user/hduser/movie
以YARN模式启动pyspark
HADOOP_CONF_DIR=/usr/local/hadoop/etc/hadoop pyspark --master yarn --deploy-mode client
训练数据
读取数据
rawUD = sc.textFile("hdfs://master:9000/user/hduser/movie/data/u.data")
导包
from pyspark.mllib.recommendation import Rating
注:这里需要提前安装numpy,安装方法:
1、根据自己软件版本到这里下载whl包https://pypi.org/project/numpy/1.14.2/#files
2、传入linux的文件夹,pip install 即可
读取前3个字段
rawRatings = rawUD.map(lambda line:line.split("\t")[:3])
ratingsRDD = rawRatings.map(lambda x:(x[0],x[1],x[2]))
x[0]:用户
x[1]:产品
x[2]:用户对此的评价
查看不重复的数据
numUsers = ratingsRDD.map(lambda x:x[0]).distinct().count()
训练模型
导包
from pyspark.mllib.recommendation import ALS
ALS.train
显式评分(Explicit Rating)训练
ALS.tarin(ratings,rank,iterations=5,lamda_=0.01)
model = ALS.train(ratingsRDD, 10, 10, 0.01)
注:如果出现没有numpy异常,就检查下每个服务器是否安装numpy
隐式评分(Implicit Rating)训练
ALS.tarinImplicit(ratings,rank,iterations=5,lamda_=0.01)
返回对象
利用模型进行推荐
model.recommendProducts(user:Int, num:Int)
针对用户进行推荐
针对用户100,推荐最有可能喜欢的前五个电影
model.recommendProducts(user=100, num=5)
查看针对用户100推荐产品的评分
model.predict(100, 1311)
针对电影进行推荐用户
针对电影200推荐最有可能喜欢的前5个用户
model.recommendUsers(200,5)
显示电影名称
导入item
itemRDD = sc.textFile("hdfs://master:9000/user/hduser/movie/data/u.item")
创建ID-电影名字典
movieTitle = itemRDD.map(lambda line:line.split("|")).map(lambda a:(float(a[0]),a[1])).collectAsMap()
开始推荐
recommendP = model.recommendProducts(100,5)
for p in recommendP:
print("user:"+str(p[0])+","+"recommended:"+str(movieTitle[p[1]])+","+"rating:"+str(p[2]))
综上,构建推荐系统程序
需要构建的两个程序
推荐系统示意图
RecommendTrain代码
#!/usr/bin/env python3
# coding=utf-8
# __author__: Alexander
from pyspark import SparkContext
from pyspark import SparkConf
from pyspark.mllib.recommendation import ALS
def CreateSparkContext():
sparkConf = SparkConf() \
.setAppName("RecommendTrain") \
.set("spark.ui.showConsoleProgress", "false") \
sc = SparkContext(conf = sparkConf)
print("master="+sc.master)
SetLogger(sc)
SetPath(sc)
return sc
def SetLogger(sc):
logger = sc._jvm.org.apache.log4j
logger.LogManager.getLogger("org").setLevel(logger.Level.ERROR)
logger.LogManager.getLogger("akka").setLevel(logger.Level.ERROR)
logger.LogManager.getRootLogger().setLevel(logger.Level.ERROR)
def SetPath(sc):
global Path
if sc.master[0:5] == "local":
Path = "file:/root/pythonwork/movie/"
else:
Path = "hdfs://master:9000/user/hduser/"
def SaveModel(sc):
try:
model.save(sc, Path+"movie/ALSmodel")
print("Model is saved")
except:
print("Error,Model is already exist")
def PrepareData(sc):
file = sc.textFile(Path + "movie/data/u.data")
rawRatings = file.map(lambda line: line.split("\t")[:3])
ratingsRDD = rawRatings.map(lambda x: (x[0], x[1], x[2]))
return ratingsRDD
if __name__ == "__main__":
sc = CreateSparkContext()
print("-----------Preparing----------")
ratingsRDD = PrepareData(sc)
print("-----------Training-----------")
print("Start ALS training, rank=5,iterations=20, lambda=0.1")
model = ALS.train(ratingsRDD, 5, 20, 0.1)
print("-----------Saving Model-----------")
SaveModel(sc)
运行
HADOOP_CONF_DIR=/usr/local/hadoop/etc/hadoop spark-submit --driver-memory 512m --executor-cores 2 --master yarn --deploy-mode client RecommendTrain.py
Recommend代码
代码
#!/usr/bin/env python3
# coding=utf-8
# __author__: Alexander
from pyspark.mllib.recommendation import MatrixFactorizationModel
from pyspark import SparkContext
from pyspark import SparkConf
import sys
def CreateSparkContext():
sparkConf = SparkConf() \
.setAppName("Recommend") \
.set("spark.ui.showConsoleProgress", "false") \
sc = SparkContext(conf=sparkConf)
print("master="+sc.master)
SetLogger(sc)
SetPath(sc)
return sc
def SetLogger(sc):
logger = sc._jvm.org.apache.log4j
logger.LogManager.getLogger("org").setLevel(logger.Level.ERROR)
logger.LogManager.getLogger("akka").setLevel(logger.Level.ERROR)
logger.LogManager.getRootLogger().setLevel(logger.Level.ERROR)
def SetPath(sc):
global Path
if sc.master[0:5] == "local":
Path = "file:/root/pythonwork/"
else:
Path = "hdfs://master:9000/user/alex/"
def PrepareData(sc):
print("Loading Data......")
itemRDD = sc.textFile(Path+"movie/data/u.item")
movieTitle = itemRDD.map(lambda line: line.split("|"))\
.map(lambda a: (float(a[0]), a[1]))\
.collectAsMap()
return movieTitle
def Recommend(model):
if sys.argv[1] == "--U":
RecommendMovies(model, movieTitle, int(sys.argv[2]))
if sys.argv[1] == "--M":
RecommendUsers(model, movieTitle, int(sys.argv[2]))
def RecommendMovies(model, movieTitle, inputUserID):
RecommendMovie = model.recommendProducts(inputUserID, 10)
print("User ID:" + str(inputUserID))
for i in RecommendMovie:
print("user {0},movie {1},rating {2}"
.format(i[0], movieTitle[i[1]], i[2]))
def RecommendUsers(model, inputMovieID):
RecommendUser = model.recommendUsers(inputMovieID, 10)
print("Movie ID:" + str(inputMovieID))
for i in RecommendUser:
print("user {0}, rating {2}"
.format(i[0], i[2]))
def loadModel(sc):
try:
model = MatrixFactorizationModel.load(sc, Path+"movie/ALSmodel")
print("Loading ALS Model.....")
except:
print("Error,ALS Model is not found!")
return model
if __name__ == "__main__":
if len(sys.argv) != 3:
print("Please input 2 parameter")
exit(-1)
sc = CreateSparkContext()
print("-----------Preparing----------")
movieTitle = PrepareData(sc)
print("-----------Training-----------")
print("Loading Model")
model = loadModel(sc)
print("-----------Recommend-----------")
Recommend(model)
运行
HADOOP_CONF_DIR=/usr/local/hadoop/etc/hadoop spark-submit --driver-memory 512m --executor-cores 2 --master yarn --deploy-mode client Recommend.py --U 100
注:运行时其实传递了三个参数:
sys.argv[0]=‘Recommend.py’,也就是代码程序路径
sys.argv[1]=’–U’,代表执行对用户推荐电影
sys.argv[2]=‘100’,代表要推荐的用户ID
运行结果: