NVIDIA cuML Machine Learning Skill:deepagents 中 GPU 加速机器学习实战指南
【免费下载链接】deepagentsThe batteries-included agent harness.项目地址: https://gitcode.com/GitHub_Trending/de/deepagents
在 LangChain deepagents 的 NVIDIA 示例工程中,cuml-machine-learning技能(Skill)为 Agent 提供了基于 NVIDIA RAPIDS cuML 的 GPU 加速机器学习能力。它面向表格数据的分类、回归、聚类、降维与预处理任务,通过一份 SKILL.md 文档,将"何时用、如何初始化、怎么写代码、有哪些坑"完整固化,让 Agent 在 GPU 沙箱中直接写出可运行的 cuML 脚本。读完本文,你将掌握该技能的完整用法,理解其在 deepagents 多智能体 + GPU 沙箱架构中的运行机制,并学会用同一套代码在 CPU 环境无缝回退。
技能定位:什么时候该用 cuML
技能文件头部的 YAML frontmatter 定义了 Agent 的触发条件:
--- name: cuml-machine-learning description: Use for GPU-accelerated machine learning on tabular data using NVIDIA cuML. Triggers when tasks involve classification, regression, clustering, dimensionality reduction, or model training on datasets. ---按技能文档的约定,以下任务都应优先启用该技能:
- 训练分类模型(预测类别、欺诈检测、文本分类)
- 训练回归模型(数值预测、价格预估、数量估算)
- 数据聚类(客户分群、文档分组、模式发现)
- 降维(高维数据可视化、特征压缩)
- 大规模数据集的预处理与特征工程
- 任何行数达到 1 万行以上、需要 GPU 加速的机器学习任务
这套触发逻辑对应 deepagents 的 **Skills 渐进式披露(progressive disclosure)**机制。核心实现位于 libs/deepagents/deepagents/middleware/skills.py 的SKILLS_SYSTEM_PROMPT:Agent 的系统提示中只会列出每个技能的name与description,当任务命中某个描述时才通过read_file读取完整 SKILL.md。因此 frontmatter 中的description必须包含足够的触发关键词——这正是本技能"classification / regression / clustering / dimensionality reduction"等词被精心写入的原因。
初始化样板:必须先做 GPU 冒烟测试
技能文档强调每个脚本都必须以固定的初始化样板开头,它的作用不只是 import,而是真实执行一次 GPU ML 运算来验证环境可用性:
import pandas as pd import numpy as np try: import cudf import cuml # Smoke-test: verify GPU ML works end-to-end _test_data = cudf.DataFrame({'a': [1.0, 2.0, 3.0, 4.0], 'b': [5.0, 6.0, 7.0, 8.0]}) _km = cuml.cluster.KMeans(n_clusters=2, n_init=1, random_state=42) _km.fit(_test_data) assert len(_km.labels_) == 4 GPU = True except Exception as e: print(f"[GPU] cuml unavailable, falling back to scikit-learn: {e}") GPU = False def read_csv(path): return cudf.read_csv(path) if GPU else pd.read_csv(path) def to_pd(df): """Convert cuML/cuDF output to pandas. Use this instead of .to_pandas() directly.""" if not GPU: return df try: return df.to_pandas() except Exception as e: print(f"[GPU] .to_pandas() failed, using Arrow fallback: {e}") return df.to_arrow().to_pandas()这段代码包含三个关键设计:
- 真实运算冒烟测试:
KMeans.fit()会在 GPU 上完成一轮真实的聚类,assert len(_km.labels_) == 4验证输出形状正确。仅 import 成功并不能证明 cuML 可用——这正是它与普通"try-import"写法的本质区别。 - 双层数据读取抽象:
read_csv()在 GPU 模式下走cudf.read_csv,否则回退pandas.read_csv,后续代码无需感知数据框架差异。 - 带 Arrow 兜底的转换函数:
to_pd()优先用.to_pandas(),失败时回退到.to_arrow().to_pandas()。文档明确要求用它替代直接调用.to_pandas()。这一细节与仓库的踩坑记录高度吻合——examples/nvidia_deep_agent/src/backend.py 中注明 RAPIDS 25.02 自带的 numba-cuda 0.2.0 存在设备枚举缺陷,会导致.to_pandas()与.describe()崩溃,因此镜像构建时强制pip_install("numba-cuda>=0.28", ...)。
需要特别说明:GPU/CPU 回退不是摆设。虽然示例工程默认使用带 A10G GPU 的 RAPIDS 镜像,但通过运行时上下文可以把沙箱切换为纯 CPU 镜像(仅安装 pandas、numpy、scipy、scikit-learn),此时GPU = False分支会保证脚本仍能正确执行。详细机制见下文"运行机制"一节。
双模式导入模式:GPU 与 CPU 的 API 镜像
cuML 的卖点是与 scikit-learn 兼容的 API,因此技能文档提供了一一对应的导入映射。GPU 模式下:
# GPU mode if GPU: from cuml.cluster import KMeans, DBSCAN, HDBSCAN from cuml.ensemble import RandomForestClassifier, RandomForestRegressor from cuml.linear_model import LinearRegression, Ridge, Lasso, LogisticRegression from cuml.neighbors import KNeighborsClassifier, KNeighborsRegressor from cuml.svm import SVC, SVR from cuml.decomposition import PCA, TruncatedSVD from cuml.manifold import UMAP, TSNE from cuml.preprocessing import StandardScaler, MinMaxScaler, LabelEncoder from cuml.model_selection import train_test_split from cuml.metrics import accuracy_score, r2_score, mean_squared_error # CPU fallback else: from sklearn.cluster import KMeans, DBSCAN, HDBSCAN from sklearn.ensemble import RandomForestClassifier, RandomForestRegressor from sklearn.linear_model import LinearRegression, Ridge, Lasso, LogisticRegression from sklearn.neighbors import KNeighborsClassifier, KNeighborsRegressor from sklearn.svm import SVC, SVR from sklearn.decomposition import PCA, TruncatedSVD from sklearn.manifold import TSNE from sklearn.preprocessing import StandardScaler, MinMaxScaler, LabelEncoder from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score, r2_score, mean_squared_error # UMAP not in sklearn — skip or pip install umap-learn两处需要注意的差异:
- UMAP 是 cuML 独有能力,scikit-learn 中没有对应实现,CPU 分支需跳过或额外
pip install umap-learn。 - 模块归属刻意对齐:
cuml.cluster对应sklearn.cluster、cuml.ensemble对应sklearn.ensemble,其余一一对应。因此只要保持这套导入模式,训练代码几乎可以零修改地在 GPU/CPU 之间切换。
快速参考:六类核心操作
1. 训练/测试划分(起点)
X = df[["feature1", "feature2", "feature3"]].astype("float32") y = df["target"] X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)注意特征矩阵在切分前就完成.astype("float32")转换——这是 cuML 对数据类型的要求(详见下文)。
2. 分类
model = RandomForestClassifier(n_estimators=100, max_depth=10, random_state=42) model.fit(X_train, y_train) predictions = model.predict(X_test) accuracy = float(accuracy_score(to_pd(y_test), to_pd(predictions))) print(f"Accuracy: {accuracy:.4f}") # Feature importances (tree models only) importances = to_pd(model.feature_importances_) for name, imp in zip(feature_names, importances): print(f" {name}: {imp:.4f}")三个要点:
- 评估指标计算前,
y_test与predictions都经过to_pd()转回 pandas 再比较,避免 GPU 端数据框架在指标函数中的兼容性问题。 - 特征重要性只对树模型(随机森林)有效。
feature_names需在脚本中显式定义(例如从df.columns中筛选)。
3. 回归
model = Ridge(alpha=1.0) model.fit(X_train, y_train) predictions = model.predict(X_test) r2 = float(r2_score(to_pd(y_test), to_pd(predictions))) mse = float(mean_squared_error(to_pd(y_test), to_pd(predictions))) print(f"R² Score: {r2:.4f}") print(f"MSE: {mse:.4f}") # Coefficients coeffs = to_pd(model.coef_) print(f"Intercept: {float(model.intercept_):.4f}")回归任务同时报告 R² 与 MSE 两个指标,并输出线性模型的系数与截距,方便向用户解释模型逻辑。
4. 聚类(KMeans)
X = df[["feature1", "feature2"]].astype("float32") model = KMeans(n_clusters=4, n_init=10, random_state=42) model.fit(X) labels = to_pd(model.labels_) centroids = to_pd(model.cluster_centers_) inertia = float(model.inertia_) print(f"Inertia: {inertia:.2f}") print(f"Cluster sizes: {labels.value_counts().sort_index().to_dict()}") print(f"Centroids:\n{centroids}")聚类结果需要同时报告:簇内平方和(inertia,用于评估簇数是否合适)、每个簇的样本数分布、以及质心坐标。
5. 降维(PCA)
scaler = StandardScaler() X_scaled = scaler.fit_transform(X.astype("float32")) pca = PCA(n_components=3) X_reduced = pca.fit_transform(X_scaled) variance_ratio = to_pd(pca.explained_variance_ratio_) print(f"Explained variance: {[f'{v:.4f}' for v in variance_ratio]}") print(f"Total explained: {float(sum(variance_ratio)):.4f}")降维前必须先标准化(StandardScaler),否则量纲差异会主导主成分方向;输出时报告每个主成分的解释方差比及累计值。
6. 降维(UMAP — 仅 GPU)
if GPU: reducer = UMAP(n_components=2, n_neighbors=15, min_dist=0.1, random_state=42) embedding = to_pd(reducer.fit_transform(X_scaled)) print(f"UMAP embedding shape: {embedding.shape}")UMAP 是可视化高维结构的常用手段,技能文档明确将其限定在 GPU 分支内(CPU 下 scikit-learn 无此实现)。
7. 预处理
# Scale numeric features scaler = StandardScaler() X_scaled = scaler.fit_transform(X.astype("float32")) # Encode categorical columns le = LabelEncoder() df["category_encoded"] = le.fit_transform(df["category"])分类特征必须先用LabelEncoder(或 OneHotEncoder)编码为数值,cuML 不支持直接吃类别文本。
数据类型要求
技能文档对 cuML 的输入数据提出四条硬性约束,写脚本时务必逐条核对:
- 特征必须是 float32 或 float64,代码中统一用
X.astype("float32")强转; - 整数目标值(分类标签)可直接使用;
- 类别列必须先编码(
LabelEncoder或OneHotEncoder); - cuML 不支持稀疏矩阵,必须使用稠密数据。
其中"稠密数据"这条与下面的 Gotchas 表格首行直接呼应,是 Agent 在沙箱中运行 cuML 脚本时最常见的报错来源之一。
常见坑与解决方案
技能文档用一个速查表固化了五个高频问题,Agent 遇到对应报错时可直接对号入座:
| Issue | Fix |
|---|---|
TypeError: sparse input | Convert to dense:X.toarray()or don't use sparse |
PCAsolver='randomized'fails | Usesolver='full'or omit (cuML auto-selects) |
| UMAP not available on CPU | Skip UMAP in CPU mode orpip install umap-learn |
| Float64 slower than float32 | Cast to float32:X.astype("float32") |
| Large dataset OOM | Reduce features or sample data before fitting |
这五条并非空泛建议,而是 Agent 在真实运行中反复踩坑后的经验沉淀。其中"Float64 slower than float32"与"Large dataset OOM"共同指向同一个最佳实践:训练前把特征矩阵统一转为 float32,必要时先降维或抽样再拟合。这些坑位被写进 SKILL.md 后,Agent 下次执行同类任务时会主动规避——这正是 deepagents 自改进记忆机制的体现(见下文"运行机制")。
结果输出规范
技能文档对 Agent 的汇报格式也有明确约定,要求报告机器学习结果时包含:
- 数据集形状(行数 × 特征数)与目标分布
- 训练/测试划分的大小
- 以格式化表格呈现关键指标(accuracy、R²、MSE 等)
- 多分类任务需给出每个类别的指标
- 聚类任务需给出簇大小与质心摘要
- 降维任务需给出解释方差比
- 按幅度排序的特征重要性列表
- 数据质量问题说明(类别不平衡、缺失值、异常值)
这些规范与 examples/nvidia_deep_agent/src/prompts.py 中DATA_PROCESSOR_INSTRUCTIONS的输出格式要求(Task Topic / Summary / Results / Insights)配合使用:Agent 先将完整结果写入/shared/[task_topic].txt,再向用户呈现结构化摘要。
在 deepagents 中的运行机制:技能如何被加载与执行
理解了技能内容本身,再来看它在整个示例工程中的运转闭环。
第一步:技能注册进子 Agent。在 examples/nvidia_deep_agent/src/agent.py 中,data-processor-agent通过"skills": ["/skills/"]挂载了整个技能目录,并由create_deep_agent指定backend=create_backend与context_schema=Context(可传sandbox_type: "gpu" | "cpu")。
第二步:技能文件注入沙箱。examples/nvidia_deep_agent/src/backend.py 的_seed_sandbox()会在沙箱创建时遍历本地skills/目录,把每个子目录下的SKILL.md上传到沙箱内的/skills/<skill-name>/SKILL.md。GPU 沙箱使用nvcr.io/nvidia/rapidsai/base:25.02-cuda12.8-py3.12基础镜像(cuDF、cuML 预装)并挂载 A10G GPU;CPU 沙箱则是一个仅含 pandas、numpy、scipy、scikit-learn 的轻量镜像。
第三步:Agent 按流程执行。DATA_PROCESSOR_INSTRUCTIONS规定的工作流是:理解任务 →read_file读取相关 SKILL.md → 基于技能中的样板代码写脚本到/workspace/→ 用execute工具运行 → 检查输出、最多重试两次 → 汇总结果。也就是说,本文前面展示的初始化样板、导入模式与各类操作代码,正是 Agent 每次写脚本时直接复制的模板。
第四步:技能元数据由中间件解析。libs/deepagents/deepagents/middleware/skills.py 中的_parse_skill_metadata()负责解析 SKILL.md 的 YAML frontmatter,并校验name与description:name 限制 64 字符、仅允许小写字母数字与单连字符,且必须与所在目录名一致(cuml-machine-learning目录名即为此格式);description 限制 1024 字符。解析失败或格式违规的技能会被跳过并记录警告,但不会中断 Agent 运行。
第五步:自改进记忆。技能文档不仅是"单向使用说明"。按DATA_PROCESSOR_INSTRUCTIONS的约定,当 Agent 在沙箱中解决了一个技能未覆盖的报错、或发现了库的新行为时,会立即用edit_file更新对应的 SKILL.md,以 1~3 行的简洁注释追加到相关章节或 "Known Limitations" 小节。这也解释了为什么 Gotchas 表格中会出现"PCAsolver='randomized'fails"这类极具现场感的条目——它们是 Agent 自学习循环的产物。仓库 README 中的示例是:若发现cudf.DataFrame.interpolate()未实现,就把这条限制写回 cuDF 技能文件,避免未来重复踩坑。
与配套技能协同:从模型到图表的完整链路
cuML 技能在示例工程中并非孤立存在,它与另外三个 GPU 技能形成完整的数据分析链路:
| 技能 | 职责 | 与 cuML 的协作点 |
|---|---|---|
| cudf-analytics | GPU 数据读取、统计、groupby、异常检测 | 提供read_csv()/to_pd()的同款样板与 IQR/Z-score 异常检测,是 ML 前的数据准备阶段 |
| cuml-machine-learning | GPU 机器学习(分类/回归/聚类/降维) | 本文主题 |
| data-visualization | matplotlib/seaborn 出版级图表 | 用 cuML 输出的feature_importances_画特征重要性条形图、用聚类标签画散点图、用预测结果画混淆矩阵热力图 |
| gpu-document-processing | GPU 大批量文档处理 | 处理后的结构化文本可作为 cuML 文本分类的输入 |
一个典型的多步骤任务会串起全部技能:用 cuDF 读取并清洗 CSV → 用 cuML 训练分类器并输出特征重要性 → 用 matplotlib/seaborn 把重要性排序和混淆矩阵渲染成 PNG → 通过read_file在对话中内联展示图表。README 中的示例查询"Upload this CSV and train a classifier to predict customer churn. Show feature importances."正是这条链路的直接体现。
总结
cuml-machine-learning技能是一份高度工程化的 Agent 提示工程产物:用固定样板解决环境探测与数据转换、用双模式导入解决 GPU/CPU 兼容、用 Quick Reference 固化六类核心操作、用 Gotchas 表格兜底高频报错、用 Output Guidelines 规范汇报质量。配合 deepagents 的 SkillsMiddleware 渐进式披露、Modal GPU 沙箱的自动种子化,以及"出错即回写技能文件"的自改进循环,它把"在 GPU 上跑机器学习"这件事从一次性脚本升级为可复用、可积累、可自我进化的 Agent 能力。
【免费下载链接】deepagentsThe batteries-included agent harness.项目地址: https://gitcode.com/GitHub_Trending/de/deepagents
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考