AGNES层次聚类方法

第1关:距离的计算

任务描述

本关任务:根据本关所学知识,完成calc_min_dist函数,calc_max_dist函数以及calc_avg_dist函数分别实现计算两个簇之间的最短距离、最远距离和平均距离。

相关知识

为了完成本关任务,你需要掌握:

  • 为什么需要距离
  • 距离的计算
为什么需要距离

AGNES算法是一种自底向上聚合的层次聚类算法,它先会将数据集中的每个样本看作一个初始簇,然后在算法运行的每一步中找出距离最近的两个簇进行合并,直至达到预设的簇的数量。所以AGNES算法需要不断的计算簇之间的距离,这也符合聚类的核心思想(物以类聚,人以群分),因此怎样度量两个簇之间的距离成为了关键。

距离的计算

衡量两个簇之间的距离通常分为最小距离、最大距离和平均距离。在AGNES算法中可根据具体业务选择其中一种距离作为度量标准。

最小距离

最小距离描述的是两个簇之间距离最近的两个样本所对应的距离。例如下图中圆圈和菱形分别代表两个簇,两个簇之间离得最近的样本的欧式距离3.3,则最小距离为3.3

假设给定簇Ci​与Cj​,则最小距离为:

dmin​=minxini,zinj​dist(x,z)

最大距离

最大距离描述的是两个簇之间距离最远的两个样本所对应的距离。例如下图中圆圈和菱形分别代表两个簇,两个簇之间离得最远的样本的欧式距离23.3,则最大距离为23.3

假设给定簇Ci​与Cj​,则最大距离为:

dmin​=maxxini,zinj​dist(x,z)

平均距离

平均距离描述的是两个簇之间样本的平均距离。例如下图中圆圈和菱形分别代表两个簇,计算两个簇之间的所有样本之间的欧式距离并求其平均值。

假设给定簇Ci​与Cj​,∣Ci​∣,∣Cj​∣分别表示簇i与簇j中样本的数量,则平均距离为:

dmin​=∣Ci​∣∣Cj​∣1​sumxini​sumzinj​dist(x,z)

编程要求

根据提示,在右侧Begin-End区域补充代码,完成clac_min_dist函数,calc_max_dist函数以及calc_avg_dist函数分别实现计算两个簇之间的最短距离、最远距离和平均距离。注意:距离请使用欧氏距离。

calc_min_dist函数中的参数:

  • cluster1:簇1中的样本数据,类型为ndarray
  • cluster2:簇2中的样本数据,类型为ndarray

calc_max_dist函数中的参数:

  • cluster1:簇1中的样本数据,类型为ndarray
  • cluster2:簇2中的样本数据,类型为ndarray

calc_avg_dist函数中的参数:

  • cluster1:簇1中的样本数据,类型为ndarray
  • cluster2:簇2中的样本数据,类型为ndarray
测试说明

只需完成clac_min_dist函数,calc_max_dist函数以及calc_avg_dist函数即可,平台会对你编写的代码进行测试,并会按顺序打印最小距离、最大距离与平均距离。以下为其中一个测试用例,其中cluster1部分表示属于簇1的样本数据,cluster2部分表示属于簇2的样本数据:

测试输入: {'cluster1':[[0, 1, 0], [1, 0, 1], [1, 2, 3.2], [0, 0, 1.2], [1, 1, 0.1]], 'cluster2':[[10.1, 20.3, 9], [8.2, 15.3, 11]]}

预期输出: 17.016756, 23.977906, 21.133420

import numpy as np


def calc_min_dist(cluster1, cluster2):
    '''
    计算簇间最小距离
    :param cluster1:簇1中的样本数据,类型为ndarray
    :param cluster2:簇2中的样本数据,类型为ndarray
    :return:簇1与簇2之间的最小距离
    '''

    #********* Begin *********#
    min_dist = float('inf')
    for i in range(len(cluster1)):
        for j in range(len(cluster2)):
            dist = np.sqrt(np.sum((cluster1[i]-cluster2[j])**2))
            if dist < min_dist:
                min_dist = dist
    return min_dist
    #********* End *********#


