机器学习之DBSCAN密度聚类详解

摘要: DBSCAN(Density-Based Spatial Clustering of Applications with Noise)是一种基于密度的经典聚类算法,与K-Means等基于距离的划分方法不同,DBSCAN通过计算样本点的密度分布来发现任意形状的簇,并能够自动识别噪声点。本文详细阐述DBSCAN的核心概念、算法原理与步骤,并通过多个实战案例演示如何使用scikit-learn实现DBSCAN聚类,同时与K-Means进行对比分析,帮助读者在实际场景中选择合适的聚类算法。

关键词: DBSCAN、密度聚类、噪声检测、scikit-learn、聚类算法、异常检测


1. 引言

聚类是机器学习中无监督学习的重要任务之一,其目标是将数据集中的样本划分为若干个簇,使得同一簇内的样本相似度较高,不同簇之间的样本相似度较低。传统的K-Means算法通过计算样本到簇中心的距离进行划分,要求簇呈凸球形且大小相近,在处理非球形簇、密度不均匀数据集以及噪声数据时表现不佳。

DBSCAN由Martin Ester、Hans-Peter Kriegel、Jörg Sander和Xiaowei Xu于1996年提出,其核心思想是通过样本的密度连通性来构建簇,能够发现任意形状的簇,并对噪声数据具有天然的鲁棒性。本文将从原理、参数选择、算法对比、适用场景和代码实现等多个维度对DBSCAN进行系统介绍。


2. DBSCAN核心概念

2.1 基本定义

DBSCAN的运行依赖于两个关键参数:

  • 邻域半径ε(eps):以某一样本点为中心,其ε邻域指的是距离该点不超过ε的所有样本集合。

  • 最小点数MinPts(min_samples):用于判断一个点是否为核心点所需的最小邻域样本数。

在此基础上,数据集中的每个点可以被分为三类:

核心点(Core Point): 如果一个点的ε邻域内包含的样本点数不少于MinPts,则该点为核心点。核心点位于数据的稠密区域,是簇形成的基础。

边界点(Border Point): 如果一个点本身不是核心点,但其落在某个核心点的ε邻域内,则该点为边界点。边界点虽然不属于稠密区域,但它是簇的组成部分。

噪声点(Noise Point): 如果一个点既不是核心点也不是边界点,即其ε邻域内的样本数少于MinPts,且不落在任何核心点的邻域内,则该点为噪声点。噪声点不会被分配到任何簇中。

2.2 密度可达与密度相连

理解DBSCAN还需要两个关键概念:

密度直达(Density-Reachable): 若存在一条样本链 p_1, p_2, \\ldots, p_n,其中 p_{i+1} 位于 p_i 的ε邻域内,且 p_1 为核心点,则称 p_np_1 密度直达。密度直达关系是单向的。

密度相连(Density-Connected): 若存在一个核心点 o,使得样本点 pq 均由 o 密度直达,则称 pq 密度相连。密度相连具有对称性,是DBSCAN构建簇的核心依据。

基于以上概念,DBSCAN的簇可以定义为:由密度相连关系能够到达的所有样本点组成的最大集合。这意味着,同一簇内的任意两个样本点之间都存在一条密度相连的路径。


3. DBSCAN算法步骤

DBSCAN的完整执行流程如下:

输入: 数据集 D = {x_1, x_2, \\ldots, x_n},邻域半径ε,最小点数MinPts。

输出: 若干个簇,以及噪声点集合。

算法步骤:

步骤1: 将数据集中所有样本点标记为"未访问"状态,并为每个点维护一个簇标签(初始为-1,表示不属于任何簇)。

步骤2: 遍历数据集中的每一个点:

  • 若该点已被访问,则跳过。

  • 否则,将其标记为"访问中"。

  • 计算该点的ε邻域集合 N_{\\varepsilon}(p)

  • \|N_{\\varepsilon}(p)\| \< MinPts,将该点暂时标记为噪声点(后续可能被重新归类)。

  • \|N_{\\varepsilon}(p)\| \\geq MinPts,该点为核心点,创建新簇,将该点及其密度直达的所有点加入簇中。

步骤3: 对于新创建的簇,迭代扩展:对于簇中的每一个非核心点,检查其是否落在某个核心点的ε邻域内,若是则将其加入当前簇(边界点的处理)。

步骤4: 重复步骤2-3,直到所有点均被访问。最终未被分配到任何簇的点即为噪声点。

伪代码实现:

