k均值聚类、k中心点聚类

K均值聚类
K-means算法是很典型的基于距离的聚类算法,采用距离作为相似性的评价指标,即认为两个对象的距离越近,其相似度就越大。该算法认为簇是由距离靠近的对象组成的,因此把得到紧凑且独立的簇作为最终目标。算法采用误差平方和准则函数作为聚类准则函数。

算法过程如下:

1)从N个文档随机选取K个文档作为质心 
2)对剩余的每个文档测量其到每个质心的距离,并把它归到最近的质心的类 
3)重新计算已经得到的各个类的质心 
4)迭代2~3步直至新的质心与原质心相等或小于指定阈值,算法结束

#_*_coding:utf-8_*_
#作者      :hjy
#创建时间   :19-3-4 上午11:09 
#文件       :K_Mean.py
#IDE       :PyCharm
from math import sqrt
import random
from PIL import ImageDraw, Image

def readfile(filename):
    """
    读取表格型数据,获取特征数据集
    :param filename:
    :return: rownames, colnames, data
    """
    lines = [line for line in open(filename)]

    #第一行是列标题
    colnames = lines[0].strip().split('\t')[1:]
    rownames = []
    data = []
    for line in lines[1:]:
        p = line.strip().split('\t')
        #每行的第一列是行名
        rownames.append(p[0])
        #剩余部分就是该行对应的数据
        onerow = [float(x) for x in p[1:]]
        data.append(onerow)
    return rownames, colnames, data


def pearson(v1, v2):
    """
    计算两个聚类中心点的皮尔逊相似度
    :param v1:
    :param v2:
    :return:
    """
    #简单求和
    sum1 = sum(v1)
    sum2 = sum(v2)

    #求平方和
    sum1Sq = sum([pow(v, 2) for v in v1])
    sum2Sq = sum([pow(v, 2) for v in v2])

    #求乘积之和
    pSum =sum([v1[i] * v2[i] for i in range(len(v1))])

    #计算距离
    num = pSum-(sum1 * sum2/len(v1))
    den = sqrt((sum1Sq - pow(sum1, 2)/len(v1)) * (sum2Sq - pow(sum2, 2)/len(v1)))
    if den == 0:
        return 0
    return 1.0-num/den


def tanamoto(v1, v2):
    """
    使用tanimoto系数表示距离(相似度):两个向量的交集/两个向量的并集
    :param v1:
    :param v2:
    :return:
    """
    c1, c2, shr=0, 0, 0
    for i in range(len(v1)):
        if v1[i] != 0:
            c1 += 1
        if v2[i] != 0:
            c2 += 1
        if v1[i] != 0 and v2[i] != 0:
            shr += 1
    return 1.0 - (float(shr)/(c1 + c2 - shr))


def kcluster(rows, distance=pearson, k=4):
    """
    K-mean算法
    :param rows: 数据集
    :param distance:
    :param k:聚类数目
    :return:
    """
    #确定每个点的特征的最大值和最小值
    ranges = [(min([row[i] for row in rows]), max(row[i] for row in rows)) for i in range(len(rows[0]))]

    #随机创建K个中心点
    clusters = [[random.random()*(ranges[i][1]-ranges[i][0])+ranges[i][0] for i in range(len(rows[0]))] for j in range(k)]

    lastmatches = None
    for t in range(100):
        print('迭代 %d' %t)
        bestmatches = [[] for i in range(k)] #生成k个空数组,用于存储k个聚类点包含的成员

        #在每行中寻找距离最近的点
        for j in range(len(rows)):
            row = rows[j]
            bestmatch = 0
            for i in range(k):
                d = distance(clusters[i], row)
                if d <distance(clusters[bestmatch], row):
                    bestmatch = i #计算与哪个聚类点最近
            bestmatches[bestmatch].append(j)

        #如果结果与上一次相同,则整个过程结束
        if bestmatches == lastmatches:
            break
        lastmatches = bestmatches

        #把中心点移动到成员的平均位置处
        for i in range(k):
            avgs = [0.0] * len(rows[0])
            if len(bestmatches[i]) > 0:
                for rowid in bestmatches[i]:
                    for m in range(len(rows[rowid])):
                        avgs[m] += rows[rowid][m]
                for j in range(len(avgs)):#在每个维度都计算均值
                    avgs[j] /= len(bestmatches[i])
                clusters[i] = avgs

    return bestmatches#返回k个聚类点,以及所包含的所有成员

k-means聚类的优缺点:
k-means算法的优点:

(1)k-means算法是解决聚类问题的一种经典算法,算法简单、快速。

(2)对处理大数据集,该算法是相对可伸缩的和高效率的,因为它的复杂度大约是O(nkt),其中n是所有对象的数目,k是簇的数目,t是迭代的次数。通常k<<n。这个算法通常局部收敛。

(3)算法尝试找出使平方误差函数值最小的k个划分。当簇是密集的、球状或团状的,且簇与簇之间区别明显时,聚类效果较好。

缺点:

(1)k-平均方法只有在簇的平均值被定义的情况下才能使用,且对有些分类属性的数据不适合。

(2)要求用户必须事先给出要生成的簇的数目k。

(3)对初值敏感,对于不同的初始值,可能会导致不同的聚类结果。

(4)不适合于发现非凸面形状的簇,或者大小差别很大的簇。

(5)对于”噪声”和孤立点数据敏感,少量的该类数据能够对平均值产生极大影响。

k中心点算法
k中心算法的基本过程是:首先为每个簇随意选择一个代表对象,剩余的对象根据其与每个代表对象的距离(此处距离不一定是欧氏距离,也可能是曼哈顿距离)分配给最近的代表对象所代表的簇;然后反复用非代表对象来代替代表对象,以优化聚类质量。聚类质量用一个代价函数来表示。当一个中心点被某个非中心点替代时,除了未被替换的中心点外,其余各点被重新分配。 
为了减轻k均值算法对孤立点的敏感性,k中心点算法不采用簇中对象的平均值作为簇中心,而选用簇中离平均值最近的对象作为簇中心。 
算法如下: 
输入:包含n个对象的数据库和簇数目k; 
输出:k个簇 
(1)随机选择k个代表对象作为初始的中心点 
(2)指派每个剩余对象给离它最近的中心点所代表的簇 
(3)随机地选择一个非中心点对象y 
(4)计算用y代替中心点x的总代价s 
(5)如果s为负,则用可用y代替x,形成新的中心点 
(6) 重复(2)(3)(4)(5),直到k个中心点不再发生变化.

原文:https://blog.csdn.net/luanpeng825485697/article/details/78993977 
 

  • 0
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值