pyspark3.4.1 spark.ml基于鸢尾花的聚类算法案例

123 阅读2分钟

K-Means 算法的原理

  1. 输入
    • 数据集 X={x1,x2,...,xn}X = \{x_1, x_2, ..., x_n\},每个数据点 xix_i 是一个 dd-维向量。
    • 簇数kk
  2. 步骤
    1. 初始化 kk 个簇中心(可以随机初始化或使用其他方法)。
    2. 分配簇:
      • 对每个点 xix_i​,将其分配到距离最近的簇中心 cjc_j​: c(xi)=argminjxicj2 c(xi​)=argmin_{j}​||xi​−cj​||^2
    3. 更新簇中心:
      • 计算每个簇中所有点的均值作为新簇中心: Cj=1CjxiCjxiC_j= \frac{1}{C_j}\sum​_{x_i \in C_j} x_i
    4. 重复步骤 2 和步骤 3,直到簇中心收敛或达到最大迭代次数。
  3. 输出
    • 每个点的簇标签。
    • 每个簇的中心。

Spark ML中的高斯混合模型(GMM)聚类算法

高斯混合模型(Gaussian Mixture Model, GMM)是一种基于概率模型的聚类算法。它假设数据是由多个高斯分布混合而成,每个高斯分布对应一个簇。


1. GMM算法的基本原理

  1. 高斯分布
    • 每个簇 k被假设为一个高斯分布: N(xμk,Σk)=1(2π)d/2Σk1/2e12(xμk)TΣk1(xμk)\mathcal{N}(\mathbf{x}|\mu_k, \Sigma_k) = \frac{1}{(2\pi)^{d/2} |\Sigma_k|^{1/2}} e^{-\frac{1}{2} (\mathbf{x} - \mu_k)^T \Sigma_k^{-1} (\mathbf{x} - \mu_k)}
  • μk\mu_k:第 k 个高斯分布的均值向量。
  • Σk\Sigma_k:第 k 个高斯分布的协方差矩阵。
  • d:数据的维度。
  1. 混合模型

    • 假设数据点 x 的生成来自一个混合分布: p(x)=k=1KπkN(xμk,Σk)p(\mathbf{x}) = \sum_{k=1}^K \pi_k \mathcal{N}(\mathbf{x}|\mu_k, \Sigma_k)
    • πk\pi_k:第 k 个分布的混合权重,满足 k=1Kπk=1\sum_{k=1}^K \pi_k = 1
  2. 模型参数

    • 模型需要估计参数 {πk,μk,Σk}\{\pi_k, \mu_k, \Sigma_k\}
    • 使用期望最大化(EM)算法进行参数估计。

2. GMM的特点

  • 优势
    • 可以发现形状复杂的簇(非球形)。
    • 提供每个数据点属于某个簇的概率分布,支持软聚类。
  • 局限性
    • 对高维数据可能需要较大的计算成本。
    • 对初始参数敏感,可能陷入局部最优。
    • 需要预设簇的数量 k。
# -*- coding: utf-8 -*-  
# @Time : 2024/10/2 12:42  
# @Author   : pblh123@126.com  
# @File : pyspark_ClusteringAlgorithm.py
# @Describe : 距离算法kmeans,gmm  
import os  
import warnings  
  
from pyspark.ml.clustering import KMeans, GaussianMixture  
from pyspark.ml.evaluation import ClusteringEvaluator  
from pyspark.ml.feature import VectorAssembler  
from pyspark.sql import SparkSession  
from pyspark.sql.types import DoubleType  
  
from utils.window_Utils import windows_enviroment_set  
  
# 过滤警告信息  
warnings.simplefilter("ignore")  
windows_enviroment_set()  
  
