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

好的,下面是Python代码实现Kmeans聚类自编码,使用PCA降维后的二维鸢尾花数据集,取K=2进行聚类处理: ``` python import numpy as np import matplotlib.pyplot as plt from sklearn.cluster import KMeans from sklearn.decomposition import PCA # 读入鸢尾花数据集 data = np.loadtxt('iris_pca.txt', delimiter=',') # 取前两列数据作为特征 X = data[:, :2] # 使用Kmeans算法进行聚类 kmeans = KMeans(n_clusters=2, random_state=0).fit(X) labels = kmeans.labels_ # 构建自编码器 input_dim = X.shape[1] encoding_dim = 1 hidden_dim = 2 input_data = Input(shape=(input_dim,)) hidden_layer = Dense(hidden_dim, activation='relu')(input_data) encoding_layer = Dense(encoding_dim, activation='relu')(hidden_layer) decoding_layer = Dense(hidden_dim, activation='relu')(encoding_layer) output_data = Dense(input_dim, activation='linear')(decoding_layer) autoencoder = Model(inputs=input_data, outputs=output_data) autoencoder.compile(optimizer='adam', loss='mse') # 使用聚类中心初始化编码器权重 autoencoder.layers[1].set_weights([kmeans.cluster_centers_.T]) # 训练自编码器 autoencoder.fit(X, X, epochs=100) # 得到编码器的输出 encoder = Model(inputs=input_data, outputs=encoding_layer) encoded_X = encoder.predict(X) # 对于每个样本,将其通过编码器得到的低维表示与K个聚类中心计算距离,将其归为距离最近的簇 new_labels = [] for i in range(X.shape[0]): dist = [np.linalg.norm(encoded_X[i] - kmeans.cluster_centers_[j]) for j in range(kmeans.n_clusters)] new_labels.append(np.argmin(dist)) # 可视化聚类结果 plt.figure(figsize=(10, 6)) plt.scatter(X[:, 0], X[:, 1], c=new_labels, cmap='viridis') plt.xlabel('PCA component 1') plt.ylabel('PCA component 2') plt.show() ``` 需要注意的是,上述代码中使用了Keras库构建自编码器,需要先安装Keras库。另外,PCA降维的代码未提供,需要先进行PCA降维处理,将数据降维为二维。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值