层级聚类(Hierarchical Clustering)

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from numpy import *

"""
Code for hierarchical clustering, modified from
Programming Collective Intelligence by Toby Segaran
(O‘Reilly Media 2007, page 33).
"""

class cluster_node:
    def __init__(self, vec, left=None, right=None, distance=0.0, id=None, count=1):#面向对象oo 构造函数
        self.left = left
        self.right = right
        self.vec = vec
        self.id = id
        self.distance = distance
        self.count = count  # only used for weighted average

def L2dist(v1, v2):
    return sqrt(sum((v1 - v2) ** 2))

def L1dist(v1, v2):
    return sum(abs(v1 - v2))

# def Chi2dist(v1,v2):
#     return sqrt(sum((v1-v2)**2))

def hcluster(features, distance=L2dist):
    # cluster the rows of the "features" matrix
    distances = {}
    currentclustid = -1

    # clusters are initially just the individual rows
    clust = [cluster_node(array(features[i]), id=i) for i in range(len(features))]#每一个实例都赋值id

    while len(clust) > 1:
        lowestpair = (0, 1)
        closest = distance(clust[0].vec, clust[1].vec)

        # loop through every pair looking for the smallest distance
        for i in range(len(clust)):
            for j in range(i + 1, len(clust)):
                # distances is the cache of distance calculations
                if (clust[i].id, clust[j].id) not in distances:
                    distances[(clust[i].id, clust[j].id)] = distance(clust[i].vec, clust[j].vec)

                d = distances[(clust[i].id, clust[j].id)]

                if d < closest:
                    closest = d
                    lowestpair = (i, j)#距离最小的一对点

        # calculate the average of the two clusters
        mergevec = [(clust[lowestpair[0]].vec[i] + clust[lowestpair[1]].vec[i]) / 2.0                     for i in range(len(clust[0].vec))]#计算一个类中的两个点的距离的中间点

        # create the new cluster
        newcluster = cluster_node(array(mergevec), left=clust[lowestpair[0]],
                                  right=clust[lowestpair[1]],
                                  distance=closest, id=currentclustid)#将左右儿子已接近两点距离 两点的中心向量进行赋值,构造新的节点

        # cluster ids that weren‘t in the original set are negative
        currentclustid -= 1
        del clust[lowestpair[1]]#删除掉已经合并为一个节点的左右两个(在clust里面)节点
        del clust[lowestpair[0]]
        clust.append(newcluster)

    return clust[0]#返回一个包含所有节点的树结构

def extract_clusters(clust, dist):#
    # extract list of sub-tree clusters from hcluster tree with distance<dist
    clusters = {}
    if clust.distance < dist:
        # we have found a cluster subtree
        return [clust]
    else:
        # check the right and left branches
        cl = []
        cr = []
        if clust.left != None:
            cl = extract_clusters(clust.left, dist=dist)
        if clust.right != None:
            cr = extract_clusters(clust.right, dist=dist)
        return cl + cr

def get_cluster_elements(clust):
    # return ids for elements in a cluster sub-tree
    if clust.id >= 0:
        # positive id means that this is a leaf
        return [clust.id]
    else:
        # check the right and left branches
        cl = []
        cr = []
        if clust.left != None:
            cl = get_cluster_elements(clust.left)
        if clust.right != None:
            cr = get_cluster_elements(clust.right)
        return cl + cr

def printclust(clust, labels=None, n=0):
    # indent to make a hierarchy layout
    for i in range(n): print ‘ ‘,
    if clust.id < 0:
        # negative id means that this is branch
        print ‘-‘
    else:
        # positive id means that this is an endpoint
        if labels == None:
            print clust.id
        else:
            print labels[clust.id]

    # now print the right and left branches
    if clust.left != None: printclust(clust.left, labels=labels, n=n + 1)
    if clust.right != None: printclust(clust.right, labels=labels, n=n + 1)

def getheight(clust):
    # Is this an endpoint? Then the height is just 1
    if clust.left == None and clust.right == None: return 1

    # Otherwise the height is the same of the heights of
    # each branch
    return getheight(clust.left) + getheight(clust.right)

def getdepth(clust):
    # The distance of an endpoint is 0.0
    if clust.left == None and clust.right == None: return 0

    # The distance of a branch is the greater of its two sides
    # plus its own distance
    return max(getdepth(clust.left), getdepth(clust.right)) + clust.distance

  

时间: 2024-08-10 17:17:57

层级聚类(Hierarchical Clustering)的相关文章

系统聚类(hierarchical clustering analysis)

漫谈 Clustering (5): Hierarchical Clustering

