1. 程式人生 > 其它 >模糊聚類_用Python實現模糊動態聚類(傳遞閉包法)

模糊聚類_用Python實現模糊動態聚類(傳遞閉包法)

技術標籤:模糊聚類

FuzzyPy-模糊聚類(傳遞閉包法)

一、傳遞閉包法的操作步驟
  • 第一步: 計算相似矩陣 的傳遞閉包。即依次計算 、、...,當第一次出現 時 就相似矩陣對應的傳遞閉包;

  • 第二步: 將傳遞閉包中的元素從大到小排列:;

  • 第三步: 求出所有 對應的截矩陣 ,根據截矩陣進行分類,並記錄分類結果;

  • 第四步: 寫出動態聚類結果(輸出動態聚類報告);

  • 第五步: 畫出動態聚類圖。

二、關鍵技術分析與準備工作
1、涉及的主要程式設計技術和模糊數學的計算方法
  • (1)傳遞閉包的計算:模糊矩陣的合成;矩陣相等的判斷

  • (2)找出截集水平:篩選傳遞閉包中的重複元素並排序

  • (3)動態分類:計算截矩陣;找出元素為1的元素對應下標,並放入同一集合;

  • (4)輸出聚類結果:字串操作

  • (5)動態聚類圖*:相關繪圖工具的使用(暫不開發)

2、準備工作

要實現以上技術內容需要安裝以下包庫:

  • Python

  • Numpy

  • scikit-fuzzymath(skfuzzy)

三、實現步驟
1、匯入相關庫

方便起見直接將skfuzzy中所有函式匯入。

importnumpyasnp
fromskfuzzyimport*
2、生成相似矩陣

為方便起見

  • 直接寫成 n*n的隨機矩陣,取n=5

  • 相似矩陣的元素都只取2位小數

n=5
R=np.random.rand(n,n)
R=R.dot(R.T)
R=R/np.max(R)
row,col=np.diag_indices_from(R)
R[row,col]=np.ones([n])
R=(R*100).astype(np.int)/100
print(R)
[[1.   0.53 0.5  0.36 0.57]
[0.53 1. 0.42 0.45 0.65]
[0.5 0.42 1. 0.44 0.48]
[0.36 0.45 0.44 1. 0.71]
[0.57 0.65 0.48 0.71 1. ]]
3、計算傳遞閉包

注意: 由於傳遞閉包至多隻需要做 [ln(n)]+1次,因此最簡單的實現方法就是直接從0[ln(n)]+1

t_R=R
foriinrange(np.log2(n).astype(np.int)+1):
t_R2=maxmin_composition(t_R,t_R)
ifnp.sum(np.abs(t_R-t_R2))!=0:
t_R=t_R2
else:
break
print('傳遞閉包為R的2^{0}次方:\r\n'.format(i))
print(t_R)
傳遞閉包為R的 2^2 次方:

[[1. 0.57 0.5 0.57 0.57]
[0.57 1. 0.5 0.65 0.65]
[0.5 0.5 1. 0.5 0.5 ]
[0.57 0.65 0.5 1. 0.71]
[0.57 0.65 0.5 0.71 1. ]]
4、篩選傳遞閉包的所有元素並排序

這個非常簡單

  • 去重:直接用numpyunique方法即可

  • 變成陣列:直接用reshape(-1)就變成了一維陣列

  • 排序:直接用sort。由於預設是升序,因此排完後再用[::-1]倒序即可

lambdas=np.sort(np.unique(t_R).reshape(-1))[::-1]
print(lambdas)
[1.   0.71 0.65 0.57 0.5 ]

這裡可以小秀一下:

lam_str=''
for(i,lam)inzip(range(len(lambdas)),lambdas):
ifi!=len(lambdas)-1:
lam_str+=str(lam)+'>'
else:
lam_str+=str(lam)
print('截集水平:'+lam_str)
截集水平:1.0 > 0.71 > 0.65 > 0.57 > 0.5
5、算出所有截矩陣、分類、記錄分類結果

這裡需要注意一個問題,我們計算截矩陣的根本目的是找出在該截集水平時有關係的元素的對應下標。在Python裡面這個操作其實可以直接實現,可以不用算出截矩陣。

截矩陣的實現方法非常簡單:(t_R >= lambda)*1

