Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

模糊聚类分析(FCM)

模糊聚类(Fuzzy C-Means, FCM)是一种基于模糊集合理论的软聚类方法,允许数据点以不同的隶属度同时属于多个类别,能够更真实地反映现实世界中数据边界模糊的特征。


模糊集合回顾

模糊集合理论由 Zadeh 于 1965 年提出,是模糊聚类的数学基础。

经典集合与模糊集合的区别

在经典集合论中,一个元素要么属于某个集合,要么不属于,隶属关系是非此即彼的。设论域为 \( U \),经典集合 \( A \) 的特征函数为:

\[ \chi_A(x) = \begin{cases} 1, & x \in A \ 0, & x \notin A \end{cases} \]

而模糊集合将隶属关系推广到连续区间 \([0, 1]\)。模糊集合 \( \tilde{A} \) 由隶属函数 \( \mu_{\tilde{A}}(x) \) 定义:

\[ \mu_{\tilde{A}}: U \to [0, 1] \]

其中 \( \mu_{\tilde{A}}(x) \) 表示元素 \( x \) 属于模糊集合 \( \tilde{A} \) 的程度。

模糊划分

设数据集 \( X = {x_1, x_2, \ldots, x_n} \) 被划分为 \( c \) 个模糊类,模糊划分矩阵 \( U = [u_{ik}] \) 满足:

\[ \sum_{i=1}^{c} u_{ik} = 1, \quad \forall k = 1, 2, \ldots, n \]

\[ 0 < \sum_{k=1}^{n} u_{ik} < n, \quad \forall i = 1, 2, \ldots, c \]

\[ u_{ik} \in [0, 1], \quad \forall i, k \]

这三个条件分别保证了:每个样本的隶属度之和为1、没有空类也没有全集类、隶属度取值在合理范围内。


FCM基本原理

FCM算法通过迭代优化目标函数,同时更新聚类中心和隶属度矩阵,直至收敛。

目标函数

FCM算法的目标是最小化如下加权平方误差目标函数:

\[ J_m(U, V) = \sum_{i=1}^{c} \sum_{k=1}^{n} u_{ik}^m | x_k - v_i |^2 \]

其中:

  • \( c \) 为聚类数目
  • \( n \) 为样本数目
  • \( u_{ik} \) 为第 \( k \) 个样本属于第 \( i \) 类的隶属度
  • \( v_i \) 为第 \( i \) 个聚类中心
  • \( m > 1 \) 为模糊指数(加权指数)
  • \( | x_k - v_i | \) 为样本 \( x_k \) 到聚类中心 \( v_i \) 的欧氏距离

隶属度矩阵

通过拉格朗日乘子法对目标函数求解,在约束 \( \sum_{i=1}^{c} u_{ik} = 1 \) 下,得到隶属度更新公式:

\[ u_{ik} = \frac{1}{\displaystyle\sum_{j=1}^{c} \left( \frac{| x_k - v_i |}{| x_k - v_j |} \right)^{\frac{2}{m-1}}} \]

聚类中心更新

对目标函数关于 \( v_i \) 求偏导并令其为零,得到聚类中心更新公式:

\[ v_i = \frac{\displaystyle\sum_{k=1}^{n} u_{ik}^m \cdot x_k}{\displaystyle\sum_{k=1}^{n} u_{ik}^m} \]

聚类中心是所有样本点的加权平均,权重为隶属度的 \( m \) 次幂。


算法步骤

FCM算法是一个交替优化的迭代过程,类似于EM算法的思想。

完整算法流程

输入:数据集 \( X = {x_1, x_2, \ldots, x_n} \),聚类数 \( c \),模糊指数 \( m \),收敛阈值 \( \varepsilon \),最大迭代次数 \( T_{max} \)