def kmeans():  
    # 指定CSV文件路径  
    path = r"D:\PycharmProjects\2024\pyspark\datas\iris.txt"  
    # 使用Spark读取CSV文件并推断列的数据类型,然后重命名列  
    df_raw = spark.read.option("inferSchema", "true").option("sep", ","). \  
        csv(path).toDF("c0", "c1", "c2", "c3", "label")  
    # 将列的数据类型转换为Double  
    df_double = df_raw.select(  
        df_raw["c0"].cast(DoubleType()),  
        df_raw["c1"].cast(DoubleType()),  
        df_raw["c2"].cast(DoubleType()),  
        df_raw["c3"].cast(DoubleType()),  
        df_raw["label"]  
    )  
    # 创建 VectorAssembler    assembler = VectorAssembler(inputCols=["c0", "c1", "c2", "c3"], outputCol="features")  
    # 使用 VectorAssembler 转换数据  
    df = assembler.transform(df_double).select("features")  
    # 创建 KMeans 模型  
    kmeans = KMeans().setK(3)  # 设置簇的数量  
    kmeans.setFeaturesCol("features")  # 设置特征列  
    kmeans.setPredictionCol("prediction")  # 设置预测列  
    # 训练 KMeans 模型  
    kmeansmodel = kmeans.fit(df)  
    # 进行聚类预测  
    results = kmeansmodel.transform(df)  
    # 打印结果  
    for result in results.collect():  
        print(str(result.features) + " => cluster " + str(result.prediction))  
  
    # 打印 KMeans 模型的聚类中心  
    for center in kmeansmodel.clusterCenters():  
        print("Clustering Center: {}".format(center))  
    # 创建聚类评估器  
    evaluator = ClusteringEvaluator()  
    # 计算轮廓系数  
    silhouette = evaluator.evaluate(results)  
    print("Silhouette Score:", silhouette)  
  
def gmm():  
    # 指定CSV文件路径  
    path = r"D:\PycharmProjects\2024\pyspark\datas\iris.txt"  
    # 使用Spark读取CSV文件并推断列的数据类型,然后重命名列  
    df_raw = spark.read.option("inferSchema", "true").option("sep", ","). \  
        csv(path).toDF("c0", "c1", "c2", "c3", "label")  
    # 将列的数据类型转换为Double  
    df_double = df_raw.select(  
        df_raw["c0"].cast(DoubleType()),  
        df_raw["c1"].cast(DoubleType()),  
        df_raw["c2"].cast(DoubleType()),  
        df_raw["c3"].cast(DoubleType()),  
        df_raw["label"]  
    )  
    # 创建 VectorAssembler    assembler = VectorAssembler(inputCols=["c0", "c1", "c2", "c3"], outputCol="features")  
    # 使用 VectorAssembler 转换数据  
    df = assembler.transform(df_double).select("features")  
    # 创建 Gaussian Mixture 模型  
    gm = GaussianMixture().setK(3).setPredictionCol("Prediction") \  
        .setProbabilityCol("Probability")  
    # 训练模型  
    gmm = gm.fit(df)  
    # 使用 Gaussian Mixture 模型进行聚类预测  
    result = gmm.transform(df)  
    # 显示结果  
    result.show(150, truncate=False)  
    # 获取聚类簇数  
    k = gmm.getK()  
    # 打印每个组件的权重、均值向量和协方差矩阵  
    for i in range(k):  
        print("Component {}: ".format(i))  
        print("Weight: {}".format(gmm.weights[i]))  
        print("Mu Vector: \n{}".format(gmm.gaussians[i].mean))  
        print("Sigma Matrix: \n{}".format(gmm.gaussians[i].cov))  
  
  
if __name__ == '__main__':  
    # 1. 创建SparkSession  
    spark = SparkSession.builder \  
        .appName("PysparkmllibclusteringAlgorithm_spark341") \  
        .master("local[2]") \  
        .getOrCreate()  
    # sparkcontext  
    sc = spark.sparkContext  
    spark.sparkContext.setLogLevel("WARN")  
  
    # 2. spark业务代码 business code    kmeans()  
    gmm()  
  
    # 3. 关闭sparkSession, sparkcontext  
    sc.stop()  
    spark.stop()

image.png