Mahout笔记

一、推荐

均差 :     测试数据减真实数据的和的平均值
均方差:   测试数据减真实数据的平方值的和的平均值

查准率:   在top结果中相关的结果的比例
查全率:   所有的相关结果包含在top结果中的比例

布尔型偏好值: 只有用户id和物品id 并没有偏好强度


DataModel来生成data model,UserSimilarity生成User-user之间的相似度矩阵,用户的邻居的定义用UserNeighborhood定义,推荐引擎使用Recommender实现。

UserNeighborhood为基于n个最相似的用户为邻域   还可基于阀值创建邻域。
ThresholdUserNeighborhood(0.7,similarity,model) 只要相似度超过该阀值即为邻域.0.7即为阀值,是标准的皮尔逊相关系数



一 、基于用户的推荐程序

基本版:
    for(用户 u 尚未表达偏好的)  每个物品i
        for(对 i 有偏好的) 每个其他用户 v
             计算 u  和 v 之间的相似度 s
             按权重为 s  将 v 对 i 的偏好并入平均值
   return  值最高的物品 (按加权平均排序)

缺点: 每个物品都检查速度慢。实际应用中,通常会先计算出一个最相似的用户的邻域,然后仅考虑这些用户评价过的物品

mahout版本:
     for每个其他用户 w
            计算用户 u 和 w 的相似度 s
           按相似度排序后,将位置靠前的用户作为邻域 n
     for(n 中有偏好,而 u 中无偏好的)每个物品 i
               for(n 中用户对 i 有偏好的)每个其他用户 v
          计算用户 u 和用户 v 的相似度 s
               按权重 s 将 v 对 i  的偏好并入平均值


标准计算公式的实现 : 加权

皮尔逊相关系数并不直接反应其用到的物品数量,而我们是需要这个数字的。考虑的信息越多,所得的结果越可靠。   在基于较多的物品计算相关系数时,让相关值
向1.0偏移。 而使负相关值向-1偏移。当基于较少的物品时,可以让相关值向偏好的均值偏移。

Mahout缓存封装机制
  CachingUserSimilarity 是UserSimilarity的一种实现。它封装了另一个UserSimilariy的实现并缓存其结果。它利用另一个实现进行计算,并将结果进行内部缓存。 当需要提供一个已经计算过的用户相似度时,就可以直接返回。
  代码:       UserSimilarity similarity = new CachingUserSimilarity( new SpearmanCorrelationSimilarity(model), model);


相似度计算:

1.采用欧式距离定义相似度:

EuclideanDistanceSimilarity  edcs = new EuclideanDistanceSimilarity(model)
将用户想象成多维空间中的点,维数等于总的物品数。偏好值是坐标。 用户与用户之间的距离越近相似度越高,为0时完全相同。
优点: 可以计算出任何用户之间的相似度。


2.采用余弦相似度度量:

余弦相似度也将用户视为空间中的点。假设:两条从原点出发的射线分别到一个点。两条射线之间的夹角越大,相似度越低,夹角越小,相似度越高。余弦相似度和皮尔逊相关系数的计算
过程相同,所以对象也相同 PearsonCorrelationSimilarity

3.采用斯皮尔曼相关系数基于相对排名定义相似度:
 
偏好值最低的改为1,其次低的改为2,依次类推,然后在变换后的偏好值上计算皮尔逊相关系数,这就是斯皮尔曼相关系数。 保留的顺序,但是也丢掉了用户对不同物品喜好程度的具体差异。
学术价值大于实用价值,运行十分缓慢。  实现: SpearmanCorrelationSimilarity

4.采用忽略偏好值基于谷本系数计算相似度:

谷本系数也叫做Jaccard系数。它由两个用户共同表达过的偏好的物品的数目除以至少一个用户表达过偏好的物品数目而得。 完全忽略偏好值。只关心是否表达过偏好。一般只有偏好值为布尔值或
根本没有偏好值可用时,才会采取这一方法。实现: TanimotoCoefficientSimilarity

5.基于对数似然比计算相似度:

与谷本系数相同,不考虑具体偏好值。与谷本系数不同,它考虑两个用户由于机缘巧合发生重叠的不可能性。不可能性越大,相似度越高。
基于此的相似度往往优于基于谷本系数计算的相似度。从某种意义上说,这是一个更智能的度量标准。 实现:  LogLikelihoodSimilarity


