人工智能之核心基础 机器学习
第九章 聚类算法—公式关注公众号
文章目录
- 人工智能之核心基础 机器学习
- 9.1 K-Means 聚类
- 🎯 核心思想:让“群内紧凑,群间分离”
- 🔑 算法步骤(迭代优化)
- ❓ 如何选择 K 值?——两大经典方法
- 方法1:肘部法则(Elbow Method)
- 方法2:轮廓系数(Silhouette Coefficient)
- 🧪 K-Means 代码实现
- 9.2 层次聚类(Hierarchical Clustering)
- 🌳 核心思想:构建“族谱树”
- 两种方式:
- 🔍 距离度量(簇间距离)
- 🧪 层次聚类代码
- 9.3 DBSCAN 聚类(基于密度)
- ⚡ 核心思想:找“人多的地方”,忽略“孤魂野鬼”
- 🔑 四大核心概念
- 🧪 DBSCAN 代码
- 9.4 聚类评估指标
- 9.5 实战案例
- 案例1:K-Means 用户分群(电商场景)
- 案例2:DBSCAN 异常交易检测
- 🎯 本章总结:三大聚类算法对比
- 资料关注
9.1 K-Means 聚类
🎯 核心思想:让“群内紧凑,群间分离”
想象你要在操场上把学生分成 K 组做游戏,目标是:
- 每组学生站得尽量近
- 不同组之间离得尽量远
K-Means 就是通过不断调整“组长位置”(聚类中心)来实现这个目标。
🔑 算法步骤(迭代优化)
- 随机选 K 个点作为初始中心
- 分配:每个样本归到最近的中心(用欧氏距离)
- 更新:重新计算每个簇的新中心(均值)
- 重复 2~3,直到中心不再变化或达到最大迭代次数
✅距离度量:默认使用欧氏距离
dist ( x , c ) = ∑ i = 1 d ( x i − c i ) 2 \text{dist}(x, c) = \sqrt{\sum_{i=1}^d (x_i - c_i)^2}dist(x,c)=i=1∑d(xi−ci)2
❓ 如何选择 K 值?——两大经典方法
方法1:肘部法则(Elbow Method)
- 计算不同 K 下的簇内平方和(WCSS):
WCSS = ∑ k = 1 K ∑ x ∈ C k ∥ x − μ k ∥ 2 \text{WCSS} = \sum_{k=1}^K \sum_{x \in C_k} \|x - \mu_k\|^2WCSS=k=1∑Kx∈Ck∑∥x−μk∥2 - WCSS 随 K 增大而减小
- 找“拐点”(像手肘)——再增加 K,WCSS 下降变缓
方法2:轮廓系数(Silhouette Coefficient)
衡量样本与其所在簇的相似度 vs 与其他簇的不相似度
取值范围:[-1, 1],越接近1越好
公式:
s ( i ) = b ( i ) − a ( i ) max ( a ( i ) , b ( i ) ) s(i) = \frac{b(i) - a(i)}{\max(a(i), b(i))}s(i)=max(a(i),b(i))b(i)−a(i)- a ( i ) a(i)a(i):样本 i 到同簇其他点的平均距离
- b ( i ) b(i)b(i):样本 i 到最近其他簇的平均距离
💡推荐:优先看轮廓系数,更可靠!
🧪 K-Means 代码实现
importnumpyasnpimportmatplotlib.pyplotaspltfromsklearn.clusterimportKMeansfromsklearn.datasetsimportmake_blobsfromsklearn.metricsimportsilhouette_score# 生成模拟数据X,_=make_blobs(n_samples=300,centers=4,cluster_std=1.0,random_state=42)# 肘部法则选Kwcss=[]sil_scores=[]K_range=range(2,10)forkinK_range:kmeans=KMeans(n_clusters=k,random_state=42)kmeans.fit(X)wcss.append(kmeans.inertia_)# WCSSsil_scores.append(silhouette_score(X,kmeans.labels_))# 可视化fig,ax=plt.subplots(1,2,figsize=(12,4))ax[0].plot(K_range,wcss,'bo-')ax[0].set_title('肘部法则')ax[0].set_xlabel('K')ax[0].set_ylabel('WCSS')ax[1].plot(K_range,sil_scores,'ro-')ax[1].set_title('轮廓系数')ax[1].set_xlabel('K')ax[1].set_ylabel('Silhouette Score')plt.show()# 最终聚类(假设选K=4)kmeans=KMeans(n_clusters=4,random_state=42)y_pred=kmeans.fit_predict(X)plt.scatter(X[:,0],X[:,1],c=y_pred,cmap='viridis',s=30)plt.scatter(kmeans.cluster_centers_[:,0],kmeans.cluster_centers_[:,1],c='red',marker='x',s=200,linewidths=3)plt.title("K-Means 聚类结果 (K=4)")plt.show()9.2 层次聚类(Hierarchical Clustering)
🌳 核心思想:构建“族谱树”
不像 K-Means 需要预先指定 K,层次聚类会生成一棵树状图(Dendrogram),你可以在任意高度切一刀得到想要的簇数。
两种方式:
| 类型 | 过程 | 特点 |
|---|---|---|
| 凝聚式(Agglomerative) | 自底向上:每个点是一簇 → 逐步合并最相似的两簇 | ✅ 常用,适合中小数据 |
| 分裂式(Divisive) | 自顶向下:所有点是一簇 → 逐步分裂 | ❌ 计算复杂,少用 |
🔍 距离度量(簇间距离)
- 单链接(Single Linkage):两簇中最近两点的距离 → 易产生“链式效应”
- 全链接(Complete Linkage):两簇中最远两点的距离 → 簇更紧凑
- 平均链接(Average Linkage):所有点对的平均距离→ 平衡
- Ward 法:合并后WCSS增加最小→ 类似K-Means,推荐!
🧪 层次聚类代码
fromscipy.cluster.hierarchyimportdendrogram,linkagefromsklearn.clusterimportAgglomerativeClustering# 凝聚式层次聚类linked=linkage(X,method='ward')# Ward法# 绘制树状图plt.figure(figsize=(10,5))dendrogram(linked,truncate_mode='level',p=5)# 只显示最后5层plt.title("层次聚类树状图")plt.xlabel("样本/簇")plt.ylabel("距离")plt.show()# 指定K=4进行聚类hac=AgglomerativeClustering(n_clusters=4,linkage='ward')y_hac=hac.fit_predict(X)plt.scatter(X[:,0],X[:,1],c=y_hac,cmap='plasma',s=30)plt.title("层次聚类结果 (K=4)")plt.show()9.3 DBSCAN 聚类(基于密度)
⚡ 核心思想:找“人多的地方”,忽略“孤魂野鬼”
K-Means 假设簇是球形的,但现实数据可能有任意形状(如月牙、环形)。
DBSCAN 通过密度发现任意形状的簇,并自动识别噪声点!
🔑 四大核心概念
| 概念 | 定义 |
|---|---|
| ε 邻域(Epsilon Neighborhood) | 以点为中心、半径 ε 的圆内所有点 |
| 核心点(Core Point) | ε 邻域内至少有MinPts个点(包括自己) |
| 边界点(Border Point) | 在某核心点的 ε 邻域内,但自身不是核心点 |
| 噪声点(Noise Point) | 既不是核心点,也不在任何核心点邻域内 |
✅优点:
- 无需指定簇数量
- 能发现任意形状簇
- 自动剔除噪声
❌缺点:
- 对参数 ε 和 MinPts 敏感
- 密度差异大的数据效果差
🧪 DBSCAN 代码
fromsklearn.clusterimportDBSCAN# DBSCAN聚类dbscan=DBSCAN(eps=1.5,min_samples=5)y_db=dbscan.fit_predict(X_with_outliers)# 使用前面加了异常点的数据# 可视化plt.scatter(X_with_outliers[y_db!=-1,0],X_with_outliers[y_db!=-1,1],c=y_db[y_db!=-1],cmap='Set1',s=30,label='正常簇')plt.scatter(X_with_outliers[y_db==-1,0],X_with_outliers[y_db==-1,1],c='black',marker='x',s=100,label='噪声点')plt.title("DBSCAN 聚类结果")plt.legend()plt.show()print(f"发现{len(set(y_db))-(1if-1iny_dbelse0)}个簇")print(f"噪声点数量:{list(y_db).count(-1)}")9.4 聚类评估指标
📌 注意:无监督学习没有真实标签,所以不能用准确率!只能用内部指标(仅基于数据和聚类结果)
| 指标 | 公式思想 | 越好方向 | 特点 |
|---|---|---|---|
| 轮廓系数(Silhouette) | 群内紧密 vs 群间分离 | 越大越好(max=1) | 直观,推荐首选 |
| Calinski-Harabasz(CH) | 簇间离散 / 簇内离散 | 越大越好 | 计算快,适合凸形簇 |
| Davies-Bouldin(DB) | 平均簇内距 / 簇间距 | 越小越好 | 对K-Means友好 |
fromsklearn.metricsimportcalinski_harabasz_score,davies_bouldin_score labels=kmeans.labels_print("轮廓系数:",silhouette_score(X,labels))print("CH指数:",calinski_harabasz_score(X,labels))print("DB指数:",davies_bouldin_score(X,labels))9.5 实战案例
案例1:K-Means 用户分群(电商场景)
# 模拟用户数据:年消费、访问频率、平均订单金额np.random.seed(42)users=np.random.rand(500,3)users[:,0]*=10000# 年消费:0~10000元users[:,1]*=50# 访问频率:0~50次/月users[:,2]*=500# 平均订单:0~500元# 标准化(K-Means对尺度敏感!)fromsklearn.preprocessingimportStandardScaler scaler=StandardScaler()users_scaled=scaler.fit_transform(users)# 聚类kmeans=KMeans(n_clusters=3,random_state=42)user_clusters=kmeans.fit_predict(users_scaled)# 分析各群特征importpandasaspd df=pd.DataFrame(users,columns=['年消费','访问频率','平均订单'])df['群组']=user_clustersprint(df.groupby('群组').mean())输出示例:
年消费 访问频率 平均订单 群组 0 8500.2 45.1 420.3 → 高价值用户 1 1200.5 10.2 80.1 → 普通用户 2 5000.8 30.5 200.7 → 中等活跃用户案例2:DBSCAN 异常交易检测
# 模拟交易数据:金额、时间(小时)、地点(经纬度简化)transactions=np.random.randn(1000,3)transactions[:,0]=np.abs(transactions[:,0])*1000# 金额 >0transactions[:,1]=(transactions[:,1]+12)%24# 时间 0-24# 加入异常交易:深夜大额anomalies=np.array([[15000,3,0.5],[20000,2,-0.8]])transactions_full=np.vstack([transactions,anomalies])# DBSCAN检测dbscan=DBSCAN(eps=2.0,min_samples=10)labels=dbscan.fit_predict(transactions_full)# 输出异常交易anomaly_indices=np.where(labels==-1)[0]print("检测到异常交易:")foridxinanomaly_indices:amt,hour,loc=transactions_full[idx]print(f" 金额: ¥{amt:.0f}, 时间:{hour:.1f}点, 位置特征:{loc:.2f}")🎯 本章总结:三大聚类算法对比
| 算法 | 是否需指定K | 簇形状 | 噪声处理 | 速度 | 适用场景 |
|---|---|---|---|---|---|
| K-Means | ✅ 是 | 球形 | ❌ 不能 | ⭐⭐⭐⭐ | 用户分群、快速原型 |
| 层次聚类 | ❌ 否(可后选) | 球形 | ❌ 不能 | ⭐⭐ | 小数据、需要树状结构 |
| DBSCAN | ❌ 否 | 任意 | ✅ 自动识别 | ⭐⭐⭐ | 异常检测、非球形簇 |
💡建议:
- 先试K-Means(快、简单)
- 如果簇形状奇怪 → 用DBSCAN
- 数据量小且想探索层次关系 → 用层次聚类
资料关注
公众号:咚咚王
gitee:https://gitee.com/wy18585051844/ai_learning
《Python编程:从入门到实践》
《利用Python进行数据分析》
《算法导论中文第三版》
《概率论与数理统计(第四版) (盛骤) 》
《程序员的数学》
《线性代数应该这样学第3版》
《微积分和数学分析引论》
《(西瓜书)周志华-机器学习》
《TensorFlow机器学习实战指南》
《Sklearn与TensorFlow机器学习实用指南》
《模式识别(第四版)》
《深度学习 deep learning》伊恩·古德费洛著 花书
《Python深度学习第二版(中文版)【纯文本】 (登封大数据 (Francois Choliet)) (Z-Library)》
《深入浅出神经网络与深度学习+(迈克尔·尼尔森(Michael+Nielsen)》
《自然语言处理综论 第2版》
《Natural-Language-Processing-with-PyTorch》
《计算机视觉-算法与应用(中文版)》
《Learning OpenCV 4》
《AIGC:智能创作时代》杜雨+&+张孜铭
《AIGC原理与实践:零基础学大语言模型、扩散模型和多模态模型》
《从零构建大语言模型(中文版)》
《实战AI大模型》
《AI 3.0》