手撕K-means聚类算法

一.数据集来源

                本博客采用的数据集来源于uci公开数据集(wine数据)

        http://archive.ics.uci.edu/ml/datasets/Wine

手撕K-means聚类算法_第1张图片

数据集属性:

1)酒精
2)苹果酸
3)灰分

4)灰分的藻盐度

5)镁
6)总酚
7)黄烷类化合物
8)非黄烷类酚
9)原花青素
10)颜色强度
11)色相
12)稀释葡萄酒的OD280 / OD315

13)脯氨酸

 二.数据处理

从网站上下载的源文件格式是.data,我不知道怎么用python导入,参考另一个博主的文章https://blog.csdn.net/weixin_43860294/article/details/104687097?utm_medium=distribute.pc_aggpage_search_result.none-task-blog-2~aggregatepage~first_rank_ecpm_v1~rank_v31_ecpm-1-104687097.pc_agg_new_rank&utm_term=python%E8%AF%BB%E5%8F%96data%E6%96%87%E4%BB%B6&spm=1000.2123.3001.4430进行了一些调整,将数据保存在了excel中。

三.K-means算法的实现

# -*- coding: utf-8 -*-
"""
Created on Fri Apr  1 14:14:15 2022

@author: 21091
"""

#导入包
import pandas as pd
import numpy as np
from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler
import matplotlib.pyplot as plt
from sklearn.metrics import silhouette_score
from sklearn.decomposition import PCA
#读取数据
data=pd.read_excel(r'C:\Users\21091\Downloads\wine.xlsx')
#使用的是standardscalar规范化处理
scalar=StandardScaler()
data=scalar.fit(data).transform(data)

scores=[]  #存放轮廓系数
distortions=[]#簇内误差平方和  SSE
for i in range(2,10):
    Kmeans_model=KMeans(n_clusters=i)
    predict_=Kmeans_model.fit_predict(data)
    scores.append( silhouette_score(data,predict_))
    distortions.append(Kmeans_model.inertia_)
print("轮廓系数:",scores)
print("簇内误差平方和:",distortions)
#SSE  手肘法
plt.figure(1)
plt.plot(range(2,10),distortions,marker='x')
plt.xlabel('Number of clusters')
plt.ylabel('Distortion')
plt.title('distortions')
plt.savefig("手肘法")
#轮廓系数法
plt.figure(2)
plt.plot(range(2,10),scores,marker='x')
plt.xlabel('Number of clusters')
plt.ylabel('scores')
plt.title('scores')
plt.savefig("轮廓系数法")


def random_k_point(number:int):
    """
    随机法确定初始点
    """
    #定义匿名函数在data[1,len(data)]中随机选择
    k=lambda: data[np.random.randint(len(data)),:] 
    #返回一个随机列表
    return  [np.array(k()) for i in range(number)]
def Kmeans(data,k):
    """
    输入:data-数据集
            k-聚类个数
    输出:data后面新增一列表示类别
    
    """
    p=len(data[0,:]) #数据维度
    cluscenter  = np.array(random_k_point(k))
    lastcluscenter = np.array(random_k_point(k))
    index_=np.zeros(len(data)) #初始化标签

    while 1:
        for i in range(len(data)): #从0到len(data)-1循环
            sumsqure=np.zeros((k))
            for j in range(k):
                sumsqure[j]=np.sqrt(sum(data[i,:]-cluscenter[j,:])**2)#欧式距离
            s=pd.Series(sumsqure).sort_values() #升序排序
            index_[i]=s.index[0]
        clusdata=np.hstack((data,index_.reshape(len(data),1)))
        #更新聚类中心
        for i in range(k):
            cluscenter[i,:]=np.mean(clusdata[clusdata[:,p]==i,:-1],0).reshape(1,p)
        t=abs(lastcluscenter-cluscenter)
        if sum(sum(t))==0:  #对矩阵两次求和转为标量后与0比较
            break
        else:
            for k in range(k):
                lastcluscenter[k,:]=cluscenter[k,:]
        return clusdata,cluscenter
#这里的k是通过前面手肘法和轮廓系数法画图后观察得到的
k=3
#因为wine数据集是14维数据,直接画图不利于观察聚类效果,这里用PCA对r,s进行降维处理
#数据降维
pca=PCA(n_components=2)
pca.fit(data)
data=pca.transform(data)

r,s=Kmeans(data,k)
plt.figure(3)
for i in range(k):
    x=r[r[:,-1]==i,0]
    y=r[r[:,-1]==i,1]
    plt.scatter(s[i,0],s[i,1],s=300)
    plt.scatter(x,y)
plt.savefig("K-means实现红酒分类")

四.运行结果

手撕K-means聚类算法_第2张图片

手撕K-means聚类算法_第3张图片

手撕K-means聚类算法_第4张图片

手撕K-means聚类算法_第5张图片 

 

 上述代码的gitee地址:

https://gitee.com/bullu/bullu/blob/master/K-means/Kmeans_Wine

 

你可能感兴趣的:(kmeans,k-means,机器学习,聚类,python)