K-means 是我们最常用的基于欧式距离的聚类算法,其认为两个目标的距离越近,相似度越大。
K-means 的算法步骤为:
选择 k 个样本作为初始聚类中心 ;
针对数据集中每个样本分别计算它到 k 个聚类中心的距离并将其分到距离最小的聚类中心所对应的类中;
针对每个类别,重新计算它的聚类中心
重复上面 2 3 两步操作,直到达到某个中止条件(迭代次数、最小误差变化等)。
Python代码:
import findspark
findspark.init()
from pyspark.sql import SparkSession
from pyspark.ml.clustering import KMeans
from pyspark.sql.types import DoubleType
from pyspark.sql.functions import col
from pyspark.ml.feature import VectorAssembler
import matplotlib.pyplot as plt
if __name__ == '__main__':
spark = SparkSession.builder.master("local[8]").config("spark.executor.memory", "3g").appName("mymodel").getOrCreate()
df = spark.read.format("CSV").option("header","true").load("hdfs://192.168.181.132:9000/events/data/events.csv")
cols = [c for c in df.columns if c.startswith("c_")]
feas = cols.copy()
cols.insert(0,"event_id")
#VectorAssembler可以将多列合成一列,但是输入的数据必须不能是str或者float
df1 = df.select([col(c).cast(DoubleType()) for c in cols])
va = VectorAssembler().setInputCols(feas).setOutputCol("features")
res = va.transform(df1).select("event_id", "features")
#准备一个距离数组
distance=[]
#准备一个点数据,events的数据记录数是3137972,算他的开方是1172,如果弄成1172个质点,消耗太大,所以要再开方是42,所以往后选了50
points = [i for i in range(2,50)]
for po in points:
model = KMeans().setK(po).setFeaturesCol("features").setPredictionCol("predict").fit(res)
distance.append(model.computeCost(res))
#使用matplotlib绘制线形图
plt.plot(points,distance)
plt.show()
spark.stop()
得到的图形如下,可见他的拐点为,这个点就是这个数据集中距离最小的