Fuzzy Clustering详解

第十九次写博客,本人数学基础不是太好,如果有幸能得到读者指正,感激不尽,希望能借此机会向大家学习。这一篇文章是原型聚类中介绍的第三个算法,主要是谈一谈“模糊聚类”(Fuzzy Clustering)。其他有关于原型聚类算法的讨论可以移步到该类算法的导航页《原型聚类算法综述(原型聚类算法开篇)》。

模糊集合

  模糊集合论(Fuzzy Set Theory):允许对象以0到1之间的某个隶属度属于一个集合;
  模糊逻辑(Fuzzy Logic):允许一个陈述以0到1之间的确定度为真。
下面以天气为例,假设有两个集合分别为“雨天”和“晴天”,那么某一天的降水概率为15%,则他在“雨天”集合中具有0.15的隶属度,而在“晴天”集合中具有0.85的隶属度。

模糊簇

  假设数据集D={xi∣i=1,2,...,m}D=\{\mathbf{x}_i|i=1,2,...,m\}D={xi​∣i=1,2,...,m}中的每个样本点xi=(xi1,xi2,...,xim)\mathbf{x}_i=\left(x_{i1},x_{i2},...,x_{im}\right)xi​=(xi1​,xi2​,...,xim​)为一个nnn维向量,那么为了确保簇形成“模糊为划分”(Fuzzy Psuedo-partion),需要满足以下条件:
1) 对于每个样本点xi\mathbf{x}_ixi​与每个簇Cj(j=1,2,...,k)C_j\left(j=1,2,...,k\right)Cj​(j=1,2,...,k),隶属度(权值)wijw_{ij}wij​要满足:

2) 每个样本点xi\mathbf{x}_ixi​的所有权值之和为1:

3) 每个簇CjC_{j}Cj​以非零的权值至少包含一个样本点,且不以权值为1包含所有样本点:

模糊c均值(Fuzzy C-Means)

  模糊c均值(Fuzzy C-Means)简称FCM,是K-Means的一种模糊版本,算法伪代码如下图所示,

由上图可以看出,模糊c均值与K-Means通过相似的步骤进行质心与簇划分的交替迭代更新,直到满足迭代停止条件为止。虽然两种算法均可以以最小化总误差平方和SSE为目标,但是在K-Means中,每个样本以0或1的隶属度被划分到对应的簇中,因此总SSE被定义为:

而在模糊聚类中,每个样本都可以以0到1的隶属度被划分到每个簇中,因此在模糊c均值中,总SSE定义为:

可以将上式看做是SSE的加权版本,其中,p∈[1,∞)p\in[1,\infty)p∈[1,∞)是确定权值wijw_{ij}wij​影响的指数,他的取值分为以下几种情况:
1) p=2p=2p=2时,可以简化权值wijw_{ij}wij​更新公式;
2) p≈1p\thickapprox1p≈1时,模糊c均值近乎与K-Means相同;
3) ppp越大,划分结果越模糊。

  算法第1行:模糊c均值与K-Means的初始化方法类似,通常对权值wijw_{ij}wij​进行随机初始化,但是要保证每个样本点xi\mathbf{x}_ixi​的所有权值之和为1,因此也会面临局部最优的问题,具体的解决方法与在K-Means中讨论过的相同。
  算法第3行:簇质心(原型)的计算与K-Means中的更新方法类似,只不过要考虑到数据集中的所有样本点和他们对应于该簇的隶属度,具体的计算方法如下所示:

同样,如果将隶属度规定为0或1,那么上式会退化为K-Means中的质心更新公式。
  算法第4行:在更新模糊伪划分wijw_{ij}wij​时,需要保证每个样本点xi\mathbf{x}_ixi​的所有权值之和为1,更新公式如下所示:

p=2p=2p=2时,上式可以简化为

直观上看,可以将隶属度(权值)wijw_{ij}wij​理解为样本点xi\mathbf{x}_ixi​与簇CjC_jCj​的临近度,xi\mathbf{x}_ixi​越靠近CjC_jCj​,wijw_{ij}wij​越大,反之越小。
  下面是使用模糊c均值进行聚类的一个例子,从这个例子中我们可以看出,该算法产生的最终聚类结果显示出了簇中每个样本点的隶属度,与K-Means相比,他的计算复杂度明显增加,除此之外,他与K-Means有着相同的特点。


代码实现

