原型聚类总结

概述

原型聚类是指聚类结构能通过一组原型刻画,原型是指样本空间中具有代表性的点。通常情况下,算法先对原型进行初始化,然后对原型进行迭代更新求解,下面是几种著名的原型聚类算法。

K均值算法

给定样本集合D,K均值算法针对聚类所得簇划分C,最小化平方误差

E=∑ki=1∑x∈Ci||x?μi||22

其中μi=1|Ci|∑x∈Cix是簇Ci的均值向量。直观来看,这个误差刻画了簇内样本围绕簇均值向量的紧密程度,E值越小则簇内样本相似度越高。

K均值法采用贪心策略,通过迭代近似求解上式,算法首先随机选择k个向量作为初始均值向量,然后是迭代过程,根据均值向量将样本划分到距离最近的均值向量所在的簇中,划分完成之后更新新的均值向量,直到迭代完成。

代码见最后

二分K均值法

K均值法依赖于初始均值向量的选择,导致算法可能收敛到局部最小值,一种改进的方法是二分K均值法,这里的二分不是指算法课程中的二分,而是一分为二的意思。

二分K均值法初始时将所有点看成一个簇,在簇的数量小于K的时候进行迭代,算法的核心是选择一个簇一分为二,这里一分为二的方法还是K均值法,只不过K变成了2。二分K均值依次计算每个簇一分为二后新的总平方误差,选择划分后总体平方误差最小的簇进行划分,代码见最后。

学习向量量化LVQ

与K均值法类似,学习向量量化也是试图找到一组原型向量来刻画聚类结构,但不同的是,LVQ假设数据样本带有类别信息,学习过程利用样本的这些监督信息来辅助聚类,可看作通过聚类来形成类别的子类结构,每个子类对应一个聚类簇。

给定样本集,原型向量个数,各原型向量的类别标记,学习率,

算法首先初始化一组原型向量,可以从该类别中随机选取一个向量作为原型向量。初始化完成之后,开始迭代过程,每次从样本集中选取一个样本(x,y),将这个样本划分到距离它最近的原型向量p所在的簇中,如果这两个向量的类别标记相同,那么更新p为

p=p+η?(x?p)

若类别标记不相同,更新p为

p=p?η?(x?p)

直观上来看,若类别标记相同,原型向量向x的方向靠拢,否则远离。算法的停止条件是达到最大迭代轮数或者原型向量更新很小。

算法学习得到一组原型向量,对任意样本来说,它将被划分到与其最近的原型向量所代表的簇中,该划分通常称为“Voronoi”划分。

代码见最后

高斯混合聚类

与K均值,LVQ用原型向量刻画聚类结构不同,高斯混合聚类采用概率模型来表达聚类原型。

多元高斯分布的定义:对于n维样本空间中的随即向量x,若x服从高斯分布,其概率密度函数为

p(x)=1(2π)n/2|Σ|1/2e?1/2(x?μ)TΣ?1(x?μ)

可以看到,高斯分布完全由均值向量μ和协方差矩阵Σ确定,将概率密度函数记为p(x|μ,Σ)

我们定义高斯混合分布为

pM(x)=∑ki=1αip(x|μi,Σi)

该分布共由k个混合成分构成,每个混合成分对应一个高斯分布,其中μi,Σi是第i个高斯混合成分的参数,而αi>0是相应的混合系数。

假设样本的生成过程由高斯分布给出,首先,根据αi定义的先验分布选择高斯混合成分,然后根据被选择的混合成分的概率密度函数进行采样。

若训练集D由上述过程生成,令随机变量zj∈{1...k}表示生成样本xj的高斯混合成分,其取值未知,显然,zj的先验概率P(zj=i)=αi 。根据贝叶斯定理,zj的后验分布等于

pM(zj=i|xj)=P(zj=i)pM(xj|zj=i)pM(xj)=αipM(xj|μi,Σi)∑kl=1αlpM(xj|μl,Σl)

将这个后验概率记为γji

当高斯混合分布已知,即所有参数都已知时,可以计算每个样本由第i个高斯混合成分生成的后验概率,取其中的最大值然后标记样本所属该簇。

