聚类分析
1. 聚类任务
无监督学习:通过对无标记训练样本的学习来揭示数据的内在性质及规律。
聚类:把数据集中的样本划分为若干互斥子集,每个子集称一个簇cluster。
两个基本问题:性能度量与距离计算。
2. 性能度量
vslidity index.作为判断和优化目标。
- 外部指标:将聚类结果与某个参考模型比较。
- 内部指标:直接考察聚类结果而不利用任何参考模型。
聚类分簇C,参考模型C*,令λ与λ* 分别表示与C和C*对应的簇标记向量。将样本两两配对考虑,定义(i<j) a = ∣ S S ∣ , S S 为 λ 都相等 b = ∣ S D ∣ , S D 为 λ 相等、 λ ∗ 不相等,即在 C 中隶属相同簇但 C ∗ 中不隶属 c = ∣ D S ∣ , D S 为 λ 不相等, λ ∗ 相等,即在 C ∗ 中隶属相同簇但 C 中不隶属 d = ∣ D D ∣ , D D 为都不相等 \begin{array}{l} a=|SS|,SS为λ都相等 \\ b=|SD|,SD为λ相等、λ* 不相等,即在C中隶属相同簇但C*中不隶属 \\ c=|DS|,DS为λ不相等,λ* 相等,即在C*中隶属相同簇但C中不隶属 \\ d=|DD|,DD为都不相等 \end{array} a=∣SS∣,SS为λ都相等b=∣SD∣,SD为λ相等、λ∗不相等,即在C中隶属相同簇但C∗中不隶属c=∣DS∣,DS为λ不相等,λ∗相等,即在C∗中隶属相同簇但C中不隶属d=∣DD∣,DD为都不相等一共m个样本,则a+b+c+d=m(m-1)/2.
常用聚类性能度量外部指标
- Jaccard系数 J C = a a + b + c JC=\frac{a}{a+b+c} JC=a+b+caFM系数 F M I = a a + b ∗ a a + c FMI=\sqrt{\frac{a}{a+b}*\frac{a}{a+c}} FMI=a+ba∗a+ca Rand指数 R I = 2 ( a + d ) m ( m − 1 ) RI=\frac{2(a+d)}{m(m-1)} RI=m(m−1)2(a+d)性能度量结果值在[0,1]区间,值越大越好。
考虑聚类结果的簇划分,定义avg©为簇内样本间的平均距离,diam©为簇内样本的最远距离,dmin(Ci,Cj)对应两簇最近样本之间的距离,dcen(Ci,Cj)对应簇Ci与Cj中心点间的距离。
a
v
g
(
c
)
=
2
∣
C
∣
(
∣
C
∣
−
1
)
∑
1
≤
i
<
j
≤
∣
C
∣
d
i
s
t
(
x
i
,
x
j
)
avg(c)=\frac{2}{|C|(|C|-1)}\textstyle \sum_{1\le i<j\le|C|}{}dist(x_{i},x_{j})
avg(c)=∣C∣(∣C∣−1)2∑1≤i<j≤∣C∣dist(xi,xj)
常用聚类性能度量内部指标
- DB指数 D B I = 1 k ∑ i = 1 k max j ≠ i ( a v g ( C i ) + a v g ( c j ) d c e n ( μ i , μ j ) ) DBI=\frac{1}{k}\sum_{i=1}^{k}\max_{j\ne i}(\frac{avg(C_{i})+avg(c_{j})}{d_{cen}(\mu _{i},\mu_{j})}) DBI=k1i=1∑kj=imax(dcen(μi,μj)avg(Ci)+avg(cj))Dunn指数 D I = min 1 ≤ i ≤ k { min j ≠ i ( d m i n ( C i , C j ) m a x 1 ≤ l ≤ k d i a m ( C l ) ) } DI=\min_{1\le i\le k}\left \{ \min_{j\ne i}(\frac{d_{min}(C_{i},C_{j})}{max_{1\le l\le k}diam(C_{l})}) \right \} DI=1≤i≤kmin{j=imin(max1≤l≤kdiam(Cl)dmin(Ci,Cj))}DBI值越小越好,DI值越大越好
3. 距离计算
距离的性质(非负与取等、对称、三角不等式)。
- 向量距离->Minkowski distance
d
i
s
t
m
k
(
x
i
,
x
j
)
=
(
∑
u
=
1
n
∣
x
i
u
−
x
j
u
∣
p
)
1
p
dist_{mk}(x_{i},x_{j})=({\sum_{u=1}^{n}|x_{iu}-x_{ju}|^{p} })^{\frac{1}{p}}
distmk(xi,xj)=(u=1∑n∣xiu−xju∣p)p1p=1为曼哈顿距离,p=2为欧式距离。
连续属性,离散属性。有序属性,无序属性。 - 无序属性的VDM距离(Value Difference Metric) V D M p ( a , b ) = ∑ i = 1 k ∣ m u , a , i m u , a − m u , b , i m u , b ∣ p VDM_{p}(a,b)=\sum_{i=1}^{k}|\frac{m_{u,a,i}}{m_{u,a}}-\frac{m_{u,b,i}}{m_{u,b}}|^{p} VDMp(a,b)=i=1∑k∣mu,amu,a,i−mu,bmu,b,i∣p其中mu,a表示属性u上取值为a的样本数,mu,a,i表示第i个样本簇中属性u上取值为a的样本数,k为样本簇数。
- 混合属性:
M
i
n
k
o
v
D
M
p
(
x
i
,
x
j
)
=
(
∑
u
=
1
n
c
∣
x
i
u
−
x
j
u
∣
p
+
∑
u
=
n
c
+
1
n
V
D
M
p
(
x
i
u
,
x
j
u
)
)
1
p
MinkovDM_{p}(x_{i},x_{j})=({\sum_{u=1}^{n_{c}}|x_{iu}-x_{ju}|^{p} }+\sum_{u=n_{c}+1}^{n}VDM_{p}(x_{iu},x_{ju}))^{\frac{1}{p}}
MinkovDMp(xi,xj)=(u=1∑nc∣xiu−xju∣p+u=nc+1∑nVDMp(xiu,xju))p1加权距离:略。
相似度度量:基于距离/超越距离(非度量距离)。
4. 原型聚类
Prototype-based clustering:假设聚类结构能够通过一组原型刻画。先对原型初始化,然后迭代更新求解。
k均值算法
针对所得簇划分,最小化平方误差
E
=
∑
i
=
1
k
∑
x
ϵ
C
i
∣
∣
x
−
μ
i
∣
∣
2
2
E=\sum_{i=1}^{k}\sum_{x\epsilon C_{i}}||x-\mu_{i}||_{2}^{2}
E=∑i=1k∑xϵCi∣∣x−μi∣∣22,其中μi为簇Ci的均值向量。
贪心策略,迭代优化:1. 随机选择K个初始质心。
2. 将每个样本分配到最近的质心所属的簇。
3. 重新计算每个簇的质心。
4. 重复步骤2和3,直到质心不再变化或达到最大迭代次数。通常设置最大轮数火最小调整幅度阈值,达到则停止。
学习向量量化
LVQ:假设数据样本带有类别标记,学习过程利用样本的这些监督信息来辅助聚类。
-
对原型向量初始化(例如各类别标记随机选一个)。
-
迭代优化:随机选一个样本找到最近的原型向量,并更新原型向量->同类,靠拢;异类,远离。
-
簇划分:每个原型向量定义一个相关的区域Ri,称Voronoi划分。
高斯混合聚类
采用概率模型表达聚类原型。
推导:
-
高斯分布:服从高斯分布->概率密度函数为 p ( x ∣ μ , Σ ) = 1 ( 2 π ) n 2 ∣ Σ ∣ 1 2 e − 1 2 ( x − μ ) T Σ − 1 ( x − μ ) p(x|\mu,\Sigma)=\frac{1}{(2\pi)^{\frac{n}{2}}|\Sigma |^{\frac{1}{2}}}e^{-\frac{1}{2}(x-\mu)^{T}\Sigma^{-1}(x-\mu)} p(x∣μ,Σ)=(2π)2n∣Σ∣211e−21(x−μ)TΣ−1(x−μ)其中∑为协方差矩阵,μ为n维均值向量。
-
高斯混合分布:由k个混合成分组成,每个成分对应一个高斯分布,αi(混合系数)合1: p M ( x ) = ∑ i = 1 k α i ⋅ p ( x ∣ μ i , Σ i ) p_{M}(x)=\sum_{i=1}^{k}\alpha_{i}·p(x|\mu_{i},\Sigma_{i}) pM(x)=∑i=1kαi⋅p(x∣μi,Σi)
记 γ j i \gamma_{ji} γji为样本xj由第i个高斯混合成分生成的后验概率(贝叶斯公式可得)。
每个样本xj的簇标记 λ j = arg max i ϵ { 1 , 2 , … , k } γ j i \lambda_{j}=\argmax_{i\epsilon \left\{1,2,…,k\right\}}\gamma_{ji} λj=argmaxiϵ{1,2,…,k}γji。即簇划分由原型对应后验概率确定。 -
原理:假设数据集由多个高斯分布的混合组成,通过期望最大化算法(EM算法)来估计每个高斯分布的参数。
即最大化 L L ( D ) = l n ( ∏ j = 1 m p M ( x j ) ) LL(D)=ln(\prod_{j=1}^{m}p_{M}(x_{j})) LL(D)=ln(j=1∏mpM(xj))求偏导、拉格朗日乘子法->EM算法更新过程如图所示:
- 初始化每个高斯分布的参数。
- 计算每个样本属于每个高斯分布的概率。
- 更新每个高斯分布的参数。
- 重复步骤2和3,直到参数收敛。
5. 密度聚类
DBSCAN:基于一组neigh-borhood参数(
ϵ
,
M
i
n
P
t
s
\epsilon,MinPts
ϵ,MinPts)来刻画样本分布的紧密程度。
相关概念:领域,核心对象(
ϵ
\epsilon
ϵ-领域至少包含MinPts个样本),密度直达,密度可达(此二不一定对称),密度相连(对称)。
簇:由密度可达关系导出的密度相连的最大密度样本集合。满足连接性和最大性。
- 对于每个点,找到其在给定半径(ε)内的邻居点数。
- 如果邻居点数大于或等于最小样本数(MinPts),则该点为核心点,构成一个簇。
- 递归地将核心点的邻居点加入簇中,直到没有新的点可以加入。
6. 层次聚类
在不同层次对数据集进行划分,从而形成树形的聚类结构。
AGNES算法:自底而上聚合策略,先将数据集中的每个样本看作一个初始聚类簇,然后在算法运行的第一步中找到距离最近的两个聚类簇合并,不断重复直到达到预设个数。
对于聚类簇的距离:最小距离、最大距离、平均距离。(单链接、全链接、均链接算法)
凝聚层次聚类(Agglomerative Hierarchical Clustering):每个样本开始时作为一个单独的簇,逐步合并最近的簇,直到所有样本合并成一个簇。
分裂层次聚类(Divisive Hierarchical Clustering):开始时所有样本作为一个簇,逐步将最不相似的样本分离出去,直到每个样本单独成簇。
7. 常见聚类方法的比较
- k均值聚类:优点:简单高效,适用于大规模数据集。
缺点:需要预先指定K值,对初始质心敏感,适用于球形簇。 - 层次聚类:优点:不需要预先指定簇数,能生成聚类树。
缺点:计算复杂度较高,适用于小规模数据集。 - DBSCAN:优点:能识别任意形状的簇,能处理噪声数据。
缺点:参数ε和MinPts的选择较为敏感。 - 高斯混合模型:优点:能处理具有不同形状和大小的簇。
缺点:计算复杂度较高,容易陷入局部最优解。
代码(参考http://t.csdnimg.cn/cbU5w)
import pandas as pd
import os
import matplotlib.pyplot as plt
import numpy as np
from sklearn.preprocessing import StandardScaler
from sklearn.cluster import KMeans
from sklearn.decomposition import PCA
# 设置字体
plt.rcParams['font.sans-serif'] = ['SimHei'] # 使用黑体显示中文
# 设置文件的完整路径
file_path = 'D:\兹游奇绝\没课\数模打卡 7月\\1999年全国31个省份城镇居民家庭平均每人全年消费性支出数据.csv'
# 检查文件是否存在
if not os.path.exists(file_path):
print(f"文件路径错误:{file_path} 不存在")
else:
try:
# 使用 pandas 的 read_csv 函数读取 CSV 文件
data = pd.read_csv(file_path, encoding='gbk')
print("文件读取成功!")
print(data.head())
# 第四步:选择数据的第二列到最后一列
data_selected = data.iloc[:, 1:]
print(data_selected.head())
# 检查每列的数据类型,并确保所有列都是数值类型
numeric_columns = data_selected.select_dtypes(include=[np.number]).columns
data_selected = data_selected[numeric_columns]
print(data_selected.head())
# 第五步:数据的标准化处理
scaler = StandardScaler()
X_scaled = scaler.fit_transform(data_selected)
print(X_scaled[:5])
# 第六步:绘制手肘图,确定最佳聚类数K
wcss = []
max_clusters = 10 # 设置最大聚类数量
for i in range(1, max_clusters + 1):
kmeans = KMeans(n_clusters=i, random_state=42)
kmeans.fit(X_scaled)
wcss.append(kmeans.inertia_)
plt.plot(range(1, max_clusters + 1), wcss, marker='o')
plt.title('手肘图')
plt.xlabel('聚类数 K')
plt.ylabel('簇内误差平方和 (WCSS)')
plt.show()
# 第七步:进行聚类分析
best_k = 2
kmeans = KMeans(n_clusters=best_k, random_state=42)
kmeans.fit(X_scaled)
labels = kmeans.labels_
data['亚类别'] = labels
print(data)
# 第八步:绘制聚类图
pca = PCA(n_components=2)
principal_components = pca.fit_transform(X_scaled)
pca_df = pd.DataFrame(data=principal_components, columns=['PC1', 'PC2'])
pca_df['Cluster'] = labels
plt.figure(figsize=(10, 6))
colors = ['red', 'blue']
for cluster in range(best_k):
cluster_data = pca_df[pca_df['Cluster'] == cluster]
plt.scatter(cluster_data['PC1'], cluster_data['PC2'], s=50, c=colors[cluster], label=f'Cluster {cluster}')
plt.title('聚类图')
plt.xlabel('主成分 1')
plt.ylabel('主成分 2')
plt.legend()
plt.show()
except UnicodeDecodeError:
print("编码错误,请检查文件编码是否为 gbk")
except pd.errors.EmptyDataError:
print("文件为空,请检查文件内容")
except Exception as e:
print(f"读取文件时发生错误:{e}")
一些运行结果: