深入理解K均值算法:Python中的应用与实践

写在开头

聚类算法是数据科学中的重要工具,而K均值算法则是其中的一颗璀璨明珠。本篇博客将带您深入了解K均值算法的原理、实现步骤,并通过Python实例展示其在实际项目中的应用与调优技巧。

1. K均值算法基础

1.1 什么是K均值算法?

K均值算法是一种无监督学习的聚类算法,用于将数据集中的数据点划分为K个簇,使得每个簇内的数据点相似度较高,而不同簇之间的相似度较低。其目标是通过最小化簇内数据点与其对应聚类中心的距离的平方和,来实现对数据的有效分组。

算法的执行过程如下:

  • 选择K个初始聚类中心,可以是随机选择或采用特定的初始化方法,如K均值++算法。
  • 将每个数据点分配到最近的聚类中心所属的簇。
  • 更新每个簇的中心位置,将其移动到簇内所有数据点的平均位置。
  • 重复以上两步,直至聚类中心不再发生明显变化或达到预定的迭代次数。

1.2 K均值算法的工作原理

K均值算法的工作原理可以概括为以下几个关键步骤:

步骤1:选择初始聚类中心

  • K均值算法开始时需要选择K个初始聚类中心。这可以通过随机选择数据集中的K个点或使用更智能的初始化方法,如K均值++算法。

步骤2:分配数据点到最近的聚类中心

  • 对于每个数据点,计算其与每个聚类中心的距离,将其分配到距离最近的簇中。

步骤3:更新聚类中心

  • 对每个簇,计算其所有数据点的平均值,并将聚类中心移动到该平均值的位置。

步骤4:迭代直至收敛

  • 重复步骤2和步骤3,直至聚类中心不再发生明显变化或达到预定的迭代次数。这时算法被认为收敛。

1.3 算法的优势与局限性

优势:

  • 简单易实现: K均值算法相对简单,易于理解和实现。
  • 计算效率高: 算法的计算复杂度较低,适用于大规模数据集。
  • 适用性广泛: 在数据聚类结构相对简单的情况下,K均值算法表现良好。

局限性:

  • 对初始值敏感: 初始聚类中心的选择可能影响算法的收敛结果,不同初始值可能导致不同的聚类结果。
  • 对异常值敏感: 算法容易受到异常值和噪声的影响,可能导致聚类结果失真。
  • 需要预先确定簇的数量K: 在实际问题中,确定簇的数量K并非总是容易,且K值的选择对最终结果有较大影响。

2. K均值算法的实现步骤

K均值算法的实现步骤是理解该算法的关键。让我们深入研究每个步骤,从初始聚类中心的选择到最终的收敛。

2.1 初始聚类中心的选择方法

初始聚类中心的选择直接影响着K均值算法的收敛速度和聚类结果。两种常用的方法是:

2.1.1 随机选择初始中心点

最简单的方法是从数据集中随机选择K个数据点作为初始聚类中心。这种方法简单直观,但可能受到初始点选择的不确定性影响。

2.1.2 K均值++算法

K均值++算法通过一系列计算,选择离已选中聚类中心越远的点作为新的聚类中心,有效避免了随机选择带来的问题,提高了算法的稳定性。具体步骤包括:

  • 从数据集中随机选择第一个中心点。
  • 对于剩余的数据点,计算每个点到已选中中心点的距离,选择距离较远的点作为新的中心点。
  • 重复上述步骤,直到选择出K个初始聚类中心。

2.2 数据点与聚类中心的距离计算

K均值算法的核心是通过计算数据点与聚类中心的距离,将数据点分配到最近的簇。两种常用的距离计算方法是:

2.2.1 欧氏距离计算

欧氏距离是最常用的距离计算方法,其计算公式为:

∑ i = 1 n ( x i − y i ) 2 \sqrt{\sum_{i=1}^{n} (x_i - y_i)^2} i=1n(xiyi)2

其中 x i x_i xi y i y_i yi 分别是两个数据点在第i个维度上的坐标。

2.2.2 曼哈顿距离计算

曼哈顿距离是另一种常见的距离计算方法,其计算公式为:

∑ i = 1 n ∣ x i − y i ∣ \sum_{i=1}^{n} |x_i - y_i| i=1nxiyi

2.3 更新聚类中心

