基于传递闭包的模糊聚类
写在前面
这篇文章是课设的相关记录,有些地方可能会写的不对,欢迎大家指正。如果我有哪里写的不清楚也可以私信与我沟通,各位写课设的学弟学妹加油~
实验目的
掌握建立模糊等价矩阵的方法,会求传递闭包矩阵;掌握利用传递闭包进行模糊聚类的一般方法;会使用 Python 进行模糊矩阵的有关运算。
背景知识
“聚类”就是按照一定的要求和规律对事物进行区分和分类的过程,在这一过程中没有任何关于分类的先验知识,仅靠事物间的相似性
作为类属划分的准则,属于无监督分类的范畴。传统的聚类分析是基于等价关系的一种硬划分,它把每个待辨识的对象根据等价关系严格地划分到某个类中,具有非此即彼的性质,因此这种分类类别界限是分明的。但是,现实的分类往往伴随着模糊性,即考虑的不是有无关系,而是关系的深浅程度,它们在形态和类属方面存在着中介性,适合进行软划分。人们用模糊的方法来处理聚类问题,并称之模糊聚类分析。常用的模糊聚类方法有(1)基于模糊等价矩阵的聚类方法(传递闭包法、Bool 矩阵法);(2)基于模糊相似矩阵的直接聚类法(直接聚类法、最大树法、编 网法);(3)基于目标函数的模糊聚类分析法。三种方法各有优缺点:直接聚类法不用计算模糊等价矩阵,计算量较小,可以比较直接地进行聚类。基于模糊等价矩阵的聚类方法较之编网法理论上更成熟,当矩阵阶数较高时,手工计算量较大,但在计算机上还是容易实现的。第三种聚类提出“聚类中心”的概念,这种方法可以得出某一对象在多大程度上属于某一类,但一般需要知道聚类数。
本实验采用基于传递闭包的模糊聚类方法,传递闭包法聚类首先需要通过标定的模糊相似矩阵
R
\boldsymbol R
R,然后求出包含矩阵
R
\boldsymbol R
R 的最小模糊传递矩阵,即
R
\boldsymbol R
R 的传递闭包
T
R
\boldsymbol {TR}
TR,最后依据
T
R
\boldsymbol {TR}
TR 进行聚类。具体包括以下几个步骤:
1、得到特征指标矩阵
设论域
U
=
{
x
1
,
x
2
,
…
,
x
n
}
\boldsymbol {U=\{x_1,x_2,…,x_n\}}
U={x1,x2,…,xn} 为被分类对象,每个对象又由
m
\boldsymbol m
m 个特征指标表示其性状:
x
i
=
{
x
i
1
,
x
i
2
,
…
,
x
i
m
}
,
i
=
1
,
2
,
…
,
n
\boldsymbol {x_i=\{x_{i1},x_{i2},…,x_{im}\},i=1,2,…,n}
xi={xi1,xi2,…,xim},i=1,2,…,n
则得到原始数据矩阵为
X
=
(
x
i
j
)
n
∗
m
\boldsymbol {X=(x_{ij})_{n*m}}
X=(xij)n∗m。
2、采用最大值规格化法将数据规格化
在实际问题中,不同的数据一般有不同的量纲,为了使有不同量纲的数据可以相互比较,需要将原始数据
x
i
j
\boldsymbol {x_{ij}}
xij 压缩至 [0,1] 区间,这一过程称为数据规格化。通常的方法有标准差规格化、极差规格化、最大值规格化等。
本案例采用最大值规格化,就是将
x
i
j
\boldsymbol {x_{ij}}
xij 换成
x
i
j
′
\boldsymbol {x'_{ij}}
xij′ ,即
x
i
j
′
=
x
i
j
M
j
\boldsymbol {x'_{ij}=\cfrac {x_{ij}}{M_j}}
xij′=Mjxij,其中
M
j
=
m
a
x
(
x
1
j
,
x
2
j
,
x
3
j
,
…
,
x
n
j
)
\boldsymbol {M_j=max(x_{1j},x_{2j},x_{3j},…,x_{nj})}
Mj=max(x1j,x2j,x3j,…,xnj) 。
由上式可知,对原始数据进行正规化处理以后,变量最大值为 1,最小值为 0,即新数据在区间 [0,1] 内。
3、采用最大最小法构造得到模糊相似矩阵
为了建立模糊相似矩阵,引入相似系数
r
i
j
\boldsymbol r_{ij}
rij 表示两个样本
x
i
\boldsymbol x_{i}
xi 与
x
j
\boldsymbol x_{j}
xj 之间的相似程度,组成模糊相似矩阵
R
=
(
r
i
j
)
n
∗
n
\boldsymbol {R=(r_{ij})_{n*n}}
R=(rij)n∗n 。建立方法有最大最小法、算术平均最小法、几何平均最小法等。最大最小法的具体公式为:
r
i
j
=
∑
k
=
1
m
x
i
k
∧
x
j
k
∑
k
=
1
m
x
i
k
∨
x
j
k
\boldsymbol {r_{ij}=\cfrac {\sum ^m_{k=1}{x_{ik}\land{x_{jk}}}}{\sum ^m_{k=1}{x_{ik}\vee{x_{jk}}}}}
rij=∑k=1mxik∨xjk∑k=1mxik∧xjk
算术平均最小法的具体公式为:
r
i
j
=
∑
k
=
1
m
x
i
k
∧
x
j
k
1
2
∑
k
=
1
m
x
i
k
+
x
j
k
\boldsymbol {r_{ij}=\cfrac {\sum ^m_{k=1}{x_{ik}\land{x_{jk}}}}{\cfrac{1}{2}\sum ^m_{k=1}{x_{ik}+{x_{jk}}}}}
rij=21∑k=1mxik+xjk∑k=1mxik∧xjk
4、采用平方法合成传递闭包
通过上述方法得到的模糊相似矩阵
R
\boldsymbol {R}
R 一般只具有自反性和对称性,不满足传递性。要对
R
\boldsymbol {R}
R 进行变换,使得
R
\boldsymbol {R}
R 成为一个模糊等价关系,即满足传递性。由于
R
\boldsymbol {R}
R 的传递性不易验证,因此,进行聚类分析时,需用
R
\boldsymbol {R}
R 的传递闭包
t
(
R
)
\boldsymbol {t(R)}
t(R) 代替
R
\boldsymbol {R}
R 以此作为
R
\boldsymbol {R}
R 的近似,这种方法称为 Washall 算法,又称传递闭包法。
模糊等价矩阵的定义:设
R
=
(
r
i
j
)
n
∗
n
\boldsymbol {R=(r_{ij})_{n*n}}
R=(rij)n∗n是
n
\boldsymbol {n}
n 阶模糊方阵,
I
\boldsymbol {I}
I 是
n
\boldsymbol {n}
n 阶单位方阵,若
R
\boldsymbol {R}
R 满足
(1)自反性:
I
≤
R
⇔
r
i
i
=
1
\boldsymbol {I\leq R\Leftrightarrow r_{ii}=1}
I≤R⇔rii=1
(2)对称性:
R
T
=
R
⇔
r
i
j
=
r
j
i
\boldsymbol {R^T= R\Leftrightarrow r_{ij}=r_{ji}}
RT=R⇔rij=rji
(3)传递性:
R
2
≤
R
⇔
m
a
x
{
(
r
i
k
∧
r
k
j
)
∣
1
≤
k
≤
n
}
≤
r
i
j
\boldsymbol {R^2\leq R\Leftrightarrow max\{(r_{ik}\land r_{kj})\mid 1\leq k\leq n\}\leq r_{ij}}
R2≤R⇔max{(rik∧rkj)∣1≤k≤n}≤rij
则称
R
\boldsymbol {R}
R 为模糊等价矩阵。由模糊等价矩阵的传递性可知
R
2
≤
R
\boldsymbol {R^2\leq R}
R2≤R ,而通过自反性可以推出
R
≤
R
2
\boldsymbol {R\leq R^2}
R≤R2 ,从而得到:对于模糊等价矩阵,实际上有
R
2
=
R
\boldsymbol {R^2 = R}
R2=R 。
关系的闭包的定义:
关系的闭包运算是关系上的一元运算,它把给出的关系
R
\boldsymbol {R}
R 扩充成一个新关系
R
′
\boldsymbol {R'}
R′ ,使
R
′
\boldsymbol {R'}
R′ 具有一定的性质,且所进行的扩充又是最“节约”的。比如自反闭包,相当于把关系
R
\boldsymbol {R}
R 对角线上的元素全改成 1 ,其他元素不变,这样得到的
R
′
\boldsymbol {R'}
R′ 是自反的,且是改动次数最少的,即是最“节约”的。
一个关系
R
\boldsymbol {R}
R 的闭包,是指加上最小数目的有序偶而形成的具有自反性、对称性或传递性的新的有序偶集,此集就是关系
R
\boldsymbol {R}
R 的闭包。
设
R
\boldsymbol {R}
R 是集合
A
\boldsymbol {A}
A 上的二元关系,
R
\boldsymbol {R}
R 的自反(对称、传递)闭包是满足以下条件的关系
R
′
\boldsymbol {R'}
R′ :
(i)
R
′
\boldsymbol {R'}
R′ 是自反的(对称的、传递的);
(ii)
R
′
⊇
R
\boldsymbol {R'} \supe \boldsymbol {R}
R′⊇R ;
(iii)对于
A
\boldsymbol {A}
A 上的任何自反(对称、传递)关系
R
′
′
\boldsymbol {R''}
R′′ ,若
R
′
′
⊇
R
\boldsymbol {R''} \supe \boldsymbol {R}
R′′⊇R,则有
R
′
′
⊇
R
′
\boldsymbol {R''} \supe \boldsymbol {R'}
R′′⊇R′。
R
\boldsymbol {R}
R 的自反、对称、传递闭包分别记为
r
(
R
)
\boldsymbol {r(R)}
r(R) 、
s
(
R
)
\boldsymbol {s(R)}
s(R) 和
t
(
R
)
\boldsymbol {t(R)}
t(R) 。
从模糊相似矩阵得到传递闭包,采用的方法是平方法,具体方法是:把一个相似矩阵
R
\boldsymbol {R}
R 进行自乘操作,得到
R
2
\boldsymbol {R^2}
R2 并且检验
R
2
\boldsymbol {R^2}
R2 是否满足传递性,如果
R
2
\boldsymbol {R^2}
R2 满足传递性则停止,否则计算
R
4
\boldsymbol {R^4}
R4 并且检验
R
4
\boldsymbol {R^4}
R4 是否满足传递性,如果
R
4
\boldsymbol {R^4}
R4 满足传递性则停止,否则计算
R
8
\boldsymbol {R^8}
R8 …,依此类推。这里的自乘操作是模糊集合下的算子,即用模糊集合操作的“交”和“并”取代了原来矩阵操作中的“乘”和“加”操作。理论上已经证明,该相乘操作只需要进行最多
log
2
n
+
1
\boldsymbol {\log_2n+1}
log2n+1 次,就可以得到
t
(
R
)
\boldsymbol {t(R)}
t(R) 。
5、计算截集,得到模糊聚类结果
由于模糊相似矩阵
R
\boldsymbol {R}
R 本身已经是自反的、对称的,其传递闭包
t
(
R
)
\boldsymbol {t(R)}
t(R) 又是传递的,则
t
(
R
)
\boldsymbol {t(R)}
t(R) 一定是模糊等价矩阵,可以决定一个划分。
将
t
(
R
)
\boldsymbol {t(R)}
t(R) 中的元素从大到小排列,逐一作为
α
\boldsymbol \alpha
α 求得对应的
α
\boldsymbol \alpha
α 水平截集。
α
\boldsymbol \alpha
α 水平截集是指隶属度大于等于
α
\boldsymbol \alpha
α 的元素组成的集合,可表示为
R
α
=
{
x
,
y
∣
μ
R
(
x
,
y
)
≥
α
}
\boldsymbol {R_\alpha=\{x,y|\mu_R(x,y)\ge \alpha\}}
Rα={x,y∣μR(x,y)≥α},其对应的特征函数为
μ
R
α
(
x
,
y
)
=
{
1
if
(
x
,
y
)
∈
R
α
0
if
(
x
,
y
)
∉
R
α
\boldsymbol { \mu_{R_\alpha}(x,y)= \begin{cases} 1 &\text{if } (x,y) \in R_\alpha \\ 0 &\text{if } (x,y) \notin R_\alpha \end{cases} }
μRα(x,y)={10if (x,y)∈Rαif (x,y)∈/Rα
注意:模糊集合的水平截集不再是模糊集合,而是一个确定集合。
按
α
\boldsymbol \alpha
α 由大到小进行聚类,得到模糊聚类结果。
数据源:本案例所用数据来自教材《计算智能导论》,原文如下:
在对教师的课堂教学质量进行评价时,考虑以下五项指标:师德师表、教学过程、教学方法、
教学内容以及基本功。每项满分 20,总分 100。现在有
{
x
1
,
x
2
,
x
3
,
x
4
}
\boldsymbol {\{x_1,x_2,x_3,x_4\}}
{x1,x2,x3,x4} 四位老师进行参评,参评成绩如下矩阵,试对老师的成绩进行分类
X
=
[
17
15
14
15
16
18
16
13
14
12
18
18
19
17
18
16
18
16
15
18
]
\boldsymbol {X=\begin{bmatrix}17&15&14&15&16\\18&16&13&14&12\\18&18&19&17&18\\16&18&16&15&18\end{bmatrix}}
X=
1718181615161818141319161514171516121818
完整代码及注释讲解
import numpy as np
np.set_printoptions(precision=2) # 设置矩阵输出精度,保留两位小数
def MaxNormalization(a):
"""
采用最大值规格化法将数据规格化为
"""
c = np.zeros_like(a, dtype=float) # 输出为形状和a一致的矩阵,其元素全部为0
for j in range(c.shape[1]): # 遍历c的列
for i in range(c.shape[0]): # 遍历c的行
c[i, j] = a[i, j]/np.max(a[:, j]) # 每一列的元素除以每一列的最大值
return c
def FuzzySimilarMatrix(a):
"""
用最大最小法构造得到模糊相似矩阵
"""
a = MaxNormalization(a) # 用标准化后的数据
c = np.zeros((a.shape[0], a.shape[0]), dtype=float)
mmax = []
mmin = []
for i in range(c.shape[0]): # 遍历c的行
for j in range(c.shape[0]): # 遍历c的行
mmax.extend([np.fmax(a[i, :], a[j, :])]) # 取i和和j行的最大值,即求i行和j行的并
mmin.extend([np.fmin(a[i, :], a[j, :])]) # 取i和和j行的最大值,即求i行和j行的交
for i in range(len(mmax)):
mmax[i] = np.sum(mmax[i]) # 求并的和(将每个特征求得的并相加,作为i样本和j样本的并)
mmin[i] = np.sum(mmin[i]) # 求交的和(将每个特征求得的交相加,作为i样本和j样本的交)
mmax = np.array(mmax).reshape(c.shape[0], c.shape[1]) # 变换为与c同型的矩阵(每一行代表该样本对于对应的列数的样本的并值)
mmin = np.array(mmin).reshape(c.shape[0], c.shape[1]) # 变换为与c同型的矩阵(每一行代表该样本对于对应的列数的样本的交值)
for i in range(c.shape[0]): # 遍历c的行
for j in range(c.shape[1]): # 遍历c的列
c[i, j] = mmin[i, j]/mmax[i, j] # 赋值相似度
return c
def MatrixComposition(a, b):
"""
合成模糊矩阵a和模糊矩阵b
"""
a, b = np.array(a), np.array(b)
c = np.zeros_like(a.dot(b))
for i in range(a.shape[0]): # 遍历a的行元素
for j in range(b.shape[1]): # 遍历b的列元素
empty = []
for k in range(a.shape[1]):
empty.append(min(a[i, k], b[k, j])) # 行列元素比小
c[i, j] = max(empty) # 比小结果取大
return c
def TransitiveClosure(a):
"""
平方法合成传递闭包
"""
a = FuzzySimilarMatrix(a) # 用模糊相似矩阵
c = a
while True:
m = c
c = MatrixComposition(MatrixComposition(a, c), MatrixComposition(a, c))
if (c == m).all(): # 闭包条件
return np.around(c, decimals=2) # 返回传递闭包,四舍五入,保留两位小数
break
else:
continue
def CutSet(a):
"""
水平截集
"""
a = TransitiveClosure(a) # 用传递闭包
return np.sort(np.unique(a).reshape(-1))[::-1]
def get_classes(temp_pairs):
lists = []
for item1 in temp_pairs:
temp_list = []
for item2 in temp_pairs:
if item1[0] == item2[1]:
temp_list.append(item2[0])
lists.append(list(set(temp_list)))
return(list(np.unique(lists)))
def Result(a):
"""
模糊聚类结果
"""
lambdas = CutSet(a)
a = TransitiveClosure(a)
classes = []
for lam in lambdas:
if lam == lambdas[0]:
classes.append([[a] for a in range(len(a))])
else:
pairs = np.argwhere(a >= lam)
classes.append(get_classes(pairs))
return classes
def main():
"""
特性指标矩阵
"""
input = np.array([[17, 15, 14, 15, 16],
[18, 16, 13, 14, 12],
[18, 18, 19, 17, 18],
[16, 18, 16, 15, 18]], dtype=object)
print("特性指标矩阵\n", input)
print("\n采用最大值规格化法将数据规格化为\n", MaxNormalization(input))
print("\n用最大最小法构造得到模糊相似矩阵\n", FuzzySimilarMatrix(input))
print("\n平方法合成传递闭包\n", TransitiveClosure(input))
print("\n水平截集为\n", CutSet(input))
print("\n模糊聚类结果\n", Result(input))
if __name__ == "__main__":
main()
实验内容
1)为什么按最大最小法得到的一定是一个方阵?且一定是自反方阵?且一定是对称方阵?
因为最大最小法表示两个样本之间的相似程度, i \boldsymbol {i} i 会将所有样本表示一遍, j \boldsymbol {j} j 也会将所有样本表示一遍,所以 i \boldsymbol {i} i 和 j \boldsymbol {j} j 的范围都是 0~样本数 ,所以得到的一定是方阵。
自反矩阵是关系矩阵的主对角线上元素值全部为 1 的矩阵。当 i = j \boldsymbol {i=j} i=j 时,有 ∑ k = 1 m x i k ∧ x j k = ∑ k = 1 m x i k ∨ x j k \boldsymbol {\sum ^m_{k=1}x_{ik}\land x_{jk}=\sum ^m_{k=1}x_{ik}\vee x_{jk}} ∑k=1mxik∧xjk=∑k=1mxik∨xjk,所以 x i j = ∑ k = 1 m x i k ∧ x j k ∑ k = 1 m x i k ∨ x j k = 1 \boldsymbol {x_{ij}=\cfrac {\sum ^m_{k=1}{x_{ik}\land{x_{jk}}}}{\sum ^m_{k=1}{x_{ik}\vee{x_{jk}}}}=1} xij=∑k=1mxik∨xjk∑k=1mxik∧xjk=1,所以得到的方阵一定是自反方阵。
对称方阵是以主对角线为对称轴,各元素对应相等的矩阵。 x i j = ∑ k = 1 m x i k ∧ x j k ∑ k = 1 m x i k ∨ x j k = x j i = ∑ k = 1 m x j k ∧ x i k ∑ k = 1 m x j k ∨ x i k \boldsymbol {x_{ij} =\cfrac {\sum ^m_{k=1}{x_{ik}\land{x_{jk}}}}{\sum ^m_{k=1}{x_{ik}\vee{x_{jk}}}} = x_{ji} = \cfrac {\sum ^m_{k=1}{x_{jk}\land{x_{ik}}}}{\sum ^m_{k=1}{x_{jk}\vee{x_{ik}}}}} xij=∑k=1mxik∨xjk∑k=1mxik∧xjk=xji=∑k=1mxjk∨xik∑k=1mxjk∧xik,所以它一定是对称方阵。
2)为什么可以根据水平截集对数据进行分类?(提示:一个等价关系唯一 确定一个划分)
由于模糊相似矩阵 R \boldsymbol {R} R 本身已经是自反的、对称的,其传递闭包 t ( R ) \boldsymbol {t(R)} t(R) 又是传递的,则 t ( R ) \boldsymbol {t(R)} t(R) 一定是模糊等价矩阵,可以决定一个划分。
α \boldsymbol \alpha α 水平截集是指隶属度大于等于 α \boldsymbol \alpha α 的元素组成的集合,可以根据 α \boldsymbol \alpha α 的特征函数判断数据的分类。
一个等价关系唯一确定一个划分,水平截集是对模糊等价矩阵的划分,因为该矩阵具有等价关系,所以对其进行水平截集划分,必定有划分后数据集的并为全集,两两之间的交为空集。
对于本题而言,每一个水平截集都可以作为对模糊等价矩阵中的元素进行分类的依据,模糊等价矩阵中第 i \boldsymbol {i} i 行 j \boldsymbol {j} j 列的数据代表了第 i \boldsymbol {i} i 个样本与第 j \boldsymbol {j} j 个样本之间的关联度,用水平截集将关联度进行分类,进而可以将分类后有相同关联度的样本分为一类,以此来实现样本间的分类。
3)请解释代码 72 行中两个-1 的含义:return np.sort(np.unique(a).reshape(-1))[::-1]
reshape
中的-1
:np.unique(a)
是对于含有重复元素的数组,提取其中所有出现元素,并且返回排序后结果,reshape(-1)
是根据unique
操作后返回的数组的长度和其余维,来推断输出的维度。
[::-1]
中的-1
:取从后向前(相反)的元素,即将排序后的水平截集逆序输出。
4)在平方法的代码实现中,如何判断平方后的矩阵是否满足传递性?为什么可以这么判断?
判断方法:将平方后的矩阵与被平方的矩阵相比较,如果平方后的矩阵与被平方的矩阵相同,则具有传递性。
原理:因为模糊相似矩阵 R \boldsymbol {R} R 具有自反性和对称性,由自反性的性质 I ≤ R \boldsymbol {I\leq R} I≤R 可得 R ≤ R 2 \boldsymbol {R\leq R^2} R≤R2。若平方后的矩阵满足传递性,则该矩阵必须有 R 2 ≤ R \boldsymbol {R^2\leq R} R2≤R 的性质,所以该矩阵若满足 R 2 = R \boldsymbol {R^2= R} R2=R的条件,则该矩阵满足传递性。
5)请修改代码,将最大最小法替换为算术平均最小法。这会改变最终的聚类结果么?
将本文上面的原代码的
第16-35行
改为:""" 用算数平均最小法构造得到模糊相似矩阵 """ a = MaxNormalization(a) # 用标准化后的数据 c = np.zeros((a.shape[0], a.shape[0]), dtype=float) msum = [] mmin = [] for i in range(c.shape[0]): # 遍历 c 的行 for j in range(c.shape[0]): # 遍历 c 的行 msum.extend([(a[i, :]+a[j, :])]) # 取 i 行和 j 行的和(#修改处) # print("msum:",msum) mmin.extend([np.fmin(a[i, :], a[j, :])]) # 取 i 行和 j 行的最小值,即求 i 行和 j 行的交 for i in range(len(msum)): msum[i] = np.sum(msum[i]) # 求和的和(将每个特征求得的和相加,作为i样本和j样本的和)(#修改处) mmin[i] = np.sum(mmin[i]) # 求交的和(将每个特征求得的交相加,作为i样本和j样本的交) # print("msum':",msum) msum = np.array(msum).reshape(c.shape[0], c.shape[1]) #变换为与 c 同型的矩阵(每一行代表改样本对于对应的列数的样本的和)(#修改处) mmin = np.array(mmin).reshape(c.shape[0], c.shape[1]) #变换为与 c 同型的矩阵(每一行代表改样本对于对应的列数的样本的交值) for i in range(c.shape[0]): # 遍历 c 的行 for j in range(c.shape[1]): # 遍历 c 的列 c[i, j] = mmin[i, j]/(0.5*msum[i, j]) # 赋值相似度(#修改处) return c
原来的聚类结果是:
[[[0], [1], [2], [3]], [[0], [1], [2, 3]], [[0, 2, 3], [1]], [0, 1, 2, 3]]
现在的聚类结果是:
[[[0], [1], [2], [3]], [[0], [1], [2, 3]], [0, 1, 2, 3]]
会改变最终的聚类结果。
实验结果与分析
本实验通过水平截集将样本之间的关联度进行分类,最后四个特征分类结果都一样的归为一类,每一个水平截集都可以进行一次分类,也就是说有多少个水平截集最后的结果就可以有多少种分类。
由第 5)小题可知,当得到模糊相似矩阵的方法不同时,最后的分类结果也有可能不同。
实验小结
本实验难点在于理解数学原理,具体用python的运算方法照着代码逐行理解即可,并不难。