机器学习之K-Means聚类

1.聚类

聚类:简而言之就是物以类聚,与分类不同的是,对目标是未知的。它是一种无监督的学习(Unsupervised Learning)方法,不需要预先标注好的训练集。
分类:目标类别已知,对数据进行归类。

2.K-Means 算法

kmeans算法又名k均值算法。其算法思想大致为:先从样本集中随机选取 k个样本作为簇中心,并计算所有样本与这 k个“簇中心”的距离,对于每一个样本,将其划分到与其距离最近的“簇中心”所在的簇中,对于新的簇计算各个簇的新的“簇中心”。   
根据以上描述,我们大致可以猜测到实现kmeans算法的主要三点:   
(1)簇个数 k的选择   (2)各个样本点到“簇中心”的距离   (3)根据新划分的簇,更新“簇中心”

2.1瓜的分类

现在有一批数据,西瓜的甜度和水分。

甜度水分
1.6589854.285136
3.4536873.424321
4.8381381.151539

可以对这些西瓜来进行一个聚类,数据展示如下:在这里插入图片描述

1.产生K个随机质心
# 为给定数据集构建一个包含 k 个随机质心的集合。随机质心必须要在整个数据集的边界之内,这可以通过找到数据集每一维的最小和最大值来完成。然后生成 0~1.0 之间的随机数并通过取值范围和最小值,以便确保随机点在数据的边界之内。
def randCent(dataSet, k):
    n = shape(dataSet)[1] # 列的数量,即数据的特征个数
    centroids = mat(zeros((k,n))) # 创建k个质心矩阵
    for j in range(n): # 创建随机簇质心,并且在每一维的边界内
        minJ = min(dataSet[:,j])    # 最小值
        rangeJ = float(max(dataSet[:,j]) - minJ)    # 范围 = 最大值 - 最小值
        centroids[:,j] = mat(minJ + rangeJ * random.rand(k,1))    # 随机生成,mat为numpy函数,需要在最开始写上 from numpy import *
    return centroids
2.计算两个向量的欧氏距离

n维空间的公式
在这里插入图片描述

# 计算两个向量的欧式距离(可根据场景选择其他距离公式)
def distEclud(vecA, vecB):
    return sqrt(sum(power(vecA - vecB, 2))) # la.norm(vecA-vecB)
3.K-Means 聚类算法
def kMeans(dataSet, k, distMeans=distEclud, createCent=randCent):
    m = shape(dataSet)[0]
    clusterAssment = mat(zeros((m, 2)))    # 用于存放该样本属于哪类及质心距离
    # clusterAssment第一列存放该数据所属的中心点,第二列是该数据到中心点的距离
    centroids = createCent(dataSet, k)

    plt.title('start', fontsize=24)
    plt.xlabel('X', fontsize=14)
    plt.ylabel('Y', fontsize=14)
    for i in range(shape(dataSet)[0]):
        plt.scatter(dataSet[i, 0], dataSet[i, 1], s=50, c='b', alpha=0.5)
    for i in range(shape(centroids)[0]):
        plt.scatter(centroids[i, 0], centroids[i, 1], s=50, c='r', alpha=1, marker='x')
    # 设置刻度标记的大小
    plt.tick_params(axis='both', which='major', labelsize=14)
    plt.show()

    clusterChanged = True   # 用来判断聚类是否已经收敛
    while clusterChanged:
        clusterChanged = False
        for i in range(m):  # 把每一个数据点划分到离它最近的中心点
            minDist = inf	# inf表示无穷大
            minIndex = -1
            for j in range(k):
                distJI = distMeans(centroids[j, :], dataSet[i, :])
                if distJI < minDist:
                    minDist = distJI
                    minIndex = j  # 如果第i个数据点到第j个中心点更近,则将i归属为j
            if clusterAssment[i, 0] != minIndex:
                clusterChanged = True  # 如果分配发生变化,则需要继续迭代
            clusterAssment[i, :] = minIndex, minDist**2   # 并将第i个数据点的分配情况存入字典
        for cent in range(k):   # 重新计算中心点
            ptsInClust = dataSet[nonzero(clusterAssment[:, 0].A == cent)[0]]   # 取第一列等于cent的所有列
            centroids[cent, :] = mean(ptsInClust, axis=0)  # 算出这些数据的中心点
        show(dataSet, clusterAssment, centroids)
    return centroids, clusterAssment
4.数据plt展示与运行
def show(dataSet, clusterAssment, centroids):
    plt.title('K Means', fontsize=24)
    plt.xlabel('X', fontsize=14)
    plt.ylabel('Y', fontsize=14)
    for i in range(shape(dataSet)[0]):
        if clusterAssment[i, 0] == 0:
            col = 'b'
        if clusterAssment[i, 0] == 1:
            col = 'c'
        if clusterAssment[i, 0] == 2:
            col = 'g'
        if clusterAssment[i, 0] == 3:
            col = 'm'
        plt.scatter(dataSet[i, 0], dataSet[i, 1], s=50, c=col, alpha=0.5)
    for i in range(shape(centroids)[0]):
        plt.scatter(centroids[i, 0], centroids[i, 1], s=50, c='r', alpha=1, marker='x')
    # 设置刻度标记的大小
    plt.tick_params(axis='both', which='major', labelsize=14)
    plt.show()

# 用测试数据及测试kmeans算法
datMat = mat(loadDataSet('testSet.txt'))
myCentroids, clustAssing = kMeans(datMat, 4)
# print(clustAssing)
print(myCentroids)
5.结果

在这里插入图片描述

3.K-Means 算法缺点

  • 需手动设置k值。 在算法开始预测之前,我们需要手动设置k值,即估计数据大概的类别个数,不合理的k值会使结果缺乏解释性
  • 可能收敛到局部最小值, 在大规模数据集上收敛较慢
  • 对于异常点、离群点敏感
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值