实验7: 谱聚类
一、实验目的
了解谱聚类的构建过程和代码实现,应用谱聚类解决简单的实际问题。
二、实验准备
安装python和pycharm,了解python基础编程和pycharm使用。
三、实验内容
基于程序中生成的数据,补充完整下面谱聚类算法相关程序,粘贴运行成功的结果截图,并给每行程序添加注释。
import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn import datasets #导入相应的包
def calculate_w_ij(a,b,sigma=1):#计算距离
w_ab = np.exp(-np.sum((a-b)**2)/(2*sigma**2)) #高斯相似度,距离远,相似度小
return w_ab
def Construct_Matrix_W(data,k=5):
# 计算临接矩阵
rows = data.shape[0]#取出数据行数
W = np.zeros((rows,rows))#对矩阵进行初始化:初始化W为rows*rows的方阵
for i in range(rows):#遍历行
for j in range(rows):#遍历列
if(i!=j):#计算不重复点的距离
W[i][j] = calculate_w_ij(data[i,:],data[j,:])#调用函数计算距离
t = np.argsort(W[i,:])#对W中进行行排序,并提取对应索引
for x in range(rows-k):#对W进行处理
W[i][ t[x] ] = 0
W = (W+W.T)/2 #主要是想处理可能存在的复数的虚部,都变为实数
return W
def Calculate_Matrix_L_sym(W): # 计算标准化的拉普拉斯矩阵
degreeMatrix = np.sum( W , axis=1 )#按照行对W矩阵进行求和
L = np.diag(degreeMatrix) - W#计算对应的对角矩阵减去w
#拉普拉斯矩阵标准化,就是选择Ncut切图
sqrtDegreeMatrix = np.diag(1.0 / (degreeMatrix ** (0.5))) # D^(-1/2)
L_sym = np.dot(np.dot(sqrtDegreeMatrix, L), sqrtDegreeMatrix) # D^(-1/2) L D^(-1/2)
return L_sym
def normalization(matrix): # 归一化
sum = np.sqrt(np.sum(matrix**2,axis=1,keepdims=True))#求数组的正平方根
nor_matrix = matrix/sum#求平均
return nor_matrix
def showCluster(res, k): #绘制聚类结果函数
m,n = res[:,0:2].shape#m,n是(800,2)
mark =['or','ob', 'og', 'ok', 'oy']#设置mark
if k > len(mark):#如果k值大于mark的最大长度,即不能找到对应值
print("k值太大了")#进行提示
return 1#返回标识符
for i in range(m):
markIndex = int(res[i,2])
plt.plot(res[i, 0], res[i, 1], mark[ markIndex ])
plt.show()
if __name__=="__main__":
data,y= datasets.make_moons(n_samples=800, shuffle=True, noise=0.05, random_state=None)#导入数据
'''
制作样本数据,产生的结果为一个简单的样本数据集,用于可视化聚类算法和分类算法。
参数:n_samples:整数型, 可选,默认为100。总的产生的样本点的数量。
shuffle:布尔型,可选填(默认为True)。是否对样本进行重新洗牌。
noise:浮点型orNone型(默认为None)。加到数据里面的高斯噪声的标准差。
返回值:data:产生的形状为[n_samples, 2]的一个数组。产生的样本。
y:产生的形状为[n_samples]维的一个数组。每个样本的分类结果(0或1)
'''
W = Construct_Matrix_W(data)#计算data的邻接矩阵
L_sym = Calculate_Matrix_L_sym(W)#依据W计算标准化拉普拉斯矩阵
lam, H = np.linalg.eig(L_sym)#特征值分解
t = np.argsort(lam)#将lam中的元素进行排序,返回排序后的下标
H = np.c_[H[:,t[0]],H[:,t[1]]]#0和1类的两个矩阵按行连接,就是把两矩阵左右相加,要求行数相等。
H = normalization(H)#归一化处理
model = KMeans(n_clusters=2)#新建2簇的Kmeans模型
model.fit( H )#训练
labels =model.labels_#得到聚类后的每组数据对应的标签类型
res = np.c_[data,labels]#按照行数连接data和labels
showCluster(res,k=2)#绘制聚类结果
运行结果: