Spark与机器学习 学习笔记

标准差(Standard Deviation):又常称均方差,反映了数字集的离散程度 (对方差做根号)

向量:点积(数量积)   对应坐标乘积和   
      向量积

      一阶范数       表示向量元素之和
      二阶范数       表示向量长度
      无限大-范数    表示向量元素绝对值的最大值

      点积/二阶范数 = 角度

 


稳定性是指系统受到瞬时扰动,扰动消失后系统回到原来状态的能力,而鲁棒性是指系统受到持续扰动能保持原来状态的能力。

 

1.公开数据集

 
2.探索可视化数据


3.处理和转换数据

  过滤非规整或由值缺失的数据
  填充非规整或缺失的数据(零值,中值,相邻)
  对异常值做鲁棒处理(一些极值并不一定是错的,需要做鲁棒回归)
  异常值转换,值域覆盖过大,可以使用对数 或者 高斯核 进行转换

4.数据中提取特征

  数值特征
  类别特征 (可以提取成一个二元特征向量)
  文本特征 (词袋 表示法   分词 过滤 替换 向量化<二元特征向量>)
  其他特征 (大部分其他特征等最终都会转成数值)
  派生特征 (时间->小时->早中晚->二元特征向量)


  名义变量 没有顺序关系
  有序变量


  正则化特征:减去平均数,特征对齐
              标准正则转换,平均值 和 标准差(平均方差),代表数值的离散程度

  正则化特征向量:


=======================================================================

基于spark的推荐引擎


推荐 + 搜索


1.适用场景:

  可选项众多:用户不知道如何搜索
  偏个人喜好:

2.分类:

  基于内容的过滤:

     先提取物品本身的内容和属性     
     可以将用户标识为:他所接触的物品属性的综合。

  协同过滤

     根据用户的偏好行为,来划分相似的用户群,基于用户的推荐
     根据用户的偏好行为,来划分相似的物品集,基于物品的推荐  
     (最近邻模型)


3.矩阵分解

   因子矩阵

   https://blog.csdn.net/xuejianxinokok/article/details/79230190

   A 高阶特征权重矩阵  (高阶特征 可雪,乐碧    由  可乐雪碧芬达组成)
   B 低阶特征权重矩阵 (低阶特征 可乐雪碧芬达  由  能量,蛋白质等)

   矩阵分解的目标,将一个稀疏的特征矩阵(低阶) 转换成 ----> 高阶的特征权重矩阵(便于预测,存储等)

   (最小二乘法)

 


步骤:


   1.提取特征:

            val ratings = rawRatings.map { case Array(user, movie, rating) =>
               Rating(user.toInt, movie.toInt, rating.toDouble) }  

            生成一个打分的矩阵


   2.训练模型:

            显示评级数据的训练模型
            
            rank :ALS模型因子的个数,特征矩阵中的隐含特征个数
            iterations :对应运行时的迭代次数,ALS每次迭代都能降低误差,但一般10次后就不会有什么变化了
            lambda : 正则参数 应该通过用测试数据 进行交叉验证

            val model = ALS.train(ratings, 50, 10, 0.01) [MatrixFactorizationModel 因式分解后的矩阵模型 RDD]
            model.userFeatures  [RDD]
            model.productFeatures [RDD]


        |------------------------------------------------------------------------
            | 隐式反馈数据的训练模型 (待看)
            |

        | trainImplicit  alpha 和 lambda 两个正则化参数,通过测试数据交叉验证。
            | alpha参数越搞,训练的模型越认为用户和他所评级的电影之间没有相关性。            
               
   3.使用模型
            

            为用户推荐物品:(预测)

                  计算用户对物品的预计评级,预计得分可视作相应用户因子向量和物品因子向量的点积(数量积)。
                  val predictedRating = model.predict(789, 123)                                      用户对某个产品的预期得分                 Double
                  val topKRecs = model.recommendProducts(789, 10)                                    用户对所有产品前十的推荐(根据预期得分) Array[Rating]
                  topKRecs.map(rating => (titles(rating.product),rating.rating)).foreach(println)    转成电影名  


                  val moviesForUser =  ratings.keyBy(_.user).lookup(789)  ratings就是Rating(user movie rating)这个结构的数据
                  moviesForUser.sortBy(-_.rating).take(10).map(rating => (titles(rating.product), rating.rating)).foreach(println)


            找到某个物品相似的其他物品 (分类)
           
                  import org.jblas.DoubleMatrix  线性代数库
                  val aMatrix = new DoubleMatrix(Array(1.0, 2.0, 3.0))      
          
                  两个向量的点积与各向量范数(或长度 二阶范数)的乘积的商       
                 
                  def cosineSimilarity(vec1: DoubleMatrix, vec2: DoubleMatrix): Double = {
                          vec1.dot(vec2) / (vec1.norm2() * vec2.norm2())
                  }
                  
                  val itemId = 567
          val itemFactor = model.productFeatures.lookup(itemId).head
                  val itemVector = new DoubleMatrix(itemFactor)  //评估的product
                    
                  val sims = model.productFeatures.map{ case (id, factor) =>
                      val factorVector = new DoubleMatrix(factor)
                       val sim = cosineSimilarity(factorVector, itemVector)
                       (id, sim)
                  }
                  
                  val sortedSims = sims.top(K)(Ordering.by[(Int, Double), Double] { case
          (id, similarity) => similarity })
 
                  使用余弦函数判断相似度

 