在K均值算法中,数据点被分配到簇后,需要更新每个簇的中心位置。更新的方法是取簇中所有点的均值作为新的聚类中心。具体步骤如下:

  • 对于每个簇,计算该簇中所有数据点在每个维度上的均值,得到新的聚类中心。

2.4 重复迭代直至收敛

K均值算法是一个迭代算法,通过不断迭代更新聚类中心,直到满足停止条件。常见的停止条件有:

  • 固定迭代次数。
  • 聚类中心不再发生明显变化。

算法迭代的具体步骤如下:

  1. 初始化K个聚类中心。
  2. 将每个数据点分配到最近的聚类中心。
  3. 更新每个簇的聚类中心。
  4. 重复步骤2和3,直到满足停止条件。

这些实现步骤相互协作,确保了K均值算法的有效性和稳定性。在深入理解这些步骤后,我们将更好地掌握K均值算法的实际应用和调优技巧。

- K均值在Python中的应用

3.1 Python中的K均值算法库

在Python中,有着众多优秀的机器学习库,其中scikit-learn是应用最广泛的之一。其提供了丰富的聚类算法实现,包括了K均值算法。通过导入相应的模块,我们能够轻松地在Python中调用K均值算法的函数,实现高效的聚类。

3.2 数据准备与预处理

在应用K均值算法之前,我们需要对数据进行准备和预处理,确保数据的质量和一致性。这包括数据加载、清洗以及对特征的标准化。通过Python中的pandas和numpy库,我们能够方便地进行这些数据处理的步骤,为算法的输入做好充足的准备。

假设我们有以下的数据:

import pandas as pd

# 示例数据集
data = {'Feature1': [1, 2, 2.5, 3, 6, 5, 4.5, 5.5],
        'Feature2': [2, 1.5, 2.8, 3.5, 4, 5, 4.5, 5]}

df = pd.DataFrame(data)

在数据加载后,我们可以使用matplotlib库进行简单的数据可视化,以更好地了解我们的数据分布:

import matplotlib.pyplot as plt

plt.scatter(df['Feature1'], df['Feature2'])
plt.xlabel('Feature1')
plt.ylabel('Feature2')
plt.title('Data Distribution')
plt.show()

3.3 调用算法进行聚类

scikit-learn库提供了KMeans类,通过实例化该类并调用相应的方法,我们能够在Python中轻松实现K均值算法的聚类。在这一步骤中,我们将介绍如何设置算法的参数,包括聚类数目K、初始化方法等,并展示如何通过fit方法对数据进行聚类。

下面是具体的实现代码:

from sklearn.cluster import KMeans
# 确定簇的数量为2
kmeans = KMeans(n_clusters=2)
# 进行训练
kmeans.fit(df)
# 在输入的数据集上增加对应的簇类别
labels = kmeans.labels_
df['Cluster'] = labels

KMeans函数详解:

KMeans 是 scikit-learn 库中实现K均值算法的类,用于进行聚类分析。以下是对 KMeans 常用参数的详细解释供参考,不同版本之间的默认值可能会有区别,这里给出一些供大家参考:

  • n_clusters(默认值:8):

    • 用途:指定簇的数量,即K值。这是K均值算法中必须提供的参数。
  • init(默认值:‘k-means++’):

    • 用途:确定初始簇中心的方法。
    • 可选值:
      • ‘k-means++’:使用智能初始化方法,尽量确保初始中心之间的距离较远,有助于算法收敛更快。
      • ‘random’:随机选择数据中的点作为初始簇中心。
  • n_init(默认值:10):

    • 用途:指定算法运行的次数,每次使用不同的初始簇中心,以避免陷入局部最小值。
    • 对于给定的 n_clusters 值,选择具有最小惯性(簇内平方和)的运行结果。
  • max_iter(默认值:300):

    • 用途:指定每次运行的最大迭代次数,控制算法的运行时间。
  • tol(默认值:1e-4):

    • 用途:控制算法收敛的阈值,当两次迭代的中心之间的最大差异小于 tol 时,认为算法已经收敛。
  • algorithm(默认值:‘auto’):

    • 用途:指定K均值算法的实现方式。
    • 可选值:
      • ‘auto’:根据数据的大小和类型自动选择适当的算法。
      • ‘full’:使用经典的EM-style算法。
      • ‘elkan’:更有效的K均值算法,适用于较大的数据集。
  • random_state(默认值:None):

    • 用途:设置随机种子,确保每次运行得到的结果一致,便于复现实验。
  • n_jobs(默认值:None):

    • 用途:指定并行运算的数量,加速运行。设置为 -1 表示使用所有可用的CPU核心。
  • precompute_distances(默认值:‘auto’):

    • 用途:控制是否在算法运行前计算所有数据点之间的距离。
    • 可选值:
      • ‘auto’:根据数据大小自动判断是否计算距离。
      • True:始终计算距离。
      • False:不计算距离。

