模糊聚类分析(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} \)
步骤:
-
初始化:随机生成满足约束条件的隶属度矩阵 \( U^{(0)} \),设迭代计数 \( t = 0 \)
-
更新聚类中心:根据当前隶属度矩阵计算聚类中心 \[ 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 \]
-
更新隶属度矩阵:根据新的聚类中心更新隶属度 \[ 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}}} \]
-
收敛判断:若 \( | 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.0 | 1.0 |
| \( x_2 \) | 1.5 | 2.0 |
| \( x_3 \) | 2.0 | 1.0 |
| \( x_4 \) | 5.0 | 5.0 |
| \( x_5 \) | 5.5 | 4.0 |
| \( x_6 \) | 6.0 | 5.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-Means | FCM |
|---|---|---|
| 聚类类型 | 硬聚类 | 软聚类(模糊聚类) |
| 隶属关系 | 每个样本只属于一类 | 每个样本以不同隶属度属于各类 |
| 目标函数 | \( 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()
关键差异总结
- 信息丰富度:FCM为每个样本提供属于各类的概率信息,K-Means只给出确定性标签
- 边界处理:对于类别重叠区域的样本,FCM的隶属度能反映其不确定性,而K-Means强制将其归为某一类
- 鲁棒性:FCM对初始化的敏感性略低于K-Means,因为隶属度的渐进调整使算法更平滑
- 适用场景:当类别边界清晰时两者效果相近;当边界模糊或需要不确定性信息时,FCM更为适合
应用注意事项与局限性
正确使用FCM需要了解其适用条件和潜在问题。
聚类数目的确定
FCM和K-Means一样,需要预先指定聚类数 \( c \)。常用确定方法:
-
划分系数(PC)和划分熵(PE):遍历不同 \( c \) 值,选择PC最大或PE最小的值
-
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 \) 值。
-
模糊轮廓系数:将经典轮廓系数推广到模糊聚类情形
初始化策略
FCM对初始值敏感,可能收敛到局部最优。改进策略包括:
- 多次运行:不同随机初始化运行多次,选择目标函数最小的结果
- K-Means++初始化:先用K-Means++选择初始聚类中心,再据此构造初始隶属度矩阵
- 确定性初始化:基于数据分布特征(如主成分方向)确定初始中心
主要局限性
-
球形假设:标准FCM假设各类服从球形分布,对椭圆形或不规则形状的类效果不佳。改进方法包括使用马氏距离的 Gustafson-Kessel 算法
-
噪声敏感:虽然比K-Means略好,但FCM仍对噪声和异常值敏感。可采用 Possibilistic C-Means (PCM) 或 Noise Clustering 方法
-
高维问题:在高维空间中,距离度量失效(维度灾难),FCM的性能会显著下降。建议先进行降维处理
-
计算效率:FCM每次迭代需计算所有样本到所有中心的距离并更新整个隶属度矩阵,在大规模数据集上效率较低
-
聚类数敏感:错误的聚类数选择会严重影响结果质量
实际应用建议
- 数据预处理:标准化各特征,消除量纲影响
- 参数选择:先取 \( m = 2 \) 进行初步实验,再根据有效性指标微调
- 结果验证:结合领域知识和多种聚类有效性指标综合判断
- 对比分析:与K-Means等其他方法对比,评估模糊聚类的必要性
- 可视化辅助:利用隶属度分布的热力图或雷达图辅助解读结果
典型应用领域
| 领域 | 应用场景 | 模糊性来源 |
|---|---|---|
| 图像处理 | 图像分割、目标识别 | 像素颜色渐变、边界模糊 |
| 医学诊断 | 疾病分型、组织分类 | 病理特征的连续性变化 |
| 市场营销 | 客户细分、消费行为分析 | 消费者偏好的多样性 |
| 遥感分析 | 土地利用分类 | 地物类型的渐进过渡 |
| 故障诊断 | 设备状态监测 | 正常与故障的渐进过渡 |
本章小结
FCM是模糊数学与聚类分析结合的经典方法,在处理具有模糊边界的数据时具有独特优势。
- FCM通过引入隶属度矩阵,将硬聚类推广为软聚类,每个样本可以“部分地“属于多个类别
- 目标函数 \( J_m \) 通过交替优化隶属度和聚类中心来实现最小化
- 模糊指数 \( m \) 控制聚类的模糊程度,\( m = 2 \) 是最常用的选择
- 与K-Means相比,FCM提供了更丰富的信息,特别是对边界样本的不确定性描述
- 实际应用中需要注意初始化、聚类数选择和数据预处理等问题
在数学建模竞赛中,当问题涉及分类但类别边界不清晰时,FCM是一种值得优先考虑的方法。它不仅能给出分类结果,还能量化每个样本归属各类的可能性,为决策提供更全面的依据。