上次实现的模糊均值聚类算法有一点小问题。与聚类中心的距离应该是平方,我直接做了一个开方。
直觉模糊集是模糊集的扩展,因此理论上而言直觉模糊C均值聚类算法的聚类效果会更好。
直觉模糊集的定义是:设<A,B>是U的一对模糊子集构成的序偶。如果对于任意x属于U,都成立A(x)+B(x)<=1则称C=<A,B>是U上的一个直觉模糊子集。称为A,B为隶属度和非隶属度。
不过这种算法最大的问题是资料中给定的目标函数并不统一。我查阅了四份资料,给出了三种不同的定义方式,而且相互并不等价,因此我选择了一种最简单的方式(唯一我能解出偏导的方式.......)进行推导和实现。其中这四分资料分别为:https://blog.csdn.net/liyuefeilong/article/details/43816495。
王昭,范九伦,娄昊,赵凤.一种融入局部信息的直觉模糊C-均值聚类图像分割算法[J].计算机应用研究,2014,31(09):2864-2866+2872.
兰蓉,林洋.抑制式非局部空间直觉模糊C-均值图像分割算法[J].电子与信息学报,2019,41(06):1472-1479.
Lan R, Fan J L, Liu Y, et al. Image thresholding by maximizing the similarity degree based on intuitionistic fuzzy sets[M]//Quantitative Logic and Soft Computing 2016. Springer, Cham, 2017: 631-640.
我使用兰蓉论文中对犹豫度的定义方法,添加一个条件:最小化犹豫,进行求解。然而我认为这四篇论文的区别就在于对犹豫度的定义。理论上犹豫度应该为1-A(x)-B(x)=Π(x),但是论文中定义的为Π(x)=2A(X)(1-A(X))。这是我没有理解的。因此总的目标函数转变为:
约束条件和FCM相同为:
QQ截图20190707164619.jpg
因此根据约束条件下的最值求法-拉格朗日乘数法。可以写为以下形式。
QQ截图20190707165045.jpg
对c求偏导可以发现增加的条件也就是第二项作为常数没有发挥作用。因此聚类中心的公式与FCM完全相同。具体求导过程较为简单可以参考以下两篇博客的求导过程。
https://blog.51cto.com/9269309/1867818
https://www.cnblogs.com/xiaohuahua108/p/6187178.html
对μ的偏导较为麻烦,而且为了求偏导方便m直接设置为2(换成别的值我就求不出来了.....)。具体迭代过程是针对单个值因此第二个求和符号可以略去以方便计算。
图片.png
可以求解出j对于u的偏导,并令其等于0.
QQ截图20190707170907.jpg
很容易求出:
QQ截图20190707171149.jpg
再带入约束条件:
QQ截图20190707171720.jpg
(此处省略了下标)
可以求出:
QQ截图20190707172016.jpg
因此可以将此带入u的表达式,最终算出u的最终表达式。
QQ截图20190707172409.jpg
因此对比FCM的表达式,只是多了个-2。我觉得怪怪的。而且实际聚类结果也非常奇怪。 1.png
贴出代码吧,希望学习模糊集和图像分割的朋友能指出问题所在。
import numpy as np
class IFCM():
def __init__(self,n_clusters):
super(IFCM, self).__init__()
self.n_clusters = n_clusters
self.u = None
self.core = None
def initialize_U(self,data_num):
u = np.random.rand(data_num, self.n_clusters)
data_max = np.sum(u, axis=1)
# print(data_max)
data_max = np.tile(data_max, (self.n_clusters,1)).T
u = np.true_divide(u,data_max)
self.u = u
return u
def fit(self,data,max_item=100):
m=2
self.u = self.initialize_U(data.shape[0])
for i in range(max_item):
############################更新聚类中心############################
new_core = []
for data_dimension in range(self.n_clusters):
u_tmp = np.tile(self.u[:,data_dimension],(data.shape[1],1)).T
u_tmp = np.power(u_tmp,m)
new_core.append(np.true_divide(np.sum(np.multiply(u_tmp,data),axis=0),\
np.sum(u_tmp,axis=0)))
new_core = np.array(new_core)
self.core = new_core
# print(new_core)
#############################计算各点与聚类中心的距离################
new_core_tmp = new_core.reshape((new_core.shape[0],1,new_core.shape[1]))
new_core_tmp = np.tile(new_core_tmp,((1,data.shape[0],1)))
data_tmp = data.reshape((1,data.shape[0],data.shape[1]))
data_tmp = np.tile(data_tmp,((self.n_clusters,1,1)))
distance_tmp = np.subtract(new_core_tmp,data_tmp)
distance_tmp = np.power(distance_tmp,2)
distance_tmp = np.sum(distance_tmp,axis=2)
# distance_tmp = np.power(distance_tmp,1/2).T
distance_tmp = distance_tmp.T-2
#############################更新隶属矩阵###########################
tmp1 = distance_tmp.reshape((distance_tmp.shape[0],distance_tmp.shape[1],1))
tmp1 = np.tile(tmp1,(self.n_clusters))
tmp2 = np.tile(distance_tmp,(self.n_clusters))
tmp2 = tmp2.reshape((distance_tmp.shape[0],distance_tmp.shape[1],self.n_clusters))
new_u = np.true_divide(tmp1,tmp2)
new_u = np.sum(new_u,axis=2)
new_u = np.power(new_u,-1)
#############################查看迭代是否终止########################
subtract_2_u = np.sum(np.fabs(np.subtract(self.u,new_u)))
self.u = new_u
# print(subtract_2_u)
if subtract_2_u == 0:
break
# print(new_u)
def fit_predict(self,data,max_item=1000):
ans = []
if self.u == None:
self.fit(data,max_item=max_item)
ans = np.argmax(self.u, axis=1)
return ans
if __name__ =='__main__':
cls = IFCM(n_clusters=2)
# cls.fit(np.random.rand(5, 3),2)
ans = cls.fit_predict(np.random.rand(5, 3),2)
print(ans)
网友评论