【二分-kMeans算法】二分K均值聚类分析与Python代码实现

一、k-means算法优缺点
k均值简单并且可以用于各种数据类型,它相当有效,尽管常常多次运行。然后k均值并不适合所有的数据类型。它不能处理非球形簇,不同尺寸和不同密度的簇。对包含离群点(噪声点)的数据进行聚类时,k均值也有问题。

https://github.com/Thinkgamer/Machine-Learning-With-Python

二、k-means算法python实现

#encoding:utf-8
from numpy import *

def loadDataSet(filename):
    dataMat = []          #创建元祖
    fr = open(filename)
    for line in fr.readlines():
        curLine = line.strip().split("\t")
        fltLine = map(float,curLine) #使用map函数将curLine里的数全部转换为float型
        dataMat.append(fltLine)
    return dataMat

def distEclud(vecA,vecB):          #计算两个向量的欧式距离
    return sqrt(sum(power(vecA-vecB,2)))

def randCent(dataSet,k):            #位给定数据集构建一个包含k个随机质心的集合
    n = shape(dataSet)[1]   #shape函数此时返回的是dataSet元祖的列数
    centroids = mat(zeros((k,n)))       #mat函数创建k行n列的矩阵,centroids存放簇中心
    for j in range(n):
        minJ = min(dataSet[:,j])           #第j列的最小值
        rangeJ = float(max(dataSet[:,j]) - minJ)
        centroids[:,j] = minJ + rangeJ * random.rand(k,1)  #random.rand(k,1)产生shape(k,1)的矩阵
    return centroids

def kMeans(dataSet,k,disMeas = distEclud,createCent = randCent):
    m = shape(dataSet)[0] #shape函数此时返回的是dataSet元祖的行数
    clusterAssment = mat(zeros((m,2)))      #创建一个m行2列的矩阵,第一列存放索引值,第二列存放误差,误差用来评价聚类效果
    centroids = createCent(dataSet,k)  #创建k个质心,调用createCent()函数
    clusterChanged =True #标志变量,若为true则继续迭代
    print "质心位置更新过程变化:"
    while clusterChanged:
        clusterChanged = False
        for i in range(m):
            minDist = inf #inf为正无穷大
            minIndex = -1  #创建索引
            for j in range(k):
                #寻找最近的质心
                disJI = disMeas(centroids[j,:],dataSet[i,:]) #计算每个点到质心的欧氏距离
                if disJI<minDist:
                    minDist = disJI
                    minIndex = j
            if clusterAssment[i,0] != minIndex:
                clusterChanged = True
            clusterAssment[i,:] = minIndex,minDist**2
            print centroids
            #更新质心的位置
            for cent in range(k):
                ptsInClust = dataSet[nonzero(clusterAssment[:,0].A==cent)[0]]#通过数组过滤来获得给定簇的所有点
                #nonzero(a)函数返回值为元祖a的所有非零值得下标所构成的元祖
                #eg:b2 = array([[True, False, True], [True, False, False]])
                #print nonzero(b2)
                #=>(array([0, 0, 1]), array([0, 2, 0]))
                #print array(nonzero(b2))
                #=>[[0, 0, 1],[0, 2, 0]]
                centroids[cent,:] = mean(ptsInClust,axis=0)  #计算所有点的均值,选项axis=0表示沿矩阵的列方向进行均值计算
    return centroids,clusterAssment  #返回所有的类质心与点分配结果

def bikMeans(dataSet,k,disMeas = distEclud):
    m = shape(dataSet)[0] #shape函数此时返回的是dataSet元祖的行数
    clusterAssment = mat(zeros((m,2)))      #创建一个m行2列的矩阵,第一列存放索引值,第二列存放误差,误差用来评价聚类效果
    #创建一个初始簇
    centroid0 = mean(dataSet,axis=0).tolist()[0]
    centList = [centroid0]
    print centList
    print len(centList)
    for j in range(m):
        clusterAssment[j,1] = disMeas(mat(centroid0),dataSet[j,:])**2 #计算所有点的均值,选项axis=0表示沿矩阵的列方向进行均值计算
    while (len(centList)<k):
        lowestSSE = inf #inf正无穷大
        for i in range(len(centList)):
            #尝试划分每一簇
            ptsInCurrCluster = dataSet[nonzero(clusterAssment[:,0].A==i)[0],:]
            centroidMat,splitClustAss = kMeans(ptsInCurrCluster,2,disMeas)

            sseSplit = sum(splitClustAss[:,1])
            sseNotSplit = sum(clusterAssment[nonzero(clusterAssment[:,0].A!=i)[0],1])
            print "sseSplit and notSplit:",sseSplit,sseNotSplit
            if (sseSplit + sseNotSplit)<lowestSSE:
                bestCentToSplit = i
                bestNewCents = centroidMat
                bestClustAss = splitClustAss.copy()
                lowestSSE = sseSplit + sseNotSplit
        #更新簇的分配结果
        bestClustAss[nonzero(bestClustAss[:,0].A == 1)[0],0] = len(centList)
        bestClustAss[nonzero(bestClustAss[:,0].A == 0)[0],0] = bestCentToSplit

        print "the bestCentToSplit is :",bestCentToSplit
        print "the len of bestClustAss is:",len(bestClustAss)
        centList[bestCentToSplit] = bestNewCents[0,:]
        centList.append(bestNewCents[1,:])
        clusterAssment[nonzero(clusterAssment[:,0].A == bestCentToSplit)[0],:] =bestClustAss
    return centList,clusterAssment
        #return mat(centList),clusterAssment

