第三节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=1∑Nj=1∑uijm∣∣xi−cj∣∣2,1≤m<∞
其中
- 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=1∑Cuij=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=1∑C(∣∣xi−ck∣∣∣∣xi−cj∣∣)m−121
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=1∑Nuijmi=1∑Nuijmxi
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)=∣∣SSEt−SSEt−1∣∣<ξ
二:算法流程
- 初始化隶属度矩阵 U 0 U^0 U0:若有 N N N个样本,指定类别个数为 C C C,则隶属度矩阵应为 N N N× C C C
- 根据公式更新聚类中心 c j c_j cj
- 根据公式更新隶属度矩阵(注意保存更新前的隶属度矩阵)
- 判断是否收敛,若收敛则停止迭代,反之返回步骤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算法