Fuzzy C-Means Clustering(模糊C均值)

别看了 有错的 我懒得改了
强推https://www.bilibili.com/video/BV18J411a7yY?t=591
看完你还不会那我也没办法了









\

算法原理

  模糊c-均值聚类算法 fuzzy c-means algorithm (FCMA)或称(FCM)。在众多模糊聚类算法中,模糊C-均值(FCM)算法应用最广泛且较成功,它通过优化目标函数得到每个样本点对所有类中心的隶属度,从而决定样本点的类属以达到自动对样本数据进行分类的目的。
  先来讲讲这个算法的名字噢,什么叫Fuzzy,什么叫模糊呢,在经典的集合理论,一个元素是否属于集合,只有真或者假两种情况,也可以说只有0和1两种情况,0为假1为真。比如我们想要定义一个集合表示“年轻人”,那么我们需要设置一个阈值,当一个人的年龄小于这阈值的时候,就认为这个人属于这个集合,反之则不属于。假如用A表示年轻人这个集合,以20岁为阈值。则这个集合的隶属度函数可以表示如下:
μ A ( z ) = { 1 , z < 20 0 , z ≥ 20 \mu_A(z)= \begin{cases} 1, z < 20 \\ 0, z \geq 20 \end{cases} μA(z)={1,z<200,z20
上面的公式可以用下面左图表示:
在这里插入图片描述
  使用经典的集合理论,我们会面临着一些实际的问题,比如当一个人的年龄是20岁零1秒的时候,这个人就不再是年轻人了,这种粗暴的分类方式,在实际中并不实用。因此我们需要有过渡的函数来描述这个情况。上图中右边的图提供了一种解决方法,图中的斜线表示年龄的过渡。
于是就可以定义三个隶属度函数来确定年龄与三个模糊子集的关系:
μ A ( z ) = { 1 , z ≤ 20 30 − z 10 , 20 < z < 30 0 , z ≥ 30 \mu_A(z)= \begin{cases} 1, z \leq 20 \\ \frac {30-z}{10}, 20< z < 30 \\ 0, z \geq 30 \end{cases} μA(z)=1,z201030z,20<z<300,z30
  OK,模糊的概念大概懂了,那么C-Means的C又是什么东西呢,额这个,好像没有什么含义,就像K-Means的k一样,只是代表聚类的个数,可能是cluster的c?又可能是模糊控制器(Fuzzy Controller)里的c。但是这个无关紧要,懂得模糊的概念就好了。

  然后我们来正式说一下模糊c-均值是什么。模糊c-均值是一种允许一个数据属于一个或多个簇的方法,它不同于K-Means一个数据只能属于一个簇,它自发明以来广泛应用于模式识别中。
  那么这种算法它的优化目标、目标函数是什么呢?看下面的公式:
m i n    J m = ∑ i = 1 N ∑ j = 1 C μ i j m ∣ ∣ x i − v j ∣ ∣ 2 , 1 < m < ∞ s . t .    ∑ j = 1 C μ i j = 1 (1) min\ \ J_m=\sum_{i=1}^N \sum_{j=1}^C \mu_{ij}^m||x_i-v_j||^2, 1<m<\infty \tag1\\ s.t.\ \ \sum_{j=1}^C \mu_{ij}=1 min  Jm=i=1Nj=1Cμijmxivj2,1<m<s.t.  j=1Cμij=1(1)
符号定义:
N : N: N: 是样本总个数
C : C: C: 簇心数目,就是一开始输入的参数,你想这N个数据分成3份就将C置为3,5份就置为5,懂吧
μ : \mu: μ: 一个 N × C N\times C N×C的矩阵,其中 μ i j \mu_{ij} μij x i x_i xi属于类别 j j j的隶属度
v j : v_j: vj: j j j个类别的中心
m : m: m: C C C一样是自己设置的参数,不同的 m m m会有不同的聚类效果,需要根据不同的数据集进行调节

这个公式呢就是说每一个数据 x i x_i xi到每一个聚类中心 v j v_j vj距离的二范式再乘上 x i x_i xi属于类别 j j j的隶属度的 m m m次方,要最小化它们的总和,直观一点就是希望每一个数据尽可能与它们所属的聚类中心接近。

  那么就开始求如何使这个函数最小化了,(众所周知),求最小嘛,基本操作将它对某个变量求偏导,令偏导结果为零即可,因为有一个等式约束,我们先引入拉格朗日乘子 λ \lambda λ,于是原式可以写成:

m i n    J = ∑ i = 1 N ∑ j = 1 C μ i j m ∣ ∣ x i − v j ∣ ∣ 2 − λ ( ∑ j = 1 C μ i j − 1 ) (2) min\ \ J=\sum_{i=1}^N \sum_{j=1}^C \mu_{ij}^m||x_i-v_j||^2 -\lambda(\sum_{j=1}^C \mu_{ij}-1) \tag2 min  J=i=1Nj=1Cμijmxivj2λ(j=1Cμij1)(2)
然后对 λ \lambda λ求偏导并令其为零,得:
∂ J ∂ λ = ∑ j = 1 C μ i j − 1 = 0 (3) \frac{\partial J}{\partial\lambda}=\sum_{j=1}^C \mu_{ij}-1=0 \tag3 λJ=j=1Cμij1=0(3)
再对 μ i j \mu_{ij} μij求偏导并令其为零,得:
∂ J ∂ μ i j = m ⋅ μ i j m − 1 ∣ ∣ x i − v j ∣ ∣ 2 − λ = 0 (4) \frac{\partial J}{\partial\mu_{ij}}=m\cdot \mu_{ij}^{m-1} ||x_i-v_j||^2 -\lambda=0 \tag4 μijJ=mμijm1xivj2λ=0(4)
由(4)可得
μ i j = ( λ m ∣ ∣ x i − v j ∣ ∣ 2 ) 1 m − 1 (5) \mu_{ij}=\left( \frac{\lambda}{m||x_i-v_j||^2}\right)^\frac{1}{m-1} \tag5 μij=(mxivj2λ)m11(5)
将(5)代入(3)得:
∑ j = 1 C ( λ m ∣ ∣ x i − v j ∣ ∣ 2 ) 1 m − 1 − 1 = 0 ∑ j = 1 C ( λ m ) 1 m − 1 ( 1 ∣ ∣ x i − v j ∣ ∣ 2 ) 1 m − 1 − 1 = 0 ( λ m ) 1 m − 1 ∑ j = 1 C ( 1 ∣ ∣ x i − v j ∣ ∣ 2 ) 1 m − 1 − 1 = 0 \begin{aligned} \sum_{j=1}^C \left( \frac{\lambda}{m||x_i-v_j||^2}\right)^\frac{1}{m-1}-1 &=0 \\ \sum_{j=1}^C \left( \frac{\lambda}{m}\right)^\frac{1}{m-1} \left( \frac1{||x_i-v_j||^2}\right)^\frac{1}{m-1}-1 &=0 \\ \left( \frac{\lambda}{m}\right)^\frac{1}{m-1}\sum_{j=1}^C \left( \frac1{||x_i-v_j||^2}\right)^\frac{1}{m-1}-1 &=0 \end{aligned} j=1C(mxivj2λ)m111j=1C(mλ)m11(xivj21)m111(mλ)m11j=1C(xivj21)m111=0=0=0
于是我们就可以得到:
( λ m ) 1 m − 1 = 1 ∑ j = 1 C ( 1 ∣ ∣ x i − v j ∣ ∣ 2 ) 1 m − 1 (6) \left( \frac{\lambda}{m}\right)^\frac{1}{m-1} =\frac1{\sum_{j=1}^C \left( \frac1{||x_i-v_j||^2}\right)^\frac{1}{m-1}} \tag6 (mλ)m11=j=1C(xivj21)m111(6)
将(6)再代入(4)得:
μ i j = 1 ∑ k = 1 C ( 1 ∣ ∣ x i − v k ∣ ∣ 2 ) 1 m − 1 ( 1 ∣ ∣ x i − v j ∣ ∣ 2 ) 1 m − 1 = 1 ∑ k = 1 C ( ∣ ∣ x i − v j ∣ ∣ 2 ∣ ∣ x i − v k ∣ ∣ 2 ) 1 m − 1 (7) \mu_{ij} = \frac1{\sum_{k=1}^C \left( \frac1{||x_i-v_k||^2}\right)^\frac{1}{m-1}} \left( \frac1{||x_i-v_j||^2}\right)^\frac{1}{m-1} = \frac1{\sum_{k=1}^C \left( \frac{||x_i-v_j||^2}{||x_i-v_k||^2}\right)^\frac{1}{m-1}} \tag7 μij=k=1C(xivk21)m111(xivj21)m11=k=1C(xivk2xivj2)m111(7)

再对 v i v_i vi求偏导并令其为零,得:
∂ J ∂ v i = − 2 ∑ i = 1 N μ i j m ( x i − v j ) (8) \frac{\partial J}{\partial v_i}=-2\sum_{i=1}^N\mu_{ij}^m(x_i-v_j) \tag8 viJ=2i=1Nμijm(xivj)(8)
v j = ∑ i = 1 N μ i j m x i ∑ i = 1 N μ i j m (9) v_j=\frac{\sum_{i=1}^N\mu_{ij}^mx_i}{\sum_{i=1}^N\mu_{ij}^m}\tag9 vj=i=1Nμijmi=1Nμijmxi(9)
式(9)即为聚类中心 v j v_j vj的更新公式。

总结一下模糊C均值的更新公式如下:
μ i j = 1 ∑ k = 1 C ( ∣ ∣ x i − v j ∣ ∣ 2 ∣ ∣ x i − v k ∣ ∣ 2 ) 1 m − 1          v j = ∑ i = 1 N μ i j m x i ∑ i = 1 N μ i j m \mu_{ij}=\frac1{\sum_{k=1}^C \left( \frac{||x_i-v_j||^2}{||x_i-v_k||^2}\right)^\frac{1}{m-1}}\ \ \ \ \ \ \ \ v_j=\frac{\sum_{i=1}^N\mu_{ij}^mx_i}{\sum_{i=1}^N\mu_{ij}^m} μij=k=1C(xivk2xivj2)m111        vj=i=1Nμijmi=1Nμijmxi

算法步骤

  1. 确定类别数C,参数m,和迭代停止误差 ε \varepsilon ε以及最大迭代次数T
  2. 初始化聚类中心 V = { v 1 , v 2 , . . . , v C } V=\lbrace{v_1,v_2,...,v_C\rbrace} V={v1,v2,...,vC}
  3. For t=1 to T:
      Calculate U t U_t Ut with V t − 1 V_{t-1} Vt1 and (7)
      Calculate V t V_t Vt with U t U_t Ut and (9)
      If E t = ∣ ∣ V t − V t − 1 ∣ ∣ e r r ≤ ε E_t=||V_t-V_{t-1}||_{err} \leq \varepsilon Et=VtVt1errε
      Stop and put ( U f , V f ) = ( U t , V t ) (U_f, V_f)=(U_t, V_t) (Uf,Vf)=(Ut,Vt); Else
    Next t

举个例子

我们考虑FCM在一维下应用的情况。 使用二十个数据和三个聚类来初始化算法并计算U矩阵。 下图显示了每个基准面和每个聚类的成员隶属度。 根据隶属函数,数据的颜色是最近的群集的颜色。

在这里插入图片描述

在上图所示的仿真中,我们使用了模糊系数 m = 2 m = 2 m=2,其中模糊分布取决于簇的特定位置。 因为尚未执行任何步骤,所以无法很好地识别群集。 现在可以运行算法,直到验证停止条件为止。 下图显示了在第8步达到的最终条件,其中 m = 2 m = 2 m=2 ε = 0.3 \varepsilon= 0.3 ε=0.3

在这里插入图片描述
不同的初始化会导致算法的不同演化,它们可以收敛到相同的结果,但是迭代步骤的数量就不一样了。

python实现FCM对iris数据集进行聚类
import numpy as np
from sklearn import datasets
import matplotlib.pyplot as plt
from sklearn.decomposition import PCA
import scipy.io as scio

C = 3
m = 2
# T = 5000
# EPS = 0.0000001
colors = ['r', 'b', 'g']

def norm2(x):
    x = np.mat(x)
    return np.dot(x.reshape(1, -1), x.reshape(-1, 1))


def cal(x_i, c_j, c_k):
    x_i = np.mat(x_i).reshape(1, -1)
    c_j = np.mat(c_j).reshape(1, -1)
    c_k = np.mat(c_k).reshape(1, -1)
    return float(np.power(norm2(x_i-c_j)/norm2(x_i-c_k), 2.0/(m-1)))


def fuzzy_c_means(data, m, C, EPS, T):
    data = np.mat(data)
    n, p = data.shape
    V = [np.random.random([1, p]) for _ in range(C)]
    U = [[0 for i in range(C)] for j in range(n)]
    for i in range(n):
        for j in range(C):
            down = 0
            for k in range(C):
                down += cal(data[i], V[j], V[k])
            U[i][j] = 1.0/down
    for _ in range(T):
        for j in range(C):
            down = 0
            V[j] = np.zeros([1, p])
            for i in range(n):
                u_i_j_m = pow(U[i][j], m)
                V[j] += data[i]*u_i_j_m
                down += u_i_j_m
            V[j] /= down

        upgrade = 0
        for i in range(n):
            for j in range(C):
                down = 0
                for k in range(C):
                    down += cal(data[i], V[j], V[k])
                tmp = 1.0 / down
                upgrade += abs(U[i][j]-tmp)
                U[i][j] = tmp

        if upgrade < EPS:
            break
    for i in range(n):
        idx = np.argmax(U[i])
        plt.scatter(float(data[i][:, 0]), float(data[i][:, 1]), c=colors[idx])
    plt.show()


if __name__ == '__main__':
    a = datasets.load_iris()
    data = a['data']
    pca = PCA(n_components=2)
    data = pca.fit_transform(data)
    fuzzy_c_means(data=data, m=2, C=C, EPS=1e-7, T=5000)


原数据通过PCA降到二维空间中的分布情况如下图所示
在这里插入图片描述
通过FCM进行聚类后的结果如下图所示
在这里插入图片描述

参考博客

http://home.deib.polimi.it/matteucc/Clustering/tutorial_html/cmeans.html
https://blog.csdn.net/einsdrw/article/details/37930331

  • 4
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值