Python实战:用sklearn实现FCM模糊聚类(附完整代码与数据集)
·
Python实战:用sklearn实现FCM模糊聚类(附完整代码与数据集)
在数据科学领域,聚类分析是最基础也最常用的技术之一。不同于传统的硬聚类方法(如K-means)要求每个数据点只能属于一个类别,模糊C均值聚类(FCM)允许数据点以不同隶属度属于多个类别,这种"软分配"特性使其在处理边界模糊的数据时表现尤为出色。本文将手把手教你如何用Python的sklearn生态系统实现FCM算法,从数据预处理到结果可视化全流程覆盖,特别适合已经掌握基础机器学习概念、想要进阶实践的数据从业者。
1. 环境准备与数据加载
1.1 安装必要库
虽然scikit-learn没有原生实现FCM,但可以通过sklearn-fuzzy扩展库轻松实现。首先确保已安装以下依赖:
pip install scikit-learn numpy matplotlib scikit-fuzzy pandas
注意:如果使用Jupyter Notebook,建议在单元格开头添加
%matplotlib inline以显示图表。
1.2 数据集选择与加载
我们使用经典的鸢尾花数据集作为演示,该数据集包含150个样本,每个样本有4个特征(花萼长度、花萼宽度、花瓣长度、花瓣宽度):
from sklearn import datasets
import pandas as pd
iris = datasets.load_iris()
X = iris.data
feature_names = iris.feature_names
df = pd.DataFrame(X, columns=feature_names)
查看数据前五行:
| 花萼长度 (cm) | 花萼宽度 (cm) | 花瓣长度 (cm) | 花瓣宽度 (cm) |
|---|---|---|---|
| 5.1 | 3.5 | 1.4 | 0.2 |
| 4.9 | 3.0 | 1.4 | 0.2 |
| 4.7 | 3.2 | 1.3 | 0.2 |
| 4.6 | 3.1 | 1.5 | 0.2 |
| 5.0 | 3.6 | 1.4 | 0.2 |
2. FCM算法核心实现
2.1 模型初始化与参数解释
使用sklearn-fuzzy的cmeans函数实现FCM:
import skfuzzy as fuzz
# 定义关键参数
n_clusters = 3 # 聚类数量
m = 2.0 # 模糊因子(通常1.1-2.5)
max_iter = 100 # 最大迭代次数
error = 1e-5 # 停止阈值
# 转置数据以满足函数输入要求
data = X.T
参数说明:
- 模糊因子m:控制聚类模糊程度,m=1退化为K-means,m越大隶属度越分散
- 停止条件:当隶属度矩阵变化小于
error或达到max_iter时终止
2.2 训练模型与结果提取
执行聚类并获取关键输出:
cntr, u, u0, d, jm, p, fpc = fuzz.cluster.cmeans(
data, n_clusters, m, error, max_iter
)
# 获取每个样本的隶属度
cluster_membership = np.argmax(u, axis=0)
关键输出变量:
cntr:最终聚类中心坐标(3×4矩阵)u:隶属度矩阵(3×150矩阵)fpc:模糊划分系数(0-1,值越大聚类效果越好)
3. 结果分析与可视化
3.1 聚类效果评估
计算并打印关键指标:
print(f"模糊划分系数(FPC): {fpc:.3f}")
print("聚类中心坐标:")
for i, center in enumerate(cntr):
print(f"Cluster {i}: {center}")
典型输出示例:
模糊划分系数(FPC): 0.892
聚类中心坐标:
Cluster 0: [5.88 2.74 4.36 1.39]
Cluster 1: [6.85 3.07 5.74 2.07]
Cluster 2: [5.00 3.42 1.46 0.24]
3.2 多维数据可视化
由于原始数据是四维的,我们选择前两个主成分进行可视化:
from sklearn.decomposition import PCA
import matplotlib.pyplot as plt
# 降维到2D
pca = PCA(n_components=2)
X_pca = pca.fit_transform(X)
# 绘制聚类结果
fig, ax = plt.subplots(figsize=(10,6))
for i in range(n_clusters):
ax.scatter(
X_pca[cluster_membership==i, 0],
X_pca[cluster_membership==i, 1],
label=f'Cluster {i}',
alpha=0.7
)
# 标记聚类中心
centers_pca = pca.transform(cntr)
ax.scatter(
centers_pca[:,0], centers_pca[:,1],
marker='X', s=200, c='black',
label='Cluster Centers'
)
ax.set_title('FCM聚类结果(PCA降维)')
ax.legend()
plt.show()

