Eclipse 保存电影推荐模型时,发生异常 Exception in thread “dag-scheduler-event-loop“ java.lang.StackOverflowError

文章目录

    • 发现问题
    • 解决方案
      • 1、环境配置
      • 2、错误原因
      • 3、解决方法
    • 模型使用
    • 源程序如下
    • 参考

发现问题

在 Eclipse 运行 ALS 算法进行电影推荐模型时,保存模型 model.save(sc,Path+"ALSmodel")时,发生报错 Exception in thread "dag-scheduler-event-loop" java.lang.StackOverflowError

Eclipse 保存电影推荐模型时,发生异常 Exception in thread “dag-scheduler-event-loop“ java.lang.StackOverflowError_第1张图片
运行 hadoop fs -ls /user/hduser查看模型是存在的

在这里插入图片描述
尝试运行模型,然而找不到模型

Eclipse 保存电影推荐模型时,发生异常 Exception in thread “dag-scheduler-event-loop“ java.lang.StackOverflowError_第2张图片
经在网上搜索,找到如下解决方案



解决方案


1、环境配置

(1)Linux 系统:VirtualBox 6.1.14, Ubuntu 16.04

(2)hadoop 2.7.1

(3)Anaconda 2.5.0

(4)pyspark 2.0.0

(5)Eclipse 3.85

2、错误原因

错误原因可能是内存过小,数据量过大,发生栈溢出,无法保存模型。
因此用 checkpoint(self) 标记当前 RDD 的校验点,它会被保存为在由 SparkContext.setCheckpointDir()方法设置的 checkpoint 目录下的文件集中的一个文件。
简而言之就是当前 RDD 的校验点被保存为了一个文件,而这个文件在一个目录下,这个目录用来让RDD们可以在其下被 checkpoint。

注:如果是在一个集群上跑,这个目录必须是一个HDFS路径。

3、解决方法

在原程序的主程序 if __name__ == "__main__":下添加

sc.setCheckpointDir('checkpoint')

或者

sc.setCheckpointDir('hdfs://master:9000/user/hduser/checkpoint')

两种均可

如下图红线

Eclipse 保存电影推荐模型时,发生异常 Exception in thread “dag-scheduler-event-loop“ java.lang.StackOverflowError_第3张图片

从图中就可以看到模型保存成功,如果添加的是第二条代码,我们可以看到在相应目录上多出一个 checkpoint 文件夹

Eclipse 保存电影推荐模型时,发生异常 Exception in thread “dag-scheduler-event-loop“ java.lang.StackOverflowError_第4张图片
接下来进行模型使用。



模型使用

在 eclipse 运行 spark-submit Standalone 外部工具执行 Recommend.py ,输入参数 --U 200或者 --M 200如下图

Eclipse 保存电影推荐模型时,发生异常 Exception in thread “dag-scheduler-event-loop“ java.lang.StackOverflowError_第5张图片
其中

  • --U 200是针对用户 ID=200 推荐电影
  • --M 200是针对电影 ID=200 推荐用户

点击 OK等待运行结果

Eclipse 保存电影推荐模型时,发生异常 Exception in thread “dag-scheduler-event-loop“ java.lang.StackOverflowError_第6张图片
至此完成了在 eclipse 中运行 ALS 推荐算法进行电影推荐。



源程序如下

1、RecommendTrain.py

from pyspark.mllib.recommendation import ALS
from pyspark import SparkConf, SparkContext

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:/home/hduser/pythonsparkexample/PythonProject/"
    else:   
        Path="hdfs://master:9000/user/hduser/"