步骤

  1. 初始化:随机生成满足约束条件的隶属度矩阵 \( U^{(0)} \),设迭代计数 \( t = 0 \)

  2. 更新聚类中心:根据当前隶属度矩阵计算聚类中心 \[ v_i^{(t)} = \frac{\sum_{k=1}^{n} (u_{ik}^{(t)})^m \cdot x_k}{\sum_{k=1}^{n} (u_{ik}^{(t)})^m}, \quad i = 1, 2, \ldots, c \]

  3. 更新隶属度矩阵:根据新的聚类中心更新隶属度 \[ u_{ik}^{(t+1)} = \frac{1}{\sum_{j=1}^{c} \left( \frac{| x_k - v_i^{(t)} |}{| x_k - v_j^{(t)} |} \right)^{\frac{2}{m-1}}} \]

  4. 收敛判断:若 \( | U^{(t+1)} - U^{(t)} | < \varepsilon \) 或 \( t > T_{max} \),则停止;否则 \( t = t + 1 \),转步骤2

输出:最终隶属度矩阵 \( U \) 和聚类中心 \( V \)

硬聚类结果提取

若需要将模糊聚类结果转化为硬聚类(明确分类),采用最大隶属度原则:

\[ x_k \in \text{Cluster } i^* \quad \text{其中} \quad i^* = \arg\max_{i} , u_{ik} \]


模糊指数m的选择

模糊指数 \( m \) 是FCM中最关键的超参数,直接影响聚类的模糊程度和结果质量。

m的影响分析

  • 当 \( m \to 1 \) 时,隶属度趋向于0或1,FCM退化为硬聚类(类似K-Means)
  • 当 \( m \to \infty \) 时,所有隶属度趋向于 \( 1/c \),聚类失去区分能力
  • \( m \) 越大,聚类边界越模糊;\( m \) 越小,聚类边界越清晰

常用选择策略

策略建议值适用场景
经验值\( m = 2 \)大多数实际问题的首选
理论推荐\( m \in [1.5, 2.5] \)一般数据集
验证选择通过有效性指标比较对结果敏感的应用

基于有效性指标的选择

可以通过划分系数(Partition Coefficient, PC)和划分熵(Partition Entropy, PE)来评估不同 \( m \) 值下的聚类质量:

\[ \text{PC} = \frac{1}{n} \sum_{i=1}^{c} \sum_{k=1}^{n} u_{ik}^2 \]

\[ \text{PE} = -\frac{1}{n} \sum_{i=1}^{c} \sum_{k=1}^{n} u_{ik} \log(u_{ik}) \]

PC越大(接近1)表示聚类越清晰,PE越小(接近0)表示聚类越确定。选择使PC最大或PE最小的 \( m \) 值。


实际案例分析

通过一个完整的数值计算案例来展示FCM的具体运算过程。

问题设置

设有6个二维数据点需要聚类为2类(\( c = 2 \)),模糊指数 \( m = 2 \):

样本\( x_1 \)\( x_2 \)
\( x_1 \)1.01.0
\( x_2 \)1.52.0
\( x_3 \)2.01.0
\( x_4 \)5.05.0
\( x_5 \)5.54.0
\( x_6 \)6.05.0

第一次迭代

步骤1:初始化隶属度矩阵

随机初始化(满足每列之和为1):

\[ U^{(0)} = \begin{pmatrix} 0.8 & 0.7 & 0.9 & 0.2 & 0.3 & 0.1 \ 0.2 & 0.3 & 0.1 & 0.8 & 0.7 & 0.9 \end{pmatrix} \]

步骤2:计算聚类中心

当 \( m = 2 \) 时,\( u_{ik}^m = u_{ik}^2 \)。对于聚类中心 \( v_1 \):

权重:\( u_{11}^2 = 0.64,; u_{12}^2 = 0.49,; u_{13}^2 = 0.81,; u_{14}^2 = 0.04,; u_{15}^2 = 0.09,; u_{16}^2 = 0.01 \),权重之和 \( W_1 = 2.08 \)

\[ v_{1,x_1} = \frac{0.64 \times 1.0 + 0.49 \times 1.5 + 0.81 \times 2.0 + 0.04 \times 5.0 + 0.09 \times 5.5 + 0.01 \times 6.0}{2.08} = \frac{3.75}{2.08} \approx 1.803 \]

\[ v_{1,x_2} = \frac{0.64 \times 1.0 + 0.49 \times 2.0 + 0.81 \times 1.0 + 0.04 \times 5.0 + 0.09 \times 4.0 + 0.01 \times 5.0}{2.08} = \frac{3.04}{2.08} \approx 1.462 \]

因此 \( v_1 \approx (1.803, 1.462) \)。

