聚类分析——基于Kaggle数据集实战

今天给大家分享的主题是聚类分析,会对聚类算法进行一个理论知识讲解,然后再从实战角度对聚类进行操作,并给大家分析一下聚类算法目前的应用场景以及操作过程中的注意事项,帮助大家更好的理解聚类算法,并且能够在实际的场景中使用,本次实战使用的数据集是Kaggle的Apple Quality数据集,该数据集会同步到“明天科技屋”公众号,如果大家不想去官网下载,进入公众号回复关键词即可获得。

首先,给大家讲解一下聚类算法,聚类算法是一种无监督学习,用于将数据集中的样本分为具有相似特征的群或簇。聚类算法的目标是识别数据中的隐藏结构,并根据样本之间的相似性将他们分在一起。聚类算法在实际中的应用主要侧重在以下几个方面:一、目标划分、特征画像,将目标数据按照特征的相似性,将目标划分为不同的类别,然后再对不同的类别进行特征描述,最后做出与研究目标相关的建议,这一块的话在论文和竞赛中使用比较常见,尤其是竞赛中做客户的特征画像,分析不同群体特征,从而给出针对性的建议;一、使用聚类算法用于数据分类,这一块内容主要是论文研究中使用,并且对群体的聚类结果用于分类判断实际效果也不是很好,并且使用的频率也比较少,具体来讲,对于一个二分类问题,使用聚类将数据分成两类,然后与实际的分类标签做对比,得出聚类的效果,我们后面的代码中对该内容会进行演示;三、用于数据异常值检测,利用聚类算法可以发现数据集中的异常点或群体,帮助识别欺诈行为、故障检测等,例如:DBSCAN 可以识别具有足够高密度的区域为簇,并将稀疏区域视为异常值。

接下来,给大家介绍几种常见的聚类算法:

1、K均值聚类(Kmeans Clustering):

  • K均值算法是一种迭代算法,通过将数据分配到k个簇中,使得每个数据与所属簇中心的聚类最小化,从而实现聚类。
  • 算法初始步骤包括初始化k个聚类中心,计算每个每个数据点与初始聚类中心的距离,将数据分配到最近的聚类中心,更新每个簇的中心,重复以上步骤直至收敛。
  • k均值适用于连续型数据,需要预先指定簇的数量k

2、层次聚类(Hierarchical Clustering):

  • 层次聚类通过构建树形结构将数据点逐步合并或分裂成簇,从而实现聚类。
  • 可以分为凝聚式(Agglomerative)和分列式(Divisive)两种方法,前者从每个数据点作为单独簇开始,逐步合并最接近的簇,后者从所有数据点作为一个簇开始,逐步分类为更小的簇。
  • 层次聚类不需要预先指定簇的数量,可以通过树状图方便展示聚类过程。

3、密度聚类(Density-based Clustering):

  • 密度聚类算法居于样本之间的密度确定样本的簇边界。
  •  DBSCAN(Density-Based Spatial Clustering of Applications with Noise)是一种流行的密度聚类算法,它通过标记核心对象,直接密度可达和密度相连来识别簇,同时能够处理噪声数据。

4、谱聚类(Spectral Clustering):

  • 谱聚类利用数据的特征向量(拉普拉斯矩阵的特征向量)将数据映射到低纬空间,然后应用k均值等传统聚类算法。
  • 谱聚类在处理非球型分布等数据时效果较好,通常对高维数据和图数据有较好的表现。

下面将会用实际代码操作讲解聚类算法的过程以及注意事项:

聚类算法的一般流程通常包括以下步骤:

1、数据准备

  • 收集和准备要进行聚类的数据
  • 如果有缺失值和异常值,需要对数据进行清洗和预处理

2、特征选择和标准化处理:

  • 选择用于聚类的特征,例如:高相关性特征排除
  • 对数据进行标准化和归一化,确保不同特征之间具有相似的尺度

3、选择合适的聚类算法:

  • 根据数据的性质和需求选择适合的聚类算法,如 K均值聚类、层次聚类、密度聚类等。
  • 每种算法有不同的假设和适用场景,需根据具体情况选择最合适的算法。

4、设置聚类模型参数:

  • 对于某些聚类算法,如 K均值聚类,需要设置聚类的数量K。
  • 对于密度聚类算法,需要设置参数如最小样本数(MinPts)和半径ε。

5、训练模型:

  • 在准备好的数据上训练所选的聚类算法模型。
  • 模型将尝试展出数据中的样本之间的模式和关系,将其分为不同的簇。

