R聚类算法-DBSCAN算法

2022-05-09 14:11:22 浏览数 (1)

DBSCAN算法(Density-Based Spatial Clustering of Application with Noise)密度聚类算法 基于密度的聚类算法,K-means和层次聚类对于球状的簇聚类效果很好,DBSCAN可以用于更多复杂形状簇的聚类。

R中实现DBSCAN算法的API “fpc”包 install.packages(“fpc”) dbscan(data,eps,MinPts)

  • data 样本数据 eps
  • 领域的大小,使用圆的半径表示
  • Minpts 领域内,点的个数的阈值

理解概念:

密度(Density) 空间中任意一点的密度是以该点为圆心,以EPS为半径的圆区域内包含的点数目 N的密度为1,B、C的密度为2,A的密度为4

邻域(Neighborhood) 空间中任意一点的邻域是以该点为圆心、以EPS为半径的圆区域内包含的点集合

核心点(Core Points) 空间中某一点的密度,如果大于某一给定阈值MinPts,则称该点为核心点 设MinPts为3,则核心点为A

边界点(Border Points) 空间中某一点的密度>1并且小于MinPts 图中的边界点为B、C

噪声点(Noise Points) 数据集中不属于核心点,也不属于边界点的点,密度值为1 图中噪声点为N

算法实现:

代码语言:javascript复制
data <- read.csv('data.csv')

plot(data[, 1], data[, 2])

eps <- 0.2;
MinPts <- 5;

d <- as.matrix(dist(data))

#将所有点标记为核心点、边界点或噪声点
ps <- data.frame(index=c(NA), density=c(NA), type=c(NA))
for(i in 1:nrow(data)) {
  #i <- 1;
  index <- which(d[i, ]<eps)
  #密度,空间中任意一点的密度是以该点为圆心、以 Eps 为半径的圆区域内包含的点数
  density <- length(index);
  if(density>MinPts) {
    #核心点(Core Points)
    #空间中某一点的密度,如果大于某一给定阈值MinPts,则称该为核心点
    ps[i, ] <- c(i, density, 1)
  } else if(density>1) {
    #边界点(Border Points)
    #空间中某一点的密度,如果小于某一给定阈值MinPts,则称该为边界点
    ps[i, ] <- c(i, density, 2)
  } else {
    #噪声点(Noise Points)
    #数据集中不属于核心点,也不属于边界点的点,也就是密度值为1的点
    ps[i, ] <- c(i, density, 0)
  }
}

#把噪声点过滤掉,因为噪声点无法聚类,它们独自一类
corePoints <- data[which(ps$type!=0), ]
coreDists <- as.matrix(dist(corePoints))

#首先,把每个点的领域都作为一类
#邻域(Neighborhood)
#空间中任意一点的邻域是以该点为圆心、以 Eps 为半径的圆区域内包含的点集合
cluster <- list();
for(i in 1:nrow(coreDists)) {
  cluster[[i]] <- names(which(coreDists[i, ]<eps));
}

#然后,将有交集的领域,都合并为新的领域
for(i in 1:length(cluster)) {
  for(j in 1:length(cluster)) {
    if(any(cluster[[j]] %in% cluster[[i]]) && i!=j) {
      if(ps[cluster[[i]][1], ]$type==1 && ps[cluster[[i]][2], ]$type==1) {
        cluster[[i]] <- unique(append(cluster[[i]], cluster[[j]]))
        cluster[[j]] <- list();
      }
    }
  }
}

#最后,找出独立(也就是没有交集)的领域,就是我们最后的聚类的结果了
result <- list();
for(i in 1:length(cluster)) {
  if(length(cluster[[i]])>0) {
    result[[length(result) 1]] <- cluster[[i]]
  }
}

#找出每个点所在领域的序号,作为他们最后聚类的结果标记
for(i in 1:length(result)) {
  for(j in result[[i]]) {
    data[j, 3] <- i
  }
}

plot(data[, 1], data[, 2], col=data[,3])

如何使用”fpc”包中的dbscan函数进行密度聚类。 很简单!

代码语言:javascript复制
#install.packages('fpc')

library('fpc')

data <- read.csv('data.csv')
plot(data[, 1], data[, 2])

# 用fpc包中的dbscan函数进行密度聚类
model2 <- dbscan(data, eps=0.2, MinPts=5)
plot(data[, 1], data[, 2], col=model2$cluster)

0 人点赞