kmeans算法

3.1划分方法

 聚类算法距离——k-means算法

 k-means算法

输入:簇的数;数据集;
输出:k个簇
方法:从数据集中找出k个对象当作原始的簇心;

 k-means算法的再次解读

 k-means聚类算法练习-1

下面10个样本进行簇划分

 使用代码计算连续值属性距离

import numpy as np 
a=np.array([(3,4),(3,6),(7,3),(4,7),(3,8),(8,5),(4,5),(4,1),(7,4),(5,5)])
lines=""
for i in a:
    for j in a:
        dis=np.sqrt(np.sum((j-i)**2))
        lines += "%.2f"%dis + ","  #保留两位小数     #“str(dis)+","
    lines+='\n'
file=open("result.csv",mode="w",encoding="utf-8")
file.write(lines)
file.close()

 第一轮迭代完得到的分别以p7、p10为中心的两个簇

下面开始计算每个簇中心的均值

p7、p1、p2、p4、p5、p8样本点的x值相加求平均,y值相加求平均得到一个新的簇中心点
p10、p3、p6、p9样本点的x值相加求平均,y值相加求平均得到一个新的簇中心点

新的簇中心点再来和所有的样本数据点求距离

 实例

问题一
序号4和7是一样的(巧合),其实换做其他的序号3和7,与之前的结果不一样

问题二
结论是:k-means算法 的初始中心点对k-means算法有极大的影响,不同的初始点可能最终聚类的结果不同,特别是数据样本比较少的情况下

代码演示k-means算法

 数据样本

data.txt
3,4 3,6 7,3 4,7 3,8 8,5 4,5 4,1 7,4 5,5

 

"""
随机取k个中心点
计算所有点到中心点到距离
将所有点放入中心点所在到簇
    更新中心点
        如果中心点不变,结束迭代
迭代
"""
import numpy as np 

#获取数据集
def loadDataSet(filename):
    return np.loadtxt(filename,delimiter=',',dtype=np.float)

#取k个中心点
def initCenters(dataset,k):
    """
    返回的k个中心点
    dataset:数据集
    k:中心点的个数
    return:
    """
    centersIndex=np.random.choice(len(dataset),k,replace=False)
    return dataset[centersIndex]

#计算距离
def distance(x,y):
    return np.sqrt(np.sum((x-y)**2))

#kmeans的核心算法
def kmeans(dataset,k):
    """
    dataset:数据集
    k:中心点的个数
    return:k个簇
    """
    #初始化中心点
    # centers=initCenters(dataset,k)
    centers=np.array([[4,5],[5,5]],dtype=np.float)
    n,m=dataset.shape
    #用于存储每个样本属于哪个簇
    clusters=np.full(n,np.nan)
    #迭代
    flag=True
    while flag:
        flag=False
        #计算所有点到簇中心的距离
        for i in range(n):
            minDist,clustersIndex=99999999,0
            for j in range(len(centers)):
                dist=distance(dataset[i],centers[j])
                if dist<minDist:
                    #为样本分簇
                    minDist=dist
                    clustersIndex=j
             #判断簇是否改变       
            if clusters[i]!=clustersIndex:
                clusters[i]=clustersIndex
                flag=True
        print(centers)
        print(clusters)
        #更新簇中心
        for i in range(k):
            subdataset=dataset[np.where(clusters==i)]   #得到下标
            centers[i]=np.mean(subdataset,axis=0)
        print("循环一次")       
    return clusters 


if __name__=='__main__':
    dataset=loadDataSet('data.txt')
    print(kmeans(dataset,2))

结果

 加上簇点显示代码(相比上面只添加了红色字段部分)

"""
随机取k个中心点
计算所有点到中心点到距离
将所有点放入中心点所在到簇
    更新中心点
        如果中心点不变,结束迭代
迭代
"""
import numpy as np 
import matplotlib.pyplot as plt   
#获取数据集
def loadDataSet(filename):
    return np.loadtxt(filename,delimiter=',',dtype=np.float)

#取k个中心点
def initCenters(dataset,k):
    """
    返回的k个中心点
    dataset:数据集
    k:中心点的个数
    return:
    """
    centersIndex=np.random.choice(len(dataset),k,replace=False)
    return dataset[centersIndex]

#计算距离
def distance(x,y):
    return np.sqrt(np.sum((x-y)**2))

