FCM聚類演算法詳解(Python實現iris資料集)
參考:https://blog.csdn.net/on2way/article/details/47087201
模糊C均值(Fuzzy C-means)演算法簡稱FCM演算法,是一種基於目標函式的模糊聚類演算法,主要用於資料的聚類分析。理論成熟,應用廣泛,是一種優秀的聚類演算法。本文關於FCM演算法的一些原理推導部分介紹,加上自己的理解和在課題專案中的應用以文字的形式呈現出來。
首先介紹一下模糊這個概念,所謂模糊就是不確定,確定性的東西就是資訊量很小的東西,而不確定性的東西就說很像什麼,這種資訊量很大。比如說把20歲作為年輕不年輕的標準,那麼一個人21歲按照確定性的劃分就屬於不年輕,而我們印象中的觀念是21歲也很年輕,這個時候可以模糊一下,認為21歲有0.9分像年輕,有0.1分像不年輕,這裡0.9與0.1不是概率,而是一種相似的程度,把這種一個樣本屬於結果的這種相似的程度稱為樣本的隸屬度,一般用u表示,表示一個樣本相似於不同結果的一個程度指標。
基於此,假定資料集為X,如果把這些資料劃分成c類的話,那麼對應的就有c個類中心為C,每個樣本j屬於某一類i的隸屬度為uij,那麼定義一個FCM目標函式(1)及其約束條件(2)如下所示:
看一下目標函式(式1)而知,由相應樣本的隸屬度與該樣本到各個類中心的距離相乘組成的,m是一個隸屬度的因子,個人理解為屬於樣本的輕緩程度,就像與這種一樣。式(2)為約束條件,也就是一個樣本屬於所有類的隸屬度之和要為1。觀察式(1)可以發現,其中的變數有,並且還有約束條件,那麼如何求這個目標函式的極值呢?
這裡首先採用拉格朗日乘數法將約束條件拿到目標函式中去,前面加上係數,並把式(2)的所有j展開,那麼式(1)變成下列所示:
現在要求該式的目標函式極值,那麼分別對其中的變數uij、ci求導數,首先對uij求導。
分析式(3),先對第一部分的兩級求和的uij求導,對求和形式下如果直接求導不熟悉,可以把求和展開如下:
這個矩陣要對uij求導,可以看到只有uij對應的保留,其他的所有項中因為不含有uijuij,所以求導都為0。那麼對uij求導後就為。
再來看後面那個對uij求導,同樣把求和展開,再去除和uij不相關的(求導為0),那麼只剩下這一項:,它對uij求導就是λj了。
那麼最終J對uij的求導結果並讓其等於0就是:
這個式子化簡下,將uij解出來就是:
進一步:
要解出uij則需要把λj去掉才行。這裡重新使用公式(2)的約束條件,並把算出來的uij代入式(2)中有:
這樣就有(其中把符號i換成k):
把這個重新代入到式(4)中有:
好了,式子(5)就是最終的uij迭代公式。
下面在來求J對ci的導數。由公式(2)可以看到只有這一部分裡面含有ci,對其二級求和展開如前面所示的,那麼它對ci的導數就是:
即:
好了,公式(6)就是類中心的迭代公式。
我們發現uij與ci是相互關聯的,彼此包含對方,有一個問題就是在fcm演算法開始的時候既沒有uij也沒有ci,那要怎麼求解呢?很簡單,程式開始的時候我們隨便賦值給uij或者ci其中的一個,只要數值滿足條件即可。然後就開始迭代,比如一般的都賦值給uij,那麼有了uij就可以計算ci,然後有了ci又可以計算uij,反反覆覆,在這個過程中還有一個目標函式J一直在變化,逐漸趨向穩定值。那麼當J不在變化的時候就認為演算法收斂到一個比較好的解了。可以看到uij和ci在目標函式J下似乎構成了一個正反饋一樣,這一點很像EM演算法,先E在M,有了M在E,在M直至達到最優。
公式(5),(6)是演算法的關鍵。現在來重新從巨集觀的角度來整體看看這兩個公式,先看(5),在寫一遍
假設看樣本集中的樣本1到各個類中心的隸屬度,那麼此時j=1,i從1到c類,此時上述式中分母裡面求和中,分子就是這個點相對於某一類的類中心距離,而分母是這個點相對於所有類的類中心的距離求和,那麼它們兩相除表示什麼,是不是表示這個點到某個類中心在這個點到所有類中心的距離和的比重。當求和裡面的分子越小,是不是說就越接近於這個類,那麼整體這個分數就越大,也就是對應的uij就越大,表示越屬於這個類,形象的圖如下:
再來巨集觀看看公式(6),考慮當類i確定後,式(6)的分母求和其實是一個常數,那麼式(6)可以寫成:
這是類中心的更新法則。說這之前,首先讓我們想想kmeans的類中心是怎麼更新的,一般最簡單的就是找到屬於某一類的所有樣本點,然後這一類的類中心就是這些樣本點的平均值。那麼FCM類中心怎麼樣了?看式子可以發現也是一個加權平均,類i確定後,首先將所有點到該類的隸屬度u求和,然後對每個點,隸屬度除以這個和就是所佔的比重,乘以xj就是這個點對於這個類i的貢獻值了。畫個形象的圖如下:
由上述的巨集觀分析可知,這兩個公式的迭代關係式是這樣的也是可以理解的。
資料集用的是iris資料,有需要資料的朋友可以呼叫sklearn.load_iris。或者下載下來
from pylab import *
from numpy import *
import pandas as pd
import numpy as np
import operator
import math
import matplotlib.pyplot as plt
import random
# 資料儲存在.csv檔案中
df_full = pd.read_csv("iris.csv")
columns = list(df_full.columns)
features = columns[:len(columns) - 1]
# class_labels = list(df_full[columns[-1]])
df = df_full[features]
# 維度
num_attr = len(df.columns) - 1
# 分類數
k = 3
# 最大迭代數
MAX_ITER = 100
# 樣本數
n = len(df) # the number of row
# 模糊引數
m = 2.00
# 初始化模糊矩陣U
def initializeMembershipMatrix():
membership_mat = list()
for i in range(n):
random_num_list = [random.random() for i in range(k)]
summation = sum(random_num_list)
temp_list = [x / summation for x in random_num_list] # 首先歸一化
membership_mat.append(temp_list)
return membership_mat
# 計算類中心點
def calculateClusterCenter(membership_mat):
cluster_mem_val = zip(*membership_mat)
cluster_centers = list()
cluster_mem_val_list = list(cluster_mem_val)
for j in range(k):
x = cluster_mem_val_list[j]
xraised = [e ** m for e in x]
denominator = sum(xraised)
temp_num = list()
for i in range(n):
data_point = list(df.iloc[i])
prod = [xraised[i] * val for val in data_point]
temp_num.append(prod)
numerator = map(sum, zip(*temp_num))
center = [z / denominator for z in numerator] # 每一維都要計算。
cluster_centers.append(center)
return cluster_centers
# 更新隸屬度
def updateMembershipValue(membership_mat, cluster_centers):
# p = float(2/(m-1))
data = []
for i in range(n):
x = list(df.iloc[i]) # 取出檔案中的每一行資料
data.append(x)
distances = [np.linalg.norm(list(map(operator.sub, x, cluster_centers[j]))) for j in range(k)]
for j in range(k):
den = sum([math.pow(float(distances[j] / distances[c]), 2) for c in range(k)])
membership_mat[i][j] = float(1 / den)
return membership_mat, data
# 得到聚類結果
def getClusters(membership_mat):
cluster_labels = list()
for i in range(n):
max_val, idx = max((val, idx) for (idx, val) in enumerate(membership_mat[i]))
cluster_labels.append(idx)
return cluster_labels
def fuzzyCMeansClustering():
# 主程式
membership_mat = initializeMembershipMatrix()
curr = 0
while curr <= MAX_ITER: # 最大迭代次數
cluster_centers = calculateClusterCenter(membership_mat)
membership_mat, data = updateMembershipValue(membership_mat, cluster_centers)
cluster_labels = getClusters(membership_mat)
curr += 1
print(membership_mat)
return cluster_labels, cluster_centers, data, membership_mat
def xie_beni(membership_mat, center, data):
sum_cluster_distance = 0
min_cluster_center_distance = inf
for i in range(k):
for j in range(n):
sum_cluster_distance = sum_cluster_distance + membership_mat[j][i] ** 2 * sum(
power(data[j, :] - center[i, :], 2)) # 計算類一致性
for i in range(k - 1):
for j in range(i + 1, k):
cluster_center_distance = sum(power(center[i, :] - center[j, :], 2)) # 計算類間距離
if cluster_center_distance < min_cluster_center_distance:
min_cluster_center_distance = cluster_center_distance
return sum_cluster_distance / (n * min_cluster_center_distance)
labels, centers, data, membership = fuzzyCMeansClustering()
print(labels)
print(centers)
center_array = array(centers)
label = array(labels)
datas = array(data)
# Xie-Beni聚類有效性
print("聚類有效性:", xie_beni(membership, center_array, datas))
xlim(0, 10)
ylim(0, 10)
# 做散點圖
fig = plt.gcf()
fig.set_size_inches(16.5, 12.5)
f1 = plt.figure(1)
plt.scatter(datas[nonzero(label == 0), 0], datas[nonzero(label == 0), 1], marker='o', color='r', label='0', s=10)
plt.scatter(datas[nonzero(label == 1), 0], datas[nonzero(label == 1), 1], marker='+', color='b', label='1', s=10)
plt.scatter(datas[nonzero(label == 2), 0], datas[nonzero(label == 2), 1], marker='*', color='g', label='2', s=10)
plt.scatter(center_array[:, 0], center_array[:, 1], marker='x', color='m', s=30)
plt.show()
效果一般啊。。。
竟然聚類的結果感覺和剛開始的好像差不多啊。不會被聚成一類?但是回過頭來看這個演算法,本身要得到的結果就是隸屬度u(也就是各樣本的權重)以及Ci聚類中心,有幾個聚類中心就有幾類,可以看到,還是挺準的。
相關文章
- 機器學習經典聚類演算法 —— k-均值演算法(附python實現程式碼及資料集)機器學習聚類演算法Python
- R語言實現K-Means演算法資料集irisR語言演算法
- 程式設計實現DBSCAN密度聚類演算法,並以西瓜資料集4.0為例進行聚類效果分析程式設計聚類演算法
- 資料探勘聚類之k-medoids演算法實現聚類演算法
- 譜聚類的python實現聚類Python
- 用Python實現文件聚類Python聚類
- C均值聚類 C實現 Python實現聚類Python
- 【Python機器學習實戰】聚類演算法(1)——K-Means聚類Python機器學習聚類演算法
- 機器學習之k-means聚類演算法(python實現)機器學習聚類演算法Python
- 硬聚類(HCM)和模糊聚類(FCM)在彩色影象分割中的具體應用聚類
- 【Python機器學習實戰】聚類演算法(2)——層次聚類(HAC)和DBSCANPython機器學習聚類演算法
- 利用python的KMeans和PCA包實現聚類演算法PythonPCA聚類演算法
- kmeans聚類演算法matlab實現聚類演算法Matlab
- MMM全連結聚類演算法實現聚類演算法
- 聚類演算法與K-means實現聚類演算法
- 【機器學習】:Kmeans均值聚類演算法原理(附帶Python程式碼實現)機器學習聚類演算法Python
- 機器學習經典分類演算法 —— k-近鄰演算法(附python實現程式碼及資料集)機器學習演算法Python
- coco資料集詳解
- 【python資料探勘課程】二十.KNN最近鄰分類演算法分析詳解及平衡秤TXT資料集讀取PythonKNN演算法
- 聚類演算法聚類演算法
- kmeans實現文字聚類聚類
- EM 演算法-對鳶尾花資料進行聚類演算法聚類
- 計算機如何感知大資料——聚類演算法計算機大資料聚類演算法
- 一文簡述多種無監督聚類演算法的Python實現聚類演算法Python
- 聚類之K均值聚類和EM演算法聚類演算法
- 聚類(part3)--高階聚類演算法聚類演算法
- MVO優化DBSCAN實現聚類優化聚類
- Mahout聚類演算法學習之Canopy演算法的分析與實現聚類演算法
- 非完整資料聚類初探聚類
- 資料探勘-層次聚類聚類
- 資料處理 聚類分析聚類
- 『資料結構與演算法』棧:詳解與程式碼實現資料結構演算法
- 層級聚類和Python實現的初學者指南(附連結)聚類Python
- Python程式設計實現蟻群演算法詳解Python程式設計演算法
- 手把手教你在Python中實現文字分類(附程式碼、資料集)Python文字分類
- 手把手教你在多種無監督聚類演算法實現Python(附程式碼)聚類演算法Python
- 深度解讀DBSCAN聚類演算法:技術與實戰全解析聚類演算法
- 資料探勘之 層次聚類聚類