6.基于曼哈顿距离计算相似度:

实现:CityBlockSimilarity(model)


推测偏好值:

有时数据过少会成为问题,通过为用户没有评价过的物品推测一个偏好值,可以通过PreferenceInferrer接口引入这种机制,目前可用AveragingPreferenceInferrer这一实现,
它为每个用户计算其已经评估物品的平均值,并以此作为未评估物品的偏好值。
实现: 在UserSimilarity实现中调用setPreferenceInferrer() 方法开启这个选项。   在实际应用中并不是很有效。不会增加任何信息量反而会严重拖慢计算速度。可用于实验。




二 、基于物品的推荐程序:

for(用户 u 尚未表达偏好的) 每个物品 i
    for(用户 u 表达偏好的) 每个物品 j
         计算 i 和 j 之间的相似度 s
         按权重为 s 将 u 对 j 的偏好并入平均值
return 值最高的物品(按加权平均排序)


 Slope-one推荐算法:
   for每个物品 i
        for每个其他物品 j
          for对 i 和 j 均有偏好的用户 u 
               将物品对 (i 和 j )间的偏好值差异加入 u 的偏好

   最终的推荐算法:
  
      for用户 u 未表达过偏好的每个物品 i
             for用户 u 表达过偏好的每个物品 j
                    找到 j 与 i 之间的平均偏好值差异
                    添加该差异到 u 对 j 的偏好值
                     添加其至平均值
    return 值最高的物品(按平均差异排序)


基于SVD 奇异值分解 推荐算法

基于SVD的推荐方法能够根据物品找到用户之间的相似的特征,通过这些特征就可以把两个用户联系起来,根据特征的重叠计算出某种相似度。
new SVDRecommender(model,new ALSWRFactorizer(model,10,0.05,10))  第一个参数为SVD最终要生成的特征数目,第二个参数为正则化的分解器特征。
最后一个为需要执行的训练步骤数。


基于线性插值物品的推荐算法:  KNN

KnnItemBasedRecommender。也使用了邻域的概念



基于聚类的推荐算法:

UserSimilarity similarity = new LogLikelihoodSimilarity(model);                               //用户之间的相似性
ClusterSimilarity clustersimilarity = new FarthestNeighborClusterSimilarity(similarity);  //用户簇之间的相似性





第五章:

通过MemoryDiffStorage限制solpe-one算法的内存占有量

DiffStorage diffStorage = new MemoryDiffStorage(model,Weighting.WEIGHTED,10000000L);    //存储的差值个数限制在一千万个。
return new SolpOneRecommender(model,Weighting.WEIGHTED,Weighting.WEIGHTED,deffstorage);

recommend(long userID,int howMany,IDRescorer rescorer)    IDRescorer可过滤掉指定的推荐结果和修改指定的偏好值。实现IDRescorer接口即可。





LFM 隐语义模型推荐:  根据物品会自动聚类,

  1. 我们不需要关心分类的角度,结果都是基于用户行为统计自动聚类的,全凭数据自己说了算。
  2. 不需要关心分类粒度的问题,通过设置LFM的最终分类数就可控制粒度,分类数越大,粒度约细。
  3. 对于一个item,并不是明确的划分到某一类,而是计算其属于每一类的概率,是一种标准的软分类。
  4. 对于一个user,我们可以得到他对于每一类的兴趣度,而不是只关心可见列表中的那几个类。
  5. 对于每一个class,我们可以得到类中每个item的权重,越能代表这个类的item,权重越高。

LFM和基于邻域的比较:
  
          1. LFM是标准的学习方法,而邻域是统计方法。
         2.LFM不能实现在线实时推荐
          3.ItemCF支持很好的推荐解释,可根据历史,LFM没有推荐解释,自动聚类。


基于标签的推荐系统:
        统计每个用户最常用的标签
       对于每个标签,统计被打过该标签次数最多的物品
       对于每一个用户,首先找到他常用的标签,然后找到该标签最热门的物品作为推荐给这位用户。


 

二、聚类

mahout三种向量:

在mahout中,向量被实现为三个不同的类,每个类都是针对不同场景优化的:DenseVector、RandomAccessSparseVector和SequentialAccessSparseVector。

1、DenseVector可被视为一个double型数组,其大小为数据中的特征个数。因为不管数组的元素之是不是0,数组中所有元素都被预先分配了空间。我们称之为密集的(dense)。

