2022年 11月 5日

python实现谱聚类(spectral clustering)

先贴一个链接,我觉得这个博主写的好,过程也很详细。我是按照他最下方的算法流程写的。有问题的话也希望大家提出来。
数据挖掘——谱聚类(spectral clustering)基本原理及python实现

我的数据是鸢尾花数据集,这里就不提供下载地址了,大家网上一搜都有。我们直接进行实现过程。
导入数据:

df = pd.read_csv("iris.txt", header=None, sep="\s+")
df.head()
  • 1
  • 2

在这里插入图片描述
去掉标签列

df = df.iloc[:, :4]
df.head()
  • 1
  • 2

在这里插入图片描述
我这里对数据进行了归一化处理,其实也不用,我用了是因为要习惯以后的数据处理。我就不贴代码了,大家忽略这一步,不影响后续的步骤,结果可能会跟我有点误差。

数据的格式:
在这里插入图片描述
我们创建一个空矩阵:

createMatrix = pd.DataFrame(np.zeros((m,m)))
createMatrix.head()
  • 1
  • 2

在这里插入图片描述
我们在这求相似矩阵(邻接矩阵)使用的是高斯核函数,上面的博主用的是KNN:

def AffMatrix(arrA, arrB):
    c = 0.5
    a = -(np.sum(np.square(np.array(arrA)-np.array(arrB))))
    b = 2 * (np.square(c))
    w = np.exp(a/b)
    return w
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

我们通过高斯核函数对数据进行计算,然后将结果放入创建的空矩阵中:

def W_Matrix(m, createMatrix):
    for i in range(m):
        x = df.iloc[i,:].values.tolist()
        for j in range(m):
            y = df.iloc[j,:].values.tolist()
            createMatrix.iloc[i,j] = AffMatrix(x,y) #计算的高斯核函数放入创建的空矩阵中
    createMatrix = createMatrix - np.identity(m) # np.identity()创建单位对角矩阵  //  生成对角线为0的矩阵
    return createMatrix
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

得到一个对角线为0的邻接矩阵
在这里插入图片描述
然后来求D(度)矩阵:

D = pd.DataFrame(np.diag(np.sum(W)))
D
  • 1
  • 2

在这里插入图片描述
再求出标准化的拉普拉斯矩阵L:

Dn = np.mat(np.diag(np.power(np.sum(W), -0.5)))
W = np.mat(W)
L = Dn * W * Dn
L
  • 1
  • 2
  • 3
  • 4

在这里插入图片描述
再计算L的特征值和特征向量:

eigvals, eigvecs = np.linalg.eig(L)
print(eigvals)
print("-----------------------------------")
print(eigvecs)
  • 1
  • 2
  • 3
  • 4

在这里插入图片描述
在这里插入图片描述
大家都知道鸢尾花的数据集是分类成3类的,这里我们k=3,通过对特征值排序后的选择列来求出特征向量的列:

k = 3
indices = eigvals.argsort()[-k:]
k_max_eigvecs = eigvecs[:,indices]
k_max_eigvecs
  • 1
  • 2
  • 3
  • 4

在这里插入图片描述
特征向量单位化:

X = np.linalg.norm(k_max_eigvecs, axis=1)
Y = pd.DataFrame(np.zeros((m,k)))
for i in range(m):
    for j in range(k):
        Y.iloc[i,j] = k_max_eigvecs[i,j]/X[i]
print("特征向量单位化:", Y)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

在这里插入图片描述
调用KMeans算法:

from sklearn.cluster import KMeans
  • 1

计算出分类结果:

NJW = KMeans(n_clusters=k).fit_predict(k_max_eigvecs)
NJW
  • 1
  • 2

在这里插入图片描述
与原来的数据集放到一个DataFrame里面:

df1 = pd.concat([df,pd.DataFrame(NJW)], axis=1, ignore_index=True)
df1.head()
  • 1
  • 2

在这里插入图片描述
可视化:

def draw(data):
    colorSet = ["black", "blue", "green", "yellow", "red", "purple", "orange", "brown"]
    for i in range(m):
        x = data.iloc[i,0]
        y = data.iloc[i,1]
        color = colorSet[int(data.iloc[i,4]) % len(colorSet)]
        plt.scatter(x,y, marker="o", c=color, s=20)
    plt.xlabel("x")
    plt.ylabel("y")
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

调用方法:

draw(df1)
  • 1

在这里插入图片描述