定义
将相似元素聚为一类
通常分为Q型聚类(样本聚类)、R型聚类(指标聚类)。
数据变换
\(A=
\begin{pmatrix}a_{11}&a_{12}&a_{13}&\cdots&a_{1p}\\
a_{21}&a_{22}&a_{23}&\cdots&a_{2p}\\
a_{31}&a_{32}&a_{33}&\cdots&a_{3p}\\\cdots&\cdots&\cdots&\cdots&\cdots&\\a_{n1}&a_{n2}&a_{n3}&\cdots&a_{np}\end{pmatrix}\)
通常不同指标有不同量纲,所以要数据变换
1.规格化变换
2.标准化变换
变换后矩阵为
\(B=
\begin{pmatrix}b_{11}&b_{12}&b_{13}&\cdots&b_{1p}\\
b_{21}&b_{22}&b_{23}&\cdots&b_{2p}\\
b_{31}&b_{32}&b_{33}&\cdots&b_{3p}\\\cdots&\cdots&\cdots&\cdots&\cdots&\\b_{n1}&b_{n2}&b_{n3}&\cdots&b_{np}\end{pmatrix}\)
样本间亲疏程度的测度计算
1.算常用距离
1)闵式距离
2)马氏距离
2.相似系数计算
1)夹角余弦
2)皮尔逊相关系数
基于类间距离的层次聚类
基本操作
1)将每个样品独自聚成一类,构造n个类
2)由两两距离构造距离矩阵
3)把距离最近的两个样品归为一类
4)计算新类与当前其他类的距离,将距离最近的两类聚成新类,重复第四步,直到所有样品聚成一类
5)画聚类谱系图
6)决定类的个数以及各类的样品数,并对类做出解释
类与类之间用不同的方法定义距离,可以用两类间最近样品的距离,也可以是两类间最远样品的距离,也可以是两类样本重心之间的距离
1.最短距离法
代码实现
import numpy as np
from sklearn import preprocessing as pp
import scipy.cluster.hierarchy as sch
import matplotlib.pyplot as plt
a=np.loadtxt("Pdata11_11.txt")
b=pp.minmax_scale(a.T) #数据规格化
d = sch.distance.pdist(b) #求对象之间的两两距离向量
dd = sch.distance.squareform(d) #转换为矩阵格式
z=sch.linkage(d); print(z) #进行聚类并显示
s=[str(i+1) for i in range(7)]; plt.rc('font',size=16)
sch.dendrogram(z,labels=s); plt.show() #画聚类图
输出结果
[[ 3. 4. 0.16258132 2. ]
[ 0. 2. 0.27853564 2. ]
[ 1. 8. 0.35618248 3. ]
[ 5. 6. 0.37626539 2. ]
[ 7. 9. 0.47781458 5. ]
[10. 11. 1.01602914 7. ]]
2.最长距离法
import numpy as np
from sklearn import preprocessing as pp
import scipy.cluster.hierarchy as sch
import matplotlib.pyplot as plt
a=np.loadtxt("Pdata11_11.txt")
b=pp.minmax_scale(a.T) #数据规格化
d = sch.distance.pdist(b) #求对象之间的两两距离向量
z=sch.linkage(d,'complete'); print(z) #进行聚类并显示
s=[str(i+1) for i in range(7)]; plt.rc('font',size=16)
sch.dendrogram(z,labels=s); plt.show() #画聚类图
输出结果
[[ 3. 4. 0.16258132 2. ]
[ 0. 2. 0.27853564 2. ]
[ 5. 6. 0.37626539 2. ]
[ 1. 8. 0.54290736 3. ]
[ 7. 10. 1.01397033 5. ]
[ 9. 11. 1.57203348 7. ]]
K均值聚类
先粗略分类,最后优化
假定全体样本可分成C类,并选出C个初始聚类中心,然后根据距离最小原则分配样本点,同时迭代各类的聚类中心,最后直到迭代收敛或聚类中心不再改变
K均值聚类确定k值
1.簇内离差平方和拐点法
在该拐点之后增加簇的个数,簇内离差平方和趋于平稳,在之前增加簇的个数,离差平方和大幅降低
代码实现
import numpy as np
import matplotlib.pyplot as plt; from sklearn.cluster import KMeans
mean=np.array([[-2, -2],[2, 2], [6,6]])
cov=np.array([[[0.3, 0], [0, 0.3]],[[0.4, 0], [0, 0.4]],[[0.5, 0], [0, 0.5]]])
x0=[]; y0=[];
for i in range(3):
x,y=np.random.multivariate_normal(mean[i], cov[i],1000).T
x0=np.hstack([x0,x]); y0=np.hstack([y0,y])
plt.rc('font',size=16); plt.rc('font',family='SimHei')
plt.rc('axes',unicode_minus=False); plt.subplot(121)
plt.scatter(x0,y0,marker='.') #画模拟数据散点图
X=np.vstack([x0,y0]).T
np.save("Pzdata11_1.npy",X) #保存数据供下面使用
TSSE=[]; K=10
for k in range(1,K+1):
SSE = []
md = KMeans(n_clusters=k); md.fit(X)
labels = md.labels_; centers = md.cluster_centers_
for label in set(labels):
SSE.append(np.sum((X[labels == label,:]-centers[label,:])**2))
TSSE.append(np.sum(SSE))
plt.subplot(122); plt.style.use('ggplot')
plt.plot(range(1,K+1), TSSE, 'b*-')
plt.xlabel('簇的个数'); plt.ylabel('簇内离差平方和之和'); plt.show()
2.轮廓系数法
k个簇的总轮廓系数定义为所有样本点轮廓系数的平均值
总轮廓系数<0,聚类效果不佳;而越接近1越理想。
但是这种方法计算量较大
import numpy as np; import matplotlib.pyplot as plt
from sklearn.cluster import KMeans; from sklearn import metrics
X=np.load("Pzdata11_1.npy")
S=[]; K=10
for k in range(2,K+1):
md = KMeans(k); md.fit(X)
labels = md.labels_;
S.append(metrics.silhouette_score(X,labels,metric='euclidean')) #计算轮廓系数
plt.rc('font',size=16); plt.rc('font',family='SimHei')
plt.plot(range(2,K+1), S, 'b*-')
plt.xlabel('簇的个数'); plt.ylabel('轮廓系数'); plt.show()
可见选择3最好