3.4 结果可视化与分析

聚类算法的结果可视化是理解算法效果的重要手段。通过使用Python中的matplotlib或seaborn等绘图库,我们能够将聚类结果以直观的图形呈现。除此之外,我们将深入分析聚类结果,探讨不同簇之间的特点,帮助读者更好地理解数据的结构。

通过可视化查看K均值算法的聚类结果:

plt.scatter(df['Feature1'], df['Feature2'], c=df['Cluster'], cmap='viridis')
plt.scatter(kmeans.cluster_centers_[:, 0], kmeans.cluster_centers_[:, 1], s=300, c='red', marker='X')
plt.xlabel('Feature1')
plt.ylabel('Feature2')
plt.title('K-Means Clustering Result')
plt.show()

我们使用散点图表示数据点,每个簇用不同的颜色标识,同时用红色的"X"表示聚类中心。这个可视化展示了K均值算法对数据的聚类效果。

4. K均值算法的参数调优与改进

4.1 如何选择合适的K值?

选择合适的K值对于K均值算法的成功应用至关重要。以下是两种常用的选择方法:

4.1.1 肘部法则(Elbow Method)

肘部法则是一种直观且常用的K值选择方法。其基本思想是随着聚类数K的增加,样本划分会更精细,每个簇的聚合度会逐渐提高,从而误差平方和(SSE)会逐渐减小。然而,当K达到真实聚类数时,增加K值所带来的聚合度提高会迅速减缓,形成一个肘部的拐点。该拐点对应的K值即为数据的真实聚类数。

下面是实现的python代码,供大家参考:

import os
os.environ['OMP_NUM_THREADS'] = '2'


import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn.datasets import make_blobs

# 设置中文显示
plt.rcParams['font.sans-serif'] = ['SimHei']  # 设置中文显示的字体,SimHei 是宋体的黑体版本
plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示为方块的问题

# 构建模拟数据
data, _ = make_blobs(n_samples=300, centers=4, random_state=12)

# 计算不同K值下的SSE
sse = []
k_range = range(1, 11)
for k in k_range:
    kmeans = KMeans(n_clusters=k, n_init=10, random_state=12)
    kmeans.fit(data)
    sse.append(kmeans.inertia_)

# 绘制肘部法则图像
fig, ax = plt.subplots()
ax.plot(k_range, sse, marker='o')
ax.set_xlabel('K值')
ax.set_ylabel('误差平方和(SSE)')
ax.set_title('肘部法则示例')
plt.show()


运行上述代码后,结果如下:
1
从上图中,我们可以看出k为2或者3时,比较合适。

优化版本,自动判断:

import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn.datasets import make_blobs
from kneed import KneeLocator

# 设置中文显示
plt.rcParams['font.sans-serif'] = ['SimHei']  # 设置中文显示的字体,SimHei 是宋体的黑体版本
plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示为方块的问题

# 构建模拟数据
data, _ = make_blobs(n_samples=300, centers=4, random_state=12)

# 计算不同K值下的SSE
sse = []
k_range = range(1, 11)
for k in k_range:
    kmeans = KMeans(n_clusters=k, n_init=10, random_state=12)
    kmeans.fit(data)
    sse.append(kmeans.inertia_)

# 使用KneeLocator自动检测肘部
kl = KneeLocator(k_range, sse, curve="convex", direction="decreasing")
optimal_k = kl.elbow

# 绘制肘部法则图像
fig, ax = plt.subplots()
ax.plot(k_range, sse, marker='o')
ax.set_xlabel('K值')
ax.set_ylabel('误差平方和(SSE)')
ax.set_title('自动检测肘部法则示例')