图:鸢尾花数据集的FCM聚类结果(不同颜色代表不同簇,X标记为聚类中心)
4. 高级技巧与实战建议
4.1 确定最佳聚类数
使用肘部法则结合模糊划分系数选择最优聚类数:
fpc_scores = []
cluster_range = range(2,6)
for n in cluster_range:
_, _, _, _, _, _, fpc = fuzz.cluster.cmeans(
data, n, m, error, max_iter
)
fpc_scores.append(fpc)
# 绘制FPC曲线
plt.plot(cluster_range, fpc_scores, 'o-')
plt.xlabel('Number of clusters')
plt.ylabel('Fuzzy Partition Coefficient')
plt.title('FPC vs Cluster Number')
4.2 处理高维数据的实用技巧
当特征维度较高时(>50维),建议:
- 先使用PCA/TSNE进行降维
- 对特征进行标准化处理
- 调整模糊因子m的值(通常1.5-2.0效果较好)
from sklearn.preprocessing import StandardScaler
# 标准化数据
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# 重新训练模型
data_scaled = X_scaled.T
cntr_scaled, u_scaled, *_ = fuzz.cluster.cmeans(
data_scaled, n_clusters, m, error, max_iter
)
4.3 常见问题排查
问题1:聚类结果不稳定
- 解决方案:增加
max_iter或减小error阈值,多次运行取最优
问题2:FPC值过低(<0.5)
- 检查数据是否适合聚类(计算轮廓系数)
- 尝试不同的模糊因子m值
- 考虑数据本身可能没有明显簇结构
问题3:运行速度慢
- 对大数据集使用Mini-Batch FCM变种
- 先使用K-means初始化聚类中心
# 使用K-means初始化中心
from sklearn.cluster import KMeans
kmeans = KMeans(n_clusters=3).fit(X)
initial_centers = kmeans.cluster_centers_.T
5. 完整代码示例
以下是整合所有步骤的完整可执行代码:
# 完整FCM实现示例
import numpy as np
import pandas as pd
import skfuzzy as fuzz
from sklearn import datasets
from sklearn.decomposition import PCA
import matplotlib.pyplot as plt
# 1. 数据准备
iris = datasets.load_iris()
X = iris.data
data = X.T
# 2. 参数设置
n_clusters = 3
m = 2.0
max_iter = 100
error = 1e-5
# 3. 训练FCM模型
cntr, u, *_ = fuzz.cluster.cmeans(
data, n_clusters, m, error, max_iter
)
# 4. 结果处理
cluster_membership = np.argmax(u, axis=0)
print(f"模糊划分系数: {fuzz.cluster.cmeans_predict(data, cntr, m)[1]:.3f}")
# 5. 可视化
pca = PCA(n_components=2)
X_pca = pca.fit_transform(X)
plt.figure(figsize=(10,6))
for i in range(n_clusters):
plt.scatter(
X_pca[cluster_membership==i, 0],
X_pca[cluster_membership==i, 1],
label=f'Cluster {i}'
)
centers_pca = pca.transform(cntr.T)
plt.scatter(
centers_pca[:,0], centers_pca[:,1],
marker='X', s=200, c='black',
label='Centers'
)
plt.legend()
plt.title('FCM Clustering Result')
plt.show()
更多推荐



所有评论(0)