def calc_max_dist(cluster1, cluster2):
    '''
    计算簇间最大距离
    :param cluster1:簇1中的样本数据,类型为ndarray
    :param cluster2:簇2中的样本数据,类型为ndarray
    :return:簇1与簇2之间的最大距离
    '''

    #********* Begin *********#
    max_dist = 0
    for i in range(len(cluster1)):
        for j in range(len(cluster2)):
            dist = np.sqrt(np.sum((cluster1[i]-cluster2[j])**2))
            if dist > max_dist:
                max_dist = dist
    return max_dist
    #********* End *********#


def calc_avg_dist(cluster1, cluster2):
    '''
    计算簇间平均距离
    :param cluster1:簇1中的样本数据,类型为ndarray
    :param cluster2:簇2中的样本数据,类型为ndarray
    :return:簇1与簇2之间的平均距离
    '''

    #********* Begin *********#
    avg_dist = 0
    count = 0
    for i in range(len(cluster1)):
        for j in range(len(cluster2)):
            dist = np.sqrt(np.sum((cluster1[i]-cluster2[j])**2))
            avg_dist += dist
            count += 1
    avg_dist /= count
    return avg_dist
    #********* End *********#

 第2关:AGNES算法流程

任务描述

本关任务:补充python代码,完成AGNES函数完成聚类功能。

相关知识

为了完成本关任务,你需要掌握AGNES算法流程

AGNES算法流程

AGNES算法是一种自底向上聚合的层次聚类算法,它先会将数据集中的每个样本看作一个初始簇,然后在算法运行的每一步中找出距离最近的两个簇进行合并,直至达到预设的簇的数量。

举个例子,现在先要将西瓜数据聚成两类,数据如下表所示:

编号体积重量
11.22.3
23.67.1
31.12.2
43.56.9
51.52.5

一开始,每个样本都看成是一个簇(1号样本看成是1号簇,2号样本看成是2号簇,...,5号样本看成是5号簇),假设簇的集合为C=[[1], [2], [3], [4], [5]]

假设使用簇间最小距离来度量两个簇之间的远近,从表中可以看出1号簇与3号簇的簇间最小距离最小。因此需要将1号簇和3号簇合并,那么此时簇的集合C=[[1, 3], [2], [4], [5]]

然后继续看这4个簇中哪两个簇之间的最小距离最小,我们发现2号簇与4号簇的最小距离最小,因此我们要进行合并,合并之后C=[[1, 3], [2, 4], [5]]

然后继续看这3个簇中哪两个簇之间的最小距离最小,我们发现5号簇与[1, 3]簇的最小距离最小,因此我们要进行合并,合并之后C=[[1, 3, 5], [2, 4]]

这个时候C中只有两个簇了,达到了我们的预期目标(想要聚成两类),所以算法停止。算法停止后会发现,我们已经将5个西瓜,聚成了两类,一类是小西瓜,另一类是大西瓜。

如果将整个聚类过程中的合并,与合并的次序可视化出来,就能看出为什么说AGNES是自底向上的层次聚类算法了。

AGNES伪代码如下:

 
  1. #假设数据集为D,想要聚成的簇的数量为k
  2. def AGNES(D, k):
  3. #C为聚类结果
  4. C = []
  5. #将每个样本看成一个簇
  6. for d in D:
  7. C.append(d)
  8. #C中簇的数量
  9. q=len(C)
  10. while q > k:
  11. 寻找距离最小的两个簇a和b
  12. 将a和b合并,并修改C
  13. q = len(C)
  14. return C
编程要求

Begin-End区域完成AGNES函数实现聚类功能,并将聚类结果返回(量化距离时请使用簇间最大欧氏距离)。PS:假设数据集为[[1, 2], [10, 11], [1, 3]],那么聚类结果可能为[[[1, 2], [1, 3]], [[10, 11]]]

其中:

  • feature:数据集,类型为ndarray
  • k:表示想要将数据聚成k类,类型为int
测试说明

只需完成AGNES函数即可,程序内部会调用您所完成的AGNES函数对数据进行聚类,若聚类后的簇与真实结果相似度高于0.8视为过关。

