欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

学习笔记:机器学习实战之Kmeans

程序员文章站 2022-05-20 19:50:03
...

kmeans算法注释版,新手小白,如有错误,还请不吝指教

#Kmeans算法
def kMeans(dataSet, k):
    dataSet = mat(dataSet)  #转换成mat类型
    m = shape(dataSet)[0]   #获取数据集的行数
    #第一列记录数据集的类别,第二列记录数据集到聚类中心的距离
    clusterAssment = mat(zeros((m,2)))#初始化
    centroids = randomCentroids(dataSet, k)#获取聚类中心
    clusterChanged = True   #用于判断聚类中心是否改变
    while clusterChanged:
        clusterChanged = False
        for i in range(m):
            minDist = inf   #最小距离初始化
            minIndex = -1   #最小距离下标初始化
            for j in range(k):
                #求解聚类中心与数据集的欧式距离
                distance = euclideanDistance(centroids[j,:],dataSet[i,:])
                if distance < minDist:
                    minDist = distance
                    minIndex = j
            if clusterAssment[i,:] != minIndex:
                clusterChanged = True
            clusterAssment[i,:] = minIndex,minDist**2
        print(centroids)#输出聚类中心
        for cent in range(k):
            ptsInClust = dataSet[nonzero(clusterAssment[:,0].A==cent)[0]]
            centroids[cent,:] = mean(ptsInClust, axis=0)#axis=0表示在列上对聚类中心的数据取平均值,即更新聚类中心

    return centroids, clusterAssment

对于下面这行代码,单独解释。

ptsInClust = dataSet[nonzero(clusterAssment[:,0].A==cent)[0]]

举个例子:

    a = [[0,1],[2,0],[3,0],[0,4]]
    a = mat(a)
    print(a)

输出为:

[[0 1]
 [2 0]
 [3 0]
 [0 4]]
此时a是一个4*2的矩阵,若使用nonzero()函数,则有输出
   print(nonzero(a))
(array([0, 1, 2, 3], dtype=int64), array([1, 0, 0, 1], dtype=int64))

可见,nonzero(),返回两个元组:

第一个元组里有,不为零元素的行的索引,以及该元素的类型

第二个元组中则是不为零元素的列的索引,以及该元素的类型

而对于Kmeans算法中的第25行代码中的.A,其实是就是返回数组本身。

在Kmeans这个代码里,矩阵类型和数组(array)类型的形式是一样的,所以加不加.A结果都一样。

具体参考numpy官方文档

https://docs.scipy.org/doc/numpy/reference/generated/numpy.matrix.A.html#numpy.matrix.A

贴个图,我想文档中的.A和Kmeans算法中的.A应该是一回事。

学习笔记:机器学习实战之Kmeans

拿之前的矩阵a举例(下同):

    print(nonzero(a[:,0].A))
    print(nonzero(a[:,0]))
(array([1, 2], dtype=int64), array([0, 0], dtype=int64))
(array([1, 2], dtype=int64), array([0, 0], dtype=int64))

在Kmeans算法中,要在数据集中选择和聚类中心相同类别的下标,并且将该条数据归类到该聚类中心,

首先要得到该数据的下标,假设现在要求第三个聚类中心的下标,有如下代码:

    print(nonzero(a[:,0].A==3))
    print(nonzero(a[:,0]==3))
(array([2], dtype=int64), array([0], dtype=int64))
(array([2], dtype=int64), array([0], dtype=int64))

由上面的结果可知,返回了两个元组,但是我们只想得到该条数据的下标,所以只需取它的行信息,则有:

    print(nonzero(a[:,0].A==3)[0])
    print(nonzero(a[:,0]==3)[0])
[2]
[2]

发现输出为该条数据的下标,即我们想要的结果,同时我们也可以观察到,无论有没有.A,结果都是一样的。


解释完毕,实在是学不动了,写个博客放松一下心情。


参考资料:  https://blog.csdn.net/u013698770/article/details/54632047

相关标签: Kmeans