【机器学习】聚类算法(二)

博客介绍了基于密度的聚类算法,重点阐述OPTICS算法。通过代码展示其对六个簇数据进行聚类分析,并与不同epsilon值的DBSCAN聚类比较。OPTICS无需指定簇个数和epsilon参数,能根据数据密度自动聚类,还给出了该算法的参数和属性说明。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

五、基于密度的算法

48ddbcbc88c7622bb2d2f3f6dc31adbe.png

779f6f02f913bd18090b468a481dfcfc.png

5.1 DBSCAN 算法

a5fbe7c5d8f5bcfb56762ae7524c59ad.png

import sys # 导入 sys 模块,用于访问系统相关的参数和功能
import os # 导入 os 模块,用于处理文件和目录
import math # 导入 math 模块,用于进行数学运算
import random # 导入 random 模块,用于生成随机数
from sklearn import datasets # 导入 sklearn 的 datasets 模块,用于加载数据集
import numpy as np # 导入 numpy 模块,用于进行科学计算,简写为 np


# Import helper functions
dir_path = os.path.dirname(os.path.realpath(__file__)) # 获取当前文件的绝对路径
sys.path.insert(0, dir_path + "/../utils") # 将 utils 目录添加到系统路径中,方便导入其中的模块
from utils.data_manipulation import normalize # 从 utils.data_manipulation 模块中导入 normalize 函数,用于对数据进行归一化处理
from utils.data_operation import euclidean_distance # 从 utils.data_operation 模块中导入 euclidean_distance 函数,用于计算欧几里得距离
sys.path.insert(0, dir_path + "/../unsupervised_learning/") # 将 unsupervised_learning 目录添加到系统路径中,方便导入其中的模块
from principal_component_analysis import PCA # 从 principal_component_analysis 模块中导入 PCA 类,用于进行主成分分析


# 定义 DBSCAN 类,用于实现 DBSCAN 算法
class DBSCAN():
    # 初始化方法,接受两个参数:eps 和 min_samples
    def __init__(self, eps=1, min_samples=5):
        self.eps = eps # eps 表示邻域半径,用于判断两个样本是否为邻居
        self.min_samples = min_samples # min_samples 表示核心点的最小邻居数,用于判断一个样本是否为核心点
        # List of arrays (clusters) containing sample indices
        self.clusters = [] # clusters 表示聚类结果,是一个列表,每个元素是一个数组,表示一个簇,包含了样本的索引
        self.visited_samples = [] # visited_samples 表示已经访问过的样本的索引,是一个列表
        # Hashmap {"sample_index": [neighbor1, neighbor2, ...]}
        self.neighbors = {} # neighbors 表示每个样本的邻居,是一个字典,键是样本的索引,值是一个数组,表示该样本的邻居的索引
        self.X = None   # Dataset # X 表示数据集,是一个二维数组,每一行是一个样本,每一列是一个特征


    # 定义一个私有方法,用于获取一个样本的邻居,接受一个参数:sample_i,表示样本的索引
    def _get_neighbors(self, sample_i):
        neighbors = [] # 定义一个空列表,用于存储邻居的索引
        for _sample_i, _sample in enumerate(self.X): # 遍历数据集中的每个样本及其索引
            if _sample_i != sample_i and euclidean_distance( # 如果样本的索引不等于 sample_i,且样本与 sample_i 对应的样本的欧几里得距离小于 eps
                    self.X[sample_i], _sample) < self.eps:
                neighbors.append(_sample_i) # 则将该样本的索引添加到邻居列表中
        return np.array(neighbors) # 返回邻居列表,转换为 numpy 数组


    # 定义一个私有方法,用于扩展一个簇,接受两个参数:sample_i 和 neighbors,分别表示样本的索引和邻居
    def _expand_cluster(self, sample_i, neighbors):
        cluster = [sample_i] # 定义一个列表,用于存储簇中的样本的索引,初始值为 sample_i
        # Iterate through neighbors
        for neighbor_i in neighbors: # 遍历邻居中的每个样本的索引
            if not neighbor_i in self.visited_samples: # 如果该样本的索引不在已访问过的样本列表中
                self.visited_samples.append(neighbor_i) # 则将该样本的索引添加到已访问过的样本列表中
                # Fetch the samples distant neighbors
                self.neighbors[neighbor_i] = self._get_neighbors(neighbor_i) # 获取该样本的邻居,并存储到 neighbors 字典中
                # Make sure the neighbors neighbors are more than min_samples
                if len(self.neighbors[neighbor_i]) >= self.min_samples: # 如果该样本的邻居数大于等于 min_samples,即该样本是一个核心点
                    # Choose neighbors of neighbor except for sample
                    distant_neighbors = self.neighbors[neighbor_i][ # 选择该样本的邻居中除了 sample_i 之外的样本,作为远邻
                        np.where(self.neighbors[neighbor_i] != sample_i)]
                    # Add the neighbors neighbors as neighbors of sample
                    self.neighbors[sample_i] = np.concatenate( # 将远邻添加到 sample_i 的邻居中
                        (self.neighbors[sample_i], distant_neighbors))
                    # Expand the cluster from the neighbor
                    expanded_cluster = self._expand_cluster( # 从该样本开始递归地扩展簇
  
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值