大数据先导实践实验二

实验二:大数据的处理

实验内容:
在本次实验中,请在k-mean算法、DBSCAN算法中选择任意一种算法完成聚类任务,并对于聚类结果实现可视化。
实验总体流程:
(1)完成对于pathbased、spiral、jain数据集的预处理。
(2)根据数据集中节点类别的数量确定簇的数量。
(3)编写程序实现k-means算法或DBSCAN算法。
(4)实现聚类结果的可视化(可视化结果如图所示)。
(5)分析聚类结果,观察并分析更改簇的数量后聚类结果的变化。

我选择的是DBSCAN算法,因为觉得k-mean只能处理球形簇,有些局限性

实验过程
  1. 核心思想:DBSCAN算法把点归为三类:边界点、核心点、噪声点。确定核心点主要与半径、最小点数两个参数有关,即点的半径内的点数要比最小点数大才为和核心点,而簇主要与核心点的位置有关,这里有一个密度可达的概念,是指核心点a的半径内有一个核心点b且b在另一个核心点c内,那就可以认为点a,b,c在同一个簇内。程序的核心思想也是这个

  2. 导入所需的库并准备数据

    import numpy as np
    import math
    from matplotlib import pyplot as plt
    
    import matplotlib as mpl
    //画图中文显示
    mpl.rcParams['font.sans-serif'] = ["SimHei"]
    mpl.rcParams["axes.unicode_minus"] = False
    
    t1 = np.loadtxt("./D31.txt")
    dataset = t1[:, 0:2]
    //创建一个布尔数组,是否被访问过,节省时间开销
    visted = [False for i in dataset[:, 0]]
    
  3. 准备辅助函数

    # 计算距离
    def Euclidean_distance(a, b):
        return math.sqrt(np.power(a - b, 2).sum())
    # 判断两个点是否相连
    def is_neighbor(a, b, radius):
        return Euclidean_distance(a, b) < radius
    # 判断是否为核心点
    def is_core(p_index, epx, minpts):
        nei_list = []
        for i in range(np.size(dataset[:, 0])):
            if is_neighbor(dataset[p_index], dataset[i], epx):
                nei_list.append(i)
        if len(nei_list) < minpts + 1:
            return False
        return True
    # 返回输入核心点的边界点
    def is_border(core_id, eps, size):
        border_pts = []
        for i in range(size):
            if is_neighbor(dataset[core_id], dataset[i], eps):
                border_pts.append(i)
        return border_pts
    
  4. 首先找出所有的核心点

    eps = 2.5  # 半径
    minpts = 5  # 至少含有多少个点
    core_lis = []# 存储核心点的数组
    size = np.size(dataset)
    size = int(size / 2)
    print(type(size))
    for i in range(size):
        if is_core(i, eps, minpts):
            core_lis.append(i)
    print(core_lis)
    fin_list = []# 最后的输出结果的数组
    
  5. 找出所有的密度可达的核心点构成一个簇,加入fin_list数组

    for core_lis_id, i in enumerate(core_lis):
        if visted[i] == False:# 判断该点是否被处理过
            temp_set = set()# 构建集合,为了去重,避免重复元素
            visted[i] = True
            have_same = -1# 用来判断是否与最后结果数组有相同的元素,如果有则为一个簇
            temp_set.add(i)
            for j in core_lis:# 遍历核心点数组
                if visted[j] == False:
                    if is_neighbor(dataset[i], dataset[j], eps):
                    	# 如果相邻则加入集合
                        temp_set.add(j)
            # 判断结果数组中存储的簇的元素是否有与临时集合中相同的元素,如果有则说明临时集合属于该簇
            for fin_id, i in enumerate(fin_list):
                for k in temp_set:
                    if k in i:
                        have_same = fin_id
            if have_same != -1:
                for temp_item in temp_set:
                    fin_list[have_same].add(temp_item)
            else:
                fin_list.append(temp_set)
    
  6. 根据核心点分好的簇处理边界点

    for i in range(len(fin_list)):
        temp_lis = []
        for j in fin_list[i]:
            temp_lis.append(j)
            temp_lis += is_border(j, eps, size)
        print(set(temp_lis))
        temp_lis = list(set(temp_lis))
        if len(temp_lis) == 1:
            plt.scatter(dataset[temp_lis[0], 0], dataset[temp_lis[0], 1], label=f'第{i + 1}个簇')
        else:
            plt.scatter(dataset[temp_lis[:], 0], dataset[temp_lis[:], 1], label=f'第{i + 1}个簇')
    
    
实验中遇到的困难:

关于核心点的半径和最小点数的确定,并没有想出在不引库的情况下一个完美的办法,所以只能手动调整

实验结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kMbN5O8z-1654004494367)(C:\Users\24617\AppData\Roaming\Typora\typora-user-images\image-20220520212554241.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hDM1T8FA-1654004494369)(C:\Users\24617\AppData\Roaming\Typora\typora-user-images\image-20220520212840439.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8rQIbqRf-1654004494370)(C:\Users\24617\AppData\Roaming\Typora\typora-user-images\image-20220520212850272.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7ecsXXwe-1654004494371)(C:\Users\24617\AppData\Roaming\Typora\typora-user-images\image-20220520212859311.png)]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值