# 标记自动检测得到的肘部位置
ax.vlines(optimal_k, plt.ylim()[0], plt.ylim()[1], linestyles='dashed', colors='red', label='自动检测肘部')

plt.legend()
plt.show()

# 打印自动检测得到的最优K值
print("自动检测得到的最优K值:", optimal_k)



运行上述代码后,结果如下:
2

4.1.2 轮廓系数法

轮廓系数是一种用于度量聚类效果的指标,其值在-1到1之间,数值越大表示聚类效果越好。具体计算步骤如下:

  • 对于每个样本,计算它与同簇其他样本的平均距离,记作a(i)。
  • 对于每个样本,计算它与最近异簇样本的平均距离,记作b(i)。
  • 计算样本的轮廓系数:S(i) = (b(i) - a(i)) / max{a(i), b(i)}。
  • 对所有样本的轮廓系数取平均得到整体聚类的轮廓系数。

在选择K值时,我们可以尝试不同的K值,计算其对应的轮廓系数,选择轮廓系数达到最大值的K值作为最优的聚类数。

import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn.datasets import make_blobs
from sklearn.metrics import silhouette_samples, silhouette_score

# 构建模拟数据
data, _ = make_blobs(n_samples=300, centers=4, random_state=12)

# 计算不同K值下的轮廓系数
silhouette_scores = []
k_range = range(2, 11)  # K值至少为2
for k in k_range:
    kmeans = KMeans(n_clusters=k, n_init=10, random_state=12)
    labels = kmeans.fit_predict(data)
    silhouette_avg = silhouette_score(data, labels)
    silhouette_scores.append(silhouette_avg)

# 绘制轮廓系数法图像
plt.plot(k_range, silhouette_scores, marker='o')
plt.xlabel('K值')
plt.ylabel('轮廓系数')
plt.title('轮廓系数法示例')
plt.show()

运行上述代码后,我们得到下面的输出:
3
从上图中,我们依然可以看出最佳k值为2

4.2 改进K均值算法的方法

在实际应用中,K均值算法可能受到一些限制,特别是对于不规则形状、密度差异较大的簇。为了克服这些限制,可以采用一些改进的方法,使算法更加鲁棒和适用于多样化的数据集。

4.2.1 基于密度的聚类

背景: K均值算法在处理具有不同密度簇时可能表现不佳,因为其对所有簇的权重都是相等的。

方法: 基于密度的聚类方法通过考虑数据点周围的密度来调整簇的形状。DBSCAN(Density-Based Spatial Clustering of Applications with Noise)是一种常用的基于密度的聚类算法,它能够发现任意形状的簇并鲁棒地处理噪声。

实例: 我们将演示如何使用DBSCAN算法改进K均值算法,以适应具有不同密度簇的情况。通过比较改进前后的聚类效果,读者将更好地理解这一改进方法的实际应用。

具体代码:

from sklearn.cluster import DBSCAN
import matplotlib.pyplot as plt
from sklearn.datasets import make_blobs

# 创建具有不同密度簇的数据集
X, _ = make_blobs(n_samples=300, centers=3, cluster_std=[1.0, 2.5, 0.5], random_state=12)

# 使用DBSCAN进行聚类
dbscan = DBSCAN(eps=0.5, min_samples=5)
labels = dbscan.fit_predict(X)

# 可视化聚类结果
plt.scatter(X[:, 0], X[:, 1], c=labels, cmap='viridis', marker='o', edgecolor='black')
plt.title("基于密度的聚类 - 使用DBSCAN")
plt.show()

4.2.2 高斯混合模型

背景: K均值算法假设每个簇都是由一个球形的聚类中心表示,对于复杂形状的簇可能不够灵活。

方法: 高斯混合模型(Gaussian Mixture Model,GMM)是一种基于概率分布的聚类方法,它允许每个簇具有不同的形状和方向。每个簇被建模为一个概率分布的高斯分布。

实例: 我们将介绍如何使用GMM对K均值算法进行改进,以适应复杂形状的簇。通过在实际数据集上进行对比实验,展示GMM的优越性。

具体代码:

from sklearn.mixture import GaussianMixture
import numpy as np

# 创建具有不同形状簇的数据集
X = np.concatenate([np.random.normal(0, 1, size=(100, 2)),
                    np.random.normal(5, 1, size=(100, 2)),
                    np.random.normal(10, 1, size=(100, 2))])