系列不小心又拖了好久,其实正儿八经的 blog 也好久没有写了,因为比较忙嘛,不过觉得 Hierarchical Clustering 这个话题我能说的东西应该不多,所以还是先写了吧(我准备这次一个公式都不贴  ).Hierarchical Clustering 正如它字面上的意思那样,是层次化的聚类,得出来的结构是一棵树,如右图所示.在前面我们介绍过不少聚类方法,但是都是“平坦”型的聚类,然而他们还有一个更大的共同点,或者说是弱点,就是难以确定类别数.实际上,(在某次不太正式的电话面试里)我曾

聚类(Clustering)

简介 这大概是我第一次涉及到跟智能算法相关的东西--聚类.无奈,老师布置的作业,要求2-3天看完然后汇报.毕竟第一次看这一类的文章,如果理解有偏见,欢迎指出.我的邮箱:[email protected]. 先介绍一下什么是聚类(Clustering)吧.简单地说就是把相似的数据分到一组.比如你把人进行分组,如果是按性别分,那很容易,只有俩点.如果你按年龄或者身高分组,定义一下高的还是矮的进行分组就可以了.但是我们常常会遇到很多复杂的情况,比如人的健康情况,你要把健康情况不一样的进行分组.这个涉及

[数据挖掘课程笔记]无监督学习——聚类(clustering)

什么是聚类(clustering) 个人理解:聚类就是将大量无标签的记录,根据它们的特点把它们分成簇,最后结果应当是相同簇之间相似性要尽可能大,不同簇之间相似性要尽可能小. 聚类方法的分类如下图所示: 一.如何计算样本之间的距离? 样本属性可能有的类型有:数值型,命名型,布尔型……在计算样本之间的距离时,需要将不同类型属性分开计算,最后统一相加,得到两个样本之间的距离.下面将介绍不同类型的属性的数据计算方法. 对于全部都是连续的数值型的样本来说,首先,对于值相差较大的属性来说,应该进行归一化,变

谱聚类(Spectral Clustering, SC)

谱聚类(Spectral Clustering, SC)是一种基于图论的聚类方法——将带权无向图划分为两个或两个以上的最优子图,使子图内部尽量相似,而子图间距离尽量距离较远,以达到常见的聚类的目 的.其中的最优是指最优目标函数不同,可以是割边最小分割——如图1的Smallest cut(如后文的Min cut), 也可以是分割规模差不多且割边最小的分割——如图1的Best cut(如后文的Normalized cut). 图1 谱聚类无向图划分——Smallest cut和Best cut 这样

简单易学的机器学习算法——谱聚类(Spectal Clustering)

一.复杂网络中的一些基本概念 1.复杂网络的表示 在复杂网络的表示中,复杂网络可以建模成一个图,其中,表示网络中的节点的集合,表示的是连接的集合.在复杂网络中,复杂网络可以是无向图.有向图.加权图或者超图. 2.网络簇结构 网络簇结构(network cluster structure)也称为网络社团结构(network community structure),是复杂网络中最普遍和最重要的拓扑属性之一.网络簇是整个网络中的稠密连接分支,具有同簇内部节点之间相互连接密集,不同簇的节点之间相互连接

Science14年的聚类论文——Clustering by fast search and find of density peaks

这是一个比较新的聚类方法(文章中没看见作者对其取名,在这里我姑且称该方法为local density clustering,LDC),在聚类这个古老的主题上似乎最近一些年的突破不大,这篇文章算是很好的了,方法让人很有启发(醍醐灌顶),并且是发表在Science上,受到的关注自然非常大. 本文的核心亮点:1是用比较新颖的方法来确定聚类中心,2是采用距离的local density来进行聚类的划分.在这两点中,常见的Kmeans算法采用的方法是:用每一类的均值作为中点,用距离的最近的点来确定聚类划分

一种新型聚类算法(Clustering by fast search and find of density peaksd)

最近在学习论文的时候发现了在science上发表的关于新型的基于密度的聚类算法 Kmean算法有很多不足的地方,比如k值的确定,初始结点选择,而且还不能检测费球面类别的数据分布,对于第二个问题,提出了Kmean++,而其他不足还没有解决,dbscan虽然可以对任意形状分布的进行聚类,但是必须指定一个密度阈值,从而去除低于此密度阈值的噪音点,这篇文章解决了这些不足. 本文提出的聚类算法的核心思想在于,对聚类中心的刻画上,而且认为聚类中心同时具有以下两种特点: 本身的密度大,即它被密度均不超过它的邻

学习笔记:聚类算法Kmeans

前记 Kmeans是最简单的聚类算法之一,但是运用十分广泛,最近看到别人找实习笔试时有考到Kmeans,故复习一下顺手整理成一篇笔记.Kmeans的目标是:把n 个样本点划分到k 个类簇中,使得每个点都属于离它最近的质心对应的类簇,以之作为聚类的标准.质心,是指一个类簇内部所有样本点的均值. 算法描述 Step 1. 从数据集中随机选取K个点作为初始质心         将每个点指派到最近的质心,形成k个类簇 Step 2. repeat             重新计算各个类簇的质心(即类内部