复制代码
DBSCAN(D, eps, MinPts):
    visited = {}
    cluster_id = 0
    for point in D:
        if point in visited:
            continue
        visited.add(point)
        # 核心点检测
        neighbors = region_query(point, eps)
        if len(neighbors) < MinPts:
            # 暂时标记为噪声
            cluster[point] = -1
        else:
            # 扩展簇
            expand_cluster(point, neighbors, cluster_id, eps, MinPts, visited)
            cluster_id += 1
    return cluster

4. DBSCAN与K-Means对比

K-Means和DBSCAN是两种最常用的聚类算法,它们在设计哲学和适用场景上存在显著差异。以下从多个维度进行对比分析。

4.1 参数设置方式

K-Means需要预先指定簇的数量K,这一要求在实际应用中往往难以满足------我们通常并不知道数据集中应该有多少个簇。K-Means的聚类结果对初始簇中心的选择敏感,不同的初始化可能导致截然不同的结果。

DBSCAN不需要预先指定簇的数量,簇的数量由数据的密度分布自动决定。但这并不意味着DBSCAN没有参数------ε和MinPts的选择对结果影响较大,需要通过领域知识或启发式方法(如k-距离图)来确定。

4.2 簇形状的适应性

K-Means通过计算样本到簇中心的欧氏距离进行划分,天然倾向于发现凸球形、大小相近的簇。对于月牙形、环形、螺旋形等非球形簇,K-Means往往无法正确识别。

DBSCAN基于密度连通性构建簇,可以发现任意形状的簇,包括非凸形状。这使得DBSCAN在处理复杂几何结构的数据时具有明显优势。

4.3 噪声处理能力

K-Means将每一个点都强制分配到某个簇中,即使某些点距离所有簇中心都很远(即噪声点),也会被归入最近的簇,从而污染簇的质量。

DBSCAN通过核心点-边界点-噪声点的分类机制,能够自动识别并排除噪声点。这是DBSCAN最重要的优势之一,使其在异常检测等场景中表现出色。

4.4 算法复杂度

K-Means的时间复杂度为O(nKI),其中n为样本数,K为簇数,I为迭代次数,通常收敛较快。

DBSCAN的时间复杂度为O(n²),在处理大规模数据集时可能面临性能挑战。不过,通过使用空间索引(如R树),可以将复杂度降为O(n log n)。

4.5 对比总结

特性 K-Means DBSCAN
簇数量 需手动指定K 自动发现
簇形状 凸球形 任意形状
噪声处理 无(强制归类) 自动识别
参数敏感性 初始中心选择 ε和MinPts
时间复杂度 O(nKI) O(n²)
数据分布 需大小相近 密度均匀/不均匀均可

5. DBSCAN参数选择指南

5.1 ε参数的选择

ε的选择是DBSCAN应用中的核心挑战之一。一个常用的启发式方法是绘制k-距离图(k-distance plot):对于数据集中的每个点,计算其到第k个最近邻的距离(通常取k=MinPts),然后将这些距离按升序排列并绘图。

在k-距离图中,陡峭上升的区域对应的距离值可以作为ε的候选值------这意味着选择该值作为邻域半径,能够有效区分稠密区域和稀疏区域。

5.2 MinPts参数的选择

MinPts的选取通常与数据集的维度有关。一般而言:

  • 对于低维数据,MinPts可以设为4-10之间。

  • 维度越高,需要更大的MinPts来确保邻域内的点具有统计意义。

  • scikit-learn的默认值是5,在许多场景下是一个合理的起点。

一个经验法则:将MinPts设置为数据维度的2倍。例如,对于2维数据,MinPts=4;对于10维数据,MinPts=20。


6. DBSCAN使用场景

6.1 地理空间数据聚类

在地理信息系统(GIS)和位置服务中,DBSCAN被广泛用于发现热点区域、用户行为分析和城市规划。例如,对城市中出租车GPS轨迹数据进行聚类,可以发现打车需求密集的热点区域;对犯罪事件地点进行聚类,可以识别犯罪高发区域。

6.2 异常检测

DBSCAN天然具备识别噪声点的能力,这使其成为异常检测的有力工具。在金融交易监控中,异常的转账行为可能表现为密度很低的数据点;在网络入侵检测中,异常访问模式可能无法被任何密度足够高的簇覆盖,从而被识别为噪声。

6.3 图像分割

在计算机视觉中,DBSCAN可以用于图像的语义分割。通过将图像像素或超像素映射到特征空间(如颜色、纹理、位置),DBSCAN可以将具有相似特征的区域聚类在一起,实现无监督的图像分割。