类似地计算 \( v_2 \),权重之和 \( W_2 = 2.08 \):

\[ v_2 \approx (5.264, 4.538) \]

步骤3:更新隶属度矩阵

以样本 \( x_1 = (1.0, 1.0) \) 为例,计算到两个中心的距离:

\[ d_{11} = | x_1 - v_1 | = \sqrt{(1.0 - 1.803)^2 + (1.0 - 1.462)^2} = \sqrt{0.645 + 0.213} = \sqrt{0.858} \approx 0.927 \]

\[ d_{21} = | x_1 - v_2 | = \sqrt{(1.0 - 5.264)^2 + (1.0 - 4.538)^2} = \sqrt{18.19 + 12.52} = \sqrt{30.71} \approx 5.542 \]

当 \( m = 2 \) 时,\( \frac{2}{m-1} = 2 \),隶属度更新为:

\[ u_{11}^{(1)} = \frac{1}{1 + \left(\frac{d_{11}}{d_{21}}\right)^2} = \frac{1}{1 + \left(\frac{0.927}{5.542}\right)^2} = \frac{1}{1 + 0.028} \approx 0.973 \]

\[ u_{21}^{(1)} = 1 - u_{11}^{(1)} \approx 0.027 \]

可以看出,经过一次迭代,样本 \( x_1 \) 以很高的隶属度(0.973)属于第1类,这符合直觉。

迭代收敛

经过多次迭代后,算法收敛,最终结果为:

  • 聚类中心:\( v_1 \approx (1.50, 1.33) \),\( v_2 \approx (5.50, 4.67) \)
  • 样本 \( x_1, x_2, x_3 \) 以接近1的隶属度属于第1类
  • 样本 \( x_4, x_5, x_6 \) 以接近1的隶属度属于第2类

由于两组数据分离明显,最终隶属度接近硬聚类结果。


Python代码实现

以下提供FCM算法的完整Python实现及可视化。

从零实现FCM

import numpy as np
import matplotlib.pyplot as plt

class FuzzyCMeans:
    """模糊C均值聚类算法实现"""
    
    def __init__(self, n_clusters=3, m=2.0, max_iter=200, tol=1e-6, random_state=None):
        self.n_clusters = n_clusters
        self.m = m
        self.max_iter = max_iter
        self.tol = tol
        self.random_state = random_state
        
    def _init_membership(self, n_samples):
        """随机初始化隶属度矩阵"""
        rng = np.random.default_rng(self.random_state)
        U = rng.random((self.n_clusters, n_samples))
        U = U / U.sum(axis=0, keepdims=True)
        return U
    
    def _update_centers(self, X, U):
        """更新聚类中心"""
        Um = U ** self.m
        return (Um @ X) / Um.sum(axis=1, keepdims=True)
    
    def _update_membership(self, X, centers):
        """更新隶属度矩阵"""
        n_samples = X.shape[0]
        c = self.n_clusters
        power = 2.0 / (self.m - 1)
        
        distances = np.zeros((c, n_samples))
        for i in range(c):
            distances[i] = np.linalg.norm(X - centers[i], axis=1)
        distances = np.maximum(distances, 1e-10)
        
        U = np.zeros((c, n_samples))
        for i in range(c):
            denom = np.sum((distances[i:i+1, :] / distances) ** power, axis=0)
            U[i] = 1.0 / denom
        return U
    
    def fit(self, X):
        """拟合FCM模型"""
        self.U_ = self._init_membership(X.shape[0])
        self.objective_history_ = []
        
        for iteration in range(self.max_iter):
            self.centers_ = self._update_centers(X, self.U_)
            U_new = self._update_membership(X, self.centers_)
            
            # 计算目标函数
            Um = self.U_ ** self.m
            obj = sum(np.sum(Um[i] * np.sum((X - self.centers_[i])**2, axis=1))
                      for i in range(self.n_clusters))
            self.objective_history_.append(obj)
            
            diff = np.max(np.abs(U_new - self.U_))
            self.U_ = U_new
            if diff < self.tol:
                self.n_iter_ = iteration + 1
                break
        else:
            self.n_iter_ = self.max_iter
        
        self.labels_ = np.argmax(self.U_, axis=0)
        return self
    
    def predict(self, X):
        """预测新样本的隶属度"""
        return self._update_membership(X, self.centers_)


