mllib在实现kmeans的过程中,对于距离的计算,使用了一些技巧。
首先要注意的是,mllib的jar中包org.apache.spark.mllib.linalg下定义了DenseVector,SparseVector,Vector等类或对象或特质。但实际上在真正计算过程中,mllib都是使用的breeze.linalg中的DenseVector,SparseVector,Vector等,mllib做了一个类似适配器的东西。所以名称不产生混乱,在import
breeze.linalg时都对相应的名称进行了重命名,比如Vectors.scala中的import breeze.linalg.{DenseVector => BDV, SparseVector => BSV, Vector => BV},KMeans.scala中的import breeze.linalg.{DenseVector => BDV, Vector => BV, norm => breezeNorm}。
将
org.apache.spark.mllib.linalg下的Vector转化为BV就是使用一个方法toBreeze。
在进行kmeans运行之前,会先给每一个向量数据计算一个norms,如果向量是(a, b),则norms就是
。计算出norms后再与原向量做一个匹配zip,最后new出一个
BreezeVectorWithNorm对象,这是一个包含
BreezeVector和该向量的norm的一个对象。
。计算出norms后再与原向量做一个匹配zip,最后new出一个
BreezeVectorWithNorm对象,这是一个包含
BreezeVector和该向量的norm的一个对象。
def run(data: RDD[Vector]): KMeansModel = {
// Compute squared norms and cache them.
val norms = data.map(v => breezeNorm(v.toBreeze, 2.0))
norms.persist()
val breezeData = data.map(_.toBreeze).zip(norms).map { case (v, norm) =>
new BreezeVectorWithNorm(v, norm)
}
val model = runBreeze(breezeData)

Spark MLlib的KMeans实现利用了向量的内积和范数来优化距离计算。通过预先计算每个向量的范数,并使用Breeze库的向量类型,KMeans在寻找最近中心时先计算一个下界,避免不必要的距离计算。在精度允许的情况下,通过范数和内积直接计算平方距离,提高了效率。
最低0.47元/天 解锁文章
8868

被折叠的 条评论
为什么被折叠?