6.4 客户行为分析

在电商和零售领域,通过分析用户的购买行为、浏览路径和偏好特征,DBSCAN可以将用户划分为不同的群体。由于客户行为往往呈现非球形分布(如存在小众高价值客户群体),DBSCAN相比K-Means能够更准确地捕捉这些自然形成的用户群体。

6.5 其他场景

  • 生物信息学: 基因表达数据聚类、蛋白质相互作用网络分析

  • 日志分析: 异常日志检测、系统行为模式识别

  • 推荐系统: 用户-物品交互矩阵的协同过滤聚类


7. 实战代码

本节通过四个实战案例演示如何使用scikit-learn实现DBSCAN聚类。所有代码均可直接运行。

7.1 环境准备

复制代码
# 导入必要的库
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_moons, make_circles, make_blobs
from sklearn.cluster import KMeans, DBSCAN
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import silhouette_score, adjusted_rand_score
import warnings
warnings.filterwarnings('ignore')
​
# 设置中文字体支持(如果环境支持)
plt.rcParams['font.sans-serif'] = ['SimHei', 'DejaVu Sans']
plt.rcParams['axes.unicode_minus'] = False

7.2 案例一:月牙形数据聚类------DBSCAN vs K-Means

月牙形数据是两个交叠的半月形分布,K-Means由于只能发现凸球形簇,在该数据上表现极差,而DBSCAN可以完美地将其分开。

复制代码
# 生成月牙形数据集
# make_moons生成两个交叠的半月形数据,配合noise参数添加随机扰动
X_moons, y_moons = make_moons(n_samples=300, noise=0.1, random_state=42)
​
# 使用K-Means进行聚类(假设我们知道有2个簇)
kmeans_moons = KMeans(n_clusters=2, random_state=42, n_init=10)
y_kmeans_moons = kmeans_moons.fit_predict(X_moons)
​
# 使用DBSCAN进行聚类
# eps=0.3:邻域半径,相邻月牙之间距离较近时适当调小
# min_samples=5:最小邻域点数
dbscan_moons = DBSCAN(eps=0.3, min_samples=5)
y_dbscan_moons = dbscan_moons.fit_predict(X_moons)
​
# 可视化对比
fig, axes = plt.subplots(1, 3, figsize=(15, 5))
​
# 原始数据
axes[0].scatter(X_moons[:, 0], X_moons[:, 1], c=y_moons, cmap='viridis', s=30)
axes[0].set_title('原始数据(真实标签)')
axes[0].set_xlabel('特征1')
axes[0].set_ylabel('特征2')
​
# K-Means结果
axes[1].scatter(X_moons[:, 0], X_moons[:, 1], c=y_kmeans_moons, cmap='viridis', s=30)
axes[1].scatter(kmeans_moons.cluster_centers_[:, 0], 
                kmeans_moons.cluster_centers_[:, 1], 
                c='red', marker='X', s=200, label='聚类中心')
axes[1].set_title(f'K-Means聚类(ARI={adjusted_rand_score(y_moons, y_kmeans_moons):.2f})')
axes[1].legend()
​
# DBSCAN结果
# -1标签表示噪声点,在图中用灰色显示
colors = ['gray' if label == -1 else plt.cm.tab10(label) for label in y_dbscan_moons]
axes[2].scatter(X_moons[:, 0], X_moons[:, 1], c=y_dbscan_moons, cmap='viridis', s=30)
axes[2].set_title(f'DBSCAN聚类(噪声点={np.sum(y_dbscan_moons == -1)}个)')
​
plt.tight_layout()
plt.savefig('dbscan_vs_kmeans_moons.png', dpi=150)
plt.show()
​
# 打印聚类评估指标
print("=" * 50)
print("月牙形数据聚类评估对比")
print("=" * 50)
print(f"K-Means调整兰德指数(ARI): {adjusted_rand_score(y_moons, y_kmeans_moons):.4f}")
print(f"DBSCAN调整兰德指数(ARI): {adjusted_rand_score(y_moons, y_dbscan_moons):.4f}")

运行结果分析: K-Means的ARI通常在0.3-0.5之间,说明其强行将月牙数据划分为两个交叉的球形簇,效果不佳。DBSCAN的ARI接近1.0,能够完美地将两个半月形分开,并且自动识别出噪声点。

7.3 案例二:环形数据聚类

环形数据是另一个K-Means难以处理的经典案例:内环和外环是两个独立的簇,但K-Means会将中心区域和外环混合。

