Menu
CoddyTech

DBSCAN

本课属于 Coddy Machine Learning 学习旅程的“无监督学习”单元。第 20 课,共 51 课。

本章将找出各种形状的人群,以及不属于任何人群的点。学完后,你将绘制山谷中的灯光分布图:

山谷夜间地图:一座细长弯曲的城镇、一座圆形城镇和一个小村庄,各自用不同颜色和标记表示,它们之间有 10 盏零散的灯光,以灰色 x 标记显示

首先,回顾一下“当 K-Means 失效”一课中让 k-means 失效的海豹沙洲。DBSCAN 则会跟随人群:

两张图展示了位于两条弯曲沙洲上的同一批 200 只海豹。左图中,k-means 将它们分成左右两半。右图中,DBSCAN 找到了完整的两条沙洲,其中一只海豹周围标有一个小圆圈,表示 eps

一个点在半径为 eps 的圆内有 min_samples 个点(包括它自己),就属于一个人群。人群会通过这样的点扩散。不需要选择 k:

from sklearn.cluster import DBSCAN
labels = DBSCAN(eps=0.2, min_samples=5).fit_predict(X)
print(labels.max() + 1)

这会输出 2:人群从 0 开始编号,所以最大编号加 1 就是人群的数量。

challenge icon

挑战

中等

在一座结冰的湖面上,滑冰者沿着一条蜿蜒穿过两座岛屿之间的路线竞速,观众则在观看一场冰球比赛。k-means 会把这条路线切成几段。程序会读取以米为单位的 eps。

  1. 用这个 eps 和 min_samples=5 拟合 DBSCAN,并将人群标签保存在 labels 中。
  2. 打印找到的人群数量。
  3. 用 draw_crowds(ax, X, labels) 绘制这些人群并显示图表。

换一座湖,eps 设为 3.5:

Crowds found: 3

标题为 Skaters on the Lake 的图表:150 名滑冰者组成一条蜿蜒的 S 形蓝色路线,路线左侧弯道上方有一群 30 人的橙色人群,右侧弯道下方有一群 22 人的绿色人群,图例标注了各群人数

Coddy 会描述你的图表。然后用 eps 8 运行它:这些人群去哪儿了?

亲手试试

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.cluster import DBSCAN

# 170 名滑冰者在冰封湖面上的位置,单位为米
skaters = pd.read_csv("skaters.csv")
X = np.column_stack([skaters["x_m"], skaters["y_m"]])
eps = float(input())


# 用不同颜色绘制每群人,并标出各群人数
def draw_crowds(ax, X, labels):
    for crowd in range(labels.max() + 1):
        rows = labels == crowd
        ax.scatter(X[rows, 0], X[rows, 1], s=14, label=f"{rows.sum()} skaters")
    ax.legend()


fig, ax = plt.subplots()
ax.set_title("Skaters on the Lake")
ax.set_xlabel("East (m)")
ax.set_ylabel("North (m)")

# 在下方编写你的代码
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

无监督学习中的所有课

自己练习: Python 在线编译器