第三节3:类K-Means算法之模糊K-均值算法(FCM算法)

Posted 快乐江湖

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第三节3:类K-Means算法之模糊K-均值算法(FCM算法)相关的知识,希望对你有一定的参考价值。

文章目录

一:算法思想

  • 硬聚类:传统K-均值算法中,每个对象只能从属于所有类别中的一类,称之为硬聚类。这种聚类方法会带来一个问题:所有的对象对于计算聚类中心的贡献都是相同的,也就是说,对于从属于一个类的所有元素,算法是无法将其区分开来的。这种分配方式在处理一些复杂数据集合(例如数据有重叠)会造成类别指派不合理
  • 软聚类:一个对象可以从属于多个类别的聚类方法

模糊K-均值算法(FCM算法):对于每个类别,对象都对应一个取值范围在[0,1]的数值,它表示该对象从属于某一类别的可能性。一个对象对于所有类别的对应取值和应该为1。在更新簇中心点的过程中,该数值就反映了该对象对于这一类的贡献程度,根据贡献程度的不同,反映出对象更倾向于分配到哪个类别中

FCM算法与K-均值算法的目标函数类似

J m = ∑ k = 1 N ∑ j = 1 u i j m ∣ ∣ x i − c j ∣ ∣ 2 , 1 ≤ m < ∞ J_m=\\sum_k=1^N\\sum_j=1u_ij^m||x_i-c_j||^2,1\\leq m <\\infty Jm=k=1Nj=1uijmxicj21m<

其中

  • m ( > 1 ) m(>1) m(>1):模糊系数
  • N N N:样本数
  • C C C:聚类中心数
  • c j c_j cj:第 j j j个聚类中心
  • x i x_i xi:第 i i i个样本
  • u i j u_ij uij:样本 x i x_i xi对聚类中心 c j c_j cj的隶属度,也即 x i x_i xi属于 c j c_j cj的概率。显然有 ∑ j = 1 C u i j \\sum\\limits_j=1^Cu_ij j=1Cuij=1

FCM算法通过更新 u i j u_ij uij c j c_j cj来迭代优化目标函数

u i j = 1 ∑ k = 1 C ( ∣ ∣ x i − c j ∣ ∣ ∣ ∣ x i − c k ∣ ∣ ) 2 m − 1 u_ij=\\frac1\\sum\\limits_k=1^C(\\frac||x_i-c_j||||x_i-c_k||)^\\frac2m-1 uij=k=1C(xickxicj)m121

c j = ∑ i = 1 N u i j m x i ∑ i = 1 N u i j m c_j=\\frac\\sum\\limits_i=1^Nu_ij^mx_i\\sum\\limits__i=1^Nu_ij^m cj=i=1Nuijmi=1Nuijmxi

FCM算法的收敛条件一般设置为两次迭代过程中计算的 S S E SSE SSE差值,其中 ξ \\xi ξ是预先设定好的容忍误差,当两次迭代过程中计算的 S S E SSE SSE差值小于该预设值时,判定算法收敛

E ( t ) = ∣ ∣ S S E t − S S E t − 1 ∣ ∣ < ξ E(t)=||SSE^t-SSE^t-1||<\\xi E(t)=SSEtSSEt1<ξ

二:算法流程

  1. 初始化隶属度矩阵 U 0 U^0 U0:若有 N N N个样本,指定类别个数为 C C C,则隶属度矩阵应为 N N N× C C C
  2. 根据公式更新聚类中心 c j c_j cj
  3. 根据公式更新隶属度矩阵(注意保存更新前的隶属度矩阵)
  4. 判断是否收敛,若收敛则停止迭代,反之返回步骤2

三:Python实现

import numpy as np
import copy

#  欧氏距离
def distance(data, centroid):
    return np.sqrt(np.sum(np.power(data-centroid, 2)))


def fcm(data_set, m, k, eps):
    example_nums = np.shape(data_set)[0]  # 样本数量
    cluster = np.zeros(example_nums)

    # 初始化隶属度矩阵
    random_mat = np.random.rand(example_nums, k)  # 生成随机矩阵
    random_mat_sum = 1 / np.sum(random_mat, axis=1)  # 求每一行的和
    membership_mat = np.multiply(random_mat.T, random_mat_sum)  # 使隶属度矩阵每一行和为1
    membership_mat = membership_mat.T
    membership_mat_old = np.zeros((example_nums, k))  # 便于迭代

    # 进行迭代,更新隶属度矩阵和聚类中心
    while True:
        centorids = np.empty((k, np.shape(data_set)[1]))
        # 由公式计算簇中心
        for j in range(k):
            centorids[j] = np.dot(membership_mat[:, j]**m, data_set) / (np.sum(membership_mat[:, j]**m))
        membership_mat_old = membership_mat.copy()

        # 根据公式计算新的隶属度矩阵
        for i in range(example_nums):
            for j in range(k):
                for z in range(k):
                    membership_mat[i, j] += ((distance(data_set[i], centorids[j])) / distance(data_set[i], centorids[z])) ** (2 / (m-1))
        membership_mat = 1 / membership_mat

        #  判断是否收敛
        if np.max(np.abs(membership_mat - membership_mat_old)) < eps:
            cluster = np.argmax(membership_mat, axis=1)
            return centorids, cluste
            

四:效果展示

import pandas as pd
import matplotlib.pyplot as plt
import FCM
import numpy as np

Iris_types = ['Iris-setosa', 'Iris-versicolor', 'Iris-virginica']  # 花类型
Iris_data = pd.read_csv('dataSet/Iris.csv')
# x_axis = 'PetalLengthCm'  # 花瓣长度
# y_axis = 'PetalWidthCm'   # 花瓣宽度
x_axis = 'SepalLengthCm'  # 花萼长度
y_axis = 'SepalWidthCm'  # 花萼宽度

examples_num = Iris_data.shape[0]  # 样本数量
train_data = Iris_data[[x_axis, y_axis]].values.reshape(examples_num, 2)  # 整理数据

# 归一化
min_vals = train_d

以上是关于第三节3:类K-Means算法之模糊K-均值算法(FCM算法)的主要内容,如果未能解决你的问题,请参考以下文章

第三节1:类K-Means算法之K-中心点(K-Medoid)和PAM算法

第三节2:类K-Means算法之K-中值算法(K-medians)

大数据十大经典算法之k-means

数据挖掘十大算法之K-Means K均值聚类算法

聚类算法之K均值算法(k-means)的Python实现

K-Means 聚类原理