Skip to content

Commit c64e176

Browse files
committed
Update
1 parent 6ce2c4e commit c64e176

File tree

1 file changed

+306
-0
lines changed

1 file changed

+306
-0
lines changed

CONTRIBUTE_TUTORIAL_cn.md

Lines changed: 306 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,306 @@
1+
# 共创者指引
2+
> Move fast, break things.
3+
4+
### 一、环境准备
5+
1. **Fork 仓库**
6+
7+
a. 访问 [https://github.com/PaddlePaddle/GraphNet](https://github.com/PaddlePaddle/GraphNet)
8+
9+
b. 点击右上角的 **Fork** 按钮,将仓库复制到你的账户下。
10+
11+
2. **克隆仓库到本地**
12+
13+
```bash
14+
git clone https://github.com/你的用户名/GraphNet.git
15+
cd GraphNet
16+
```
17+
3. **添加上游仓库引用**
18+
19+
```bash
20+
git remote add upstream https://github.com/PaddlePaddle/GraphNet.git
21+
```
22+
4. **安装依赖**
23+
24+
```bash
25+
pip install torch, torchvision
26+
```
27+
5. **设置提取路径**
28+
29+
```bash
30+
export GRAPH_NET_EXTRACT_WORKSPACE=/home/yourname/graphnet_workspace
31+
```
32+
### 二、编辑脚本
33+
#### 1. 编辑自动抽取脚本
34+
> 我们鼓励借助LLM Agent的能力,把本文档中的example、仓库中不同模型的example与extractor装饰器和promts一起输入,面向所需新的模型开发抽取脚本。
35+
36+
核心流程示例:
37+
```python
38+
import torch
39+
from torchvision.models import get_model, get_model_weights, list_models # 或者其他模型库
40+
from graph_net.torch.extractor import extract
41+
42+
def run_model(name: str, device_str: str) -> None:
43+
"""
44+
对指定模型执行计算图抽取流程并导出结果。
45+
46+
Args:
47+
name (str): 模型名称(例如 'resnet50'、'vit_b_16'、'bert-base-uncased' 等)。
48+
device_str (str): 运行设备标识('cpu' 或 'cuda:0' 等)。
49+
"""
50+
device = torch.device(device_str)
51+
print(f"\nTesting model: {name} on {device_str}")
52+
53+
# 1. 加载模型权重
54+
weights = None
55+
try:
56+
w = get_model_weights(name)
57+
weights = w.DEFAULT
58+
except Exception:
59+
# 若模型库不支持权重自动加载,可留空或在此手动指定本地权重路径
60+
pass
61+
62+
# 2. 实例化模型
63+
try:
64+
model = get_model(name, weights=weights)
65+
except Exception as e:
66+
print(f"[FAIL] {name}: instantiate model error - {e}")
67+
return
68+
69+
# 3. 构造输入张量(默认适用于图像分类模型)
70+
cfg = getattr(model, "default_cfg", {})
71+
C, H, W = cfg.get("input_size", (3, 224, 224))
72+
input_data = torch.rand(1, C, H, W, device=device)
73+
74+
# 4. 包装并抽取计算图
75+
model = model.to(device).eval()
76+
wrapped = extract(name=name)(model).eval()
77+
try:
78+
with torch.no_grad():
79+
wrapped(input_data)
80+
print(f"[OK] {name}")
81+
except Exception as e:
82+
print(f"[FAIL] {name}: extract error - {e}")
83+
```
84+
85+
86+
a. **准备模型**:加载模型定义及权重。
87+
88+
b. **构造输入**
89+
90+
> GraphNet的示例仅限于特定模型,在完成任务时可能需要改输入数据的构造。
91+
92+
不同模型对输入格式要求不一致,需根据模型类型生成合适的 `input_data`
93+
94+
95+
<table>
96+
<thead>
97+
<tr>
98+
<th>模型类型</th>
99+
<th>输入构造示例</th>
100+
</tr>
101+
</thead>
102+
<tbody>
103+
<tr>
104+
<td>图像分类 / CV</td>
105+
<td><code>torch.rand(1, C, H, W)</code>;如 ResNet、ViT 默认 <code>(3,224,224)</code></td>
106+
</tr>
107+
<tr>
108+
<td>视频模型</td>
109+
<td><code>torch.rand(1, C, T, H, W)</code>;如 R3D、MViT 中 <code>T=num_frames</code></td>
110+
</tr>
111+
<tr>
112+
<td>NLP 文本模型</td>
113+
<td>
114+
<pre><code class="language-python">tokenizer = AutoTokenizer.from_pretrained(model_name)
115+
inputs = tokenizer(
116+
text,
117+
return_tensors="pt",
118+
padding=True,
119+
truncation=True,
120+
max_length=512,
121+
)
122+
input_data = {key: val.to(device) for key, val in inputs.items()}</code></pre>
123+
</td>
124+
</tr>
125+
<tr>
126+
<td>多输入 / 复杂</td>
127+
<td>根据模型<code>forward</code>签名构造,如同时输入图像特征和位置编码等时,将所有Tensor按顺序或命名打包成 <code>tuple</code>/<code>dict</code></td>
128+
</tr>
129+
</tbody>
130+
</table>
131+
132+
> **提示**:如果不确定 `model.forward()` 需要哪些参数,可以先打印签名:
133+
```python
134+
import inspect
135+
print(inspect.signature(model.forward))
136+
```
137+
138+
c. **使用装饰器**
139+
140+
i. 推荐直接使用简洁的链式调用,例如上面示例中的`wrapped = extract(name=name)(model).eval()`
141+
142+
ii. 如果需要使用外置的显式`@extract`装饰器,则需要装饰模型的`nn.Module`子类。
143+
144+
145+
146+
147+
#### 2. 【可选】调整extractor
148+
在少数情况下,可能需要修改extract decorator从而适配特定模型。此时,请提前提起issue并**特别标注说明**,与我们一起规划该特性。
149+
150+
值得注意的是,这种操作更考验开发者的能力,同时我们也会对新的extractor代码质量及安全性进行人工Review。
151+
152+
同时,完成extractor的优化开发意味着可以适配新的一系列模型,从而使得您可以获得一大批的任务激励;
153+
154+
如果新方法能适配的模型数量有限,则ROI较低,这也体现了“Eat the frog first”的原则。
155+
156+
157+
158+
#### 3. TroubleShot指南:借助 LLM 自动补全输入构造
159+
> 示例代码仅覆盖部分常见模型,实际使用中可能需要根据具体模型调整输入张量的构造。
160+
> 如果在抽取计算图过程中遇到错误,可以直接把错误日志和代码文件送给LLM Agent处理。
161+
> 下方示例展示了一个Debug和输入生成的流程记录。
162+
163+
164+
在首次抽取计算图时,可能因 `input_data` 维度不匹配而导致失败。此时我们借助 LLM,根据日志提示补充或修正输入构造逻辑。
165+
166+
示例错误日志:
167+
```bash
168+
[FAIL] r2plus1d_18: Dynamo failed to run FX node with fake tensors:
169+
call_function <built-in method conv3d of type object at 0x7f14dbbd1f40>(
170+
*(FakeTensor(..., device='cuda:0', size=(1, s0, s1, s1)),
171+
Parameter(FakeTensor(..., device='cuda:0', size=(45, 3, 1, 7, 7), requires_grad=True)),
172+
None, (1, 2, 2), (0, 3, 3), (1, 1, 1), 1),
173+
**{}
174+
): got RuntimeError(
175+
'Given groups=1, weight of size [45, 3, 1, 7, 7], expected input[1, 1, s0, s1, s1]
176+
to have 3 channels, but got 1 channels instead'
177+
)
178+
```
179+
从日志可见,该模型在做 3D 卷积时,输入通道数(1)与权重通道数(3)不符。基于这一提示,向 LLM 请求补全如下输入逻辑,即为时序模型增加帧维度 `T`
180+
181+
```python
182+
if any(tok in name for tok in ("r2plus1d")):
183+
# 时序模型需按 (B, C, T, H, W) 构造输入
184+
T = cfg.get("num_frames", 16)
185+
input_data = torch.rand(1, C, T, H, W, device=device)
186+
```
187+
此时再次运行 `extract(name)(model)(input_data)`,即可成功抽取计算图。
188+
189+
190+
191+
#### 4. 常见问题
192+
* **模型名称不在 **`list_models()`****
193+
* 自行从第三方库加载模型或手动实现 `get_model` 接口。
194+
* 确保 `extract(name=name)` 中的 `name` 与导出文件名一致。
195+
196+
* **输入维度不匹配**
197+
* 捕获异常后,打印模型 `cfg``forward` 签名进行对比。
198+
* 若模型有动态输入长度(如可变 sequence length),可使用临时最大长度测试。
199+
200+
* **显存不足 / 速度慢**
201+
* 尝试先在 CPU 上小 batch 测试;
202+
* 对于超大模型,建议分阶段抽取或使用更小 `input_data`
203+
204+
205+
206+
207+
#### 5. 进阶用法
208+
* **多输入/多输出模型**
209+
* `input_data` 可为 `tuple``dict`,并在 `wrapped(...)` 时一并传入。
210+
211+
* **分布式 & 并行抽图**
212+
* 可结合 `multiprocessing``torch.multiprocessing`,多进程并行抽取多模型。
213+
214+
* **自定义 hooks**
215+
* 如果需要在特定层插入钩子,可在 `wrapped = extract(...)(model, hooks=...)` 中传入自定义函数。
216+
217+
218+
219+
### 三、抽取计算图
220+
1. **extract 抽取**
221+
222+
运行集成了`@graph_net.torch.extract``@graph_net.paddle.extract`的自动提取脚本,例如:
223+
224+
```bash
225+
# Extract the ResNet‑18 computation graph
226+
python -m graph_net.test.vision_model_test
227+
```
228+
按照预期,应当在您的`$GRAPH_NET_EXTRACT_WORKSPACE`目录下记录所抽取的文件。
229+
230+
231+
232+
2. **validate 自查**
233+
234+
```bash
235+
python -m graph_net.torch.validate --model-path $GRAPH_NET_EXTRACT_WORKSPACE/model_name
236+
```
237+
`validate` 验证您刚刚抽取的计算图符合Dataset Construction Constraints,如果结果为Success,则可以继续。
238+
239+
240+
241+
### **四、提交**计算图
242+
1. **配置贡献者用户名和email**
243+
244+
```bash
245+
python -m graph_net.config \
246+
--global \
247+
--username "john_doe" \
248+
249+
```
250+
2. **打包计算图**
251+
252+
```bash
253+
python -m graph_net.pack --output /path/to/output.zip --clear-after-pack True
254+
```
255+
该API的功能为:
256+
257+
a. 打包`$GRAPH_NET_EXTRACT_WORKSPACE`下的所有文件到`/path/to/output.zip` (可以设置到`GraphNet/samples`
258+
259+
b. 若`--clear-after-pack``True`,则打包后清空`$GRAPH_NET_EXTRACT_WORKSPACE`
260+
261+
请注意,如果有第三方算子,需要贡献者自行打包到计算图压缩包内。目前没有特别规定存放的目录结构,但只要通过了validate环节,就可以达到验收标准。
262+
263+
3. **提交修改**
264+
265+
移动上一步打包完成的计算图压缩包到**samples**目录,然后提交。
266+
```bash
267+
git add <计算图压缩包>
268+
git commit -m "描述"
269+
```
270+
4. **推送分支到远程**(你的 Fork 仓库)
271+
272+
```bash
273+
git push origin feature/your-branch-name
274+
```
275+
5. **提交 Pull Request**
276+
277+
> **注意**:为方便管理,每个PR应遵守Single Responsibility Principle (SRP)原则,**仅新增单一份计算图、或聚焦于单一功能改进**,避免将多个修改混合提交。例如,如果您修改了抓取方法,然后为支持某类模型收集了数据,那么其中每份单个模型的计算图、修改的新一份抓取方法,都应打开为独立的PR。
278+
279+
1. 访问你的 Fork 仓库页面(`https://github.com/你的用户名/GraphNet`)。
280+
281+
2. 页面会提示 **Compare & Pull Request**,点击它。
282+
283+
3. 使用以下模版填写:
284+
285+
**// ------- PR 标题 --------**
286+
287+
`[Type (New Sample | Feature Enhancement | Bug Fix | Other)] Brief Description`
288+
289+
`eg. [Feature Enhancement] Support Bert Model Family on Pytorch`
290+
291+
`eg. [New Sample] Add "distilbert-base-uncased" Model Computational Graph`
292+
293+
**// ------- PR 内容 --------**
294+
295+
```markdown
296+
Model: eg. distilbert-base-uncased
297+
Framework: eg. Pytorch/Paddle
298+
Dependency: eg. torchvision, transformers
299+
Content: Description
300+
```
301+
302+
4. 点击 **Create Pull Request**
303+
304+
5. GraphNet团队会在机器人辅助下审查并合入PR。
305+
306+
> 其它信息及未明确的规范,可参照 [Paddle社区统一的代码贡献流程](https://www.paddlepaddle.org.cn/documentation/docs/zh/dev_guides/code_contributing_path_cn.html)

0 commit comments

Comments
 (0)