k-means是一种迭代求解的聚类算法,是将数据分为K组,k由人为指定,随机选取一个中心点为初始的聚类中心,然后重复计算数据到之前 n 个聚类中心最远的距离,把每个对象分配给距离它最近的聚类中心。聚类中心以及分配给它们的对象就代表一个聚类。每分配一个样本,聚类的聚类中心会根据聚类中现有的对象被重新计算。这个过程将不断重复直到满足某个终止条件。终止条件可以是没有(或最小数目)对象被重新分配给不同的聚类,没有(或最小数目)聚类中心再发生变化,误差平方和局部最小。
初始化聚类中心代码:
/**
* k-means++初始化聚类中心
*/
def kmeansppInitial(points:List[UserFeatureBean],k: Int):Array[Vector[Double]] = {
//数据集个数
val pointsNum = points.length
val random = new Random()
var kSum = 1
var flag = true
//选择第一个随机数(下标)
val temp = random.nextInt(pointsNum)
//保存随机下标号
var array = new ListBuffer[Int]()
//迭代添加元素的聚类中心数组
var updatedCenters = new ListBuffer[Vector[Double]]()
var sum = 0.0
var randomSeed = 0.0
//保存每个样本点对应到各自聚类中心的距离
var pointsAndDist = List[Double]()
var j = 0
array = array :+ temp
//将随机选择的点作为第一个聚类中心
updatedCenters = updatedCenters :+ points(temp).getVector
while(kSum < k ){
//计算每个样本点与它所属的聚类中心的距离
pointsAndDist = points.map(v =>
vectorDis(v.getVector,closestCenter(updatedCenters.toArray,v.getVector))
)
sum = pointsAndDist.reduceLeft((a,b) => a + b)
println("sum=="+ sum)
flag = true
while(flag){
randomSeed = sum * (random.nextInt(100) + 1) / 100
breakable{
for(i <- 0 to pointsAndDist.length - 1){
randomSeed -= pointsAndDist(i)
if(randomSeed <= 0){
j = i
break
}
}
}
if(sum == 0.0){
flag = false
kSum += 1
}else if(array.contains(j)){
//求得的新中心点的下标在数组中存在
flag= true
}else{
array = array :+ j
updatedCenters = updatedCenters :+ points(j).getVector
flag = false
kSum += 1
}
}
}
//kmean++初始化中心点如下
val centers = new Array[Vector[Double]](updatedCenters.length)
for(i <- 0 to updatedCenters.length - 1){
centers(i) = updatedCenters(i)
}
centers
}
更多文章请关注《万象专栏》
转载请注明出处:https://www.wanxiangsucai.com/read/cv14063