datMat = mat(loadDataSet('data.txt'))
myCentList,myNewAssment = bikMeans(datMat,2)
print "最终质心:\n",myCentList
print "索引值和均值:\n",myNewAssment

参考资料
1:【关联规则】Apriori算法分析与Python代码实现,具体分析请参考博客:
http://blog.csdn.net/gamer_gyt/article/details/51113753
2:【关联规则】FP-Tree算法分析与Python代码实现,具体分析请参考博客:
http://blog.csdn.net/gamer_gyt/article/details/51113753
3:【决策树算法】基于信息论的三种决策树算法之ID3算法分析与Python代码实现,具体分析请参考博客:
http://blog.csdn.net/gamer_gyt/article/details/51242815
4:【聚类算法】二分-kMeans算法(二分K均值聚类)分析与Python代码实现,具体分析请参考博客:
http://blog.csdn.net/gamer_gyt/article/details/48949227
5:【回归算法】Logistic回归算法分析与Python代码实现,具体分析请参考博客:
http://blog.csdn.net/gamer_gyt/article/details/51236978
http://blog.csdn.net/gamer_gyt/article/details/51242150
6:【分类算法】AdaBoost算法分析与Python代码实现,具体分析请参考博客:
http://blog.csdn.net/gamer_gyt/article/details/51372309
7:【分类算法】朴素贝叶斯算法分析与Python代码实现,具体分析请参考博客:
http://blog.csdn.net/gamer_gyt/article/details/47205371
http://blog.csdn.net/gamer_gyt/article/details/47860945
8:【回归算法】预测数值型数据-回归(Regression)分析与Python代码实现,具体分析请参考博客:
http://blog.csdn.net/gamer_gyt/article/details/51405251
9:【降维技术】PCA降维技术分析与Python代码实现,具体分析请参考博客:
http://blog.csdn.net/gamer_gyt/article/details/51418069
10:【推荐系统】基于标签的推荐系统,具体分析请参考博客:
http://blog.csdn.net/gamer_gyt/article/details/51684716
11:【推荐系统】基于图推荐系统,具体分析请参考博客:
http://blog.csdn.net/gamer_gyt/article/details/51694250
12:【推荐系统】基于用户和Item的协同过滤推荐算法,具体分析请参考博客:
http://blog.csdn.net/gamer_gyt/article/details/51346159
13:基于随机变量的熵来进行数据建模和分析
http://blog.csdn.net/gamer_gyt/article/details/53729868
14:推荐算法的回顾总结
http://blog.csdn.net/gamer_gyt/article/details/74367714

  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
以下是使用Python实现二分-k均值聚类算法进行图像分割的完整代码: ``` python import numpy as np from PIL import Image def load_image(filename): img = Image.open(filename) return np.array(img) def save_image(filename, data): img = Image.fromarray(np.uint8(data)) img.save(filename) def kmeans(data, k, max_iter=100): centers = np.random.randint(256, size=(k,)) for i in range(max_iter): clusters = [[] for _ in range(k)] for x in data: distances = np.abs(centers - x) idx = np.argmin(distances) clusters[idx].append(x) new_centers = [np.mean(cluster) for cluster in clusters] if np.allclose(new_centers, centers): break centers = new_centers return centers, clusters def bisecting_kmeans(data, k, max_iter=100): clusters = [data] while len(clusters) < k: max_sse = -1 for i, cluster in enumerate(clusters): centers, subclusters = kmeans(cluster, 2, max_iter) sse = 0 for subcluster in subclusters: distances = np.abs(subcluster - centers[0]) sse += np.sum(distances ** 2) if sse > max_sse: max_sse = sse max_idx = i max_centers = centers max_subclusters = subclusters clusters.pop(max_idx) clusters.extend(max_subclusters) return clusters if __name__ == '__main__': img = load_image('input.jpg') data = img.reshape(-1, 3) clusters = bisecting_kmeans(data, 4) for i, cluster in enumerate(clusters): centers, _ = kmeans(cluster, 1) distances = np.abs(cluster - centers[0]) mask = np.argmin(distances, axis=1) == 0 data[mask] = centers[0] img = data.reshape(img.shape) save_image('output.jpg', img) ``` 该代码使用PIL库读取和保存图像,numpy库进行数组操作。首先,将输入图像转换成数据数组。然后使用二分-k均值聚类算法将数据分成四个簇。接下来,对于每个簇,使用k均值聚类算法将其压缩为一个点,并使用该点将簇中所有像素点赋值为该点的颜色。最后,将数据数组转换回图像并保存输出图像。 注意,这里默认输入图像为RGB格式,如果输入图像为其他格式,需要根据实际情况进行修改。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

东华果汁哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值