import numpy as np
def AGNES(feature, k):
    '''
    AGNES聚类并返回聚类结果
    假设数据集为`[1, 2], [10, 11], [1, 3]],那么聚类结果可能为`[[1, 2], [1, 3]], [[10, 11]]]
    :param feature:训练数据集所有特征组成的ndarray
    :param k:表示想要将数据聚成`k`类,类型为`int`
    :return:聚类结果
    '''
    #********* Begin *********#
    # 找到距离最小的下标
    def find_Min(M):
        min = np.inf
        x = 0;
        y = 0
        for i in range(len(M)):
            for j in range(len(M[i])):
                if i != j and M[i][j] < min:
                    min = M[i][j];
                    x = i;
                    y = j
        return (x, y, min)
    #计算簇间最大距离
    def calc_max_dist(cluster1, cluster2):
        max_dist = 0
        for i in range(len(cluster1)):
            for j in range(len(cluster2)):
                dist = np.sqrt(np.sum(np.square(cluster1[i] - cluster2[j])))
                if dist > max_dist:
                    max_dist = dist
        return max_dist
    #初始化C和M
    C = []
    M = []
    for i in feature:
        Ci = []
        Ci.append(i)
        C.append(Ci)
    for i in C:
        Mi = []
        for j in C:
            Mi.append(calc_max_dist(i, j))
        M.append(Mi)
    q = len(feature)
    #合并更新
    while q > k:
        x, y, min = find_Min(M)
        C[x].extend(C[y])
        C.pop(y)
        M = []
        for i in C:
            Mi = []
            for j in C:
                Mi.append(calc_max_dist(i, j))
            M.append(Mi)
        q -= 1
    return C
    #********* End *********#

 第3关:红酒聚类

任务描述

本关任务:sklearn中的AgglomerativeClustering类实现了AGNES算法,本关你需要使用 sklearnAgglomerativeClustering来对红酒数据进行聚类。

相关知识

为了完成本关任务,你需要掌握:AgglomerativeClustering

数据集介绍

数据集为一份红酒数据,一共有178个样本,每个样本有13个特征,这里不会提供你红酒的标签,你需要自己根据这13个特征对红酒进行聚类,部分数据如下图:

数据获取代码:

 
  1. import pandas as pd
  2. data_frame = pd.read_csv('./step3/dataset.csv', header=0)
AgglomerativeClustering

AgglomerativeClustering的构造函数中有两个常用的参数可以设置:

  • n_clusters:将数据聚成n_clusters个类
  • linkage:设置AGNES聚类时使用最小簇间距离、最大簇间距离还是平均距离。传入ward表示最小簇间距离,传入complete表示最大簇间距离,传入average表示平均距离

AgglomerativeClustering类中的fit_predict函数用于训练模型并获取聚类结果,fit_predict函数有一个向量输入:

  • X:数据集,形状为**[样本数量,特征数量]**的ndarray

AgglomerativeClustering的使用代码如下:

 
  1. from sklearn.cluster import AgglomerativeClustering
  2. agnes = AgglomerativeClustering(k=5)
  3. # 注意:x为ndarray
  4. result = agnes.fit_predict(x)
编程要求

Begin-End区域填写Agglomerative_cluster(data)函数完成红酒数据聚类任务,簇的数量为3。其中:

  • data:数据样本,类型为ndarrayshape=[样本数量, 特征数量]

  • return: 聚类结果,类型为ndarray

注意:直接使用原始数据进行聚类的效果可能不太理想,你可能需要对数据进行预处理。

提示:AGNES算法需要计算距离,想想什么样的预处理方式对依赖距离的算法有好的效果。

测试说明

只需返回聚类结果即可,程序内部会检测您的代码,吻合度高于0.9视为过关。

#encoding=utf8
from sklearn.cluster import AgglomerativeClustering
 
def Agglomerative_cluster(data):
    '''
    对红酒数据进行聚类
    :param data: 数据集,类型为ndarray
    :return: 聚类结果,类型为ndarray
    '''
 
    #********* Begin *********#
    from sklearn.preprocessing import StandardScaler
    scaler = StandardScaler()
    data = scaler.fit_transform(data)
    agnes = AgglomerativeClustering(n_clusters=3)
    result = agnes.fit_predict(data)
    return result
 
    #********* End *********#

  • 28
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值