通过 HDInsight (SSH) 中基于 Linux 的 Hadoop 使用 Apache Mahout 生成电影推荐

了解如何使用 Apache Mahout 机器学习库通过 Azure HDInsight 生成电影推荐。

Mahout 是适用于 Apache Hadoop 的 计算机学习 库。 Mahout 包含用于处理数据的算法,例如筛选、分类和群集。 在本文中,用户使用推荐引擎根据好友看过的电影生成电影推荐。

先决条件

Note

在 Azure 中国区,HDInsight Linux 仅支持 3.5 或更高版本。 在 Azure 中国区无法创建 HDInsight Linux 3.2、3.3 和 3.4。 但是,可以通过 HDInsight 模拟器使用这些版本。

Important

Linux 是 HDInsight 3.4 或更高版本上使用的唯一操作系统。 有关详细信息,请参阅 HDInsight 在 Windows 上停用

Mahout 版本控制

若要深入了解 HDInsight 中的 Mahout 版本,请参阅 HDInsight 版本和 Hadoop 组件

了解建议

由 Mahout 提供的功能之一是推荐引擎。 此引擎接受 userIDitemIdprefValue 格式(项的首选项)的数据。 然后,Mahout 将执行共现分析以确定:偏好某个项的用户也偏好其他类似项。 随后,Mahout 确定拥有类似项偏好的用户,这些偏好可用于推荐。

下面的工作流是使用电影数据的简化示例:

  • 共现:Joe、Alice 和 Bob 都喜欢电影《星球大战》、《帝国反击战》和《绝地归来》。 Mahout 可确定喜欢以上电影之一的用户也喜欢其他两部。

  • 共现:Bob 和 Alice 还喜欢电影《幽灵的威胁》、《克隆人的进攻》和《西斯的复仇》。 Mahout 可确定喜欢前面三部电影的用户也喜欢这三部电影。

  • 类似性推荐:由于 Joe 喜欢前三部电影,Mahout 会查看具有类似首选项的其他人喜欢的电影,但是 Joe 还未观看过(喜欢/评价)。 在这种情况下,Mahout 推荐《幽灵的威胁》、《克隆人的进攻》和《西斯的复仇》。

了解数据

为方便起见, GroupLens 研究 以兼容 Mahout 的格式提供电影的评价数据。 此数据在 /HdiSamples/HdiSamples/MahoutMovieData 中群集的默认存储中可用。

有两个文件,即 moviedb.txtuser-ratings.txtuser-ratings.txt 文件在分析期间使用。 moviedb.txt 用于在查看结果时提供用户友好的文本信息。

user-ratings.txt 中包含的数据具有 userIDmovieIDuserRatingtimestamp 结构,指示每个用户对电影评级的情况。 下面是数据的示例:

196    242    3    881250949
186    302    3    891717742
22    377    1    878887116
244    51    2    880606923
166    346    1    886397596

运行分析

通过 SSH 到群集的连接,使用以下命令运行推荐作业:

mahout recommenditembased -s SIMILARITY_COOCCURRENCE -i /HdiSamples/HdiSamples/MahoutMovieData/user-ratings.txt -o /example/data/mahoutout --tempDir /temp/mahouttemp

Note

该作业可能需要几分钟才能完成,并可能运行多个 MapReduce 作业。

