模型学习笔记10-聚类分析(K-Means)

聚类分析是一种基于中心的聚类算法(K 均值聚类),通过迭代,将样本分到 K 个类中,使得每个样本与其所属类的中心或均值的距离之和最小。与分层聚类等按照字段进行聚类的算法不同的是,快速聚类分析是按照样本进行聚类。

模型理论

K-Means 算法是一种无监督学习,同时也是基于划分的聚类算法,一般用欧式距离作为衡量数据对象间相似度的指标,相似度与数据对象间的距离成反比,相似度越大,距离越小。算法需要预先指定初始聚类数目 k 以及 k 个初始聚类中心,根据数据对象与聚类中心之间的相似度,不断更新聚类中心的位置,不断降低类簇的误差平方和(Sum of Squared Error,SSE),当 SSE 不再变化或目标函数收敛时,聚类结束,得到最终结果。

其核心思想是

首先从数据集中随机选取 k 个初始聚类中心 Ci(1 ≤ i ≤ k) ,计算其余数据对象与聚类中心 Ci 的欧氏距离,找出离目标数据对象最近的聚类中心 Ci ,并将数据对象分配到聚类中心 Ci 所对应的簇中。然后计算每个簇中数据对象的平均值作为新的聚类中心,进行下一次迭代,直到聚类中心不再变化或达到最大的迭代次数停止。

代码

主要基于sklearn库来实现

from sklearn import cluster
from sklearn import metrics

