Download code/tt_transfusion/tests/test_reference_structure_host.py from changh95/transfusion-p150: direct link, hf CLI and curl.
- Browser
- Download file 6.46 kB
-
https://huggingface.co/changh95/transfusion-p150/resolve/main/code/tt_transfusion/tests/test_reference_structure_host.py
- Command line
-
hf download hf://changh95/transfusion-p150/code/tt_transfusion/tests/test_reference_structure_host.py
-
curl -L -o test_reference_structure_host.py https://huggingface.co/changh95/transfusion-p150/resolve/main/code/tt_transfusion/tests/test_reference_structure_host.py
6.46 kB
| # SPDX-License-Identifier: Apache-2.0 | |
| """The CPU reference reads the weights the way the spec describes them (S:transfusion:57-208): the Autoware | |
| parameters, and the module structure checked from the ONNX graph (layer counts, strides, channels, the decoder's | |
| heads / scale / LayerNorm eps, the in-graph decoration constants, ``bev_pos``, parameter counts after the BN folds), | |
| without onnxruntime or torch. | |
| TT_VISIBLE_DEVICES=none python -m pytest -q code/tt_transfusion/tests/test_reference_structure_host.py | |
| """ | |
| from __future__ import annotations | |
| import numpy as np | |
| import pytest | |
| pytest.importorskip("onnx") | |
| pytest.importorskip("yaml") | |
| from tt_transfusion.reference.config import (N_MAX, NODE_PARAMS, OUT_SIZE_FACTOR, POINTS_PER_VOXEL, # noqa: E402 | |
| TransFusionConfig) | |
| from tt_transfusion.reference.weights import PREDICTION_HEADS, load_weights # noqa: E402 | |
| from tt_transfusion.tests import _data # noqa: E402 | |
| def config(): | |
| return TransFusionConfig.from_weights(_data.weights_dir()) | |
| def weights(config): | |
| return load_weights(_data.weights_dir(), config) | |
| def test_autoware_parameters(config): | |
| c = config | |
| assert c.version == "v2.1" and c.class_names == ("CAR", "TRUCK", "BUS", "BICYCLE", "PEDESTRIAN") | |
| assert c.voxels_num == (5000, 30000, 60000) and (c.min_voxels, c.max_voxels) == (5000, 60000) | |
| assert c.point_cloud_range == (-92.16, -92.16, -3.0, 92.16, 92.16, 7.0) and c.voxel_size == (0.24, 0.24, 10.0) | |
| assert (c.grid_x, c.grid_y, c.grid_z) == (768, 768, 1) # float32 184.32 / 0.24 = 768.00006 | |
| assert (c.feature_x, c.feature_y) == (192, 192) and OUT_SIZE_FACTOR == 4 | |
| assert c.num_proposals == 500 and POINTS_PER_VOXEL == 20 and N_MAX == 65536 | |
| spec = c.grid_spec | |
| assert spec.order == "raster" and spec.max_pillars == N_MAX and spec.max_points_per_pillar == 20 | |
| assert c.score_threshold == NODE_PARAMS["score_threshold"] == 0.1 | |
| assert c.yaw_norm_thresholds.tolist() == pytest.approx([0.3, 0.3, 0.3, 0.3, 0.0]) | |
| assert c.with_node(yaw_norm_thresholds=(1.5, -1, 0.3, 0.999, 1.0)).yaw_norm_thresholds.tolist() == pytest.approx( | |
| [0.0, 0.0, 0.3, 0.999, 0.0]) # transfusion_config.hpp:79-81 | |
| assert TransFusionConfig.sanitized_score_threshold(0.0) == 0.2 and TransFusionConfig.sanitized_score_threshold(-1) == 0.2 | |
| assert TransFusionConfig.sanitized_circle_nms(0.0) == 0.5 and TransFusionConfig.sanitized_circle_nms(1.2) == 1.2 | |
| rm = c.remapper | |
| assert rm.num_labels == 8 and rm.allow[1, 2] and rm.allow[1, 4] and rm.allow[2, 4] and rm.allow[3, 4] | |
| assert int(rm.allow.sum()) == 4 | |
| assert (rm.min_area[1, 2], rm.max_area[1, 2], rm.min_area[3, 4], rm.max_area[3, 4]) == (12.1, 36.0, 36.0, 999.999) | |
| assert c.decoration_scale_zyx.tolist() == [np.float32(10.0), np.float32(0.24), np.float32(0.24)] | |
| assert c.decoration_offset_zyx.tolist() == [np.float32(2.0), np.float32(-92.04), np.float32(-92.04)] | |
| def test_refuses_another_release(tmp_path, config): | |
| import shutil | |
| for f in ("transfusion_ml_package.param.yaml", "detection_class_remapper.param.yaml"): | |
| shutil.copy(_data.weights_dir() / f, tmp_path / f) | |
| (tmp_path / "deploy_metadata.yaml").write_text("version: v2\n") | |
| with pytest.raises(ValueError, match="not supported"): | |
| TransFusionConfig.from_model_dir(tmp_path) | |
| def test_graph_structure_and_parameter_counts(weights): | |
| w = weights | |
| assert [len(b) for b in w.blocks] == [4, 6, 6] | |
| assert [(b[0].in_channels, b[-1].out_channels, b[0].stride) for b in w.blocks] == [(64, 64, 2), (64, 128, 2), | |
| (128, 256, 2)] | |
| assert all(layer.kernel == 3 and layer.padding == 1 and layer.relu for b in w.blocks for layer in b) | |
| assert [(d.kind, d.in_channels, d.out_channels, d.kernel, d.stride, d.padding) for d in w.deblocks] == [ | |
| ("conv", 64, 128, 2, 2, 0), ("conv", 128, 128, 1, 1, 0), ("conv_transpose", 256, 128, 2, 2, 0)] | |
| assert [d.bn_node is not None for d in w.deblocks] == [False, False, True] | |
| h = w.head | |
| assert (h.shared.in_channels, h.shared.out_channels, h.shared.kernel, h.shared.relu) == (384, 128, 3, False) | |
| assert (h.heatmap_hidden.out_channels, h.heatmap_hidden.relu, h.heatmap_out.out_channels) == (128, True, 5) | |
| assert h.nms_kernel == 3 and h.num_proposals == 500 | |
| d = h.decoder | |
| for a in (d.self_attn, d.cross_attn): | |
| assert (a.num_heads, a.head_dim, a.q_divisor, a.scale) == (8, 16, 4.0, 0.25) | |
| assert a.wq.shape == a.wk.shape == a.wv.shape == a.wo.shape == (128, 128) | |
| assert [eps for _, _, eps in d.norms] == [pytest.approx(1e-5)] * 3 | |
| assert d.ffn_w1.shape == (128, 256) and d.ffn_w2.shape == (256, 128) | |
| assert [(n, fin.out_channels) for n, _, fin in h.prediction_heads] == list(PREDICTION_HEADS) | |
| assert w.pfn.w0.shape == (11, 32) and w.pfn.w1.shape == (64, 64) and w.grid == (768, 768) | |
| # 5,270,580 learned ONNX parameters (S:transfusion:149); the folds turn the PFN BNs (32 + 64 channels x 4) into | |
| # 96 biases and the deblock2 BN (128 x 4) into 128 biases | |
| assert w.num_params() == 5_270_580 - (4 * 96 - 96) - (4 * 128 - 128) | |
| def test_constants_and_tables(weights): | |
| h = weights.head | |
| k = np.arange(192 * 192) | |
| assert h.bev_pos.shape == (36864, 2) | |
| assert np.array_equal(h.bev_pos[:, 0], (k % 192).astype(np.float32) + 0.5) # k = y * 192 + x | |
| assert np.array_equal(h.bev_pos[:, 1], (k // 192).astype(np.float32) + 0.5) | |
| assert h.bev_pos[1].tolist() == [1.5, 0.5] and h.bev_pos[192].tolist() == [0.5, 1.5] | |
| t = h.class_table | |
| assert t.shape == (5, 128) and np.array_equal(t[3], (h.class_encoding_w[:, 3] + h.class_encoding_b).astype( | |
| np.float32)) | |
| p = weights.pfn | |
| assert np.array_equal(p.scale_zyx, np.array([10.0, 0.24, 0.24], np.float32)) | |
| assert np.array_equal(p.offset_zyx, np.array([2.0, -92.04, -92.04], np.float32)) | |
| def test_onnx_tap_map_covers_the_reference_taps(weights): | |
| from tt_transfusion.reference.model import EXTRA_TAPS, MODULE_TAPS | |
| missing = [t for t in MODULE_TAPS + EXTRA_TAPS if t not in weights.onnx_taps] | |
| assert not missing, missing | |
| assert weights.onnx_taps["head.topk_indices"].endswith("TopK_output_1") | |
| assert weights.onnx_taps["pfn.input"] == "/pts_voxel_encoder/Mul_1_output_0" | |