查看输出

  1. 作业完成后,使用以下命令查看生成的输出:

    hdfs dfs -text /example/data/mahoutout/part-r-00000
    

    输出如下所示:

     1    [234:5.0,347:5.0,237:5.0,47:5.0,282:5.0,275:5.0,88:5.0,515:5.0,514:5.0,121:5.0]
     2    [282:5.0,210:5.0,237:5.0,234:5.0,347:5.0,121:5.0,258:5.0,515:5.0,462:5.0,79:5.0]
     3    [284:5.0,285:4.828125,508:4.7543354,845:4.75,319:4.705128,124:4.7045455,150:4.6938777,311:4.6769233,248:4.65625,272:4.649266]
     4    [690:5.0,12:5.0,234:5.0,275:5.0,121:5.0,255:5.0,237:5.0,895:5.0,282:5.0,117:5.0]
    

    第一列是 userID。 “[”和“]”中包含的值为 movieId:recommendationScore

  2. 可使用该输出以及 moviedb.txt 提供有关建议的详细信息。 首先,使用以下命令在本地复制文件:

    hdfs dfs -get /example/data/mahoutout/part-r-00000 recommendations.txt
    hdfs dfs -get /HdiSamples/HdiSamples/MahoutMovieData/* .
    

    此命令会将输出数据复制到当前目录中名为 recommendations.txt 的文件以及电影数据文件。

  3. 使用如下命令创建 Python 脚本,该脚本查找电影名称中是否存在建议输出中的数据:

    nano show_recommendations.py
    

    编辑器打开后,使用以下文本作为该文件的内容:

    #!/usr/bin/env python
    
    import sys
    
    if len(sys.argv) != 5:
         print "Arguments: userId userDataFilename movieFilename recommendationFilename"
         sys.exit(1)
    
    userId, userDataFilename, movieFilename, recommendationFilename = sys.argv[1:]
    
    print "Reading Movies Descriptions"
    movieFile = open(movieFilename)
    movieById = {}
    for line in movieFile:
        tokens = line.split("|")
        movieById[tokens[0]] = tokens[1:]
    movieFile.close()
    
    print "Reading Rated Movies"
    userDataFile = open(userDataFilename)
    ratedMovieIds = []
    for line in userDataFile:
        tokens = line.split("\t")
        if tokens[0] == userId:
            ratedMovieIds.append((tokens[1],tokens[2]))
    userDataFile.close()
    
    print "Reading Recommendations"
    recommendationFile = open(recommendationFilename)
    recommendations = []
    for line in recommendationFile:
        tokens = line.split("\t")
        if tokens[0] == userId:
            movieIdAndScores = tokens[1].strip("[]\n").split(",")
            recommendations = [ movieIdAndScore.split(":") for movieIdAndScore in movieIdAndScores ]
            break
    recommendationFile.close()
    
    print "Rated Movies"
    print "------------------------"
    for movieId, rating in ratedMovieIds:
        print "%s, rating=%s" % (movieById[movieId][0], rating)
    print "------------------------"
    
    print "Recommended Movies"
    print "------------------------"
    for movieId, score in recommendations:
        print "%s, score=%s" % (movieById[movieId][0], score)
    print "------------------------"
    

    Ctrl-XY,最后按 Enter 来保存数据。

  4. 运行 Python 脚本。 以下命令假设用户处于内含所有已下载文件的目录中:

    python show_recommendations.py 4 user-ratings.txt moviedb.txt recommendations.txt
    

    此命令查看为用户 ID 4 生成的建议。

    • user-ratings.txt 文件用于检索已被评价过的电影。

    • moviedb.txt 文件用于检索电影的名称。

    • recommendations.txt 用于检索此用户的电影建议。

      此命令的输出类似于以下文本:

      Seven Years in Tibet (1997), score=5.0
      Indiana Jones and the Last Crusade (1989), score=5.0
      Jaws (1975), score=5.0
      Sense and Sensibility (1995), score=5.0
      Independence Day (ID4) (1996), score=5.0
      My Best Friend's Wedding (1997), score=5.0
      Jerry Maguire (1996), score=5.0
      Scream 2 (1997), score=5.0
      Time to Kill, A (1996), score=5.0
      

删除临时数据

Mahout 作业不删除在处理作业时创建的临时数据。 在示例作业中指定 --tempDir 参数,以将临时文件隔离到特定路径中轻松删除。 若要删除临时文件,请使用以下命令:

hdfs dfs -rm -f -r /temp/mahouttemp

Warning

如需再次运行此命令,则还必须删除输出目录。 使用以下命令删除此目录:

hdfs dfs -rm -f -r /example/data/mahoutout

后续步骤

既已学习如何使用 Mahout,可探索在 HDInsight 上处理数据的其他方式: