先贴一个链接,我觉得这个博主写的好,过程也很详细。我是按照他最下方的算法流程写的。有问题的话也希望大家提出来。
数据挖掘——谱聚类(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