temp_pairs=np.argwhere(t_R>=lambdas[1])

print(temp_pairs)
[[0 0]
[1 1]
[2 2]
[3 3]
[3 4]
[4 3]
[4 4]]

但接下來的問題有點麻煩,我們需要將互相有關係的元素下標放在一起。

為了方便實現,我們用了一種最 笨 的辦法,這裡大致說一下思路。

  • 從截矩陣返回的內容是所有有關係的元素的下標的list,先遍歷所有下標,任意一組下標集中出現它時我們就把另一個下標放進來。這樣對每個元素而言,只要和它有關係的元素就會全部放進這一個列表;

  • 由於傳遞閉包是對稱矩陣,因此每組 非對角線 上元素的下標都會成對出現,因此只需將元素遍歷一次即可;

  • 由於 對角線元素 的下標並沒有被我們刪除,因此所有元素都會和它有關係的元素放在同一列表;

  • 每個元素遍歷完成後,清除它對應的列表的重複值;最後再對總的列表清理一次重複值,這樣就得到了一個只包含最終分類結果的列表。

為了方便起見,我們將這個方法封裝起來:

defget_classes(temp_pairs):
lists=[]

foritem1intemp_pairs:
temp_list=[]
foritem2intemp_pairs:
ifitem1[0]==item2[1]:
temp_list.append(item2[0])
lists.append(list(set(temp_list)))

return(list(np.unique(lists)))

print(get_classes(temp_pairs))
[[0], [1], [2], [3, 4]]

接下來遍歷所有的 得出所有聚類結果:

f_classes=[]
forlaminlambdas:
iflam==lambdas[0]:
f_classes.append([xforxinrange(n)])
else:
pairs=np.argwhere(t_R>=lam)
f_classes.append(get_classes(pairs))

forcinclasses:
print(c)
[[0], [1], [2], [3], [4]]
[[0], [1], [2], [3, 4]]
[[0], [1, 3, 4], [2]]
[[0, 1, 3, 4], [2]]
[0, 1, 2, 3, 4]
6、輸出聚類報告

這一步就簡單了,只需要進行簡單的字串操作即可:

report_str=[]

forcinclasses:
temp_str='classes:$\{'
forxinc:
sub_class=''
iftype(x)==list:
sub_class='\{'
foriinx:
sub_class+='x_{'+str(i)+'},'
sub_class=sub_class[:-1]+'\},'
else:
sub_class+='x_{'+str(x)+'},'
temp_str+=sub_class
temp_str=temp_str[:-1]
temp_str+='\}$'
report_str.append(temp_str)

forrinreport_str:
print(r,'\n')


classes:$\{\{x_{0}\},\{x_{1}\},\{x_{2}\},\{x_{3}\},\{x_{4}\}\}$ 

classes:$\{\{x_{0}\},\{x_{1}\},\{x_{2}\},\{x_{3},x_{4}\}\}$

classes:$\{\{x_{0}\},\{x_{1},x_{3},x_{4}\},\{x_{2}\}\}$

classes:$\{\{x_{0},x_{1},x_{3},x_{4}\},\{x_{2}\}\}$

classes:$\{x_{0},x_{1},x_{2},x_{3},x_{4}\}$

放到 markdown 裡看看效果:

classes:

classes:

classes:

classes:

classes:

四、技術總結

本文利用Python實現了基於傳遞閉包法的模糊聚類分析。整個過程可以看出其實實現方法都非常簡單。但目前仍然還是有一些不足之處:

1、相似矩陣我們是直接隨機生成的,因此要直接應用的話還得自己寫出相似矩陣的構造方法。當然這個方法很簡單,我們不多講;

2、在給定的截矩陣的前提下求出對應的分類方法get_classes還有很大的改進空間。目前的複雜度是 ,方法特別笨。另外該方法在處理單位矩陣時其實返回的是一個元素為數字的列表,這導致分類結果沒有正確將每個元素各為一類的情況展示出來,這部分必須要改進!

3、動態聚類圖還沒畫!當然這個問題還比較麻煩,暫時不弄了。

完成時間:

importdatetime
print(datetime.datetime.now())
2020-11-06 01:46:27.822593

關注我們分享更多有趣有用的知識:

7f0d855aa8336c33b01972cae3eceaca.png


點贊轉發,讓迷路的同學找到組織