# 生成测试数据并运行
np.random.seed(42)
X = np.vstack([
    np.random.randn(50, 2) * 0.8 + [2, 2],
    np.random.randn(50, 2) * 0.8 + [6, 2],
    np.random.randn(50, 2) * 0.8 + [4, 6]
])

fcm = FuzzyCMeans(n_clusters=3, m=2.0, random_state=42)
fcm.fit(X)
print(f"迭代次数: {fcm.n_iter_}")
print(f"聚类中心:\n{fcm.centers_}")

可视化与使用scikit-fuzzy库

# 可视化隶属度分布
fig, axes = plt.subplots(1, 3, figsize=(15, 5))
for idx, ax in enumerate(axes):
    scatter = ax.scatter(X[:, 0], X[:, 1], c=fcm.U_[idx], cmap='YlOrRd',
                         s=30, edgecolors='gray', linewidths=0.5)
    ax.scatter(fcm.centers_[idx, 0], fcm.centers_[idx, 1],
               marker='*', s=300, c='black', zorder=5)
    ax.set_title(f'隶属度分布 - 类别 {idx+1}')
    plt.colorbar(scatter, ax=ax, label='隶属度')
plt.tight_layout()
plt.show()

# 使用 scikit-fuzzy 库 (pip install scikit-fuzzy)
import skfuzzy as fuzz

X_T = X.T  # 转置为 (特征数 x 样本数) 格式
cntr, u, u0, d, jm, p, fpc = fuzz.cluster.cmeans(
    X_T, c=3, m=2.0, error=1e-6, maxiter=200, seed=42
)
print(f"划分系数 FPC = {fpc:.4f}")
print(f"聚类中心:\n{cntr}")

与K-Means对比

FCM与K-Means都是基于划分的聚类方法,但在处理边界数据时表现差异明显。

理论对比

对比维度K-MeansFCM
聚类类型硬聚类软聚类(模糊聚类)
隶属关系每个样本只属于一类每个样本以不同隶属度属于各类
目标函数\( J = \sum_{i}\sum_{k} | x_k - v_i |^2 \)\( J_m = \sum_{i}\sum_{k} u_{ik}^m | x_k - v_i |^2 \)
超参数聚类数 \( c \)聚类数 \( c \)、模糊指数 \( m \)
对异常值敏感度较高相对较低(异常点隶属度分散)
计算复杂度\( O(ncdt) \)\( O(nc^2dt) \)
收敛速度较快较慢
结果确定性确定性划分提供不确定性信息

其中 \( n \) 为样本数,\( c \) 为聚类数,\( d \) 为维度,\( t \) 为迭代次数。

对比实验代码

from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score

# 生成有重叠的数据
np.random.seed(0)
X_overlap = np.vstack([
    np.random.randn(100, 2) * 1.2 + [0, 0],
    np.random.randn(100, 2) * 1.2 + [3, 0]
])

# K-Means vs FCM
kmeans = KMeans(n_clusters=2, random_state=0, n_init=10)
kmeans_labels = kmeans.fit_predict(X_overlap)

fcm2 = FuzzyCMeans(n_clusters=2, m=2.0, random_state=0)
fcm2.fit(X_overlap)

# 边界样本识别
max_membership = np.max(fcm2.U_, axis=0)
boundary_mask = max_membership < 0.7

print(f"K-Means 轮廓系数: {silhouette_score(X_overlap, kmeans_labels):.4f}")
print(f"FCM 轮廓系数: {silhouette_score(X_overlap, fcm2.labels_):.4f}")
print(f"边界样本数量: {boundary_mask.sum()} / {len(X_overlap)}")

# 可视化对比
fig, axes = plt.subplots(1, 2, figsize=(12, 5))
axes[0].scatter(X_overlap[:, 0], X_overlap[:, 1],
                c=kmeans_labels, cmap='coolwarm', s=20, alpha=0.7)
axes[0].set_title('K-Means 硬聚类结果')

scatter = axes[1].scatter(X_overlap[:, 0], X_overlap[:, 1],
                          c=fcm2.U_[0], cmap='coolwarm', s=20, alpha=0.7)
