【数学建模】评价模型——聚类分析 K-Means python实现

聚类分析介绍

关键词:没有先验知识亲密程度相似性个体自动分类

K-Means聚类

  K均值聚类是一种动态聚类法,为了改进之前的算法在样品个数很大时内存和时间都消耗极大的缺点;即一种动态聚类法,先粗略分一下类,然后按照某种最优原则进行修正,直到分类比较合理为止;

思想:
  先假定样本可分为C类,选定C个初始聚类中心,然后根据最小距离原则将每个样本分配到某一类中,之后不断迭代计算各类的聚类中心,并依据新的聚类中心调整聚类情况,直到迭代收敛 or 聚类中心不再改变;

如何确定簇数 K ?

拐点法
  在不同的 K 值下计算簇内距离差平方和,然后通过可视化的方法找到拐点所对应的 K 值,重点关注斜率的变化,当斜率由大突然变小时,并且之后斜率变化缓慢,则认为突然变化的点就是目标点 K,因为之后随着 K 的增大聚类效果不会有大的变化;

这里随机生成三组二维正态分布数据,然后模拟数据,使用拐点法

import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans

mean = np.array([[-2, -2], [2, 2], [6, 6]])
cov = np.array([[[0.3, 0], [0, 0.3]], [[0.4, 0], [0, 0.4]], [[0.5, 0], [0, 0.5]]])
x0 = []
y0 = []
for i in range(3):
    x, y = np.random.multivariate_normal(mean[i], cov[i], 1000).T
    x0 = np.hstack([x0, x])
    y0 = np.hstack([y0, y])
plt.rc('font', size=16)
plt.rc('font', family='SimHei')
plt.rc('axes', unicode_minus=False)
plt.subplot(121)
plt.scatter(x0, y0, marker='.')  # 画模拟数据散点图
X = np.vstack([x0, y0]).T
np.save("Pzdata11_1.npy", X)  # 保存数据供下面使用
TSSE = []
K = 10
for k in range(1, K + 1):
    SSE = []
    md = KMeans(n_clusters=k)
    md.fit(X)
    labels = md.labels_
    centers = md.cluster_centers_
    for label in set(labels):
        SSE.append(np.sum((X[labels == label, :] - centers[label, :]) ** 2))
    TSSE.append(np.sum(SSE))
plt.subplot(122)
plt.style.use('ggplot')
plt.plot(range(1, K + 1), TSSE, 'b*-')
plt.xlabel('簇的个数')
plt.ylabel('簇内离差平方和之和')
plt.show()

结果如图:
在这里插入图片描述
很明显拐点即K=3的时候;

案例:
在这里插入图片描述
步骤:

  • 判断要不要标准化,像这个案例,量纲在同一级,可以不用标准化;
  • 选择 K 值,可以认为判断,也可以用前面说的 拐点法 选择;
# 程序文件Pex11_14.py
import numpy as np;
import pandas as pd
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt

a = pd.read_csv("iris.csv")
b = a.iloc[:, :-1]
md = KMeans(3)
md.fit(b)  # 构建模型并求解模型
labels = md.labels_
centers = md.cluster_centers_
b['cluster'] = labels  # 数据框b添加一个列变量cluster
c = b.cluster.value_counts()  # 各类频数统计
plt.rc('font', family='SimHei')
plt.rc('font', size=16)
str1 = ['^r', '.k', '*b']
plt.subplot(121)
for i in range(len(centers)):
    plt.plot(b['Petal_Length'][labels == i], b['Petal_Width']
    [labels == i], str1[i], markersize=3, label=str(i))
    plt.legend()
    plt.xlabel("(a)KMeans聚类结果")
plt.subplot(122)
str2 = ['setosa', 'versicolour', 'virginica']
ind = np.hstack([np.zeros(50), np.ones(50), 2 * np.ones(50)])
for i in range(3):
    plt.plot(b['Petal_Length'][ind == i], b['Petal_Width'][ind == i],
             str1[i], markersize=3, label=str2[i])
    plt.legend(loc='lower right')
    plt.xlabel("(b)原数据的类别")
plt.show()

在这里插入图片描述
可以发现 K-Means 的准确率还是挺高的,就那么十来个点有问题,大概错误率不到10%;

  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值