# 使用GMM进行聚类
gmm = GaussianMixture(n_components=3, covariance_type='full', random_state=12)
labels = gmm.fit_predict(X)

# 可视化聚类结果
plt.scatter(X[:, 0], X[:, 1], c=labels, cmap='viridis', marker='o', edgecolor='black')
plt.title("高斯混合模型 - 使用GMM")
plt.show()

4.2.3 实际案例分析与效果评估

案例选择: 选择一个包含不规则形状、密度变化大的数据集,以展示K均值算法改进方法的实际效果。

评估指标: 使用聚类效果评估指标,比如轮廓系数、互信息等,来量化改进算法在真实数据上的表现。

from sklearn.metrics import silhouette_score
from sklearn.datasets import make_moons
from sklearn.preprocessing import StandardScaler
from sklearn.cluster import KMeans

# 创建月牙形数据集
X, _ = make_moons(n_samples=300, noise=0.05, random_state=12)

# 使用K均值算法进行初始聚类
kmeans = KMeans(n_clusters=2, random_state=42)
initial_labels = kmeans.fit_predict(X)

# 使用DBSCAN进行基于密度的聚类
dbscan = DBSCAN(eps=0.3, min_samples=5)
dbscan_labels = dbscan.fit_predict(X)

# 计算轮廓系数
initial_score = silhouette_score(X, initial_labels)
dbscan_score = silhouette_score(X, dbscan_labels)

print(f"K均值算法轮廓系数: {initial_score}")
print(f"DBSCAN轮廓系数: {dbscan_score}")

4.3 实际案例

背景描述:
我们选择一个具体的案例,即顾客购物行为分析。假设我们有一家零售商店,希望了解顾客的购物行为,以便更好地进行市场细分和商品定价。

实现代码:

import pandas as pd
import numpy as np

# 生成1000个顾客ID
customer_ids = np.arange(1, 1001)

# 生成购物金额和购物频率的随机数据
shopping_amounts = np.random.uniform(10, 200, 1000)  # 购物金额在10到200之间
shopping_frequencies = np.random.uniform(1, 10, 1000)  # 购物频率在1到10之间

# 创建数据框
customer_data = pd.DataFrame({
    'CustomerID': customer_ids,
    'ShoppingAmount': shopping_amounts,
    'ShoppingFrequency': shopping_frequencies
})

from sklearn.cluster import KMeans
import matplotlib.pyplot as plt

# 提取用于聚类的特征
features = customer_data[['ShoppingAmount', 'ShoppingFrequency']]

# 选择聚类数K为3
kmeans = KMeans(n_clusters=3)
customer_data['Cluster'] = kmeans.fit_predict(features)

# 获取簇心坐标
cluster_centers = kmeans.cluster_centers_

# 可视化聚类结果
plt.scatter(customer_data['ShoppingAmount'], customer_data['ShoppingFrequency'], c=customer_data['Cluster'], cmap='viridis')
plt.scatter(cluster_centers[:, 0], cluster_centers[:, 1], marker='X', s=200, c='red', label='簇心')  # 添加簇心标记
plt.title('顾客购物行为聚类结果')
plt.xlabel('购物金额')
plt.ylabel('购物频率')
plt.legend()
plt.show()


from sklearn.metrics import silhouette_score

# 计算轮廓系数
silhouette_avg = silhouette_score(features, customer_data['Cluster'])
print(f"整体轮廓系数: {silhouette_avg}")

应用到实际业务中:

市场细分定价策略促销活动
1低购物金额、低购物频率推出价格亲民的商品,提高性价比实施积分制度、首次购物折扣等促销,吸引频繁光顾
2中等购物金额、高购物频率提供多样化商品选择,注重实用性和新颖性设计会员专享活动、积分兑换等奖励机制,提升客户忠诚度
13高购物金额、低购物频率提供高价值商品,确保品质定期推出限时折扣、生日特权等高价值促销

写在最后

通过这篇博客,我们希望读者能够深入理解K均值算法,掌握其实现步骤,并在实际项目中灵活应用。聚类算法是数据科学领域中的一把利器,而K均值算法则是其中最亮眼的一颗星。愿您在学习的过程中有所收获,欢迎随时探讨与交流。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

theskylife

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值