#kmeans的核心算法
def kmeans(dataset,k):
    """
    dataset:数据集
    k:中心点的个数
    return:k个簇
    """
    #初始化中心点
    # centers=initCenters(dataset,k)
    centers=np.array([[4,5],[5,5]],dtype=np.float)
    n,m=dataset.shape
    #用于存储每个样本属于哪个簇
    clusters=np.full(n,np.nan)
    #迭代
    flag=True
    while flag:
        flag=False
        #计算所有点到簇中心的距离
        for i in range(n):
            minDist,clustersIndex=99999999,0
            for j in range(len(centers)):
                dist=distance(dataset[i],centers[j])
                if dist<minDist:
                    #为样本分簇
                    minDist=dist
                    clustersIndex=j
             #判断簇是否改变       
            if clusters[i]!=clustersIndex:
                clusters[i]=clustersIndex
                flag=True
        print(centers)
        print(clusters)
        #更新簇中心
        for i in range(k):
            subdataset=dataset[np.where(clusters==i)]   #得到下标
            centers[i]=np.mean(subdataset,axis=0)
        print("循环一次")       
    return clusters,centers

#显示
def show(dataset,k,clusters,centers):
    n,m = dataset.shape
    if m>2:
        print('维度大于2')
        return 1
    #根据簇的不同marker不同
    colors = ["r","g","b","y"]
    for i in range(n):
        clusterIndex = clusters[i].astype(np.int)
        plt.plot(dataset[i][0],dataset[i][1],color=colors[clusterIndex], marker='o')
        pass
    for i in range(k):
        plt.scatter(centers[i][0],centers[i][1],marker='s')
        pass
    plt.show()
        

if __name__=='__main__':
    dataset=loadDataSet('data.txt')
    clusters,centers = kmeans(dataset,2)
    show(dataset,2,clusters,centers)

显示结果

 注意红色需要注释

"""
随机取k个中心点
计算所有点到中心点到距离
将所有点放入中心点所在到簇
    更新中心点
        如果中心点不变,结束迭代
迭代
"""
import numpy as np 
import matplotlib.pyplot as plt   
#获取数据集
def loadDataSet(filename):
    return np.loadtxt(filename,delimiter=',',dtype=np.float)

#取k个中心点
def initCenters(dataset,k):
    """
    返回的k个中心点
    dataset:数据集
    k:中心点的个数
    return:
    """
    centersIndex=np.random.choice(len(dataset),k,replace=False)
    return dataset[centersIndex]

#计算距离
def distance(x,y):
    return np.sqrt(np.sum((x-y)**2))

#kmeans的核心算法
def kmeans(dataset,k):
    """
    dataset:数据集
    k:中心点的个数
    return:k个簇
    """
    #初始化中心点
    centers=initCenters(dataset,k)
   # centers=np.array([[4,5],[5,5]],dtype=np.float)
    n,m=dataset.shape
    #用于存储每个样本属于哪个簇
    clusters=np.full(n,np.nan)
    #迭代
    flag=True
    while flag:
        flag=False
        #计算所有点到簇中心的距离
        for i in range(n):
            minDist,clustersIndex=99999999,0
            for j in range(len(centers)):
                dist=distance(dataset[i],centers[j])
                if dist<minDist:
                    #为样本分簇
                    minDist=dist
                    clustersIndex=j
             #判断簇是否改变       
            if clusters[i]!=clustersIndex:
                clusters[i]=clustersIndex
                flag=True
        print(centers)
        print(clusters)
        #更新簇中心
        for i in range(k):
            subdataset=dataset[np.where(clusters==i)]   #得到下标
            centers[i]=np.mean(subdataset,axis=0)
        print("循环一次")       
    return clusters,centers

#显示
def show(dataset,k,clusters,centers):
    n,m = dataset.shape
    if m>2:
        print('维度大于2')
        return 1
    #根据簇的不同marker不同
    colors = ["r","g","b","y"]
    for i in range(n):
        clusterIndex = clusters[i].astype(np.int)
        plt.plot(dataset[i][0],dataset[i][1],color=colors[clusterIndex], marker='o')
        pass
    for i in range(k):
        plt.scatter(centers[i][0],centers[i][1],marker='s')
        pass
    plt.show()
        

if __name__=='__main__':
    dataset=loadDataSet('data.txt')
    clusters,centers = kmeans(dataset,3)  #分成3个簇
    show(dataset,3,clusters,centers)

显示结果

k-means算法无法探测凹形簇

打算分成左边形式,带对应缺点三,所以k-means只能分成有图形式

聚簇结果的评价标准(二)

 k-means算法在电信运营中的应用案例

posted @ 2021-05-17 15:45  北极星!  阅读(215)  评论(0编辑  收藏  举报