6、聚类结果分析:

  • 分析生成聚类结果,查看每个簇中样本分布情况。
  • 可以使用可视化工具将不同簇进行可视化展示,便于理解和解释

7、评估聚类效果:

  • 对聚类效果进行评价,可以使用各种评估指标来评估聚类质量,例如:轮廓系数、DBI等指标,这一步也会在确定模型参数时使用,选择最优指标的参数进行模型训练

接下来,我们将会使用python来演示聚类算法:

本次使用的聚类算法是kmeans++算法和层次聚类两种聚类算法进行演示,其中K-means++是对传统Kmenas算法的改进,旨在改善初始质心的选择,以提高算法的性能和结果的稳定性。传统的K均值算法中,初始质心的选择通常是随机进行的,这可能导致聚类结果的不稳定性。

K-means++算法通过引入一种更智能的方式来选择初始质心,使得初始质心能够更好地代表数据集。具体来说,K-means++算法的初始质心选择过程如下:

1. **选择第一个初始质心**:从数据集中随机选择一个样本作为第一个初始质心。

2. **计算距离**:对于每个样本,计算它与已选择的质心之间的距离。

3. **加权概率选取**:根据样本与已选择的质心之间的距离,为每个样本分配一个加权概率。距离较远的样本具有较高的加权概率,距离较近的样本具有较低的加权概率。

4. **选择下一个初始质心**:使用加权概率的分布,按照概率值的大小挑选出下一个初始质心。

5. **重复步骤3和4**:重复执行步骤3和4,直到选择出所需数量的初始质心。

通过使用K-means++算法选择的初始质心,可以更好地代表数据集,提高了聚类算法的性能和结果的稳定性。

首先导入相关的程序包,主要导入的包如下:

import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler
from sklearn.manifold import TSNE
from collections import Counter
from mpl_toolkits.mplot3d import Axes3D
from sklearn.metrics import davies_bouldin_score,silhouette_score,calinski_harabasz_score,accuracy_score

接下来,读取数据和数据预处理,数据所有字段及其中文含义如下:

字段含义
A_id每个样本苹果的编号
Size尺寸
Weight重量
Sweetness甜度
Crunchiness脆度
Juiciness汁水度
Ripeness成熟度
Acidity酸度
Quality总体质量评价

数据展示如下:

对数据文件结构进行了查看以及是否存在缺失值进行审核,结果为无缺失值,对数据中4000索引的错误数据进行了删除,最后对Acidity数据列进行了适当的数据转换。数据操作代码如下:

apple = pd.read_csv('apple_quality.csv')
apple.info()
apple.drop(4000,axis=0,inplace=True)
apple['Acidity'] = apple['Acidity'].astype(float)

第二,我们对特征的相关性进行了判别,高度相关的特征会影响聚类的效果,特征之间的高度共线性可能会导致以下结果:

  1. 影响聚类结果:共线性可能导致某些特征在聚类过程中被赋予过高的权重,从而影响到最终的聚类结果。
  2. 降低算法效率:共线性特征增加了数据集的冗余性,可能导致算法收敛速度变慢或产生稳定性问题
  3. 降低解释性:如果特征之间存在强相关性,聚类结果可能变得难以解释或理解。

进行相关性判断的代码如下:

# 计算特征之间的相关性
correlation_matrix = apple.iloc[:, 1:-1].corr()

# 绘制热图
plt.figure(figsize=(8, 6))
sns.heatmap(correlation_matrix, annot=True, cmap='coolwarm', fmt=".2f")
plt.title("Correlation Heatmap")
plt.show()

展示结果如下:

大家从相关系数图中可以看见,没有特征呈现高度相关,因此,在进行聚类时,我们将所有的特征进行考虑。

下面我们将进行数据的标准化处理以及最优参数选择,我们的数据全是连续型数据,因此在训练模型之前需要进行标准化处理,以消除不同特征之间的量纲,对于分类数据,直接进行独热编码即可,对于聚类算法的评价指标有很多,常用的指标包括一下几个方面:

  1. 肘部法(Elbow Method):通过绘制不同聚类数目对应的损失函数值(如SSE)的曲线图,找到曲线出现拐点的位置,该位置对应的聚类数目就是最佳选择。

  2. 轮廓系数(Silhouette Score):计算不同聚类数目下的平均轮廓系数,选择具有最大平均轮廓系数的聚类数目作为最优选择。

  3. Davies-Bouldin Index (DBI):计算不同聚类数目下的DBI指数,选择DBI指数最小的聚类数目作为最佳选择。

  4. Calinski-Harabasz Index:计算不同聚类数目下的Calinski-Harabasz指数,选择指数最大的聚类数目作为最佳选择。

  5. Gap Statistics:通过比较原始数据和随机数据之间的差异来选择最优的聚类数目,使得Gap Statistic值最大。

