MLlib 中的聚类和分类
聚类和分类是机器学习中两个常用的算法,聚类将数据分开为不同的集合,分类对新数据进行类别预测,下面将就两类算法进行介绍。
1. 聚类和分类
(1)什么是聚类
聚类( Clustering)指将数据对象分组成为多个类或者簇( Cluster),它的目标是:在同一个簇中的对象之间具有较高的相似度,而不同簇中的对象差别较大。其实,聚类在
人们日常生活中是一种常见行为,即所谓的“物以类聚,人以群分”,其核心思想在于分组,人们不断地改进聚类模式来学习如何区分各个事物和人。
(2)什么是分类
数据仓库、数据库或者其他信息库中有许多可以为商业、科研等活动的决策提供所需要的知识。分类与预测即是其中的两种数据分析形式,可以用来抽取能够描述重要数
据集合或预测未来数据趋势。分类方法(Classif ication)用于预测数据对象的离散类别( Categorical Label);预测方法( Prediction)用于预测数据对象的连续取值。
分类流程:新样本→特征选取→分类→评价
训练流程:训练集→特征选取→训练→分类器
最初,机器学习的分类应用大多都是在这些方法及基于内存基础上所构造的算法。目前,数据挖掘方法都要求具有基于外存以处理大规模数据集合能力,同时具有可扩展
能力。
2. MLlib 中的聚类和分类
MLlib 目前已经实现了 K-Means 聚类算法、朴素贝叶斯和决策树分类算法。这里主要介绍被广泛使用的 K-Means 聚类算法和朴素贝叶斯分类算法。
(1) K-Means 算法
1) K-Means 算法简介。
K-Means 聚类算法能轻松地对聚类问题建模。 K-Means 聚类算法容易理解,并且能在分布式的环境下并行运行。学习 K-Means 聚类算法,能更容易地理解聚类算法的优
缺点,以及其他算法对于特定数据的高效性。
K-Means 聚类算法中的 K 是聚类的数目,在算法中会强制要求用户输入。如果将新闻聚类成诸如政治、经济、文化等大类,可以选择 10 ~ 20 的数字作为 K。因为这种
顶级类别的数量是很小的。如果要对这些新闻详细分类,选择 50 ~ 100 的数字也是没有问题的。
K-Means 聚类算法主要可以分为三步:
第一步是为待聚类的点寻找聚类中心;
第二步是计算每个点聚类中心的距离,将每个点聚类到离该点最近的聚类中去;
第三步是计算聚类中所有点的坐标平均值,并将这个平均值作为新的聚类中心点。反复执行第二步,直到聚类中心不再进行大范围的移动,或者聚类次数达到要求为止。
2) k-Means 示例。
下面的例子中有 7 名选手,每名选手有两个类别的比分, A 类比分和 B 类比分如表 1 所示。
表1 A 类和 B 类比分
这些数据将会聚为两个簇。随机选取 1 号和 4 号选手作为簇的中心,如表2所示。
表 2 1 号和 4 号选手信息
将 1 号和 4 号选手分别作为两个簇的中心点,下面每一步将选取的点计算和两个簇中心的欧几里德距离,哪个中心距离小就放到哪个簇中,如表 3所示。
表 3 第一步聚类
第一轮聚类的结果产生了,如表 4 所示。
表 4 第一轮结果
第二轮将使用 (1.8,2.3) 和 (4.1,5.4) 作为新的簇中心,重复以上的过程。直到迭代次数达到用户设定的次数终止。最后一轮的迭代分出的两个簇就是最后的聚类结果。
3) MLlib 之 K-Means 源码解析。
MLlib 中的 K-Means 的原理是:在同一个数据集上,跑多个 K-Means 算法(每个称为一个 run),然后返回效果最好的那个聚类的类簇中心。初始的类簇中心点的选取有两
种方法,一种是随机,另一种是采用 KMeans||(KMeans++ 的一个变种)。算法的停止条件是迭代次数达到设置的次数,或者在某一次迭代后所有 run 的 K-Means 算法都收敛。
① 类簇中心初始化。
本节介绍的初始化方法是对于每个运行的 K-Means 都随机选择 K 个点作为初始类簇:
private def initRandom(data: RDD[Array[Double]]): Array[ClusterCenters] = {
// Sample all the cluster centers in one pass to avoid repeated scans
val sample = data.takeSample(true, runs * k, new Random().nextInt()).toSeq
Array.tabulate(runs)(r => sample.slice(r * k, (r + 1) * k).toArray)
}
② 计算属于某个类簇的点。
在每一次迭代中,首先会计算属于各个类簇的点,然后更新各个类簇的中心。
// K-Means 算法的并行实现通过 Spark 的 mapPartitions 函数 , 通过该函数获取到分区的迭代器。
可以在每个分区内计算该分区内的点属于哪个类簇
// 之后对于每个运行算法中的每个类簇计算属于该类簇的点的个数以及累加和。
val totalContribs = data.mapPartitions { points =>
val runs = activeCenters.length
val k = activeCenters(0).length
val dims = activeCenters(0)(0).length
val sums = Array.fill(runs, k)(new DoubleMatrix(dims))
val counts = Array.fill(runs, k)(0L)
for (point <- points; (centers, runIndex) <- activeCenters.zipWithIndex) {
// 找到距离该点最近的类簇中心点
val (bestCenter, cost) = KMeans.findClosest(centers, point)
// 统计该运行算法开销 , 用于在之后选取开销最小的那个运行的算法
costAccums(runIndex) += cost
// 将该点加到最近的类簇的统计总和中去 , 方便之后计算该类簇的新中心点
sums(runIndex)(bestCenter).addi(new DoubleMatrix(point))
// 将距离该点最近的类簇的点数量加 1,sum.divi(count) 就是类簇的新中心
counts(runIndex)(bestCenter) += 1
}
val contribs = for (i <- 0 until runs; j <- 0 until k) yield {
((i, j), (sums(i)(j), counts(i)(j)))
}
contribs.iterator
// 对于每个运行算法的每个类簇计算属于该类簇的点的个数和加和
}.reduceByKey(mergeContribs).collectAsMap()
// mergeContribs 是一个负责合并的函数 :
def mergeContribs(p1: WeightedPoint, p2: WeightedPoint): WeightedPoint = {
(p1._1.addi(p2._1), p1._2 + p2._2)
} ③
更新类簇的中心点。
for ((run, i) <- activeRuns.zipWithIndex) {
var changed = false
for (j <- 0 until k) {
val (sum, count) = totalContribs((i, j))
if (count != 0) {
// 计算类簇的新的中心点
val newCenter = sum.divi(count).data
if (MLUtils.squaredDistance(newCenter, centers(run)(j)) > epsilon *
epsilon) {
// 此处与代码和算法的停止条件有关
changed = true
}
centers(run)(j) = newCenter
}
// 如果某个 run 的 KMeans 算法的某轮次迭代中 K 个类簇的中心点变化都不超过指定阈值 ,
则认为该 KMeans 算法收敛。
if (!changed) {
active(run) = false
logInfo("Run " + run + " finished in " + (iteration + 1) + " iterations")
}
costs(run) = costAccums(i).value
}
④ 算法停止条件。
算法的停止条件是迭代次数达到设置的次数,或者所有运行的 K-Means 算法都
收敛:
while (iteration < maxIterations && !activeRuns.isEmpty)
上文对典型聚类算法 K-Means 原理进行介绍,下面将对典型的分类算法朴素贝叶
斯算法进行介绍。
(2)朴素贝叶斯分类算法
朴素贝叶斯分类算法是贝叶斯分类算法多个变种之一。朴素指假设各属性之间是
相互独立的。研究发现,在大多数情况下,朴素贝叶斯分类算法(naive bayes classif ier)
在性能上与决策树(decision tree)、神经网络(netural network)相当。贝叶斯分类算法
在大数据集的应用中具有方法简便、准确率高和速度快的优点。但事实上,贝叶斯分类
也有其缺点。由于贝叶斯定理假设一个属性值对给定类的影响独立于其他的属性值,而
此假设在实际情况中经常是不成立的,则其分类准确率可能会下降。
朴素贝叶斯分类算法是一种监督学习算法,使用朴素贝叶斯分类算法对文本进行
分类,主要有两种模型,即多项式模型(multinomial model)和伯努利模型(bernoulli
model)。 MLlib 使用的是被广泛使用的多项式模型。本书将以一个实际的例子来简略介
绍使用多项式模型的朴素贝叶斯分类算法。
在多项式模型中,设某文档 d=(t1,t2,…,tk), tk 是该文档中出现过的单词,允许
重复。
先验概率 P(c) = 类 c 下单词总数 / 整个训练样本的单词总数
类条件概率 P(tk|c) = ( 类 c 下单词 tk 在各个文档中出现过的次数之和 +1)
/( 类 c 下单词总数 +|V|)
V 是训练样本的单词表(即抽取单词,单词出现多次,只算一个), |V| 则表示训练
样本包含多少种单词。P(tk|c) 可以看作是单词 tk 在证明 d 属于类 c 上提供了多大的证据,
而 P(c) 则可以认为是类别 c 在整体上占多大比例(有多大可能性)。
给定一组分好类的文本训练数据,如表 3-10 所示。
给定一个新样本(河北河北河北吉林香港),对其进行分类。该文本用属性向量表
示为 d=( 河北 , 河北 , 河北 , 吉林 , 香港 ),类别集合为 Y={yes, no}。
表 5 文本训练数据
类 yes 下总共有 8 个单词,类 no 下总共有 3 个单词,训练样本单词总数为 11,因
此 P(yes)=8/11, P(no)=3/11。类条件概率计算如下:
P( 河北 | yes)=(5+1)/(8+6)=6/14=3/7
P( 河北 | yes)=P( 吉林 | yes)= (0+1)/(8+6)=1/14
P( 河北 |no)=(1+1)/(3+6)=2/9
P(Japan|no)=P( 吉林 | no) =(1+1)/(3+6)=2/9
分母中的 8,是指 yes 类别下 textc 的长度,也即训练样本的单词总数, 6 是指训练
样本有河北、北京、上海、广东、吉林、香港,共 6 个单词, 3 是指 no 类下共有 3 个
单词。
有了以上类条件概率,开始计算后验概率:
P(yes | d)=(3/7)3×1/14×1/14×8/11=108/184877≈0.00058417
P(no | d)= (2/9)3×2/9×2/9×3/11=32/216513≈0.00014780
比较大小,即可知道这个文档属于类别河北。
MLlib 中的聚类和分类的更多相关文章
- Spark MLlib中KMeans聚类算法的解析和应用
聚类算法是机器学习中的一种无监督学习算法,它在数据科学领域应用场景很广泛,比如基于用户购买行为.兴趣等来构建推荐系统. 核心思想可以理解为,在给定的数据集中(数据集中的每个元素有可被观察的n个属性), ...
- Spark中的聚类算法
Spark - Clustering 官方文档:https://spark.apache.org/docs/2.2.0/ml-clustering.html 这部分介绍MLlib中的聚类算法: 目录: ...
- 利用Spark-mllab进行聚类,分类,回归分析的代码实现(python)
Spark作为一种开源集群计算环境,具有分布式的快速数据处理能力.而Spark中的Mllib定义了各种各样用于机器学习的数据结构以及算法.Python具有Spark的API.需要注意的是,Spark中 ...
- 转载:Databricks孟祥瑞:ALS 在 Spark MLlib 中的实现
Databricks孟祥瑞:ALS 在 Spark MLlib 中的实现 发表于2015-05-07 21:58| 10255次阅读| 来源<程序员>电子刊| 9 条评论| 作者孟祥瑞 大 ...
- Apache Spark源码走读之23 -- Spark MLLib中拟牛顿法L-BFGS的源码实现
欢迎转载,转载请注明出处,徽沪一郎. 概要 本文就拟牛顿法L-BFGS的由来做一个简要的回顾,然后就其在spark mllib中的实现进行源码走读. 拟牛顿法 数学原理 代码实现 L-BFGS算法中使 ...
- Java IO流体系中常用的流分类
Java输入/输出流体系中常用的流分类(表内容来自java疯狂讲义) 注:下表中带下划线的是抽象类,不能创建对象.粗体部分是节点流,其他就是常用的处理流. 流分类 使用分类 字节输入流 字节输出流 字 ...
- ASP.NET中Partial Class部分类
原文:ASP.NET中Partial Class部分类 如果您在开发项目的公用函数库,用于公用函数库的内容越丰富越好,但这不可能一下子就写好,需要一点一点的积累,这时就可以使用Partial Clas ...
- Sklearn中的回归和分类算法
一.sklearn中自带的回归算法 1. 算法 来自:https://my.oschina.net/kilosnow/blog/1619605 另外,skilearn中自带保存模型的方法,可以把训练完 ...
- Spark机器学习中ml和mllib中矩阵、向量
1:Spark ML与Spark MLLIB区别? Spark MLlib是面向RDD数据抽象的编程工具类库,现在已经逐渐不再被Spark团队支持,逐渐转向Spark ML库,Spark ML是面向D ...
随机推荐
- 特殊的css样式
在一定范围大小变化的div .div { width:auto; height:auto; min-height:100px; min-width:100px; max-height:200px; m ...
- ActiveMQ 集群(1)
Queue consumer clusters(消费者集群): 简介: 同一个queue,如果一个消费者失效, 那么任何未经确认的消息将会被发送给queue上的其它消费者.如果一个消费者比其它消费者执 ...
- NDK(17)让ndk支持完整C++,exception,rtti,
C++ Support The Android platform provides a very minimal C++ runtime support library (/system/lib/li ...
- Android studio编译之后显示中文乱码的问题解决办法
在build.gradle文件中加上 android {compileOptions.encoding = "GBK"}
- MacOS安装phpMyAdmin几点问题
1. 登录时出现“#2002 无法登录 MySQL 服务器”. 原因: phpMyAdmin为PHP编写,MacOS默认安装的php配置,设置mysql监听socket默认为/var/mysql/my ...
- Codeforces Beta Round #2B(dp+数学)
贡献了一列WA.. 数学很神奇啊 这个题的关键是怎么才能算尾0的个数 只能相乘 可以想一下所有一位数相乘 除0之外,只有2和5相乘才能得到0 当然那些本身带0的多位数 里面肯定含有多少尾0 就含有多少 ...
- noi2002银河英雄传说(并查集)
首先表示对C++读入读出问题复杂程度的敬畏,看了好多没讲明白的,本题用cin竟然过不了评测,搞scanf的读入搞了好久.... 本题确实是一道经典的并查集题型,不多讲,拿来练练手用的(其中经历很惨) ...
- UVA 821 Page Hopping 网页跳跃(BFS,简单)
题意: 给一个无权有向图,可认为边的长度为1,求两点间的平均长度(即所有点对的长度取平均),保留3位小数.保证任意点对都可达. 思路: 简单题.直接穷举每个点,进行BFS求该点到其他点的距离.累加后除 ...
- Math.trunc
- [总结]FFMPEG视音频编解码零基础学习方法--转
ffmpeg编解码学习 目录(?)[-] ffmpeg程序的使用ffmpegexeffplayexeffprobeexe 1 ffmpegexe 2 ffplayexe 3 ffprobeexe ...