#如果要在cluster模式运行(hadoop yarn 或Spark Stand alone),请按照书上的说明,先把文件上传到HDFS目录
  
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 PrepareData(sc): 
    #----------------------1.建立用户评价数据-------------
    print("开始读取用户评分数据...")
    rawUserData = sc.textFile(Path+"data/u.data")
    rawRatings = rawUserData.map(lambda line: line.split("\t")[:3] )
    ratingsRDD = rawRatings.map(lambda x: (x[0],x[1],x[2]))
    #----------------------2.显示数据项数-------------
    numRatings = ratingsRDD.count()
    numUsers = ratingsRDD.map(lambda x: x[0] ).distinct().count()
    numMovies = ratingsRDD.map(lambda x: x[1]).distinct().count() 
    print("共计:ratings: " + str(numRatings) +    
             " User:" + str(numUsers) +  
             " Movie:" +    str(numMovies))
    return(ratingsRDD)

def SaveModel(sc): 
    try:        
        model.save(sc,Path+"ALSmodel")
        print("已存储 Model 在ALSmodel")
    except Exception :
        print "Model已经存在,请先删除再存储."        
    
if __name__ == "__main__":
    sc=CreateSparkContext()
    sc.setCheckpointDir('checkpoint')
    sc.setCheckpointDir('hdfs://master:9000/user/hduser/checkpoint')
    print("==========数据准备阶段===========")
    ratingsRDD = PrepareData(sc)
    print("==========训练阶段===============")
    print("开始ALS训练,参数rank=5,iterations=20, lambda=0.1");
    model = ALS.train(ratingsRDD, 5, 20, 0.1)
    print("========== 存储Model========== ==")
    SaveModel(sc)

2、Recommend.py

import sys
from pyspark import SparkConf, SparkContext
from pyspark.mllib.recommendation import  MatrixFactorizationModel
  
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 SetPath(sc):
    global Path
    if sc.master[0:5]=="local" :
        Path="file:/home/hduser/pythonsparkexample/PythonProject/"
    else:   
        Path="hdfs://master:9000/user/hduser/"

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 PrepareData(sc): 
    print("开始读取电影ID与名称字典...")
    itemRDD = sc.textFile(Path+"data/u.item") 
    movieTitle= itemRDD.map( lambda line : line.split("|"))     \
                                   .map(lambda a: (float(a[0]),a[1]))       \
                                   .collectAsMap()                          
    return(movieTitle)

def RecommendMovies(model, movieTitle, inputUserID): 
    RecommendMovie = model.recommendProducts(inputUserID, 10) 
    print("针对用户id" + str(inputUserID) + "推荐下列电影:")
    for rmd in RecommendMovie:
        print  "针对用户id {0} 推荐电影{1} 推荐评分 {2}". \
            format( rmd[0],movieTitle[rmd[1]],rmd[2])

def RecommendUsers(model, movieTitle, inputMovieID) :
    RecommendUser = model.recommendUsers(inputMovieID, 10) 
    print "针对电影 id {0} 电影名:{1}推荐下列用户id:". \
           format( inputMovieID,movieTitle[inputMovieID])
    for rmd in RecommendUser:
        print  "针对用户id {0}  推荐评分 {1}".format( rmd[0],rmd[2])


def loadModel(sc):
    try:        
        model = MatrixFactorizationModel.load(sc, Path+"ALSmodel")
        print "载入ALSModel模型"
    except Exception:
        print "找不到ALSModel模型,请先训练"
    return model 



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]))


if __name__ == "__main__":
    if len(sys.argv) != 3:
        print("请输入2个参数")
        exit(-1)
    sc=CreateSparkContext()
    print("==========数据准备===============")
    (movieTitle) = PrepareData(sc)
    print("==========载入模型===============")
    model=loadModel(sc)
    print("==========进行推荐===============")
    Recommend(model)


参考

  • 1、林大贵.《Python+Spark 2.0+Hadoop机器学习与大数据实战》.清华大学出版社
  • 2、https://www.cnblogs.com/suanec/p/4769768.html
  • 3、https://blog.csdn.net/levy_cui/article/details/103875930

你可能感兴趣的:(Eclipse 保存电影推荐模型时,发生异常 Exception in thread “dag-scheduler-event-loop“ java.lang.StackOverflowError)