np.set_printoptions(suppress=True)
class KMeans:
    # 从原始数据中提取需要的变量数据
    def getVars(self,var_list):
        if type(var_list)==type(None):
            return self.data.columns.tolist()
        else:
            return var_list
    @staticmethod   # 定类数据和定量数据分离
    def processData(data:pd.DataFrame):
        quan_data=data.select_dtypes(exclude='object')
        qual_data=data.select_dtypes(include='object')
        return {'quan':quan_data,'qual':qual_data}
    @staticmethod   # 生成定类数据量化规则
    def generateRules(qual_arr):    
        qual_list=[]
        for qual in qual_arr.columns.tolist():
            qual_list.append(np.unique(qual_arr[qual]).tolist())
        qual_rule_list=[]
        for sub_qual_list in qual_list:
            temp_rule={}
            i=1
            for qual in sub_qual_list:
                temp_rule[qual]=i
                i+=1
            qual_rule_list.append(temp_rule)    
        res=qual_rule_list[0]
        for i in range(1,len(qual_rule_list)):
            res=dict(res,**qual_rule_list[i])
        return res
    # 确定定类数据量化规则
    def getRules(self,rule):
        if self.qual_data.columns.size==0:
            return{}
        elif type(rule)==type(None):
            return self.generateRules(self.qual_data)
        else:
            return rule
    # 根据规则将定类数据量化
    def type2digit(self):
        if len(self.rule)==0:
            return self.var_data
        else:
            qual_data=self.qual_data.copy()
            for key in self.rule.keys():
                qual_data[qual_data==key]=self.rule[key]
            return pd.merge(self.quan_data,qual_data,left_index=True,right_index=True)
    def __init__(self,data:pd.DataFrame,n_clusters,var_list:list=None,rule:dict=None) -> None:
        # 数据处理
        self.data=data                                          # 原始数据
        self.var_list=self.getVars(var_list)                    # 变量列表
        self.var_data=data[self.var_list]                       # 变量数据
        self.sample_size=self.var_data.index.size               # 样本数量
        self.quan_data=self.processData(self.var_data)['quan']  # 定量数据
        self.qual_data=self.processData(self.var_data)['qual']  # 定类数据
        self.n_clusters=n_clusters                              # 聚类数量
        self.rule=self.getRules(rule)                           # 定类量化规则
        self.digited_data=self.type2digit()                     # 定类量化后数据
        # 聚类分析
        self.k_means=cluster.KMeans(n_clusters=self.n_clusters)
        self.fit=self.k_means.fit_predict(self.digited_data[self.var_list])
        # 轮廓系数评分
        self.silhouette_score=metrics.silhouette_score(self.digited_data,self.fit)
        # 卡林斯基-哈拉巴斯指数
        self.calinski_harabasz_score=metrics.calinski_harabasz_score(self.digited_data,self.fit)
    # 统计频数频率
    def calFrequency(self):
        freq=np.array([],dtype=np.float64)
        for var in np.unique(self.k_means.labels_):
            freq=np.insert(freq,freq.size,self.k_means.labels_[self.k_means.labels_==var].size)
        rel_freq=freq/np.sum(freq)
        data=np.c_[freq.reshape(freq.size,1),rel_freq.reshape(freq.size,1)]
        return pd.DataFrame(data,columns=['频数','频率'])
    # 标签数据
    def labelData(self):
        labels=pd.DataFrame(self.k_means.labels_.reshape(self.sample_size,1),columns=['聚类种类'])
        return pd.merge(labels,self.var_data,left_index=True,right_index=True)
    # 获取聚类中心
    def getClusterCenters(self):
        return pd.DataFrame(self.k_means.cluster_centers_,columns=self.var_list)
    # 类别单独评分
    def clusterRating(self):
        silhouette=np.array([])
        calinski=np.array([])
        for var in self.var_list:
            silhouette=np.insert(silhouette,silhouette.size,metrics.silhouette_score(self.digited_data[[var]],self.fit))
            calinski=np.insert(calinski,calinski.size,metrics.calinski_harabasz_score(self.digited_data[[var]],self.fit))
        data=np.c_[silhouette.reshape(silhouette.size,1),calinski.reshape(calinski.size,1)]
        return pd.DataFrame(data,columns=['轮廓系数','卡林斯基-哈拉巴斯指数'],index=self.var_list)
    def show(self):
        print(f'n_clusters={self.n_clusters}的聚类分析结果如下:')
        print(f'聚类结果汇总:总体样本量={self.sample_size}')
        display(self.calFrequency())
        print('聚类中心点:')
        display(self.getClusterCenters())
        print('聚类结果标注')
        display(self.labelData())
        print('聚类结果评估:轮廓系数范围[-1,1],越接近1结果越好,卡林斯基-哈拉巴斯指数越大结果越好')
        print(f'总体轮廓系数={round(self.silhouette_score,6)},'+
              f'总体卡林斯基-哈拉巴斯指数{round(self.calinski_harabasz_score,6)},各变量评分结果如下:')
        display(self.clusterRating())
file='E:\DEV\python\math\data\聚类分析.xlsx'
data=pd.read_excel(file)
rule={'初中':2,'大学':4,'小学':1,'研究生':5,'高中':3}
human=KMeans(data,2,rule=rule)
human.show()
n_clusters=2的聚类分析结果如下:
聚类结果汇总:总体样本量=10000
频数	频率
0	5047.0	0.5047
1	4953.0	0.4953
聚类中心点:
收入	年龄	学历
0	15732.000396	38.264618	2.971853
1	7235.860747	38.131382	3.039758
聚类结果标注
聚类种类	收入	年龄	学历
0	1	6668	57	研究生
1	0	14658	60	研究生
2	1	6493	17	初中
3	0	12458	26	小学
4	0	12179	24	小学
...	...	...	...	...
9995	0	17053	37	高中
9996	0	11713	19	研究生
9997	0	12012	64	高中
9998	1	3890	63	高中
9999	1	10890	34	研究生
10000 rows × 4 columns

聚类结果评估:轮廓系数范围[-1,1],越接近1结果越好,卡林斯基-哈拉巴斯指数越大结果越好
总体轮廓系数=0.630062,总体卡林斯基-哈拉巴斯指数30505.381932,各变量评分结果如下:
轮廓系数	卡林斯基-哈拉巴斯指数
收入	0.630101	30506.596478
年龄	-0.000117	0.208242
学历	0.000766	5.853331
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