层次聚类

层次聚类算法的工作流程如下。首先,每个点自己单独看成一个簇。随着时间的推移,算法会通过合并两个小簇而形成一个大簇。

层次聚类_第1张图片 算法流程

首先,我们假定算法运行在欧式空间下。此时可以允许通过簇质心或者簇内平均点来表示一个簇。注意到对于单点组成的簇,该点就是簇质心,因此可以很直观地对这些簇进行初始化。然后我们将簇之间距离定义为其质心之间的欧氏距离,并选择具有最短距离的两个簇进行合并。

簇之间的距离有很多种定义:

1簇的半径

2簇的直径

3两个簇中点对之间距离的平均值

4 两个簇中所有点之间的最短距离

利用函数scipy.cluster.hierarchy,我们可以轻松实现分层聚类

# -*- coding: utf-8 -*-
import numpy as np
from scipy.cluster.hierarchy import dendrogram, linkage, fcluster
from matplotlib import pyplot as plt
 
def hierarchy_cluster(data, method='average', threshold=5.0):
   
    data = np.array(data)
    
    #使用非加权组平均法,计算簇与簇之间的距离,然后形成层次树
    Z = linkage(data, method=method) 
    
    #根据linkage的结果进行聚类
    cluster_assignments = fcluster(Z, threshold, criterion='distance')      
    print(cluster_assignments)
    num_clusters = cluster_assignments.max()
    indices = get_cluster_indices(cluster_assignments)
    
    fig = plt.figure(figsize=(5, 3))
    dn = dendrogram(Z)
    plt.show()
    
    return num_clusters, indices
 
 
 
def get_cluster_indices(cluster_assignments):
    '''映射每一类至原数据索引
    
    Arguments:
        cluster_assignments 层次聚类后的结果
    
    Returns:
        [[idx1, idx2,..], [idx3]] -- 每一类下的索引
    '''
    #有多少种聚类簇
    n = cluster_assignments.max()
    indices = []
    for cluster_number in range(1, n + 1):
        indices.append(np.where(cluster_assignments == cluster_number)[0])
    
    return indices
 
 
if __name__ == '__main__':
    
 
    arr = [[0., 21.6,2],
           
    [21.6, 0.,2],
    [22.6, 1.,2],
    
    [63.9, 42.3,2],
    [65.1, 43.5,2],
    
    [17.7, 3.9,2],
    [99.2, 77.6,2],
    
    [100,118,2],
    [101,119,2],
    [98,118,2],
    
    [54,63,2],
    [55,63,2],
    [55,64,2]
    ]
    
    
    arr = np.array(arr)
    r, c = arr.shape
    
    num_clusters, indices = hierarchy_cluster(arr)
 
 
    print ('%d clusters' % num_clusters)
    for k, ind in enumerate(indices):
        print ('cluster', k, 'is', ind)



    

程序效果图:

层次聚类_第2张图片

参考图书:大数据互联网大规模数据挖掘与分布式处理(第2版)

 

你可能感兴趣的:(数据挖掘)