spark机器学习点击量推荐

来源:互联网 发布:网络借贷平台有哪些 编辑:程序博客网 时间:2024/06/07 07:07

通过用户对音乐点击推荐相应的产品
使用分析方法:ROC分析法
ROC分析是从医疗分析领域引入了一种新的分类模型performance评判方法。
算法:AUC
AUC是一种用来度量分类模型好坏的一个标准。
AUC的值就是处于ROC curve下方的那部分面积的大小。通常,AUC的值介于0.5到1.0之间,较大的AUC代表了较好的performance。

用户产品点击列表
这里写图片描述

产品信息表
这里写图片描述

为规范数据建立的中间表
这里写图片描述

此点击推荐系统,没有分出一部分测试,验证测试和结果的误差率
step1:加载

def main(args: Array[String]): Unit = {Logger.getLogger("org.apache.spark").setLevel(Level.WARN)Logger.getLogger("org.eclipse.jetty.server").setLevel(Level.OFF)val conf=new SparkConf().setAppName("Recommender").setMaster("local").setExecutorEnv("spark.executor.memory","3072m").setExecutorEnv("SPARK_DRIVER_MEMORY","3072m")val sc = new SparkContext(conf)val base = "F:/datafile/lisence/"val rawUserArtistData = sc.textFile(base + "user_artist_data.txt")//用户产品点击表加载val rawArtistData = sc.textFile(base + "artist_data.txt")//产品数据表加载val rawArtistAlias = sc.textFile(base + "artist_alias.txt")//误差名字转换表加载evaluate(sc, rawUserArtistData,rawArtistData, rawArtistAlias) sc.stop()}

step2:执行

def evaluate(                sc: SparkContext,                rawUserArtistData: RDD[String],                rawArtistData: RDD[String],                rawArtistAlias: RDD[String]): Unit = {val bArtistAlias = sc.broadcast(buildArtistAlias(rawArtistAlias))  //Broadcast(广播)是相对较为常用方法功能,通常使用方式,包括共享配置文件,map数据集,树形数据结构等,为能够更好更快速为TASK任务使用相关变量。val allData = buildRatings(rawUserArtistData, bArtistAlias)    //转换格式不正确数据,并构建Ratingval Array(trainData, cvData) = allData.randomSplit(Array(0.9, 0.1))    //数据按比率随机分块,90%用户训练,10%真实数据验证trainData.cache()    //缓存训练数据cvData.cache()    //缓存真实数据val allItemIDs = allData.map(_.product).distinct().collect()val bAllItemIDs = sc.broadcast(allItemIDs)    //把用户中的产品所有的数据集合存起来var bestauc=Double.MinValuevar bestModel: Option[MatrixFactorizationModel] = None //最好模型for (rank   <- Array(10,50);     lambda <- Array(1.0, 0.0001);     alpha  <- Array(1.0, 40.0)) {     val model = ALS.trainImplicit(trainData, rank, 10, lambda, alpha)      //模型训练     val auc = areaUnderCurve(cvData, bAllItemIDs, model)     //求auc     unpersist(model)     if(bestauc<auc){            bestauc=auc            bestModel=Some(model)          }        }trainData.unpersist()cvData.unpersist()val artistByID = buildArtistByID(rawArtistData)val someUsers = allData.map(_.user).distinct().take(5)//这里取5个用户val someRecommendations=someUsers.map(userID=>bestModel.get.recommendProducts(userID, 5))//推荐5个产品给用户someRecommendations.map(  recs => recs.head.user + " -> " +artistByID.filter { case (id, name) => recs.map(_.product).contains(id) }.values.collect().mkString(", ")    ).foreach(println)allData.unpersist()unpersist(bestModel.get)  }

step3:auc计算

def areaUnderCurve(                      positiveData: RDD[Rating],                      bAllItemIDs: Broadcast[Array[Int]],                      model: MatrixFactorizationModel) = {    val positiveUserProducts = positiveData.map(r => (r.user, r.product))    val positivePredictions = model.predict(positiveUserProducts).groupBy(_.user)    val negativeUserProducts = positiveUserProducts.groupByKey().mapPartitions {      userIDAndPosItemIDs => {      val random = new Random()      val allItemIDs = bAllItemIDs.value        userIDAndPosItemIDs.map { case (userID, posItemIDs) =>        val posItemIDSet = posItemIDs.toSet          //此为一个产品序列        val negative = new ArrayBuffer[Int]()        var i = 0          while (i < allItemIDs.size && negative.size < posItemIDSet.size) {            //按每个产品序列长度遍历          val itemID = allItemIDs(random.nextInt(allItemIDs.size))            //随机一个用户列表里面的产品            if (!posItemIDSet.contains(itemID)) {              negative += itemID              //向数组中加入与原来不一样的产品            }            i += 1          }          negative.map(itemID => (userID, itemID))        }      }    }.flatMap(t => t)    val negativePredictions = model.predict(negativeUserProducts).groupBy(_.user)    //对用户和产品进行点击量预测    positivePredictions.join(negativePredictions).values.map {      case (positiveRatings, negativeRatings) =>        var correct = 0L        var total = 0L        for (positive <- positiveRatings;             negative <- negativeRatings) {          if (positive.rating > negative.rating) {            correct += 1          }          total += 1        }        correct.toDouble / total    }.mean()    //AUC计算  }

step4:数据处理

//去除缓存  def unpersist(model: MatrixFactorizationModel): Unit = {    model.userFeatures.unpersist()    model.productFeatures.unpersist()  }  //构建Rating  def buildRatings(                    rawUserArtistData: RDD[String],  //未转换用户产品信息表                    bArtistAlias: Broadcast[Map[Int,Int]]) = {    rawUserArtistData.map { line =>      val Array(userID, artistID, count) = line.split(' ').map(_.toInt)      val finalArtistID = bArtistAlias.value.getOrElse(artistID, artistID)      //如果匹配返回artistID匹配到的对象,没匹配到返回artistID(原来值)      Rating(userID, finalArtistID, count)    }  }  //产品数据  def buildArtistByID(rawArtistData: RDD[String]) =    rawArtistData.flatMap { line =>      val (id, name) = line.span(_ != '\t')      if (name.isEmpty) {        None      } else {        try {          Some((id.toInt, name.trim))        } catch {          case e: NumberFormatException => None        }      }    }  //把产品中不规范的数据建立映射  def buildArtistAlias(rawArtistAlias: RDD[String]): Map[Int,Int] =    rawArtistAlias.flatMap { line =>      val tokens = line.split('\t')      if (tokens(0).isEmpty) {        None      } else {        Some((tokens(0).toInt, tokens(1).toInt))      }    }.collectAsMap()

总结:
1.spark支持机器学习,对于不属于这领域的人学习更加方便了。
2.什么场景用什么算法公式对于初学者很重要。
3.观察evaluate函数,你会发现 推荐系统很简单,最重要在于算法的应用和编写。

0 0
原创粉丝点击