Kmeans和FCM
Kmeans算法作为应用最广泛的基于划分的聚类算法之一,适用于处理大样本数据。是一种典型的基于相似性度量的方法,目标是根据输入参数K将数据集划分为K类。由于初始值,相似度,聚类均值计算策略的不同,因而有很多种K均值算法的变种。在数据接近球形分布的时候,K均值算法具有较好的聚类效果。
K均值算法属于硬聚类算法,它把数据点划分到确切的某一聚类中。而模糊聚类则是软聚类,数据点可能归属于不止一个聚类,并且这些聚类与数据点通过一个成员水平联系起来。成员水平显示了数据点与某一聚类之间联系很密切。模糊聚类就是计算这些成员水平,按照成员水平来决定数据点属于哪一个或哪些聚类的过程。
一、问题描述
1、查阅无监督聚类的评价标准有哪些?选择其中一个标准作为后续试验的验证指标。
2、sonar和iris数据上分别验证两种聚类算法,同时,也可以先利用kmeans算法选择初始聚类中心,然后使用FCM聚类,观察其结果。
二、数据集说明
2.1 Iris数据集
Iris数据集,是一个多分类问题,每个类的观察值数量是均等的,一共有150个观察值,4个输入变量和1个输出变量,其通过对鸢尾花的测量数据预测鸢尾花的品种。
2.2 Sonar数据集
Sonar数据集提供了208组60维的声纳观测集数据,用来预测给定声纳从不同角度返回的强度预测目标是岩石还是矿井。其中R类代表岩石,M类代表矿井。
三、评价标准
在有监督聚类算法中,由于数据是有标签的,我们可以将原始数据的准确标签和分类后得到的标签进行对比,以此来计算聚类结果的准确性,而且可以以此作为损失函数,使得分类的错误率越来越小,模型即可得到优化。
但是在无监督学习中,由于数据本身是没有标签的,那么在聚类后我们只可以得到聚类的结果,并不知道结果是否正确,这是我们无法判断其准确率,由此我们需要一类可以评价无监督聚类结果的好坏的评价指标。由于不论是何种分类,其最终达到的目的都是使得“类内数据尽可能的紧密,类间的距离尽可能地大”,根据这个原则,我们提出了常用地四种评价指标。
下面分别介绍四种评价指标,并举例说明其计算过程:
x代表一类文档,o代表一类文档,方框代表一类文档,聚成了3个cluster。
3.1 纯度
纯度:代表正确聚类地类别数占总类别数地比例。其计算公式如下:
其中N代表总类别数,
ω
k
ω_k
ωk代表第k个聚类,C代表类别集合,
C
j
C_j
Cj表示第j类。其结算结果必然在0~1之间,完全错误时其值为0,完全正确时其值为1。
根据上述例子,可计算得到其纯度为:
p
u
r
i
t
y
=
(
5
+
4
+
3
)
/
17
=
0.71
purity=(5+4+3)/17=0.71
purity=(5+4+3)/17=0.71
3.2 熵(Entropy)
对于一个聚类i,首先计算P_ij,P_ij指的是聚类i中的成员属于类j地概率。
其中m_i是在聚类i中所有成员地个数,m_ij是聚类i中成员属于j类的个数。
每个聚类的entropy可以表示为
其中L是类的个数,整个聚类划分的entropy为
其中K是聚类的数目,m是整个聚类划分所涉及到的成员个数。
例如上面的例子:
e
1
=
−
1
/
6
l
o
g
2
(
1
/
6
)
e1=-1/6log2(1/6)
e1=−1/6log2(1/6)
e
2
=
−
[
1
/
6
l
o
g
2
(
1
/
6
)
+
1
/
6
l
o
g
2
(
1
/
6
)
]
e2=-[1/6log2(1/6)+1/6log2(1/6)]
e2=−[1/6log2(1/6)+1/6log2(1/6)]
e
3
=
2
/
5
l
o
g
2
(
2
/
5
)
e3=2/5log2(2/5)
e3=2/5log2(2/5)
整个聚类划分的
e
n
t
r
o
p
y
=
(
6
/
17
)
∗
e
1
+
(
6
/
17
)
∗
e
2
+
5
/
17
∗
e
3
entropy=(6/17)*e1+(6/17)*e2+5/17*e3
entropy=(6/17)∗e1+(6/17)∗e2+5/17∗e3
3.3 兰德指数
R
I
=
(
a
+
b
)
/
(
C
2
n
)
RI=(a+b)/(C_2^n )
RI=(a+b)/(C2n)
其中C表示实际类别信息,K表示聚类结果,a表示在C与K中都是同类别的元素对数,b表示在C与K中都是不同类别的元素对数。RI的取值为[0,1],值越大表示聚类结果与真实情况越吻合。
RI越大表示聚类效果准确性越高 同时每个类内的纯度越高。为了实现“在聚类结果随机产生的情况下,指标应该接近零”,调整兰德系数(Adjusted rand index)被提出,它具有更高的区分度:
A
R
I
=
(
R
I
−
E
[
R
I
]
)
/
(
m
a
x
(
R
I
)
−
E
[
R
I
]
)
ARI=(RI-E[RI])/(max(RI)-E[RI])
ARI=(RI−E[RI])/(max(RI)−E[RI])
ARI取值范围为[−1,1],值越大意味着聚类结果与真实情况越吻合。从广义的角度来讲,ARI衡量的是两个数据分布的吻合程度。
3.4 互信息
互信息指的是两个随机变量之间的关联程度 如下公式计算:
四、Kmeans算法
4.1 原理概述
K 均值聚类算法是应用最广泛的基于划分的聚类算法之一,适用于处理大样本数据。它是一种典型的基于相似性度量的方法,目标是根据输入参数 K 将数据集划分为 K 簇。由于初始值、相似度、聚类均值计算策略的不同,因而有很多种 K 均值算法的变种。在数据分布接近球体的情况下,K 均值算法具有较好的聚类效果。
(1)选取K个初始聚类中心,
z
1
(
1
)
,
z
2
(
1
)
,
…
,
z
K
(
1
)
z_1 (1),z_2 (1),…,z_K (1)
z1(1),z2(1),…,zK(1),其中括号内的序号为寻找聚类中心的迭代运算的次序号。聚类中心的向量值可任意设定,例如,可选开始的K个模式样本的向量值作为初始聚类中心。
(2)根据最小距离标准将要分类的模式样本 X={x}分配给K个簇中心中的某一个
z
j
(
1
)
z_j (1)
zj(1),则 x 与各聚类中心的最小距离
D
i
(
t
)
=
m
i
n
‖
x
−
z
j
‖
,
j
=
1
,
2
,
⋯
K
D_i (t)=min{‖x-z_j ‖,j=1,2,⋯K}
Di(t)=min‖x−zj‖,j=1,2,⋯K
则
x
∈
S
j
(
t
)
x∈S_j (t)
x∈Sj(t),其中 t 表示迭代次数,
S
j
S_j
Sj表示第 j 个聚类簇,囚此其聚类中心是
z
j
z_j
zj。
(3)计算各个聚类中心的新的向量值,
z
j
(
t
+
1
)
,
j
=
1
,
2
,
…
,
K
,
z_j (t+1),j=1,2,…,K,
zj(t+1),j=1,2,…,K,并计算各聚类簇中样本数据的均值向量
其中,
m
j
m_j
mj为第 j 个聚类簇
S
j
S_j
Sj的样本数目。最终的聚类准则函数为
(4)若
z
j
(
t
+
1
)
≠
z
j
(
t
)
,
j
=
1
,
2
,
…
,
K
,
z_j (t+1)≠z_j (t),j=1,2,…,K,
zj(t+1)=zj(t),j=1,2,…,K,则返回第二步,逐个重新分类模式样本,重复迭代操作;若
z
j
(
t
+
1
)
=
z
j
(
t
)
,
j
=
1
,
2
,
…
,
K
,
z_j (t+1)=z_j (t),j=1,2,…,K,
zj(t+1)=zj(t),j=1,2,…,K,则算法收敛,计算结束。
4.2 算法实现:Iris数据集分类
- 读入文件,此时数据为字符串类型
- 读取的文件类型为字符串,所以需要编写一个从字符串获取我们需要的数据信息的函数
- 从读入的数据中创建样本空间向量集合
- 随机选取数据集中的K个点作为初始化的K个聚类中心(此问题中K=3)
- 计算每个点到各个聚类中心的距离并将其归到距离其最近的类中
- 根据归类后的数据重新计算聚类中心
- 检测新的聚类中心与上一次是否相同,若相同则说明已经找到目标聚类中心,迭代结束,跳出循环
- 判断每个聚类对应的真实标签,与真实标签对照,计算分类准确率并输出
输出结果:
12 次迭代后聚类中心: [5.006 3.428 1.462 0.246 5.88360656 2.74098361 4.38852459 1.43442623 6.85384615 3.07692308 5.71538462 2.05384615]
分类准确率为: 0.8866666666666667
其分类准确率的变化趋势如图:
4.3 算法实现:Sonar数据集分类
输出结果:
分类准确率为: 0.5432692307692307
其分类准确率的变化趋势如图:
五、FCM算法
5.1 原理概述
K 均值算法属于硬聚类算法,它把数据点划分到确切的某一聚类中。而在模糊聚类亦称软聚类中,数据点则可能归属于不止一个聚类中,并且这些聚类与数据点通过一个成员水平(实际上类似于模糊集合中隶属度的概念)联系起来。成员水平显示了数据点与某一聚类之间的联系很密切。模糊聚类就是计算这些成员水平,按照成员水平来决定数据点属于哪一个或哪些聚类的过程。模糊C均值算法(Fuzzy C-Means,FCM)是模糊聚类算法中使用最广泛的算法之一。
下面介绍隶属度函数的概念。隶属度函数是描述样本x隶属于集合 A 的程度的函数,记做
μ
A
(
x
)
μ_A (x)
μA(x),其自变量范围是所有样本点﹐值域范围为[0,1],即
0
≤
μ
A
(
x
)
≤
1
0≤μ_A (x)≤1
0≤μA(x)≤1。在
μ
A
(
x
)
=
l
μ_A (x)=l
μA(x)=l 时,样本 x 完全隶属于集合 A,这种情况相当于硬聚类集合概念中的x∈A。我们用定义在样本空间X={x}上的隶属度函数表示一个模糊
集合A,或者叫作定义在论域X={x}上的一个模糊子集。对于有限个对象
x
1
,
x
2
,
⋯
,
x
m
x_1,x_2,⋯,x_m
x1,x2,⋯,xm模糊集合可以表示为:
利用模糊集的概念,一个样本隶属于哪一个聚类就不再是硬性的。该样本属于每个聚类的隶属度是区间[0,1]中的值。
FCM 的目标函数是把m个样本
x
i
,
i
=
1
,
2
,
…
,
m
{x_i,i=1,2,…,m}
xi,i=1,2,…,m分为c个模糊集合,并给出每组的聚类中心,使得代价函数的值为最小。这里使用非相似性指标作为代价函数。FCM 加上归一化约束以后﹐样本数据属于所有类的隶属度的和总应等于1:
FCM 的目标函数为:
这里
u
i
j
u_ij
uij介于0,1之间;
z
j
z_j
zj为模糊集合 j 的聚类中心;
d
i
j
=
‖
c
j
−
x
i
‖
d_ij=‖c_j-x_i ‖
dij=‖cj−xi‖
为第i个数据与第 j 个聚类中心之间的欧氏距离,这里作为一个加权指数﹔U 为隶属矩阵。
构建一个新的目标函数,也就是上式达到最小值的必要条件如下:
其中,α为柔性参数,由上述两个条件可以看出,FCM 算法是一种简单的迭代算法。实践采用 FCM 确定聚类中心 z,和隶属矩阵 U 的步骤如下:
(1)对隶属矩阵 U 使思(0;1)之间进行均匀分布的初始化,使其如下约束:
(2)计算 c 个聚类中心 z ,j=1…c
(3)计算代价函数。如果其结果小于某个阈值,或者与上一个成本函数值的变化小于某个阈值,则算法停止。
(4)计算新的矩阵 U。返回步骤(2)。
5.2 算法实现:Iris数据集分类
1,读入文件,此时数据为字符串类型
2,读取的文件类型为字符串,所以需要编写一个从字符串获取我们需要的数据信息的函数
3,从读入的数据中创建样本空间向量集合
4,随机初始化数据集中每一个数据对K个聚类蔟的隶属度,组成隶属度矩阵U(此问题中K=3)
5,根据隶属度矩阵计算K个聚类中心
6,计算代价函数,并检测新的代价函数值与上一次值的差是否小于10^(-4),若足够小则说明已经找到目标聚类中心和隶属度矩阵,迭代结束,跳出循环。
7,若未满足终止条件,则根据新的聚类中心更新隶属度矩阵U,继续迭代
8,若满足终止条件,则跳出循环,判断每个聚类对应的真实标签,与真实标签对照,计算分类准确率并输出
输出结果:
20 次迭代后聚类中心: [5.0039648 3.41411326 1.48277577 0.25352849 6.77441494 3.05220857 5.64603834 2.05325944 5.88843895 2.76089151 4.36323081 1.39694357]
第1蔟的实际标签为:0 第2蔟的实际标签为:2 第3蔟的实际标签为:1
归1分类准确率为: 0.8933333333333333
模糊分类准确率为: 0.8250662641523535
5.3 算法实现:Sonar数据集分类
输出结果:
第1蔟的实际标签为:0 第2蔟的实际标签为:1
归1分类准确率为: 0.5528846153846154
模糊分类准确率为: 0.5193918960896884
六、Kmeans算法在图像分割上的应用
导入sklearn库中的图片,如图所示:
其大小为:(768, 1024, 3),将其表现为矩阵格式:
由于含有三个通道,所以我们选择其中一个通道来进行kmeans算法的应用,其第一个通道显示如图:
分别选用K=2,3,5来对图像进行分割,并分别将原图像灰度化和分割后的图像灰度化,并将其进行对比:
k=2
k=3
k=5
将图像灰度化:
k=2
k=3
k=5
文章的pdf文件:link
七、python代码
7.1 kmeans-Iris
import numpy as np
import numpy.linalg as lg
import math
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import random
import copy
# ---------------------------------读入文件---------------------------------------
path = r'bezdekIris.data'
f = open(path, 'r')
data = f.read()
data = data.split()
# ---------------------------------从str获取信息的函数-----------------------------
def get_data(datastr):
species = {'Iris-setosa': 0, 'Iris-versicolor': 1, 'Iris-virginica': 2}
datastr = datastr.split(',')
data_part = list(map(float, datastr[:4]))
label_part = species[datastr[4]]
data_part = np.array(data_part)
return data_part, label_part
# ---------------------------------创建样本空间向量集合----------------------------
Iris_data_list = []
Iris_label_list = []
for iris in data:
iris_data, iris_label = get_data(iris)
Iris_data_list.append(iris_data)
Iris_label_list.append(iris_label)
# ----------------------------------初始化K个聚类中心-----------------------------
K = 3 # 聚类中心个数
z = [] # 存放K个聚类中心
while True:
newz = random.choice(Iris_data_list)
same_flag = False
for i in z:
if (i == newz).all():
same_flag = True
if not same_flag:
z.append(newz)
if len(z) == K:
break
assert len(z) == K
print("初始聚类中心:", z)
# -----------------------------------迭代------------------------------------------
iterations_num = 0 # 迭代次数计数器
while True:
z_old = copy.copy(z)
clusters = [[] for i in range(K)] # K个聚类蔟中包含的点
for i in range(len(Iris_data_list)):
distance = [] # 该点到K个中心的距离表
for j in range(K):
distance.append(lg.norm(Iris_data_list[i] - z[j]))
nearest_zpoint = distance.index(min(distance)) # 找出距离其最近的聚类中心
clusters[nearest_zpoint].append(i)
same_flag = True
for i in range(K):
cluster_mean = np.zeros(len(z[i]))
for j in range(len(clusters[i])):
cluster_mean += Iris_data_list[clusters[i][j]]/len(clusters[i])
z[i] = cluster_mean
if (z[i] != z_old[i]).all():
same_flag = False
iterations_num += 1
print(iterations_num, "次迭代后聚类中心:", '\n', z[0], '\n', z[1], '\n', z[2])
# 计算分类准确率
clusters_labels = []
accuracy = 0
for i in range(K):
label_list = []
for j in range(len(clusters[i])):
label_list.append(Iris_label_list[clusters[i][j]])
true_label = []
for j in range(K):
true_label.append(label_list.count(j))
accuracy += max(true_label) # 选取数量最大的标签作为其标签
print(true_label.index(max(true_label)), end=' ')
clusters_labels.append(true_label.index(max(true_label)))
accuracy = accuracy/len(Iris_label_list)
print("分类准确率为:", accuracy)
if same_flag:
if len(set(clusters_labels)) == K:
print('已找到聚类结果')
else:
print('聚类结果错误!')
break
7.2 kmeans-Sonar
import numpy as np
import numpy.linalg as lg
import math
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import random
import copy
# ---------------------------------读入文件---------------------------------------
path = r'sonar.all-data'
f = open(path, 'r')
data = f.read()
data = data.split()
# ---------------------------------从str获取信息的函数-----------------------------
def get_data(datastr):
species = {'R': 0, 'M': 1}
datastr = datastr.split(',')
data_part = list(map(float, datastr[:60]))
label_part = species[datastr[60]]
data_part = np.array(data_part)
return data_part, label_part
# ---------------------------------创建样本空间向量集合----------------------------
Sonar_data_list = []
Sonar_label_list = []
for sonar in data:
sonar_data, sonar_label = get_data(sonar)
Sonar_data_list.append(sonar_data)
Sonar_label_list.append(sonar_label)
# ----------------------------------初始化K个聚类中心-----------------------------
K = 2 # 聚类中心个数
z = [] # 存放K个聚类中心
while True:
newz = random.choice(Sonar_data_list)
same_flag = False
for i in z:
if (i == newz).all():
same_flag = True
if not same_flag:
z.append(newz)
if len(z) == K:
break
assert len(z) == K
print("初始聚类中心:", z)
# -----------------------------------迭代------------------------------------------
iterations_num = 0 # 迭代次数计数器
while True:
z_old = copy.copy(z)
clusters = [[] for i in range(K)] # K个聚类蔟中包含的点
for i in range(len(Sonar_data_list)):
distance = [] # 该点到K个中心的距离表
for j in range(K):
distance.append(lg.norm(Sonar_data_list[i] - z[j]))
nearest_zpoint = distance.index(min(distance)) # 找出距离其最近的聚类中心
clusters[nearest_zpoint].append(i)
same_flag = True
for i in range(K):
cluster_mean = np.zeros(len(z[i]))
for j in range(len(clusters[i])):
cluster_mean += Sonar_data_list[clusters[i][j]]/len(clusters[i])
z[i] = cluster_mean
if (z[i] != z_old[i]).all():
same_flag = False
iterations_num += 1
print(iterations_num, "次迭代后聚类中心:", '\n', z[0], '\n', z[1])
# 计算分类准确率
accuracy = 0
for i in range(K):
label_list = []
for j in range(len(clusters[i])):
label_list.append(Sonar_label_list[clusters[i][j]])
true_label = []
for j in range(K):
true_label.append(label_list.count(j))
accuracy += max(true_label) # 选取数量最大的标签作为其标签
print(true_label.index(max(true_label)), end=' ')
accuracy = accuracy/len(Sonar_label_list)
print("分类准确率为:", accuracy)
if same_flag:
print('已找到聚类结果')
break
7.3 FCM-Iris
import numpy as np
import numpy.linalg as lg
import math
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import random
import copy
# ---------------------------------读入文件---------------------------------------
path = r'bezdekIris.data'
f = open(path, 'r')
data = f.read()
data = data.split()
# ---------------------------------从str获取信息的函数-----------------------------
def get_data(datastr):
species = {'Iris-setosa': 0, 'Iris-versicolor': 1, 'Iris-virginica': 2}
datastr = datastr.split(',')
data_part = list(map(float, datastr[:4]))
label_part = species[datastr[4]]
data_part = np.array(data_part)
return data_part, label_part
# ---------------------------------创建样本空间向量集合----------------------------
Iris_data_list = []
Iris_label_list = []
for iris in data:
iris_data, iris_label = get_data(iris)
Iris_data_list.append(iris_data)
Iris_label_list.append(iris_label)
# ----------------------------------初始化K个聚类中心-----------------------------
K = 3 # 聚类中心个数
z = [0, 0, 0] # 存放K个聚类中心
# ----------------------------------初始化隶属矩阵U-------------------------------
U = np.random.rand(len(Iris_data_list), K)
for i in range(len(Iris_data_list)):
U[i] = U[i]/sum(U[i])
# -----------------------------------迭代------------------------------------------
J = 0
a = 2 # 柔性参数
iterations_num = 0 # 迭代次数计数器
while True:
z_old = copy.copy(z)
U_old = copy.copy(U)
J_old = J
# 计算新聚类中心
for j in range(K):
sum_ux = 0
sum_u = 0
for i in range(len(Iris_data_list)):
sum_ux += (U[i][j]**a) * Iris_data_list[i]
sum_u += U[i][j]**a
z[j] = sum_ux/sum_u
iterations_num += 1
print(iterations_num, "次迭代后聚类中心:", '\n', z[0], '\n', z[1], '\n', z[2])
# 计算代价函数
J = 0
for j in range(K):
for i in range(len(Iris_data_list)):
J += (U[i][j]**a) * (lg.norm(z[j]-Iris_data_list[i])**2)
# 终止条件
if abs(J - J_old) < 0.0001:
break
# 计算新矩阵U
for i in range(len(Iris_data_list)):
for j in range(K):
sum_ud = 0
for k in range(K):
sum_ud += ((lg.norm(z[j]-Iris_data_list[i])) / (lg.norm(z[k]-Iris_data_list[i]))) ** (2/(a-1))
U[i][j] = 1/sum_ud
# 计算第几蔟的实际标签是什么
label_order = []
for i in range(K):
K_list = [0]*K
for j in range(len(Iris_data_list)):
if np.argmax(U[j]) == i:
K_list[Iris_label_list[j]] += 1
label_order.append(K_list.index(max(K_list)))
assert len(set(label_order)) == K, '出现了两类相同蔟!'
# 输出判断结果
for i in range(K):
print('第{}蔟的实际标签为:{}'.format(i+1, label_order[i]), end=' ')
print()
# 计算实际标签对应的是第几蔟
un_label_order = [0]*K
for i in range(K):
un_label_order[label_order[i]] = i
accuracy1 = 0
for i in range(len(Iris_data_list)):
if U[i][un_label_order[Iris_label_list[i]]] == max(U[i]):
accuracy1 += 1
accuracy1 /= len(Iris_data_list)
print("归1分类准确率为:", accuracy1)
accuracy2 = 0
for i in range(len(Iris_data_list)):
accuracy2 += U[i][un_label_order[Iris_label_list[i]]]
accuracy2 /= len(Iris_data_list)
print("模糊分类准确率为:", accuracy2)
7.4 FCM-Sonar
import numpy as np
import numpy.linalg as lg
import math
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import random
import copy
# ---------------------------------读入文件---------------------------------------
path = r'sonar.all-data'
f = open(path, 'r')
data = f.read()
data = data.split()
# ---------------------------------从str获取信息的函数-----------------------------
def get_data(datastr):
species = {'R': 0, 'M': 1}
datastr = datastr.split(',')
data_part = list(map(float, datastr[:60]))
label_part = species[datastr[60]]
data_part = np.array(data_part)
return data_part, label_part
# ---------------------------------创建样本空间向量集合----------------------------
Sonar_data_list = []
Sonar_label_list = []
for sonar in data:
sonar_data, iris_label = get_data(sonar)
Sonar_data_list.append(sonar_data)
Sonar_label_list.append(iris_label)
# ---------------------------------初始化K个聚类中心------------------------------
K = 2 # 聚类中心个数
z = [0, 0] # 存放K个聚类中心
# ----------------------------------初始化隶属矩阵U-------------------------------
U = np.random.rand(len(Sonar_data_list), K)
for i in range(len(Sonar_data_list)):
U[i] = U[i]/sum(U[i])
# -----------------------------------迭代------------------------------------------
J = 0
a = 2 # 柔性参数
iterations_num = 0 # 迭代次数计数器
while True:
z_old = copy.copy(z)
U_old = copy.copy(U)
J_old = J
# 计算新聚类中心
for j in range(K):
sum_ux = 0
sum_u = 0
for i in range(len(Sonar_data_list)):
sum_ux += (U[i][j]**a) * Sonar_data_list[i]
sum_u += U[i][j]**a
z[j] = sum_ux/sum_u
iterations_num += 1
print(iterations_num, "次迭代后聚类中心:", '\n', z[0], '\n', z[1])
# 计算代价函数
J = 0
for j in range(K):
for i in range(len(Sonar_data_list)):
J += (U[i][j]**a) * (lg.norm(z[j]-Sonar_data_list[i])**2)
# 终止条件
if abs(J - J_old) < 0.0001:
break
# 计算新矩阵U
for i in range(len(Sonar_data_list)):
for j in range(K):
sum_ud = 0
for k in range(K):
sum_ud += ((lg.norm(z[j]-Sonar_data_list[i])) / (lg.norm(z[k]-Sonar_data_list[i]))) ** (2/(a-1))
U[i][j] = 1/sum_ud
# 计算第几蔟的实际标签是什么
label_order = []
for i in range(K):
K_list = [0]*K
for j in range(len(Sonar_data_list)):
if np.argmax(U[j]) == i:
K_list[Sonar_label_list[j]] += 1
label_order.append(K_list.index(max(K_list)))
assert len(set(label_order)) == K, '出现了两类相同蔟!'
# 输出判断结果
for i in range(K):
print('第{}蔟的实际标签为:{}'.format(i+1, label_order[i]), end=' ')
print()
# 计算实际标签对应的是第几蔟
un_label_order = [0]*K
for i in range(K):
un_label_order[label_order[i]] = i
accuracy1 = 0
for i in range(len(Sonar_data_list)):
if U[i][un_label_order[Sonar_label_list[i]]] == max(U[i]):
accuracy1 += 1
accuracy1 /= len(Sonar_data_list)
print("归1分类准确率为:", accuracy1)
accuracy2 = 0
for i in range(len(Sonar_data_list)):
accuracy2 += U[i][un_label_order[Sonar_label_list[i]]]
accuracy2 /= len(Sonar_data_list)
print("模糊分类准确率为:", accuracy2)
7.5 kmeans-图像分割
from scipy import misc
from sklearn.cluster import Kmeans
face = misc.face()
print(face.shape)
plt.subplot()
plt.imshow(face)
# 分别展示三个通道下的图片
print(face[:,:,0])
print(face[:,:,1])
print(face[:,:,2])
plt.figure(1)
plt.imshow(face[:,:,0])
plt.figure(2)
plt.imshow(face[:,:,1])
plt.figure(3)
plt.imshow(face[:,:,2])
a=face[:,:,1]
image=a.ravel()
print(image.shape)
image.resize(len(image),1)
print(image.shape)
kmeans = KMeans(n_clusters=2)
kmeans.fit(image)#进行聚类
pre = kmeans.predict(image)
pre.resize(768,1024)
plt.figure(1)
plt.subplot(1,2,1)
plt.imshow(a)
plt.subplot(1,2,2)
plt.imshow(pre)
plt.figure(2)
plt.subplot(1,2,1)
plt.imshow(a,cmap=plt.cm.gray)
plt.subplot(1,2,2)
plt.imshow(pre,cmap=plt.cm.gray)
kmeans = KMeans(n_clusters=3)
kmeans.fit(image)#进行聚类
pre = kmeans.predict(image)
pre.resize(768,1024)
plt.figure(1)
plt.subplot(1,2,1)
plt.imshow(a)
plt.subplot(1,2,2)
plt.imshow(pre)
plt.figure(2)
plt.subplot(1,2,1)
plt.imshow(a,cmap=plt.cm.gray)
plt.subplot(1,2,2)
plt.imshow(pre,cmap=plt.cm.gray)
kmeans = KMeans(n_clusters=5)
kmeans.fit(image)#进行聚类
pre = kmeans.predict(image)
pre.resize(768,1024)
plt.figure(1)
plt.subplot(1,2,1)
plt.imshow(a)
plt.subplot(1,2,2)
plt.imshow(pre)
plt.figure(2)
plt.subplot(1,2,1)
plt.imshow(a,cmap=plt.cm.gray)
plt.subplot(1,2,2)
plt.imshow(pre,cmap=plt.cm.gray)