PCA-Kmeans 对鸢尾花数据集进行分类

首先介绍一下(yuan)鸢尾花数据集,该数据集测量了所有150个样本的4个特征单位都是cm,分别是:
1.sepal length(花萼长度)
2.sepal width(花萼宽度)
3.petal length(花瓣长度)
4.petal width(花瓣宽度)
对应一个150行4列的矩阵,本文思路是通过PCA压缩数据将其从150行四列变成150行3列,4维变3维(每个特征对应一个维度)
在网上看了很多,k-means和PCA的结果都是二维的,我想用三维图来展示分类的的效果图就自己将代码改了一下。发个博客记录一下代码,思想大概就是将鸢尾花4维的数据转为三维后再使用k-means分类,因为提前知道了这些数据是来自三类的花,所以提前给出K-means要分类的个数为3,算法会提前随机给3个类似于重心的东西,然后离重心近的会被分到该簇。之后每个簇的重心会随着其簇内样本的增加不断改变。重心大概就是结果图中X所在的位置。

#coding=utf-8
import matplotlib.pyplot as plt
from sklearn.decomposition import PCA
from sklearn.datasets import load_iris
from mpl_toolkits.mplot3d import Axes3D
from sklearn.cluster import KMeans
import numpy as np





##计算欧式距离
def distEuclid(x, y):
    return np.sqrt(np.sum((x - y) ** 2))


##随机产生n个dim维度的数据 (这里为了展示结果 dim取2或者3)
def genDataset(n, dim):
    data = []
    while len(data) < n:
        p = np.around(np.random.rand(dim) * size, decimals=2)
        data.append(p)
    return data


## 初始化簇中心点 一开始随机从样本中选择k个 当做各类簇的中心
def initCentroid(data, k):
    num, dim = data.shape
    centpoint = np.zeros((k, dim))
    l = [x for x in range(num)]
    np.random.shuffle(l)
    for i in range(k):
        index = int(l[i])
        centpoint[i] = data[index]
    return centpoint


##进行KMeans分类
def KMeans(data, k):
    ##样本个数
    num = np.shape(data)[0]

    ##记录各样本 簇信息 0:属于哪个簇 1:距离该簇中心点距离
    cluster = np.zeros((num, 2))
    cluster[:, 0] = -1

    ##记录是否有样本改变簇分类
    change = True
    ##初始化各簇中心点
    cp = initCentroid(data, k)

    while change:
        change = False

        ##遍历每一个样本
        for i in range(num):
            minDist = 9999.9
            minIndex = -1

            ##计算该样本距离每一个簇中心点的距离 找到距离最近的中心点
            for j in range(k):
                dis = distEuclid(cp[j], data[i])
                if dis < minDist:
                    minDist = dis
                    minIndex = j

            ##如果找到的簇中心点非当前簇 则改变该样本的簇分类
            if cluster[i, 0] != minIndex:
                change = True
                cluster[i, :] = minIndex, minDist

        ## 根据样本重新分类  计算新的簇中心点
        for j in range(k):
            pointincluster = data[[x for x in range(num) if cluster[x, 0] == j]]
            cp[j] = np.mean(pointincluster, axis=0)

    print("finish!")
    return cp, cluster


##展示结果  各类簇使用不同的颜色  中心点使用X表示
def Show(data, k, cp, cluster):
    num, dim = data.shape
    color = ['b', 'r', 'g', 'c', 'y', 'm', 'k']
    ##二维图
    if dim == 2:
        for i in range(num):
            mark = int(cluster[i, 0])
            plt.plot(data[i, 0], data[i, 1], color[mark] + 'o')

        for i in range(k):
            plt.plot(cp[i, 0], cp[i, 1], color[i] + 'x')
    ##三维图
    elif dim == 3:
        ax = plt.subplot(122, projection='3d')
        for i in range(num):
            mark = int(cluster[i, 0])
            ax.scatter(data[i, 0], data[i, 1], data[i, 2], c=color[mark])
            ax.set_title('k-means result')
        for i in range(k):
            ax.scatter(cp[i, 0], cp[i, 1], cp[i, 2], c=color[i], marker='x')

    plt.show()
if __name__ == "__main__":
        data = load_iris()#以字典形式加载鸢尾花数据集
        y = data.target #使用y表示数据集中的标签
        x = data.data #使用x表示数据集中的属性数据
        #使用PCA 算法,设置降维后主成分数目为 2
        #print(x,'\n', y)
        #print(x)
        #print(type(x))
        size = 20  ##取值范围
        pca = PCA(n_components=3)
        #对原始数据进行降维,保存在 reduced_X 中
        reduced_X = pca.fit_transform(x)
        print('降维后的数据为:\n',reduced_X)#降维后的数据
        print('各主成分方差解释度为:',pca.explained_variance_ratio_)#方差解释度
        print('主成分对应的载荷矩阵为',pca.components_)
        red_x, red_y , red_z = [], [],[]
        blue_x, blue_y , blue_z= [], [],[]
        green_x, green_y, green_z=[],[],[]

        for i in range(len(reduced_X)):
            #标签为0时,3维标签数据保存到列表red_x,red_y,redz中
            if y[i] == 0:
                red_x.append(reduced_X[i][0])
                red_y.append(reduced_X[i][1])
                red_z.append(reduced_X[i][2])#
            elif y[i] == 1:
                blue_x.append(reduced_X[i][0])
                blue_y.append(reduced_X[i][1])
                blue_z.append(reduced_X[i][2])#
            else:
                green_x.append(reduced_X[i][0])
                green_y.append(reduced_X[i][1])
                green_z.append(reduced_X[i][2])#
        X = reduced_X[:, :3]  # #表示我们取特征空间中的3个维度
       #print(X.shape)
       #print(X)
       #print(type(X))
        num = 50 ##点个数
        k=3 ##分类个数
        data = X
        cp,cluster = KMeans(data,k)
        ax=plt.figure().add_subplot(121,projection='3d')
        ax.scatter(red_x, red_y,red_z,c='r', marker='o')
        ax.scatter(blue_x, blue_y,blue_z,c='b', marker='o')
        ax.scatter(green_x, green_y,green_z,c='g', marker='o')#散点图中用s,其余图用markersize可调节散点的大小
        ax.set_title('PCA result')
        Show(data,k,cp,cluster)









result

  • 5
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值