一键导入
debugging-shape-inference
Guide for debugging shape inference errors, particularly "Inferred shape and existing shape differ" from ONNX C++.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Guide for debugging shape inference errors, particularly "Inferred shape and existing shape differ" from ONNX C++.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
| name | debugging-shape-inference |
| description | Guide for debugging shape inference errors, particularly "Inferred shape and existing shape differ" from ONNX C++. |
When onnx.shape_inference.infer_shapes(model, strict_mode=True) raises
ShapeInferenceError: Inferred shape and existing shape differ in dimension N,
the error does not include the node or value name. Use the following
workflow to locate the offending value.
import onnx
model = onnx.load("model.onnx")
try:
onnx.shape_inference.infer_shapes(model, data_prop=True, strict_mode=True)
except Exception as e:
print(e) # Note the dimension index and values, e.g. dim 0: (4) vs (5)
If the model infers cleanly without value_info, the bug is in one of those
annotations (not in the graph structure):
stripped = onnx.ModelProto()
stripped.CopyFrom(model)
del stripped.graph.value_info[:]
onnx.shape_inference.infer_shapes(stripped, data_prop=True, strict_mode=True)
# If this succeeds, the error is in value_info
vis = list(model.graph.value_info)
def test_with_vis(model, vis_to_keep):
m = onnx.ModelProto()
m.CopyFrom(model)
del m.graph.value_info[:]
for vi in vis_to_keep:
m.graph.value_info.append(vi)
try:
onnx.shape_inference.infer_shapes(m, data_prop=True, strict_mode=True)
return True
except:
return False
lo, hi = 0, len(vis)
while lo < hi:
mid = (lo + hi) // 2
if test_with_vis(model, vis[:mid + 1]):
lo = mid + 1
else:
hi = mid
bad_vi = vis[lo]
print(f"Problematic value: {bad_vi.name}")
For initializers, the actual tensor shape is ground truth:
for init in model.graph.initializer:
if init.name == bad_vi.name:
print(f"Initializer shape: {list(init.dims)}")
# Extract the annotated shape from value_info
dims = []
for d in bad_vi.type.tensor_type.shape.dim:
dims.append(d.dim_value if d.HasField("dim_value") else d.dim_param)
print(f"Annotated shape: {dims}")
For intermediate values, compare against what ONNX C++ infers from scratch:
stripped = onnx.ModelProto()
stripped.CopyFrom(model)
del stripped.graph.value_info[:]
inferred = onnx.shape_inference.infer_shapes(stripped, data_prop=True)
for vi in inferred.graph.value_info:
if vi.name == bad_vi.name:
# This is what ONNX C++ thinks the shape should be
print(vi)
| Symptom | Likely cause |
|---|---|
| Initializer shape != value_info shape | Bad annotation in the original model. Fix: correct shapes from the actual tensor at inference start. |
| Intermediate value has wrong concrete dim | Our op inference computed a wrong dimension. Fix: debug the specific op's infer_* function. |
| Symbolic dim where C++ infers concrete | Our inference was less precise but not wrong. Usually not an error in strict mode. |
The engine (_engine.py) corrects initializer shapes at the start of
_process_graph using the actual tensor as ground truth. This handles
malformed models where value_info annotations disagree with initializer
tensor shapes.