【推荐算法】协同过滤算法代码(pyspark | ALS)

【推荐算法】协同过滤算法介绍_MachineCYL的博客-CSDN博客

上文介绍了协同过滤算法的原理,接下来我介绍一下协同过滤算法的代码实现。

下面我就开始介绍用pyspark中的ALS(交替最小二乘矩阵分解)来实现协同过滤代码。

一、ALS的简单介绍

ALS算法是2008年以来,用的比较多的协同过滤算法。它已经集成到Spark的Mllib库中,使用起来比较方便。从协同过滤的分类来说,ALS算法属于User-Item CF,也叫做混合CF。它同时考虑了User(用户)和Item(商品)两个方面。

用户和商品的关系,可以抽象为如下的三元组:<User,Item,Rating>。其中,Rating是用户对商品的评分,表征用户对该商品的喜好程度。

假设我们有一批用户数据,其中包含m个User和n个Item,则我们定义Rating矩阵 Rm×n。在实际使用中,由于n和m的数量都十分巨大,因此R矩阵的规模很容易就会突破1亿项。这时候,传统的矩阵分解方法对于这么大的数据量已经是很难处理了。另一方面,一个用户也不可能给所有商品评分,因此,R矩阵注定是个稀疏矩阵。而使用ALS可以达到数据降维的目的,大大减少计算量。

二、前期准备

  • 使用pyspark前要先安装spark的环境。我的spark版本是2.4.3,pyspark版本也是2.4.3。
  • 如果需要安装spark环境,可以参考:

Spark的安装及配置 - 简书

  •  pyspark安装指令如下(加清华源,下载快多了):
pip install pyspark==2.4.3 -i https://pypi.tuna.tsinghua.edu.cn/simple
  • 数据格式(如果需要获取数据,可以见下方链接):

模型训练用到的数据格式如下:主要用到userId、movieId和rating字段。

三、详细代码

定义CollaborativeFiltering类,主要封装模型训练、模型保存、用户推荐、商品推荐等代码。

class CollaborativeFiltering(object):
    def __init__(self, spark_session):
        self.spark_session = spark_session
        self.model = None

    def train(self, train_set, user_col, item_col, rating_col, epoch=10):
        """
        Build the recommendation model using ALS on the training data
        Note we set cold start strategy to 'drop' to ensure we don't get NaN evaluation metrics
        """
        als = ALS(regParam=0.01, maxIter=epoch, userCol=user_col, itemCol=item_col, ratingCol=rating_col,
                  coldStartStrategy='drop')
        self.model = als.fit(train_set)

    def eval(self, test_set, label_col='ratingFloat', metric='rmse'):
        """ Evaluate the model on the test data """
        predictions = self.model.transform(test_set)

        # self.model.itemFactors.show(10, truncate=False)
        # self.model.userFactors.show(10, truncate=False)
        evaluator = RegressionEvaluator(predictionCol="prediction", labelCol=label_col, metricName=metric)
        loss = evaluator.evaluate(predictions)
        return loss

    def save(self, model_dir="./model_param"):
        self.model.write().overwrite().save(model_dir)

    def load(self, model_dir="./model_param"):
        self.model = ALSModel.load(model_dir)

    def recommend_for_all_users(self, num_items=10):
        user_recs = self.model.recommendForAllUsers(numItems=num_items)
        return user_recs

    def recommend_for_all_items(self, num_users=10):
        item_recs = self.model.recommendForAllItems(numUsers=num_users)
        return item_recs

    def recommend_for_user_subset(self, dataset, num_items=10):
        user_recs = self.model.recommendForUserSubset(dataset=dataset, numItems=num_items)
        return user_recs

    def recommend_for_item_subset(self, dataset, num_users=10):
        item_recs = self.model.recommendForItemSubset(dataset=dataset, numUsers=num_users)
        return item_recs

新建代码文件train_cf.py,加入示例代码如下:

def parse_argvs():
    parser = argparse.ArgumentParser(description='[collaborativeFiltering]')
    parser.add_argument("--data_path", type=str, default='./data/ratings.csv')
    parser.add_argument("--model_path", type=str, default='./model_param')
    parser.add_argument("--epoch", type=int, default=10)
    parser.add_argument("--train_flag", type=bool, default=False)
    args = parser.parse_args()
    print('[input params] {}'.format(args))

    return parser, args


