基于K-means实现中草药红外光谱数据聚类

火山方舟向量数据库大模型

前言

K-means算法是一种聚类算法,用于将数据集分成具有相似特征的群组。该算法的目标是将数据点划分为k个簇,其中每个数据点属于与其最近的簇中心。K-means是一种迭代算法,它在每次迭代中更新簇中心,直到满足停止条件。

  1. 初始化:

随机选择k个数据点作为初始簇中心,分别表示为μ₁, μ₂, ..., μₖ。

  1. 分配数据点到簇:

对于每个数据点i(1 到 m),计算其到每个簇中心的距离,通常使用欧氏距离(还可以采用余弦相似度、曼哈顿距离、闵可夫斯基距离等):

picture.image

将数据点分配到距离最近的簇,表示为c(i)。 9. 更新簇中心:

对于每个簇j(1 到 k),计算该簇中所有数据点的均值, 得到的簇中心:

![picture.image](https://p3-volc-community-sign.byteimg.com/tos-cn-i-tlddhu82om/e58df4238ad5424284d5eecd9a0eca5a~tplv-tlddhu82om-image.image?=&rk3s=8031ce6d&x-expires=1742525682&x-signature=ous4FZqP%2FKuZekC9enl2iijkF9U%3D)

其中,|Cj|表示第j个簇中的数据点数量。 10. 重复步骤2 和3:

重复执行步骤2和3,直到簇中心不再发生显著变化或达到预定的迭代 数 。

K-means的目标是最小化所有数据点到其所属簇中心的距离的平方和(平方误差和):

picture.image

其中,δ(c(i)=j)是指示函数,当c(i)=j 时为1,否则为0。

这个目标函数J在每次迭代中应该减小,表示簇中心的不断优化。算法的停止条件可以是J不再显著减小或达到预定的迭代次数。 K-means的优点包括简单、易于实现和高效。然而,它也有一些缺点,例如对初始簇中心的选择敏感,对异常值敏感,以及对簇的形状和大小有假设(假设簇是凸的,并且具有相等的方差)。

在使用K-means时,通常需要事先确定簇的数量k。有一些方法,如肘部法则(Elbow Method)和轮廓分析(Silhouette Analysis),可以帮助选择合适的簇数。

代码实现


          
import pandas as pd
          
import numpy as np
          
import matplotlib.pyplot as plt
          
plt.rcParams['font.sans-serif'] = 'SimHei' # 设置中文显示
          
plt.rcParams['axes.unicode_minus'] = False
          

          
data = pd.read_excel('中草药红外光谱数据.xlsx',index_col = 0) # index_col指定索引
          
data.head()
      

picture.image

根据几种药材的中红外光谱数据,鉴别药材的种类,其中 No 列为药材的编号,其余各列第一行的数据为光谱的波数( 单位 cm -1 ) 、第二行以后的数据表示该行编号的药材在对应波段光谱照射下的吸光度。


          
print(data.shape)
          
print(data.isnull().any().any()) # 空值判断
      

picture.image


          
def func_1(x):
          
    plt.plot(x.index, x.values)
          

          
def func_2(data):
          
    fontsize = 5
          
    plt.figure(figsize=(8, 6), dpi = 300)
          
    plt.xticks(range(652, 4000, 500))
          
    plt.yticks(fontsize = fontsize)
          
    plt.xlabel('波数(cm^-1)')
          
    plt.ylabel('吸光度(AU)')
          
    plt.grid(True) # 网格线设置
          
    data.agg(lambda x: func_1(x), axis = 1)
          
    plt.show()
          

          
func_2(data)
      

picture.image

绘制中药材波谱图,展现波谱分布,可见存在离群值。


          
#异常值检验3σ
          
def func_3(x):
          
    lower = x.mean()-3*x.std() 
          
    toplimit = x.mean()+3*x.std()
          
    return (x<lower)|(x>toplimit)
          

          
ycz = data.agg(lambda x:func_3(x))
          
ycz_index = data[(ycz.sum(axis=1)>1000)].index
          
print(ycz_index)
          

          
data.drop(ycz_index,axis=0,inplace = True) # 删除异常值
          

          
func_2(data)
      

picture.image

picture.image

通过3σ法则进行异常值检测,然后删除被检测到的异常值。在实际应用中,异常值检测有助于清理数据,使得后续分析更加可靠。


          
from sklearn.cluster import KMeans
          
from collections import Counter
          
from sklearn import metrics
          
from mpl_toolkits.mplot3d import Axes3D 
          

          
SSE = []
          
for k in range(1, 11):
          
    km = KMeans(n_clusters=k)
          
    km.fit(data)
          
    SSE.append(km.inertia_)
          

          
X = range(1, 11)
          
plt.figure(figsize=(8, 6), dpi = 300)
          
plt.xlabel('k')
          
plt.ylabel('SSE')
          
plt.title('肘部图')
          
plt.plot(X, SSE, 'o-')
          
plt.grid(True)
          
plt.show()
      

picture.image

生成肘部图(Elbow Method),帮助选择K-means聚类合适簇数K ,即在图中肘部出现的位置。通常,在K值较小时,SSE会较大;而随着K的增加,SSE会逐渐减小。肘部图的"肘部"是指图中开始出现弯曲并趋于平缓的点,该点对应的K值即为较优的簇数。通过观察肘部图,可以尝试找到一个合适的K值,以在聚类中获得相对较好的性能。根据肘部图可知此时选择K=2或K=3。


          
scores = []
          
for k in range(3, 11):
          
    labels = KMeans(n_clusters = k).fit(data).labels_
          
    score = metrics.silhouette_score(data, labels)
          
    scores.append(score)
          

          
X = range(3, 11)
          
plt.figure(figsize=(8, 6), dpi = 300)
          
plt.xlabel('k')
          
plt.ylabel('轮廓系数')
          
plt.title('轮廓系数图')
          
plt.plot(X, scores, 'o-')
          
plt.grid(True)
          
plt.show()
      

picture.image

生成轮廓系数图,帮助选择K-means聚类中的合适簇数K。轮廓系数是一种评估聚类质量的指标,取值范围在[-1, 1]之间。通过观察轮廓系数图,可以尝试找到一个合适的K值,即轮廓系数较高的位置,以在聚类中获得相对较好的性能。较高的轮廓系数表示簇内相似度高、簇间相似度低,是一种有效的聚类评估指标。根据轮廓系数图可知此时选择K=3。


          
km = KMeans(n_clusters = 3) 
          
km.fit(data) 
          
print(Counter(km.labels_))  # 打印每个类多少个
          
print(km.cluster_centers_)  # 中心点
          

          
import warnings
          
# 在代码之前,添加以下行来忽略SettingWithCopyWarning
          
pd.options.mode.chained_assignment = None  # 或 pd.set_option('mode.chained_assignment', None)
          
data['class'] = pd.Series(km.labels_).values # dtaframe保存分类结果
          
data.head()
      

picture.image

根据簇数K=3执行K-means聚类,输出了每个簇的样本数量、簇中心,并将聚类结果保存到数据框中。通过这些信息,可以初步了解数据点的分布情况和聚类效果。

0
0
0
0
关于作者

文章

0

获赞

0

收藏

0

相关资源
字节跳动客户端性能优化最佳实践
在用户日益增长、需求不断迭代的背景下,如何保证 APP 发布的稳定性和用户良好的使用体验?本次分享将结合字节跳动内部应用的实践案例,介绍应用性能优化的更多方向,以及 APM 团队对应用性能监控建设的探索和思考。
相关产品
评论
未登录
看完啦,登录分享一下感受吧~
暂无评论