复制代码
# 生成环形数据
# factor参数控制内外环的间距,noise参数添加噪声
X_rings, y_rings = make_circles(n_samples=400, noise=0.05, factor=0.5, random_state=42)
​
# 数据预处理:标准化(对DBSCAN不是必须,但有助于参数设置的一致性)
scaler = StandardScaler()
X_rings_scaled = scaler.fit_transform(X_rings)
​
# K-Means聚类
kmeans_rings = KMeans(n_clusters=2, random_state=42, n_init=10)
y_kmeans_rings = kmeans_rings.fit_predict(X_rings_scaled)
​
# DBSCAN聚类
# 对于环形数据,需要适当增大eps以确保内外环的核心点可以密度连通
dbscan_rings = DBSCAN(eps=0.3, min_samples=5)
y_dbscan_rings = dbscan_rings.fit_predict(X_rings_scaled)
​
# 可视化
fig, axes = plt.subplots(1, 3, figsize=(15, 5))
​
axes[0].scatter(X_rings[:, 0], X_rings[:, 1], c=y_rings, cmap='coolwarm', s=30)
axes[0].set_title('原始数据(真实标签)')
​
axes[1].scatter(X_rings[:, 0], X_rings[:, 1], c=y_kmeans_rings, cmap='coolwarm', s=30)
axes[1].set_title('K-Means结果(无法区分环形)')
​
axes[2].scatter(X_rings[:, 0], X_rings[:, 1], c=y_dbscan_rings, cmap='coolwarm', s=30)
axes[2].set_title('DBSCAN结果(完美分离环形)')
​
plt.tight_layout()
plt.savefig('dbscan_vs_kmeans_rings.png', dpi=150)
plt.show()
​
print("=" * 50)
print("环形数据聚类评估对比")
print("=" * 50)
print(f"K-Means轮廓系数: {silhouette_score(X_rings_scaled, y_kmeans_rings):.4f}")
print(f"DBSCAN轮廓系数: {silhouette_score(X_rings_scaled, y_dbscan_rings):.4f}")

7.4 案例三:参数ε和MinPts的选择------k-距离图方法

如何科学地选择ε参数?本案例展示k-距离图的绘制方法。

复制代码
# 使用make_blobs生成一个包含噪声的数据集
X_blobs, y_blobs = make_blobs(n_samples=500, centers=4, cluster_std=0.6,
                               random_state=42)
​
# 计算每个点到其第k个最近邻的距离(k=MinPts)
from sklearn.neighbors import NearestNeighbors
​
MinPts = 5  # 选择k=5
# 使用NearestNeighbors计算最近邻
nbrs = NearestNeighbors(n_neighbors=MinPts).fit(X_blobs)
distances, indices = nbrs.kneighbors(X_blobs)
​
# 获取每个点的第k个最近邻距离(即第MinPts个邻居的距离)
k_distances = distances[:, MinPts - 1]
k_distances = np.sort(k_distances)[::-1]  # 降序排列
​
# 绘制k-距离图
fig, axes = plt.subplots(1, 2, figsize=(14, 5))
​
# 左图:k-距离图
axes[0].plot(range(len(k_distances)), k_distances, 'b-', linewidth=1)
axes[0].set_xlabel('点(按距离降序排列)', fontsize=11)
axes[0].set_ylabel(f'第{MinPts}个最近邻距离', fontsize=11)
axes[0].set_title('K-距离图:寻找拐点', fontsize=12)
axes[0].grid(True, alpha=0.3)
​
# 标注拐点区域(通常在距离曲线"肘部"处)
# 通过观察曲线,手动选择ε
eps_candidate = 0.5
axes[0].axhline(y=eps_candidate, color='r', linestyle='--', 
                label=f'候选ε={eps_candidate}')
axes[0].legend()
​
# 使用不同ε值进行DBSCAN聚类,观察效果
eps_values = [0.3, 0.5, 0.8, 1.2]
cluster_results = {}
​
for eps in eps_values:
    dbscan = DBSCAN(eps=eps, min_samples=MinPts)
    labels = dbscan.fit_predict(X_blobs)
    n_clusters = len(set(labels)) - (1 if -1 in labels else 0)
    n_noise = list(labels).count(-1)
    cluster_results[eps] = {'n_clusters': n_clusters, 'n_noise': n_noise, 'labels': labels}