下面是我自己实现的代码,可以自己手动输入ppp值,这里默认的是2,下面分别对不同ppp值进行了聚类实验并可视化出来。

代码细节

"""@author: Ἥλιος
@CSDN:https://blog.csdn.net/qq_40793975/article/details/82348358"""
print(__doc__)import time
import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets
from sklearn.preprocessing import StandardScaler
from itertools import cycle, islice# 加载数据集(从文件中)
def load_Data1(filename):data_set = []with open(filename) as fi:for line in fi.readlines():cur_line = line.strip().split('\t')flt_line = []for i in cur_line:flt_line.append(float(i))data_set.append(flt_line)data_mat = np.mat(data_set)  # 转化为矩阵形式return data_mat# 加载数据集(自建数据集)
def load_Data2(n_samples=1500):# 带噪声的圆形数据noisy_circles = datasets.make_circles(n_samples=n_samples, factor=.5, noise=.05)# 带噪声的月牙形数据noisy_moons = datasets.make_moons(n_samples=n_samples, noise=.05)# 随机分布数据no_structure = np.random.rand(n_samples, 2), np.ones((1, n_samples), dtype=np.int32).tolist()[0]# 各向异性分布数据(Anisotropicly distributed data)random_state = 170X, y = datasets.make_blobs(n_samples=n_samples, random_state=random_state)transformation = [[0.6, -0.6], [-0.4, 0.8]]X_aniso = np.dot(X, transformation)aniso = (X_aniso, y)# 不同方差的气泡形数据(blobs with varied variances)varied = datasets.make_blobs(n_samples=n_samples, cluster_std=[1.0, 2.5, 0.5], random_state=random_state)# 相同方差的气泡形数据blobs = datasets.make_blobs(n_samples=n_samples, random_state=8)# 合并数据集data_sets = [noisy_circles, noisy_moons, no_structure, aniso, varied, blobs]cluster_nums = [2, 2, 3, 3, 3, 3]data_mats = []for i in range(data_sets.__len__()):X, y = data_sets[i]X = StandardScaler().fit_transform(X)  # 对数据集进行标准化处理X_mat = np.mat(X)y_mat = np.mat(y)data_mats.append((X_mat, y_mat))# 展示数据集plt.figure(figsize=(2.5, 14))plt.subplots_adjust(left=.02, right=.98, bottom=.001, top=.96, wspace=.05, hspace=.01)for i in range(data_sets.__len__()):X, y = data_sets[i]X = StandardScaler().fit_transform(X)  # 对数据集进行标准化处理plt.subplot(len(data_sets), 1, i+1)if i == 0:plt.title("Self-built Data Set", size=18)color = np.array(y) + 1plt.scatter(X[:, 0], X[:, 1], c=color, s=10)plt.xlim(-2.5, 2.5)plt.ylim(-2.5, 2.5)plt.show()return data_mats, cluster_nums# 计算样本点A与B间距离(欧氏距离)
def dist_Euclid(VecA, VecB):return np.sqrt(np.sum(np.power(VecA-VecB, 2)))# 对k个聚类中心随机初始化(随机选取数据集中的k个样本点)
def rand_initial_center1(data_mat, k):(m, n) = np.shape(data_mat)centroids = np.mat(np.zeros((k, n), dtype=np.float32))for i in range(k):index = int(np.random.rand()*m)centroids[i, :] = data_mat[index, :]return centroids# 对k个聚类中心随机初始化(在样本空间范围内随机选取)
def rand_initial_center2(data_mat, k):n = np.shape(data_mat)[1]centroids = np.mat(np.zeros((k, n), dtype=np.float32))for i in range(n):minJ = np.min(data_mat[:, i])maxJ = np.max(data_mat[:, i])centroids[:, i] = np.mat(np.random.rand(k, 1)*(maxJ - minJ)) + minJreturn centroids# 模糊c均值
def fuzzy_cMeans(data_mat, k, dist_measure=dist_Euclid, p=2.0):  # p-决定权重的影响程度 p大于等于1m, n = np.shape(data_mat)weight_mat = np.mat(np.random.rand(m, k), dtype=np.float32)centroids = np.mat(np.zeros((k, 2)), dtype=np.float32)cluster_assment = np.mat(np.zeros((m, 3)), dtype=np.float32)  # 存储每个样本点的簇隶属、簇隶属度和距离所属簇质心的长度cluster_changed = Truewhile cluster_changed:cluster_changed = Falsefor i in range(k):  # E步:更新质心centroids[i, :] = (np.power(weight_mat[:, i], p).T*data_mat)/np.sum(np.power(weight_mat[:, i], p), axis=0)for i in range(m):  # M步:更新权重sum_dist_iq = 0  # 用来更新权重的分母for q in range(k):dist_iq = dist_measure(data_mat[i, :], centroids[q, :])sum_dist_iq += pow((1/pow(dist_iq, 2)), (1/(p-1)))for j in range(k):dist_ij = dist_measure(data_mat[i, :], centroids[j, :])weight_mat[i, j] = pow((1/pow(dist_ij, 2)), (1/(p-1))) / sum_dist_iqfor i in range(m):  # 更新簇信息max_weight = 0max_weight_index = -1for j in range(k):cur_weight = weight_mat[i, j]if cur_weight > max_weight:max_weight = cur_weightmax_weight_index = jif max_weight_index != cluster_assment[i, 0]:cluster_changed = Truecluster_assment[i, 0] = max_weight_indexcluster_assment[i, 1] = max_weightcluster_assment[i, 2] = dist_measure(data_mat[i, :], centroids[max_weight_index, :])# # 静态显示# plt.scatter(data_mat[:, 0].T.A[0], data_mat[:, 1].T.A[0], c=cluster_assment[:, 0].T.A[0])# plt.scatter(centroids[:, 0].T.tolist()[0], centroids[:, 1].T.tolist()[0], s=100, c='red', marker='x')# plt.show()return centroids, cluster_assment# Fuzzy C-Means
data_mats, cluster_nums = load_Data2()
plt.figure(figsize=(2.5, 14))
plt.subplots_adjust(left=.02, right=.98, bottom=.001, top=.96, wspace=.05, hspace=.01)
for i in range(len(data_mats)):data_mat = data_mats[i][0]  # 获取自建数据集k = cluster_nums[i]  # 获取自建数据集的簇标记t0 = time.time()  # 计算运行时间centroids, cluster_assment = fuzzy_cMeans(data_mat, k, p=1.05)t1 = time.time()color = np.multiply(cluster_assment[:, 0].A + 1, cluster_assment[:, 1].A).T[0]  # 获得渐进色图plt.subplot(len(data_mats), 1, i + 1)if i == 0:plt.title("Fuzzy c-Means(Self-programming Implementation)", size=10)im = plt.scatter(data_mat[:, 0].T.A[0], data_mat[:, 1].T.A[0], c=color, s=10, alpha=0.5)plt.scatter(centroids[:, 0].T.tolist()[0], centroids[:, 1].T.tolist()[0], s=100, c='red', marker='x')plt.xlim(-2.5, 2.5)plt.ylim(-2.5, 2.5)plt.text(.99, .01, ('%.2fs' % (t1 - t0)).lstrip('0'), transform=plt.gca().transAxes, size=15,horizontalalignment='right')plt.colorbar(im)
plt.show()