2、RandomAccessSparseVector被实现为integer型和double型之间的一个HashMap,只有非零元素被分配空间。因此,这类向量被成为稀疏向量。

3、SequentialAccessSparseVector实现为两个并列的数组,一个是integer型另一个是double型。其中只保留了非零元素。与面向随机访问的RandomAccessSparseVector不同,它是为顺序读取而优化的。

对象转为向量:维度数等于特征数。
选择一个对象的特征并把它们映射到数字的过程称为:特征选择
将这些特征编码为向量的过程称为:向量化
在计算相似度时,我们需要抵消向量大小不同而造成的影响,降低大向量的重要性,并提高较小向量的重要性的过程就叫做: 归一化(统一单位和量级)
         
 -n  默认不进行归一化  默认值为0   如果使用曼哈顿距离测度  1范数合适  如果使用欧式距离测度 向量2范数合适。

  

二、向量选择:

具体选择那种实现依赖于算法。如果算法要对向量的值做许多随机插入和更新,就适合使用像DenseVector和RandomAccessSparseVector这样支持快速随机访问的实现。另一方面,而对于像k-means聚类这样反复计算向量大小的算法,SequentialAccessSparseVector实现的执行速度就会比RandomAccessSparseVector更快。
  Mahout utils包中有一个称为VectorBenchmarks的工具类,可以使用该工具寻找某个稀疏水平上执行该运算最快的向量类型

三、如何将对象转化为向量:

在算法中,每个对象都要转化成一个n维向量。其维度数与对象的特征个数相同。

比如,一堆苹果,他们有不同的形状,重量,颜色。其中有一个苹果,它的形状是3(圆),重量是0.1(kg),颜色绿色600(波长)

那么每个苹果可以对应为向量(3,0.1,600)

但是现在维度有一个问题,就是颜色维度的值将主导最终的结果,比如,一个相对较小的10nm的色差会相当于100倍的重量差异。不过我们可以通过不同维度加权解决这个问题。


文本信息

作为聚类算法的主要应用场景 - 文本分类,对文本信息的建模也是一个常见的问题。在信息检索研究领域已经有很好的建模方式,就是信息检索领域中最常用的向量空间模型 (Vector Space Model, VSM)。因为向量空间模型不是本文的重点,这里给一个简要的介绍,有兴趣的朋友可以查阅参考目录中给出的相关文档。

文本的向量空间模型就是将文本信息建模为一个向量,其中每一个域是文本中出现的一个词的权重。关于权重的计算则有很多中:

  • 最简单的莫过于直接计数,就是词在文本里出现的次数。这种方法简单,但是对文本内容描述的不够精确。
  • 词的频率 (Team Frequency, TF):就是将词在文本中出现的频率作为词的权重。这种方法只是对于直接计数进行了归一化处理,目的是让不同长度的文本模型有统一的取值空间,便于文本相似度的比较,但可以看出,简单计数和词频都不能解决“高频无意义词汇权重大的问题”,也就是说对于英文文本中,“a”,“the”这样高频但无实际意义的词汇并没有进行过滤,这样的文本模型在计算文本相似度时会很不准确。
  • 词频 - 逆向文本频率 (Term Frequency – Inverse Document Frequency, TF-IDF):它是对 TF 方法的一种加强,字词的重要性随着它在文件中出现的次数成正比增加,但同时会随着它在所有文本中出现的频率成反比下降。举个例子,对于“高频无意义词汇”,因为它们大部分会出现在所有的文本中,所以它们的权重会大打折扣,这样就使得文本模型在描述文本特征上更加精确。在信息检索领域,TF-IDF 是对文本信息建模的最常用的方法。



距离测度:

1.欧式距离测度   EuclideanDistanceMeasure

2.平方欧式距离  SquaredEuclidenanDistanceMeasure     欧式距离的平方

3.曼哈顿距离     ManhattanDistanceMeasure      两个点之间的距离是它们坐标差的绝对值之和

4.余弦距离       CosineDistanceMeasure

5.谷本距离   TanimotoDistanceMeasure     可以同时表现点与点之间的夹角和相对距离信息

6.加权距离  WeightedDistanceMeasure    允许对不同的维度加权从而提高或减小某些维度对距离测度值的影响


聚类技术概述:

排他性聚类、有重叠聚类、层次聚类、概率聚类 

基于距离的聚类:

k-meas聚类


Canopy 聚类:

Canopy Clustering是一种小而美的聚类方法,其算法流程如下:

(1)设样本集合为S,确定两个阈值t1和t2,且t1>t2。

(2)任取一个样本点p属于S,作为一个Canopy,记为C,从S中移除p。

(3)计算S中所有点到p的距离dist。

(4)若dist

(5)若dist

(6)重复(2)~(5),直至S为空。
t1大canopy少  t1小canopy多     t2大重叠少  t2小重叠多

基于模型的聚类:
基于距离的聚类都不能满足既有重叠又有层次的情况,基于模型的聚类可以解决此问题:
基于概率分布模型的聚类算法(后面简称基于模型的聚类算法)的原理:首先需要定义一个分布模型,简单的例如:圆形,三角形等,复杂的例如正则分布,泊松分布等;然后按照模型对数据进行分类,将不同的对象加入一个模型,模型会增长或者收缩;每一轮过后需要对模型的各个参数进行重新计算,同时估计对象属于这个模型的概率。所以说,基于模型的聚类算法的核心是定义模型,对于一个聚类问题,模型定义的优劣直接影响了聚类的结果,下面给出一个简单的例子,假设我们的问题是将一些二维的点分成三组,在图中用不同的颜色表示,图 A 是采用圆形模型的聚类结果,图 B 是采用三角形模型的聚类结果。可以看出,圆形模型是一个正确的选择,而三角形模型的结果既有遗漏又有误判,是一个错误的选择。

图采用不同模型的聚类结果
图 3 采用不同模型的聚类结果 

ClusterDumper工具可以检测任何聚类算法的输出

改善聚类质量:
      去除噪声和使用合适的加权技术,使用合适的聚类测度方法
      去除噪声:mahout提供了一个钩子:LUCence Analyzer  允许在向量化的过程中注入任何过滤技术。(提供:大小写转换、去停用词、根据长度删除单词、取单词词干)


在计算密集型操作中避免性能缺陷:

    1.采用合适的向量表示
   2.使用更快的距离测度方法
    3.根据距离计算使用SparseVector类型

在IO密集型操作中避免性能缺陷:

    1.使用合适的向量表示 (ps:在mr中可以减少数据的传输,稀疏型不会加入)
    2.使用hdfs副本,这样map就可以向多个节点去拉数据
    3.减少簇的数目

分类:
训练算法生成的模型本身就是一个有效的计算机程序
训练样本包括: 训练数据(占80%-90%)、测试数据

预测变量的四种类型:
1.连续型
2.类别型
3.单词型
4.文本型
连续型和类别型的区分:取一个值的对数或平方根,如果得到的结果是未定义,那很可能是类别型,而非连续型
                                 任何有关计量单位的度量通常都是连续型的。


将可分类数据编码为向量方法:
1.每一个词一个分量
2.将向量作为词袋
3.特征散列 




训练分类模型:
1.定义目标变量的类别: 尽量将类别数降到最低为二值目标,因为这样会有更多的算法可供选择
2.搜集历史数据:确保历史数据中目标变量值的准确性
3.定义预测变量:注意目标泄漏问题(选择预测变量时,无意引入了目标变量的信息)


1、逻辑回归(LogisticRegression) 

   Logistic regression可以用来回归,也可以用来分类,主要是二分类。

2、随机梯度下降SGD (stochastic gradient descent)

      梯度下降算法在每次更新回归系数的时候都需要遍历整个数据集(计算整个数据集的回归误差),该方法对小数据集尚可。但当遇到有数十亿样本和成千上万的特征时,就有点力不从心了,它的计算复杂度太高。改进的方法是一次仅用一个样本点(的回归误差)来更新回归系数。这个方法叫随机梯度下降算法。由于可以在新的样本到来的时候对分类器进行增量的更新(假设我们已经在数据库A上训练好一个分类器h了,那新来一个样本x。对非增量学习算法来说,我们需要把x和数据库A混在一起,组成新的数据库B,再重新训练新的分类器。但对增量学习算法,我们只需要用新样本x来更新已有分类器h的参数即可),所以它属于在线学习算法。与在线学习相对应,一次处理整个数据集的叫“批处理”。


使用mahout的思考:
训练样本超过100000时,mahout就会变得有意思起来
训练时间和输入规模呈亚线性关系。


请使用浏览器的分享功能分享到微信等