因此,从原型聚类的角度来看,高斯混合聚类是采用概率模型对原型进行刻画,簇划分则由原型对应的后验概率确定。

现在的问题就是求解各混合成分的参数,这一步可以用极大似然估计。

对数似然为

LL(D)=ln(∏mj=1pM(xj))=∑mj=1ln(∑ki=1αip(xj|μi,Σi))

然后可以用EM算法进行迭代优化求解,具体见下一篇博客。

K均值法和二分K均值法代码

from numpy import *

#k均值算法

def loadData(filename):
    dataMat = []
    fr = open(filename)
    for line in fr.readlines():
        curLine = line.strip().split(‘\t‘)
        fltLine = list(map(float, curLine))
        dataMat.append(fltLine)
    return dataMat

def distEclud(vecA, vecB):
    return sqrt(sum(power(vecA-vecB, 2)))

def randCent(dataSet, k):
    n = shape(dataSet)[1]
    centroids = mat(zeros((k, n)))
    for j in range(n):
        minJ = min(dataSet[:, j])
        rangeJ = float(max(dataSet[:, j])-minJ)
        # 常数直接和数组相加结果是数组的每一项加上这个常数
        centroids[:, j] = minJ + rangeJ*random.rand(k, 1)
    return centroids

#k均值法
def kMeans(dataSet, k, distMeas=distEclud, createCent=randCent):
    m, n = shape(dataSet)
    centroids = createCent(dataSet, k)
    # 每个样本被分到了到各类,以及到这个类质心的距离
    clusterAssign = mat(-1*ones((m, 2)))
    clusterChanged = True
    while clusterChanged:
        clusterChanged = False
        for i in range(m):
            minDistance = inf; minIndex = -1
            for j in range(k):
                distanceIj = distMeas(dataSet[i, :], centroids[j, :])
                if distanceIj < minDistance:
                    minDistance = distanceIj
                    minIndex = j
            if minIndex != clusterAssign[i, 0]:
                clusterChanged = True
            clusterAssign[i, :] = minIndex, minDistance**2
        for cent in range(k):
            pointsInCluster = dataSet[nonzero(clusterAssign[:, 0] == cent)[0], :]
            centroids[cent, :] = mean(pointsInCluster, axis=0)
    return centroids, clusterAssign

# 二分k均值法
def biKmeans(dataSet, k, distMeas=distEclud):
    m, n = shape(dataSet)
    clusterAssign = mat(zeros((m, 2)))
    centroid0 =  mean(dataSet, axis=0).tolist()[0]
    centList = [centroid0], numCents = 1
    for j in range(m):
        clusterAssign[j, 1] = distMeas(dataSet[j, :], mat(centroid0))**2
    while numCents < k:
        minSSE = inf
        bestCentToSplit = -1
        bestNewCents = centList
        bestNewAssign = clusterAssign
        for i in range(numCents):
            pointsInCluster = dataSet[nonzeros(clusterAssign[:, 0] == i)[0], :]
            splitCent, splitClusterAssign = kMeans(pointsInCluster, 2)
            splitSSE = sum(splitClusterAssign[:, 1])
            noSplitSSE = sum(clusterAssign[nonzeros(cluster[:, 0] != i)[0], 1])
            currentSSE = splitSSE + noSplitSSE
            if currentSSE < minSSE:
                minSSE = currentSSE
                bestCentToSplit = i
                bestNewCents = splitCent
                bestNewAssign = splitClusterAssign

        # 更新簇的分配结果,将新得到的两个质点一个序号设为bestCentsToSplit,另一个序号设为numCents
        centList[bestCentToSplit] = bestNewCents[0, :]
        centList.append(bestNewCents[1, :])
        bestNewAssign[nonzeros(bestNewAssign[:, 0] == 0)[0], 0] = bestCentToSplit
        bestNewAssign[nonzeros(bestNewAssign[:, 0] == 1)[0], 0] = numCents
        clusterAssign[nonzeros(clusterAssign[:, 0] == bestCentToSplit)[0], :] = bestNewAssign
        numCents += 1
    return mat(centList), clusterAssign