=============================================================================

高级文本处理技术

     词袋模型(词向量空间模型) 和 TF-IDF模型


     |--------------------------------------------
     |  可以使用特征哈希垂类高维数据(高维向量)
     |  避免维护下标映射
     |  降低向量的维度


     特征提取:

    val path = "/PATH/20news-bydate-train/*"
    val rdd = sc.wholeTextFiles(path)
    val text = rdd.map { case (file, text) => text }  //RDD 所有的文本
    println(text.count)

               

        val newsgroups = rdd.map { case (file, text) => file.split("/").takeRight(2).head }                         //RDD  (分类+id) 文档数
        val countByGroup = newsgroups.map(n => (n, 1)).reduceByKey(_ + _).collect.sortBy(-_._2).mkString("\n")
        println(countByGroup)
    

       //分词过滤逻辑整合
       def tokenize(line: String): Seq[String] = {
      line.split("""\W+""")
      .map(_.toLowerCase)
     .filter(token => regex.pattern.matcher(token).matches)
      .filterNot(token => stopwords.contains(token))
        .filterNot(token => rareTokens.contains(token))
        .filter(token => token.size >= 2)
        .toSeq
       }
 
       val tokens = text.map(doc => tokenize(doc))  //RDD 所有文本对应的分词
       println(tokens.first.take(20))

       //提取词干
       NLTK OpenNLP Lucene


       //特征向量
       import org.apache.spark.mllib.linalg.{ SparseVector => SV } //SparseVector 稀疏向量
       import org.apache.spark.mllib.feature.HashingTF
       import org.apache.spark.mllib.feature.IDF
       val dim = math.pow(2, 18).toInt
       val hashingTF = new HashingTF(dim)    //26万的维度向量
       val tf = hashingTF.transform(tokens)  //hash做下标,同时算词频,得到词频向量 RDD 所有文档的词频向量
       tf.cache


       //向量值tf
       val v = tf.first.asInstanceOf[SV]
       println(v.size)
       println(v.values.size)
       println(v.values.take(10).toSeq)
       println(v.indices.take(10).toSeq)

       //tf-idf
       val idf = new IDF().fit(tf)    //根据所有文档的词频向量,算出idf向量
       val tfidf = idf.transform(tf)  //根据idf向量和词频向量 生成tfidf向量 (每个文档的tfidf向量)
       val v2 = tfidf.first.asInstanceOf[SV]
       println(v2.values.size)
       println(v2.values.take(10).toSeq)
       println(v2.indices.take(10).toSeq)


 
    模型训练
         
       文本相似度

       val hockeyText = rdd.filter { case (file, text) => file.contains("hockey") }
       val hockeyTF = hockeyText.mapValues(doc => hashingTF.transform(tokenize(doc)))
       val hockeyTfIdf = idf.transform(hockeyTF.map(_._2))   //算出hokey这个类别 各doc的tfidf向量

       import breeze.linalg._
       val hockey1 = hockeyTfIdf.sample (true, 0.1, 42).first.asInstanceOf[SV]
       val breeze1 = new SparseVector(hockey1.indices, hockey1.values, hockey1.size)
       val hockey2 = hockeyTfIdf.sample (true, 0.1, 43).first.asInstanceOf[SV]
       val breeze2 = new SparseVector(hockey2.indices, hockey2.values, hockey2.size)
       val cosineSim = breeze1.dot(breeze2) / (norm(breeze1) * norm(breeze2)) println(cosineSim)

       文本分类器
         
       朴素贝叶斯:
       import org.apache.spark.mllib.regression.LabeledPoint
       import org.apache.spark.mllib.classification.NaiveBayes  
       import org.apache.spark.mllib.evaluation.MulticlassMetrics

       val newsgroupsMap = newsgroups.distinct.collect().zipWithIndex.toMap   // 话题和下标的映射
       val zipped = newsgroups.zip(tfidf)
       val train = zipped.map { case (topic, vector) => LabeledPoint(newsgroupsMap(topic), vector) }  //话题下标 向量  A分类 特征向量集合  B分类 特征向量集合 ....
       train.cache

       val model = NaiveBayes.train(train, lambda = 0.1)


    验证:
       val testPath = "/PATH/20news-bydate-test/*"
       val testRDD = sc.wholeTextFiles(testPath)
       val testLabels = testRDD.map { case (file, text) =>
                 val topic = file.split("/").takeRight(2).head
                 newsgroupsMap(topic)
       }

       val testTf = testRDD.map { case (file, text) => hashingTF.transform(tokenize(text)) }
       val testTfIdf = idf.transform(testTf)
       val zippedTest = testLabels.zip(testTfIdf)
       val test = zippedTest.map { case (topic, vector) => LabeledPoint(topic, vector) }  //测试集 对应的主题 和 特征

       val predictionAndLabel = test.map(p => (model.predict(p.features), p.label))
       val accuracy = 1.0 * predictionAndLabel.filter (x => x._1 == x._2).count() / test.count()
       val metrics = new MulticlassMetrics(predictionAndLabel)
       println(accuracy)
       println(metrics.weightedFMeasure)

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值