在利用不同的指标计算过程中,可能会出现不同的聚类数目,原因是因为每个指标的计算方法是不同的,并且每种指标对数据的特性和聚类目标有不同的关注点和假设,因此我们需要结合多种指标来确定聚类数,这里将相关的指标计算代码都以代码呈现

数据标准化处理:

X = apple.iloc[:, 1:-1]
# 创建StandardScaler对象
scaler = StandardScaler()

# 对DataFrame中的所有列进行标准化处理
normalized_data = scaler.fit_transform(X)

# 将标准化后的数据转换为DataFrame
X_normalized = pd.DataFrame(normalized_data, columns=X.columns)

肘部法则绘图:

# 设置不同的聚类数目
num_clusters = range(1, 15)
sse = []

for n in num_clusters:
    kmeans = KMeans(n_clusters=n, random_state=0)
    kmeans.fit(X_normalized)
    sse.append(kmeans.inertia_)

# 绘制SSE曲线图
plt.plot(num_clusters, sse, marker='o')
plt.xlabel('Number of Clusters')
plt.ylabel('SSE')
plt.title('Elbow Method for Optimal Cluster Number')
plt.show()

肘部法则图结果如下:

DBI指数
# 设置不同的聚类数目
num_clusters = range(2, 10)
dbi_scores = []

for n in num_clusters:
    kmeans = KMeans(n_clusters=n, random_state=0)
    labels = kmeans.fit_predict(X_normalized)
    dbi = davies_bouldin_score(X_normalized, labels)
    dbi_scores.append(dbi)

# 输出每个聚类数目对应的DBI指数
for n, dbi in zip(num_clusters, dbi_scores):
    print(f'Number of Clusters: {n}, Davies-Bouldin Index: {dbi}')

# 找到最佳的聚类数目,即DBI指数最小的情况
best_n_clusters = num_clusters[np.argmin(dbi_scores)]
print(f'\nBest Number of Clusters: {best_n_clusters}')
轮廓系数
# 设置不同的聚类数目
num_clusters = range(2, 10)
silhouette_scores = []

for n in num_clusters:
    kmeans = KMeans(n_clusters=n, random_state=0)
    labels = kmeans.fit_predict(X_normalized)
    silhouette = silhouette_score(X_normalized, labels)
    silhouette_scores.append(silhouette)

# 输出每个聚类数目对应的轮廓系数
for n, score in zip(num_clusters, silhouette_scores):
    print(f'Number of Clusters: {n}, Silhouette Score: {score}')

# 找到最佳的聚类数目,即轮廓系数最大的情况
best_n_clusters = num_clusters[np.argmax(silhouette_scores)]
print(f'\nBest Number of Clusters: {best_n_clusters}')
Calinski-Harabasz指数
# 设置不同的聚类数目
num_clusters = range(2, 10)
ch_scores = []

for n in num_clusters:
    kmeans = KMeans(n_clusters=n, random_state=0)
    labels = kmeans.fit_predict(X_normalized)
    ch_score = calinski_harabasz_score(X_normalized, labels)
    ch_scores.append(ch_score)

# 输出每个聚类数目对应的Calinski-Harabasz Index得分
for n, score in zip(num_clusters, ch_scores):
    print(f'Number of Clusters: {n}, Calinski-Harabasz Index Score: {score}')

# 找到最优的聚类数目,即Calinski-Harabasz Index得分最大的情况
best_n_clusters = num_clusters[np.argmax(ch_scores)]
print(f'\nBest Number of Clusters: {best_n_clusters}')

综合以上各种指标,在本次案例中我们确定聚类数为5是最好的,后面的操作就是将确定好的聚类数带入实际模型中进行训练,用训练好的模型对我们的数据进行预测分类,实际过程中,会分析每一类数据的特征,对每一类数据特征进行总结、分析,提出与目标相关的评论建议。最优聚类数模型训练和标签预测的代码如下:

kmeans = KMeans(n_clusters=5,init='k-means++')
kmeans.fit(X_normalized)
# 预测每个样本的簇标签
labels = kmeans.fit_predict(X_normalized)
labels

在聚类完成之后,通常我们需要对不同类别数据的分布占比进行统计,代码如下:

# 使用Counter统计每个类别出现的次数
class_counts = Counter(labels)

# 计算每个类别所占的比例
total_samples = len(labels)
class_percentages = {k: v/total_samples for k, v in class_counts.items()}

print("类别统计:")
print(class_counts)
print("\n每个类别所占的比例:")
print(class_percentages)

统计结果如下:

除了对结果进行统计,很多时候我们还想观察一些聚类数据的分布情况,从而判断聚类效果的好坏,我们可以使用TSNE对数据进行降维处理,从而可以在二维或者三维图形中实现可视化效果,三维图形绘制代码如下:

# 使用t-SNE将数据降至3维
tsne = TSNE(n_components=3)
data_3d = tsne.fit_transform(X_normalized)

# 绘制3D散点图
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

colors = ['r', 'g', 'b', 'c', 'm'] #不同类别的颜色
for i in range(5):
    ax.scatter(data_3d[labels == i, 0], data_3d[labels == i, 1], data_3d[labels == i, 2], c=colors[i], label=f'Cluster {i}')

ax.set_xlabel('Dimension 1')
ax.set_ylabel('Dimension 2')
ax.set_zlabel('Dimension 3')
plt.legend()
plt.title('t-SNE 3D Clustering Visualization')
plt.show()

二维图形绘制代码如下:

# 使用t-SNE进行降维
tsne = TSNE(n_components=2, random_state=42)
X_tsne = tsne.fit_transform(X_normalized)

# 绘制t-SNE图并根据聚类结果进行着色
plt.scatter(X_tsne[:, 0], X_tsne[:, 1], c=labels)
plt.show()

上述是聚类算法的一种使用场景,在论文中还有一种使用场景就是使用二分类聚类,然后将聚类标签和实际标签进行对比,得出聚类对实际分类效果好坏,实际情况下,这种处理效果其实不是很好,但是可以作为一个了解,代码如下:

kmeans = KMeans(n_clusters=2,init='k-means++')
kmeans.fit(X_normalized)
# 预测每个样本的簇标签
labels = kmeans.fit_predict(X_normalized)
labels
apple['labels'] = labels
apple
apple['Quality'][apple['Quality'] == 'good'] = 1
apple['Quality'][apple['Quality'] == 'bad'] = 0
apple['Quality'] = apple['Quality'].astype(int)
# 假设y_true为真实类别标签,y_pred为聚类结果
accuracy = accuracy_score(apple['Quality'], apple['labels'])
print(accuracy)

最终的预测效果其实不是很理想,但是论文中的预测效果还是挺好的,如果大家感兴趣,可以去阅读相关论文,以上就是聚类相关的知识,相关的数据集会同步到公众号“明天科技屋”,大家回复关键词即可领取,希望大家多多关注,一键三连,更多优质好文推送!

  • 18
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
层次聚类分析是一种常见的聚类算法,通过计算不同数据样本之间的相似度,将数据样本逐步合并成不同的聚类簇。在商圈分析,我们可以使用层次聚类分析算法对基站定位数据进行聚类,以识别不同的商圈。 具体步骤如下: 1. 数据准备:收集基站定位数据,并将其转换为可计算距离的经纬度坐标。 2. 计算距离矩阵:使用距离公式计算不同基站之间的距离,得到一个距离矩阵。 3. 层次聚类分析:使用聚类算法对距离矩阵进行聚类分析,得到不同的商圈簇。 4. 结果展示:将聚类结果可视化,以便于分析和理解。 在Python,可以使用scipy库的层次聚类分析函数进行商圈分析。示例代码如下: ```python import numpy as np from scipy.cluster.hierarchy import dendrogram, linkage import matplotlib.pyplot as plt # 读取基站定位数据 data = np.loadtxt('stations.csv', delimiter=',') # 计算距离矩阵 dist_mat = np.zeros((len(data), len(data))) for i in range(len(data)): for j in range(len(data)): dist_mat[i][j] = np.sqrt((data[i][0]-data[j][0])**2 + (data[i][1]-data[j][1])**2) # 层次聚类分析 Z = linkage(dist_mat, 'ward') # 可视化结果 fig = plt.figure(figsize=(25, 10)) dn = dendrogram(Z) plt.show() ``` 在上述代码,我们首先读取了基站定位数据,并计算了距离矩阵。然后,使用scipy库的linkage函数进行层次聚类分析,并使用dendrogram函数将聚类结果可视化。在可视化结果,每个聚类簇都用不同的颜色表示,以便于分辨不同的商圈。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不一样的邓先生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值