算法效果

  上面两附图从左至右依次是p=1.05p=1.05p=1.05和p=2p=2p=2时的聚类效果,可以看出随着ppp值的增大,聚类簇越来越模糊,当ppp近似等于1时,该算法类似于K-Means,当ppp足够大时,聚类效果会变得非常不明显,大家可以去试一下,另外,这里为了方便可视化,将簇标记改为1,2,3,...1,2,3,...1,2,3,...,而不是0,1,2,...0,1,2,...0,1,2,...,下图也是如此。

  上图从左至右依次是:自建数据集和p=1.05p=1.05p=1.05时的模糊c均值,可以以清楚的看出,两个簇边界上的点以某一概率隶属于某个簇,且该算法的时间复杂度高于K-Means,还有一点需要注意的是,当簇之间的距离比较远时,该算法很容易陷入局部最优。

Fuzzy Clustering详解相关推荐

  1. 谱聚类(Spectral Clustering)详解

    原文地址为: 谱聚类(Spectral Clustering)详解 谱聚类(Spectral Clustering)详解 谱聚类(Spectral Clustering, SC)是一种基于图论的聚类方 ...

  2. Subspace Clustering详解(附带CLIQUE算法详解)

    Subspace Clustering详解 第二十四次写博客,本人数学基础不是太好,如果有幸能得到读者指正,感激不尽,希望能借此机会向大家学习.这一篇作为密度聚类算法族的第三篇,主要是介绍一种用来发现 ...

  3. 代码分析 | 单细胞转录组clustering详解

    聚类可视化 NGS系列文章包括NGS基础.转录组分析 (Nature重磅综述|关于RNA-seq你想知道的全在这).ChIP-seq分析 (ChIP-seq基本分析流程).单细胞测序分析 (重磅综述: ...

  4. 【论文必用】模糊C均值聚类的简单介绍、复现及Python代码详解、聚类可视化图的绘制过程详解!

    详解模糊C均值聚类 一.聚类 二.模糊C均值聚类 三.模糊C均值聚类的Python实现 四.参考链接 一.聚类 聚类的定义: 将物理或抽象对象的集合分成由类似的对象组成的多个类的过程被称为聚类.由聚类 ...

  5. halcon例程讲解_跟我学机器视觉-HALCON学习例程中文详解-开关引脚测量

    跟我学机器视觉-HALCON学习例程中文详解-开关引脚测量 This example program demonstrates the basic usage of a measure object. ...

  6. rocketmq 消息指定_详解RocketMQ不同类型的消费者

    原标题:详解RocketMQ不同类型的消费者 云栖君导读:本文节选自云栖社区系列丛书<RocketMQ原理与实战解析>,作者:阿里巴巴数据专家杨开元.本节将重点讲解RocketMQ不同类型 ...

  7. lucene.NET详细使用与优化详解

    lucene.NET详细使用与优化详解 http://www.cnblogs.com/qq4004229/archive/2010/05/21/1741025.html http://www.shan ...

  8. [Python从零到壹] 十一.数据分析之Numpy、Pandas、Matplotlib和Sklearn入门知识万字详解(1)

    欢迎大家来到"Python从零到壹",在这里我将分享约200篇Python系列文章,带大家一起去学习和玩耍,看看Python这个有趣的世界.所有文章都将结合案例.代码和作者的经验讲 ...

  9. 聚类分析与相关算法(Kmeans等)详解

    聚类分析与相关算法详解 1 距离度量 1.1欧几里得距离定义 1.2其他距离度量的补充 1.3余弦距离 1.4简单匹配系数 1.5jaccard系数 1.6海明距离 2 聚类问题 2.1非监督学习中的 ...

  10. 随笔分类 - HALCON学习例程中文详解

    from: https://www.cnblogs.com/chita/category/563492.html 随笔分类 - HALCON学习例程中文详解 HALCON学习例程中文详解 跟我学机器视 ...

最新文章

  1. cocoaPods安装、更新第三方库
  2. 我是如何在SQLServer中处理每天四亿三千万记录的
  3. JVM资源分析工具jprofiler使用简介
  4. Android-Binder 简析
  5. apache druid 与kafka整合使用
  6. 属格-my father's car和whose_32
  7. 【漏洞复现】局域网 ARP 中间人攻击 获取他人账号密码
  8. 英特尔一口气发布了三款处理器、两款存储、一款以太网适配器
  9. VSCode搭建vue前端开发工程的配置文件-launch.json
  10. Android学习路(正在写)
  11. C语言开发简单的学生成绩管理系统(附源码)
  12. 史上最强单片机科普,看完给跪了!
  13. 【UWB】UWB基本定位原理
  14. java项目之人事管理系统|HRM(java毕业设计Struts2、mybatis框架项目
  15. 计算机论文中期考核报告,(硕士学位论文中期考核报告范文.doc
  16. Java的class是什么意思?
  17. 饥荒服务器物品指令,饥荒控制台指令大全物品大全服务器管理命令大全.docx
  18. java mail 使用:exchange邮箱
  19. 家用汽车维修3:基于OBDII的故障分析
  20. Win10卸载CUDA 10.2

热门文章

  1. The Open Group正式发布《The Open Group IT4IT参考架构版本 2.1》
  2. VS2003安装方法----转载
  3. 魔方机器人大赛——魔方步骤转换算法
  4. 用Cython加密Python代码这么简单
  5. 机器学习练习 6 - Support Vector Machines(支持向量机)
  6. 第二篇:STM32F7 + RT-Thread + ESP8266
  7. 「Remmina」- 远程桌面客户端(SSH、SFTP、VNC、Windows Remote Desktop、...) @20210402
  8. aardio - 仿安装界面进行窗口高度调节的方法
  9. win10便签常驻桌面_做备忘录,用win10自带的便笺工具就可以了,免费又方便
  10. LetAllLinesOfCodeSpeak_杂记