​
# 右图:展示不同ε值对应的聚类数量
cluster_counts = [cluster_results[eps]['n_clusters'] for eps in eps_values]
noise_counts = [cluster_results[eps]['n_noise'] for eps in eps_values]
​
x_pos = np.arange(len(eps_values))
width = 0.35
bars1 = axes[1].bar(x_pos - width/2, cluster_counts, width, label='聚类数量', color='steelblue')
bars2 = axes[1].bar(x_pos + width/2, noise_counts, width, label='噪声点数量', color='coral')
​
axes[1].set_xlabel('ε值', fontsize=11)
axes[1].set_ylabel('数量', fontsize=11)
axes[1].set_title('不同ε值对聚类结果的影响', fontsize=12)
axes[1].set_xticks(x_pos)
axes[1].set_xticklabels([str(eps) for eps in eps_values])
axes[1].legend()
​
# 在柱状图上标注数值
for bar in bars1:
    height = bar.get_height()
    axes[1].annotate(f'{int(height)}',
                     xy=(bar.get_x() + bar.get_width() / 2, height),
                     ha='center', va='bottom', fontsize=9)
for bar in bars2:
    height = bar.get_height()
    axes[1].annotate(f'{int(height)}',
                     xy=(bar.get_x() + bar.get_width() / 2, height),
                     ha='center', va='bottom', fontsize=9)
​
plt.tight_layout()
plt.savefig('dbscan_parameter_selection.png', dpi=150)
plt.show()
​
print("=" * 50)
print("ε参数选择实验结果")
print("=" * 50)
for eps in eps_values:
    info = cluster_results[eps]
    print(f"ε={eps}: 聚类数={info['n_clusters']}, 噪声点={info['n_noise']}")

7.5 案例四:噪声点检测实战

DBSCAN在异常检测中具有天然优势。本案例演示如何使用DBSCAN识别数据集中的噪声点和异常样本。

复制代码
# 模拟一个包含正常数据和异常值的数据集
# 正常数据:三个高斯分布的簇
X_normal, y_normal = make_blobs(n_samples=300, centers=3, 
                                 cluster_std=0.8, random_state=42)
​
# 手动添加异常点(在远离正常数据区域的位置)
np.random.seed(42)
outliers = np.random.uniform(low=-8, high=8, size=(20, 2))
# 确保异常点确实远离正常簇
outliers = np.array([[9, 9], [-9, 5], [7, -8], [-6, -9], [8, 0], 
                     [-9, -3], [0, 10], [10, -2], [-8, 8], [5, 10],
                     [-10, 1], [9, -6], [-7, -7], [8, 5], [-5, 9],
                     [10, 3], [-9, -9], [6, -9], [-10, -2], [7, 8]])
​
# 合并正常数据和异常点
X_with_outliers = np.vstack([X_normal, outliers])
y_with_outliers = np.hstack([y_normal, np.full(20, -1)])  # -1标记异常点
​
# 使用DBSCAN进行异常检测
dbscan_outlier = DBSCAN(eps=0.8, min_samples=5)
y_pred_outlier = dbscan_outlier.fit_predict(X_with_outliers)
​
# 识别被标记为噪声的点(标签为-1)
noise_mask = y_pred_outlier == -1
detected_outliers = X_with_outliers[noise_mask]
​
# 可视化
fig, axes = plt.subplots(1, 2, figsize=(14, 6))
​
# 左图:真实标签(假设我们知道哪些是异常点)
colors_real = ['red' if label == -1 else plt.cm.tab10(label) 
               for label in y_with_outliers]
axes[0].scatter(X_with_outliers[:, 0], X_with_outliers[:, 1], 
                c=y_with_outliers, cmap='tab10', s=40, alpha=0.7)
axes[0].scatter(outliers[:, 0], outliers[:, 1], c='red', s=100, 
                marker='x', linewidths=2, label='真实异常点')
axes[0].set_title('原始数据(红色为人工注入的异常点)', fontsize=12)
axes[0].legend()
​
# 右图:DBSCAN检测结果
# 正常聚类点按簇标签着色,噪声点用红色×标记
colors_pred = ['red' if label == -1 else plt.cm.tab10(label) 
               for label in y_pred_outlier]
axes[1].scatter(X_with_outliers[:, 0], X_with_outliers[:, 1], 
                c=y_pred_outlier, cmap='tab10', s=40, alpha=0.7)
axes[1].scatter(detected_outliers[:, 0], detected_outliers[:, 1], 
                c='red', s=150, marker='x', linewidths=2, label='DBSCAN检测的噪声点')