axes[1].set_title('FCM 模糊聚类结果')
plt.colorbar(scatter, ax=axes[1])
plt.tight_layout()
plt.show()

关键差异总结

  1. 信息丰富度:FCM为每个样本提供属于各类的概率信息,K-Means只给出确定性标签
  2. 边界处理:对于类别重叠区域的样本,FCM的隶属度能反映其不确定性,而K-Means强制将其归为某一类
  3. 鲁棒性:FCM对初始化的敏感性略低于K-Means,因为隶属度的渐进调整使算法更平滑
  4. 适用场景:当类别边界清晰时两者效果相近;当边界模糊或需要不确定性信息时,FCM更为适合

应用注意事项与局限性

正确使用FCM需要了解其适用条件和潜在问题。

聚类数目的确定

FCM和K-Means一样,需要预先指定聚类数 \( c \)。常用确定方法:

  1. 划分系数(PC)和划分熵(PE):遍历不同 \( c \) 值,选择PC最大或PE最小的值

  2. Xie-Beni指标:综合考虑类内紧致度和类间分离度 \[ \text{XB} = \frac{\sum_{i=1}^{c}\sum_{k=1}^{n} u_{ik}^m | x_k - v_i |^2}{n \cdot \min_{i \neq j} | v_i - v_j |^2} \] 选择使XB最小的 \( c \) 值。

  3. 模糊轮廓系数:将经典轮廓系数推广到模糊聚类情形

初始化策略

FCM对初始值敏感,可能收敛到局部最优。改进策略包括:

  • 多次运行:不同随机初始化运行多次,选择目标函数最小的结果
  • K-Means++初始化:先用K-Means++选择初始聚类中心,再据此构造初始隶属度矩阵
  • 确定性初始化:基于数据分布特征(如主成分方向)确定初始中心

主要局限性

  1. 球形假设:标准FCM假设各类服从球形分布,对椭圆形或不规则形状的类效果不佳。改进方法包括使用马氏距离的 Gustafson-Kessel 算法

  2. 噪声敏感:虽然比K-Means略好,但FCM仍对噪声和异常值敏感。可采用 Possibilistic C-Means (PCM) 或 Noise Clustering 方法

  3. 高维问题:在高维空间中,距离度量失效(维度灾难),FCM的性能会显著下降。建议先进行降维处理

  4. 计算效率:FCM每次迭代需计算所有样本到所有中心的距离并更新整个隶属度矩阵,在大规模数据集上效率较低

  5. 聚类数敏感:错误的聚类数选择会严重影响结果质量

实际应用建议

  • 数据预处理:标准化各特征,消除量纲影响
  • 参数选择:先取 \( m = 2 \) 进行初步实验,再根据有效性指标微调
  • 结果验证:结合领域知识和多种聚类有效性指标综合判断
  • 对比分析:与K-Means等其他方法对比,评估模糊聚类的必要性
  • 可视化辅助:利用隶属度分布的热力图或雷达图辅助解读结果

典型应用领域

领域应用场景模糊性来源
图像处理图像分割、目标识别像素颜色渐变、边界模糊
医学诊断疾病分型、组织分类病理特征的连续性变化
市场营销客户细分、消费行为分析消费者偏好的多样性
遥感分析土地利用分类地物类型的渐进过渡
故障诊断设备状态监测正常与故障的渐进过渡

本章小结

FCM是模糊数学与聚类分析结合的经典方法,在处理具有模糊边界的数据时具有独特优势。

  1. FCM通过引入隶属度矩阵,将硬聚类推广为软聚类,每个样本可以“部分地“属于多个类别
  2. 目标函数 \( J_m \) 通过交替优化隶属度和聚类中心来实现最小化
  3. 模糊指数 \( m \) 控制聚类的模糊程度,\( m = 2 \) 是最常用的选择
  4. 与K-Means相比,FCM提供了更丰富的信息,特别是对边界样本的不确定性描述
  5. 实际应用中需要注意初始化、聚类数选择和数据预处理等问题

在数学建模竞赛中,当问题涉及分类但类别边界不清晰时,FCM是一种值得优先考虑的方法。它不仅能给出分类结果,还能量化每个样本归属各类的可能性,为决策提供更全面的依据。