您的当前位置:首页正文

k-means

2023-11-10 来源:年旅网


K-Means

1.1.1 算法说明

聚类其核心任务是:将一组目标object划分为若干个簇,每个簇之间的object尽可能相似,簇与簇之间的object尽可能相异。聚类算法是机器学习)中重要的一部分,最为简单的K-Means聚类算法.

所谓聚类问题,就是给定一个元素集合D,其中每个元素具有n个可观察属性,使用某种算法将D划分成k个子集,要求每个子集内部的元素之间相异度尽可能低,而不同子集的元素相异度尽可能高。其中每个子集叫做一个簇。

1.1.2 实例

K-Means属于基于平方误差的迭代重分配聚类算法,其核心思想十分简单:

随机选择K个中心点;

计算所有点到这K个中心点的距离,选择距离最近的中心点为其所在的簇;

简单地采用算术平均数(mean)来重新计算K个簇的中心;

重复步骤2和3,直至簇类不再发生变化或者达到最大迭代值;

输出结果。

K-Means算法的结果好坏依赖于对初始聚类中心的选择,容易陷入局部最优解,对K值的选择没有准则可依循,对异常数据较为敏感,只能处理数值属性的数据,聚类结构可能不平衡。

本实例中进行如下步骤:

1.装载数据,数据以文本文件方式进行存放;

2.将数据集聚类,设置2个类和20次迭代,进行模型训练形成数据模型;

3.打印数据模型的中心点;

4.使用误差平方之和来评估数据模型;

5.使用模型测试单点数据;

6.交叉评估1,返回结果;交叉评估2,返回数据集和结果。

1.1.3测试数据

该实例使用的数据为kmeans_data.txt。在该文件中提供了6个点的空间位置坐标,使用K-means聚类对这些点进行分类。

使用的kmeans_data.txt的数据如下所示:

0.0 0.0 0.0

0.1 0.1 0.1 0.2 0.2 0.2 9.0 9.0 9.0 9.1 9.1 9.1 9.2 9.2 9.2

1.1.4程序代码

import org.apache.log4j.{Level, Logger}

import org.apache.spark.{SparkConf, SparkContext}

import org.apache.spark.mllib.clustering.KMeans

import org.apache.spark.mllib.linalg.Vectors

object Kmeans {

def main(args: Array[String]) {

// 屏蔽不必要的日志显示在终端上

Logger.getLogger(\"org.apache.spark\").setLevel(Level.WARN)

Logger.getLogger(\"org.eclipse.jetty.server\").setLevel(Level.OFF)

// 设置运行环境

val conf = new SparkConf().setAppName(\"Kmeans\").setMaster(\"local[4]\")

val sc = new SparkContext(conf)

// 装载数据集

val data = sc.textFile(\"/home/hadoop/upload/class8/kmeans_data.txt\

val parsedData = data.map(s => Vectors.dense(s.split(' ').map(_.toDouble)))

// 将数据集聚类,2个类,20次迭代,进行模型训练形成数据模型

val numClusters = 2

val numIterations = 20

val model = KMeans.train(parsedData, numClusters, numIterations)

// 打印数据模型的中心点

println(\"Cluster centers:\")

for (c <- model.clusterCenters) {

println(\" \" + c.toString)

}

// 使用误差平方之和来评估数据模型

val cost = model.computeCost(parsedData)

println(\"Within Set Sum of Squared Errors = \" + cost)

// 使用模型测试单点数据

println(\"Vectors 0.2 0.2 0.2 is belongs to clusters:\" +

model.predict(Vectors.dense(\"0.2 0.2 0.2\".split(' ').map(_.toDouble))))

println(\"Vectors 0.25 0.25 0.25 is belongs to clusters:\" +

model.predict(Vectors.dense(\"0.25 0.25 0.25\".split(' ').map(_.toDouble))))

println(\"Vectors 8 8 8 is belongs to clusters:\" + model.predict(Vectors.dense(\"8 8 8\".split(' ').map(_.toDouble))))

// 交叉评估1,只返回结果

val testdata = data.map(s => Vectors.dense(s.split(' ').map(_.toDouble)))

val result1 = model.predict(testdata)

result1.saveAsTextFile(\"/home/hadoop/upload/class8/result_kmeans1\")

// 交叉评估2,返回数据集和结果

val result2 = data.map {

line =>

val linevectore = Vectors.dense(line.split(' ').map(_.toDouble))

val prediction = model.predict(linevectore)

line + \" \" + prediction

}.saveAsTextFile(\"/home/hadoop/upload/class8/result_kmeans2\")

sc.stop()

}

}

1.1.5 IDEA执

行情况

第一步 使用如下命令启动Spark集群

$cd /app/hadoop/spark-1.1.0

$sbin/start-all.sh

第二步 在IDEA中设置运行环境

在IDEA运行配置中设置Kmeans运行配置,由于读入的数据已经在程序中指定,故在该设置界面中不需要设置输入参数

第三步 执行并观察输出

在运行日志窗口中可以看到,通过计算计算出模型并找出两个簇中心点:(9.1,9.1,9.1)和(0.1,0.1,0.1),使用模型对测试点进行分类求出分属于族簇。

第四步 查看输出结果文件

目录中有两个输出目录:

查看结果1,在该目录中只输出了结果,分别列出了6个点所属不同的族簇

查看结果2,在该目录中输出了数据集和结果

因篇幅问题不能全部显示,请点此查看更多更全内容