axes[1].set_title(f'DBSCAN噪声检测(检测到{noise_mask.sum()}个噪声点)', fontsize=12)
axes[1].legend()
​
plt.tight_layout()
plt.savefig('dbscan_outlier_detection.png', dpi=150)
plt.show()
​
# 计算检测效果
true_outliers_mask = y_with_outliers == -1
detected_as_noise = noise_mask[true_outliers_mask]
precision = detected_as_noise.sum() / noise_mask.sum() if noise_mask.sum() > 0 else 0
recall = detected_as_noise.sum() / true_outliers_mask.sum() if true_outliers_mask.sum() > 0 else 0
​
print("=" * 50)
print("DBSCAN异常检测性能评估")
print("=" * 50)
print(f"共注入异常点: {true_outliers_mask.sum()}个")
print(f"DBSCAN检测为噪声: {noise_mask.sum()}个")
print(f"其中正确检测: {detected_as_noise.sum()}个")
print(f"精确率(Precision): {precision:.2%}")
print(f"召回率(Recall): {recall:.2%}")

8. DBSCAN的局限性

尽管DBSCAN具有诸多优点,但在实际应用中也存在一些局限性:

1. 高维数据挑战: 随着数据维度增加,"维度灾难"会导致样本之间的距离变得几乎相等,密度的概念失去意义。在高维数据上,DBSCAN的效果往往会显著下降。通常建议在高维场景下先进行降维(如PCA、t-SNE)再应用DBSCAN。

2. 参数敏感性: ε和MinPts的选择对聚类结果影响很大,且没有一种通用的最佳选择方法。在密度不均匀的数据集上,选择单一的ε值可能导致某些区域过分割而另一些区域欠分割。针对这一问题,已有改进算法如HDBSCAN(层次化DBSCAN)通过构建密度可达图的层次结构来自适应处理不同密度的簇。

3. 计算复杂度: 对于大规模数据集,O(n²)的时间复杂度可能成为瓶颈。在处理百万级样本时,建议使用基于空间索引的近似算法或考虑分布式计算框架。

4. 对密度差异敏感: 当数据集中不同簇的密度差异较大时,很难找到一组(ε, MinPts)同时满足所有簇。此时可以考虑OPTICS(Ordering Points To Identify the Clustering Structure)算法,它通过构建可达距离图来处理不同密度的簇。


9. 总结

DBSCAN是一种强大且独特的聚类算法,其基于密度连通性的设计理念使其能够发现任意形状的簇、自动识别噪声点,且无需预先指定簇的数量。这使得DBSCAN在地理空间分析、异常检测、图像分割等众多实际场景中具有广泛的应用价值。

然而,DBSCAN并非银弹。高维数据中的维度灾难、参数选择的困难以及计算复杂度限制了其在某些场景下的适用性。在实际工作中,我们应当根据数据的特点选择合适的算法------对于密度均匀的球形簇数据,K-Means可能更加高效;对于复杂形状和需要噪声检测的场景,DBSCAN是更好的选择。

掌握DBSCAN的原理和使用技巧,是每一位数据科学从业者必备的技能。希望本文能够帮助读者深入理解DBSCAN,并在实际项目中灵活运用。

相关推荐
碳基硅坊1 小时前
LoRA微调Qwen3-VL-8B-Instruct做产品质量检查
人工智能·qwen3-vl-8b
shchojj1 小时前
Generative AI applications -- Writing
人工智能
AirDroid_cn1 小时前
macOS Sequoia 通知摘要:如何启用AI生成的通知摘要,并排除特定应用?
人工智能·macos
霍夫曼vx_helloworld73521 小时前
经典图像检测技术概述
图像处理·人工智能·计算机视觉
AI人工智能+1 小时前
营业执照识别技术通过计算机视觉与人工智能技术,实现企业证照信息的自动化采集
人工智能·深度学习·ocr·营业执照识别
目黑live +wacyltd1 小时前
算法备案的实操指南(含截图示例)
人工智能·算法·llm·大模型备案·算法备案
guslegend1 小时前
第2节:工程初始化
人工智能·大模型
wuyoula1 小时前
如何在捷云鲸论坛高效获取高质量技术解答?
服务器·c++·人工智能·tcp/ip·源码
MacroZheng1 小时前
IDEA + Claude Code = 王炸!
人工智能·后端·intellij idea
蜘蛛小助理1 小时前
从 Excel 到多维表:蜘蛛表格如何解决传统数据库开发与维护痛点
数据库·人工智能·excel·数据库开发·多维表·多维表格·蜘蛛表格