if __name__ == '__main__':
    parser, args = parse_argvs()
    data_path = args.data_path
    model_path = args.model_path
    train_flag = args.train_flag
    epoch = args.epoch

    conf = SparkConf().setAppName('collaborativeFiltering').setMaster("local[*]")
    spark_session = SparkSession.builder.config(conf=conf).getOrCreate()

    # read data
    data_path = os.path.abspath(data_path)
    data_path = "file://" + data_path
    print("[spark] read file path: {}".format(data_path))

    ratingSamples = spark_session.read.format('csv').option('header', 'true').load(data_path) \
        .withColumn("userIdInt", F.col("userId").cast(IntegerType())) \
        .withColumn("movieIdInt", F.col("movieId").cast(IntegerType())) \
        .withColumn("ratingFloat", F.col("rating").cast(FloatType()))
    training, test = ratingSamples.randomSplit((0.8, 0.2), seed=2022)

    # collaborative filtering start
    cf = CollaborativeFiltering(spark_session=spark_session)

    if train_flag is True:
        cf.train(train_set=training,
                 user_col='userIdInt',
                 item_col='movieIdInt',
                 rating_col='ratingFloat',
                 epoch=epoch)

        cf.save(model_dir=model_path)
    else:
        cf.load(model_dir=model_path)

    loss = cf.eval(test_set=test, label_col='ratingFloat', metric='rmse')
    print("[Root-mean-square error] {}".format(loss))

    # Generate top 10 movie recommendations for each user
    user_recs = cf.recommend_for_all_users(num_items=10)
    user_recs.show(10, False)

    # Generate top 10 user recommendations for each movie
    movie_recs = cf.recommend_for_all_items(num_users=10)
    movie_recs.show(10, False)

    # Generate top 10 movie recommendations for a specified set of users
    user_data = ratingSamples.select("userIdInt").distinct().limit(10)
    user_sub_recs = cf.recommend_for_user_subset(dataset=user_data, num_items=10)
    user_sub_recs.show(10, False)

    # Generate top 10 user recommendations for a specified set of movies
    movie_data = ratingSamples.select("movieIdInt").distinct().limit(10)
    movie_sub_recs = cf.recommend_for_item_subset(dataset=movie_data, num_users=10)
    movie_sub_recs.show(10, False)

    spark_session.stop()

运行指令示例:

# 进行ALS模型训练和预测
python train_cf.py  --data_path "./data/ratings.csv" --train_flag True

# 不训练,直接进行ALS模型预测
python train_cf.py  --data_path "./data/ratings.csv"

代码执行结果如下(部分): 

需要获取训练数据和代码可以访问我的github,如果觉得有帮助,请star收藏,谢谢~

CollaborativeFiltering代码

参考链接 

  • 12
    点赞
  • 131
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,以下是一个基于商品推荐系统的ALS协同过滤算法代码示例: ``` from pyspark.ml.evaluation import RegressionEvaluator from pyspark.ml.recommendation import ALS from pyspark.sql import Row # 加载数据 lines = spark.read.text("ratings.csv").rdd parts = lines.map(lambda row: row.value.split(",")) ratingsRDD = parts.map(lambda p: Row(user=int(p[0]), item=int(p[1]), rating=float(p[2]), timestamp=int(p[3]))) ratings = spark.createDataFrame(ratingsRDD) # 将数据集分为训练集和测试集 (training, test) = ratings.randomSplit([0.8, 0.2]) # 建立ALS模型 als = ALS(maxIter=5, regParam=0.01, userCol="user", itemCol="item", ratingCol="rating", coldStartStrategy="drop") model = als.fit(training) # 预测测试集评分 predictions = model.transform(test) # 评估模型性能 evaluator = RegressionEvaluator(metricName="rmse", labelCol="rating", predictionCol="prediction") rmse = evaluator.evaluate(predictions) print("Root-mean-square error = " + str(rmse)) ``` 在上述代码中,我们首先读取了一个名为“ratings.csv”的文件,并将其转换为RDD类型。然后,我们将RDD转换为DataFrame类型,并将其分成训练集和测试集。接着,我们建立了一个ALS模型,并在训练集上拟合该模型。最后,我们使用测试集评估了模型性能,并计算了RMSE指标。 需要注意的是,这里的“ratings.csv”文件应该包含三列数据,分别是用户ID、商品ID和评分,例如: ``` 1,1,5.0 1,2,3.0 2,1,4.0 2,3,1.0 3,2,2.0 ... ``` 希望这个示例能够对你有所帮助!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值