dataMat = mat(loadData(‘testSet2.txt‘))
centroids, clusterAssign = kMeans(dataMat, 3)
print(centroids)

LVQ算法代码

from numpy import *

# LVQ算法

def loadData(filename):
    dataSet = []
    fr = open(filename)
    for line in fr.readlines():
        curLine = line.strip().split(‘\t‘)
        fltLine = list(map(float, curLine))
        dataSet.append(fltLine)
    return dataSet

def randomSelect(dataMat):
    m = shape(dataMat)[0]
    return dataMat[random.randint(0, m-1), :]

def distEclud(vecA, vecB):
    return sqrt(sum(power(vecA-vecB, 2)))

def LVQ(dataMat, q, labels, maxIter=500, eta=0.1, distMeas = distEclud):
    m, n = shape(dataMat)
    centroids = mat(zeros((q, n)))
    # 初始化原型向量
    for i in range(q):
        curClassDataMat = dataMat[nonzero(dataMat[:, -1] == labels[i])[0], :]
        centroids[i, :] = randomSelect(curClassDataMat)

    for i in range(maxIter):
        # 随机选择一个样本
        sample = randomSelect(dataMat)
        bestIndex = -1
        minDistance = inf
        # 选择距离这个样本最近的原型向量
        for j in range(q):
            curDistance = distMeas(sample[0, :n-1], centroids[j, :n-1])
            if curDistance < minDistance:
                minDistance = curDistance
                bestIndex = j
        # 若样本和这个原型向量类别相同
        if sample[0, -1] == centroids[bestIndex, -1]:
            centroids[bestIndex, :n-1] += eta*(sample[0, :n-1]-centroids[bestIndex, :n-1])
        # 类别不同
        else:
            centroids[bestIndex, :n-1] -= eta*(sample[0, :n-1]-centroids[bestIndex, :n-1])
    return centroids

dataMat = mat(loadData(‘waterMelon4.txt‘))
centroids = LVQ(dataMat, 5, [1, 2, 2, 1, 1], 1000)
print(centroids)

时间: 2024-10-05 13:00:26

原型聚类总结的相关文章

聚类算法分类及总结

版权声明:本文为博主原创文章,未经博主允许不得转载,或者转载的时候标出源文章网址. 一.原型聚类 1.k均值聚类(k-means聚类) 其算法流程如下; 下面我们对西瓜数据进行分析,和举例,让我们比较容易的理解K-means聚类算法: 2.学习向量化 算法思想如下: 3.高斯混合聚类 下面还是一个列子:说实话前面一连串的理论知识也没很看懂.迷迷糊糊,列子还是很清楚的. 二.密度聚类-这里主要介绍DBSCAN算法 其算法思想如下: 三.层次聚类-主要讲解AGNES 基本思想如下:

图像检索(2):均值聚类-构建BoF

在图像检索时,通常首先提取图像的局部特征,这些局部特征通常有很高的维度(例如,sift是128维),有很多的冗余信息,直接利用局部特征进行检索,效率和准确度上都不是很好.这就需要重新对提取到的局部特征进行编码,以便于匹配检索. 常用的局部特征编码方法有三种: BoF VLAD FV 本文主要介绍基于k-means聚类算法的BoF的实现. BoF的原理 k均值聚类概述 使用OpenCV实现的BoF BoF 该方法源自于文本处理的词袋模型.Bag-of-words model (BoW model)

西瓜书机器学习算法脉络梳理之聚类

什么是聚类任务 “无监督学习”中研究最多,应用最广的学习任务,除此之外,还有密度估计(density estimation)和异常检测(anomaly detection).在无监督学习中,训练样本的标记信息是未知的,目标是通过对无标记训练样本的学习揭示数据的内在性质及规律,为进一步的数据分析提供基础. 聚类(clustering)将数据集中的样本划分为若干个通常不相交的子集,每个子集称为一个“簇”(cluster),每个簇可能对应一个潜在的概念(类别).这些概念对聚类算法而言,事先是未知的,聚

周志华 机器学习 笔记

首先的阶段由卷积层和池化层组成,卷积的节点组织在特征映射块(feature maps)中,每个节点与上一层的feature maps中的局部块通过一系列的权重即过滤器连接.加权和的结果被送到非线性函数中如ReLU.一个feature maps中所有的节点分享相同的过滤器,即共享权重.这种结构的原因是双重的,第一,图像中一个值附近的值是高度相关的,第二,不同区域的值是不相干的.换句话说,一个图像某部分出现的特征会在其他部分出现,因此可以实现权值共享并且检测到相同模式在矩阵的不同部分,这种操作在数学

CODE大全——机器学习

聚类 聚类任务 背景 在无监督学习(密度估计.异常检测等)中,训练样本的标记信息是未知的(即不人为指定),旨在发现数据之间的内在联系和规律,为进一步的数据分析提供基础. 此类学习任务中研究最多.应用最广的是聚类. 定义 聚类将数据集中的样本划分为若干个通常是不相交(有的时候会相交)的子集(簇,也叫类),即将样本分类,但是分类后得到的簇的标记是未指定的,这里需要使用者自行定义. 作用 聚类既能作为一个单独过程,用于寻找数据内在的分布结构,可以作为分类等其他学习任务的前驱过程. 主要概括起来,就是寻

第十篇:K均值聚类(KMeans)

前言 本文讲解如何使用R语言进行 KMeans 均值聚类分析,并以一个关于人口出生率死亡率的实例演示具体分析步骤. 聚类分析总体流程 1. 载入并了解数据集:2. 调用聚类函数进行聚类:3. 查看聚类结果描述:4. 将聚类结果图形化展示:5. 选择最优center并最终确定聚类方案:6. 图形化展示不同方案效果并提交分析报表. 人口出生/死亡率聚类分析 - K均值聚类 1. 载入并了解数据集 1.1 从网上下载一份txt格式的关于人口出生率统计的数据(countries.txt).其内容大致如下

聚类算法:K均值、凝聚层次聚类和DBSCAN

聚类分析就仅根据在数据中发现的描述对象及其关系的信息,将数据对象分组(簇).其目标是,组内的对象相互之间是相似的,而不同组中的对象是不同的.组内相似性越大,组间差别越大,聚类就越好. 先介绍下聚类的不同类型,通常有以下几种: (1)层次的与划分的:如果允许簇具有子簇,则我们得到一个层次聚类.层次聚类是嵌套簇的集族,组织成一棵树.划分聚类简单地将数据对象划分成不重叠的子集(簇),使得每个数据对象恰在一个子集中. (2)互斥的.重叠的与模糊的:互斥的指每个对象都指派到单个簇.重叠的或是模糊聚类用来反

基于改进人工蜂群算法的K均值聚类算法(附MATLAB版源代码)

其实一直以来也没有准备在园子里发这样的文章,相对来说,算法改进放在园子里还是会稍稍显得格格不入.但是最近邮箱收到的几封邮件让我觉得有必要通过我的博客把过去做过的东西分享出去更给更多需要的人.从论文刊登后,陆陆续续收到本科生.研究生还有博士生的来信和短信微信等,表示了对论文的兴趣以及寻求算法的效果和实现细节,所以,我也就通过邮件或者短信微信来回信,但是有时候也会忘记回复. 另外一个原因也是时间久了,我对于论文以及改进的算法的记忆也越来越模糊,或者那天无意间把代码遗失在哪个角落,真的很难想象我还会全

高斯混合聚类及EM实现

一.引言 我们谈到了用 k-means 进行聚类的方法,这次我们来说一下另一个很流行的算法:Gaussian Mixture Model (GMM).事实上,GMM 和 k-means 很像,不过 GMM 是学习出一些概率密度函数来(所以 GMM 除了用在 clustering 上之外,还经常被用于 density estimation ),简单地说,k-means 的结果是每个数据点被 assign 到其中某一个 cluster 了,而 GMM 则给出这些数据点被 assign 到每个 clu