opensportslib 0.3.0.dev7__tar.gz → 0.3.0.dev8__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {opensportslib-0.3.0.dev7/opensportslib.egg-info → opensportslib-0.3.0.dev8}/PKG-INFO +1 -1
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/apis/base_task_model.py +7 -1
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/apis/classification.py +3 -1
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/apis/localization.py +6 -1
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/configs/vqa/default.yaml +10 -10
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/configs/vqa/qwen.yaml +1 -1
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/configs/vqa/qwen3_vl_native.yaml +1 -1
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/configs/vqa/qwen_lora.yaml +2 -2
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/configs/vqa/xvars.yaml +4 -4
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/core/config/accessors.py +45 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/core/trainer/classification_trainer.py +10 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/core/utils/config.py +117 -4
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/datasets/classification_dataset.py +28 -4
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/datasets/vqa_dataset.py +49 -7
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/models/base/qwen_xvars.py +2 -2
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/models/base/xvars_videochatgpt.py +58 -3
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8/opensportslib.egg-info}/PKG-INFO +1 -1
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/pyproject.toml +1 -1
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/tests/test_localization_hf_backend_override.py +148 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/tests/test_pretrained_config_merge_policy.py +71 -34
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/tests/test_vqa_api.py +94 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/tests/test_vqa_qwen_xvars.py +35 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/tests/test_vqa_xvars_videochatgpt.py +160 -3
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/LICENSE +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/LICENSE-COMMERCIAL +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/MANIFEST.in +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/README.md +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/examples/quickstart/basic_classification.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/examples/quickstart/basic_localization.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/examples/quickstart/basic_vqa.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/__init__.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/apis/__init__.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/apis/vqa.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/cli.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/configs/classification/default.yaml +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/configs/classification/sngar_frames.yaml +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/configs/classification/sngar_tracking.yaml +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/configs/classification/video.yaml +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/configs/default.yaml +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/configs/localization/calf_resnetpca512.yaml +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/configs/localization/default.yaml +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/configs/localization/h5_header_distance.yaml +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/configs/localization/h5_header_distance_angle.yaml +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/configs/localization/h5_header_distance_speed.yaml +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/configs/localization/h5_header_distance_speed_angle.yaml +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/configs/localization/h5_header_rule.yaml +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/configs/localization/h5_header_skeleton.yaml +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/configs/localization/netvladpp_resnetpca512.yaml +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/configs/localization/video_dali.yaml +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/configs/localization/video_ocv.yaml +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/configs/vqa/qwen_sngar_frames.yaml +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/core/__init__.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/core/config/__init__.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/core/config/conflicts.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/core/config/loader.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/core/config/migrate.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/core/config/migrations/__init__.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/core/config/migrations/legacy_to_canonical.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/core/config/runtime_adapter.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/core/config/schema.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/core/config/schemas/__init__.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/core/config/schemas/schema_canonical.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/core/config/schemas/schema_legacy.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/core/config/validate.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/core/loss/__init__.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/core/loss/builder.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/core/loss/calf.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/core/loss/ce.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/core/loss/combine.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/core/loss/nll.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/core/optimizer/__init__.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/core/optimizer/builder.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/core/sampler/weighted_sampler.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/core/scheduler/__init__.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/core/scheduler/builder.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/core/trainer/__init__.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/core/trainer/localization_trainer.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/core/trainer/vqa_trainer.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/core/utils/checkpoint.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/core/utils/config_normalize.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/core/utils/data.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/core/utils/ddp.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/core/utils/default_args.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/core/utils/hf_runtime.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/core/utils/lightning.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/core/utils/load_annotations.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/core/utils/seed.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/core/utils/video_processing.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/core/utils/wandb.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/datasets/__init__.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/datasets/builder.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/datasets/localization_dataset.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/datasets/utils/__init__.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/datasets/utils/h5_tracking.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/datasets/utils/tracking.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/legacy_config/classification.yaml +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/legacy_config/localization-e2e-ocv.yaml +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/legacy_config/localization-json_calf_resnetpca512.yaml +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/legacy_config/localization-json_netvlad++_resnetpca512.yaml +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/legacy_config/localization.yaml +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/legacy_config/sngar-frames.yaml +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/legacy_config/sngar-tracking.yaml +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/metrics/classification_metric.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/metrics/localization_metric.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/metrics/vqa_metric.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/models/__init__.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/models/backbones/builder.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/models/base/contextaware.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/models/base/e2e.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/models/base/learnablepooling.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/models/base/qwen_vl_native.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/models/base/rule_based.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/models/base/tracking.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/models/base/vars.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/models/base/video.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/models/base/video_chatgpt_compat.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/models/base/video_mae.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/models/builder.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/models/heads/builder.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/models/neck/builder.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/models/utils/common.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/models/utils/impl/__init__.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/models/utils/impl/asformer.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/models/utils/impl/calf.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/models/utils/impl/gsm.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/models/utils/impl/gtad.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/models/utils/impl/tsm.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/models/utils/litebase.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/models/utils/modules.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/models/utils/shift.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/models/utils/utils.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/models/utils/vqa_prediction_priors.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/models/utils/vqa_prompting.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/models/utils/xvars_clip_index.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/setup/setup.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/tools/__init__.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/tools/_common.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/tools/hf_transfer.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/tools/osl_json_to_parquet.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/tools/parquet_to_osl_json.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib.egg-info/SOURCES.txt +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib.egg-info/dependency_links.txt +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib.egg-info/entry_points.txt +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib.egg-info/requires.txt +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib.egg-info/top_level.txt +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/scripts/run_h5_header_rule_inference.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/scripts/run_header_spotting_eval.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/setup.cfg +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/tests/conftest.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/tests/test_classification_dataset_paths.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/tests/test_classification_trainer_dataloader.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/tests/test_config_architecture.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/tests/test_config_split_override_sync.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/tests/test_config_utils_smoke.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/tests/test_conversion_tools.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/tests/test_extract_xvars_features.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/tests/test_h5_header_rule_spotter.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/tests/test_h5_header_skeleton_spotter.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/tests/test_h5_tracking_dataset.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/tests/test_hf_transfer_tools.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/tests/test_localization_dali_filenames.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/tests/test_package_smoke.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/tests/test_public_apis_smoke.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/tests/test_setup_cli.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/tests/test_subset_train_infer_integration.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/tests/test_task_model_api_contract.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/tests/test_vqa_metrics_semantic.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/tests/test_vqa_training_lora.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/tools/convert/build_sn_vqa_2026_vqa.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/tools/convert/build_soccernet_gar.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/tools/convert/build_soccernet_gar_action_spotting.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/tools/convert/build_soccernet_gar_vqa.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/tools/convert/build_xvars_indexes.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/tools/convert/extract_xvars_clip_features.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/tools/convert/osl_json_to_parquet_webdataset.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/tools/convert/parquet_webdataset_to_osl_json.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/tools/download/download_hf_repo.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/tools/download/download_osl_hf.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/tools/download/upload_osl_hf.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/tools/training/classification.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/tools/training/localization.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/tools/training/vqa.py +0 -0
- {opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/tools/upload/upload_model_hf.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: opensportslib
|
|
3
|
-
Version: 0.3.0.
|
|
3
|
+
Version: 0.3.0.dev8
|
|
4
4
|
Summary: OpenSportsLib is the professional library, designed for advanced video understanding in sports. It provides state-of-the-art tools for action recognition, spotting, retrieval, and captioning, making it ideal for researchers, analysts, and developers working with sports video data.
|
|
5
5
|
Author: Jeet Vora
|
|
6
6
|
Requires-Python: >=3.12
|
|
@@ -10,7 +10,12 @@ from abc import ABC, abstractmethod
|
|
|
10
10
|
from typing import Any
|
|
11
11
|
|
|
12
12
|
from opensportslib.core.config.accessors import get_component_name_by_kind
|
|
13
|
-
from opensportslib.core.utils.config import
|
|
13
|
+
from opensportslib.core.utils.config import (
|
|
14
|
+
expand,
|
|
15
|
+
load_config_omega,
|
|
16
|
+
fetch_and_merge_config_from_HF,
|
|
17
|
+
resolve_inference_class_metadata,
|
|
18
|
+
)
|
|
14
19
|
|
|
15
20
|
|
|
16
21
|
class BaseTaskModel(ABC):
|
|
@@ -29,6 +34,7 @@ class BaseTaskModel(ABC):
|
|
|
29
34
|
|
|
30
35
|
if weights is not None:
|
|
31
36
|
self.config = fetch_and_merge_config_from_HF(self.config, weights, merge_policy="compatibility")
|
|
37
|
+
self.config = resolve_inference_class_metadata(self.config)
|
|
32
38
|
self.last_loaded_weights = weights
|
|
33
39
|
self.best_checkpoint = weights
|
|
34
40
|
|
|
@@ -15,7 +15,7 @@ from opensportslib.core.config.accessors import (
|
|
|
15
15
|
get_system_seed,
|
|
16
16
|
get_system_use_seed,
|
|
17
17
|
)
|
|
18
|
-
from opensportslib.core.utils.config import expand
|
|
18
|
+
from opensportslib.core.utils.config import expand, resolve_inference_class_metadata
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
def _is_tracking_graph_modality(modality):
|
|
@@ -269,6 +269,7 @@ class ClassificationModel(BaseTaskModel):
|
|
|
269
269
|
test_set = self._resolve_split_path("test", test_set)
|
|
270
270
|
|
|
271
271
|
self.config = resolve_config_omega(self.config, weights=weights)
|
|
272
|
+
self.config = resolve_inference_class_metadata(self.config)
|
|
272
273
|
logging.info("Configuration:")
|
|
273
274
|
logging.info(self.config)
|
|
274
275
|
|
|
@@ -335,6 +336,7 @@ class ClassificationModel(BaseTaskModel):
|
|
|
335
336
|
test_set = self._resolve_split_path("test", test_set)
|
|
336
337
|
|
|
337
338
|
self.config = resolve_config_omega(self.config, weights=weights)
|
|
339
|
+
self.config = resolve_inference_class_metadata(self.config)
|
|
338
340
|
logging.info("Configuration:")
|
|
339
341
|
logging.info(self.config)
|
|
340
342
|
if predictions is None:
|
|
@@ -18,7 +18,7 @@ from opensportslib.core.config.accessors import (
|
|
|
18
18
|
set_loader_backend,
|
|
19
19
|
get_model_family,
|
|
20
20
|
)
|
|
21
|
-
from opensportslib.core.utils.config import expand
|
|
21
|
+
from opensportslib.core.utils.config import expand, resolve_inference_class_metadata
|
|
22
22
|
from opensportslib.core.config.loader import _dali_available
|
|
23
23
|
|
|
24
24
|
|
|
@@ -276,6 +276,7 @@ class LocalizationModel(BaseTaskModel):
|
|
|
276
276
|
self._set_split_path("valid_data_frames", valid_set)
|
|
277
277
|
|
|
278
278
|
self.config = resolve_config_omega(self.config, weights=weights)
|
|
279
|
+
self.config = resolve_inference_class_metadata(self.config)
|
|
279
280
|
effective_weights = weights if weights is not None else self.last_loaded_weights
|
|
280
281
|
self._adapt_hf_backend_for_device(effective_weights)
|
|
281
282
|
check_config(self.config, split="train")
|
|
@@ -389,9 +390,11 @@ class LocalizationModel(BaseTaskModel):
|
|
|
389
390
|
self._set_split_path("test", test_set)
|
|
390
391
|
|
|
391
392
|
self.config = resolve_config_omega(self.config, weights=weights)
|
|
393
|
+
self.config = resolve_inference_class_metadata(self.config)
|
|
392
394
|
effective_weights = weights if weights is not None else self.last_loaded_weights
|
|
393
395
|
self._adapt_hf_backend_for_device(effective_weights)
|
|
394
396
|
check_config(self.config, split="test")
|
|
397
|
+
self.config = resolve_inference_class_metadata(self.config)
|
|
395
398
|
self.config.infer_split = whether_infer_split(get_split_cfg(self.config, "test"))
|
|
396
399
|
|
|
397
400
|
init_wandb(
|
|
@@ -459,9 +462,11 @@ class LocalizationModel(BaseTaskModel):
|
|
|
459
462
|
test_set = self._resolve_split_path("test", test_set)
|
|
460
463
|
self._set_split_path("test", test_set)
|
|
461
464
|
self.config = resolve_config_omega(self.config, weights=weights)
|
|
465
|
+
self.config = resolve_inference_class_metadata(self.config)
|
|
462
466
|
effective_weights = weights if weights is not None else self.last_loaded_weights
|
|
463
467
|
self._adapt_hf_backend_for_device(effective_weights)
|
|
464
468
|
check_config(self.config, split="test")
|
|
469
|
+
self.config = resolve_inference_class_metadata(self.config)
|
|
465
470
|
self.config.infer_split = whether_infer_split(get_split_cfg(self.config, "test"))
|
|
466
471
|
|
|
467
472
|
init_wandb(
|
{opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/configs/vqa/default.yaml
RENAMED
|
@@ -15,16 +15,16 @@ SYSTEM:
|
|
|
15
15
|
|
|
16
16
|
DATA:
|
|
17
17
|
common:
|
|
18
|
-
dataset_name:
|
|
19
|
-
data_root:
|
|
20
|
-
feature_index:
|
|
21
|
-
prediction_index:
|
|
18
|
+
dataset_name: dataset_name
|
|
19
|
+
data_root: ./dataset/dataset_name
|
|
20
|
+
feature_index: ./dataset/feature_index.json
|
|
21
|
+
prediction_index: ./dataset/prediction_index.json
|
|
22
22
|
runtime:
|
|
23
23
|
loader_backend: opencv
|
|
24
24
|
splits:
|
|
25
25
|
train:
|
|
26
|
-
annotation_path:
|
|
27
|
-
source_path:
|
|
26
|
+
annotation_path: ./dataset//train.json
|
|
27
|
+
source_path: ./dataset/
|
|
28
28
|
dataloader:
|
|
29
29
|
batch_size: 1
|
|
30
30
|
shuffle: true
|
|
@@ -33,8 +33,8 @@ DATA:
|
|
|
33
33
|
mp_context: spawn
|
|
34
34
|
persistent_workers: false
|
|
35
35
|
valid:
|
|
36
|
-
annotation_path:
|
|
37
|
-
source_path:
|
|
36
|
+
annotation_path: ./dataset/valid.json
|
|
37
|
+
source_path: ./dataset/
|
|
38
38
|
dataloader:
|
|
39
39
|
batch_size: 1
|
|
40
40
|
shuffle: false
|
|
@@ -43,8 +43,8 @@ DATA:
|
|
|
43
43
|
mp_context: spawn
|
|
44
44
|
persistent_workers: false
|
|
45
45
|
test:
|
|
46
|
-
annotation_path:
|
|
47
|
-
source_path:
|
|
46
|
+
annotation_path: ./dataset/test.json
|
|
47
|
+
source_path: ./dataset/
|
|
48
48
|
dataloader:
|
|
49
49
|
batch_size: 1
|
|
50
50
|
shuffle: false
|
|
@@ -10,7 +10,7 @@ MODEL:
|
|
|
10
10
|
provider: opensportslib
|
|
11
11
|
name: xvars_clip_features
|
|
12
12
|
load:
|
|
13
|
-
weights_path: /
|
|
13
|
+
weights_path: OpenSportsLab/trained-clip-vit-large-patch14
|
|
14
14
|
params:
|
|
15
15
|
feature_source: indexed_or_raw_clip
|
|
16
16
|
vision_tower: openai/clip-vit-large-patch14
|
{opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/configs/vqa/qwen_lora.yaml
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
SYSTEM:
|
|
2
2
|
paths:
|
|
3
|
-
save_dir: ./
|
|
3
|
+
save_dir: ./checkpoints_vqa_qwen
|
|
4
4
|
gpu:
|
|
5
5
|
count: 4
|
|
6
6
|
|
|
@@ -12,7 +12,7 @@ MODEL:
|
|
|
12
12
|
provider: opensportslib
|
|
13
13
|
name: xvars_clip_features
|
|
14
14
|
load:
|
|
15
|
-
weights_path: /
|
|
15
|
+
weights_path: OpenSportsLab/trained-clip-vit-large-patch14
|
|
16
16
|
params:
|
|
17
17
|
feature_source: indexed_or_raw_clip
|
|
18
18
|
vision_tower: openai/clip-vit-large-patch14
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
SYSTEM:
|
|
2
2
|
paths:
|
|
3
|
-
save_dir: ./
|
|
3
|
+
save_dir: ./checkpoints_vqa_xvars_lora
|
|
4
4
|
gpu:
|
|
5
5
|
count: 4
|
|
6
6
|
|
|
@@ -10,9 +10,9 @@ MODEL:
|
|
|
10
10
|
kind: encoder
|
|
11
11
|
source:
|
|
12
12
|
provider: opensportslib
|
|
13
|
-
#
|
|
13
|
+
# X-VARS visual checkpoint: local file path or HF model repo ID.
|
|
14
14
|
load:
|
|
15
|
-
weights_path: /
|
|
15
|
+
weights_path: OpenSportsLab/trained-clip-vit-large-patch14
|
|
16
16
|
params:
|
|
17
17
|
# CLIP architecture and image processor to instantiate.
|
|
18
18
|
feature_source: indexed_or_raw_clip
|
|
@@ -31,7 +31,7 @@ MODEL:
|
|
|
31
31
|
source:
|
|
32
32
|
provider: opensportslib
|
|
33
33
|
params:
|
|
34
|
-
repo_id: /
|
|
34
|
+
repo_id: OpenSportsLab/base_model_videoChatGPT
|
|
35
35
|
overrides: {}
|
|
36
36
|
metadata:
|
|
37
37
|
backend: xvars_videochatgpt
|
{opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/core/config/accessors.py
RENAMED
|
@@ -194,6 +194,12 @@ def get_data_num_classes(cfg: Any, default: int = 0) -> int:
|
|
|
194
194
|
if classes:
|
|
195
195
|
return len(classes)
|
|
196
196
|
|
|
197
|
+
data = _as_dict(getattr(cfg, "DATA", None))
|
|
198
|
+
common = _as_dict(data.get("common"))
|
|
199
|
+
common_num_classes = common.get("num_classes")
|
|
200
|
+
if common_num_classes is not None:
|
|
201
|
+
return int(common_num_classes)
|
|
202
|
+
|
|
197
203
|
input_cfg = get_input_cfg(cfg)
|
|
198
204
|
params = _as_dict(input_cfg.get("params"))
|
|
199
205
|
num_classes = params.get("num_classes")
|
|
@@ -222,8 +228,47 @@ def set_data_classes(cfg: Any, classes: list[str]) -> None:
|
|
|
222
228
|
common = _ensure_child(data, "common")
|
|
223
229
|
if isinstance(common, dict):
|
|
224
230
|
common["classes"] = list(classes)
|
|
231
|
+
common["num_classes"] = len(classes)
|
|
225
232
|
else:
|
|
226
233
|
setattr(common, "classes", list(classes))
|
|
234
|
+
setattr(common, "num_classes", len(classes))
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
def set_data_num_classes(cfg: Any, num_classes: int | None) -> None:
|
|
238
|
+
if num_classes is None:
|
|
239
|
+
return
|
|
240
|
+
|
|
241
|
+
data = getattr(cfg, "DATA", None)
|
|
242
|
+
if data is None:
|
|
243
|
+
data = SimpleNamespace()
|
|
244
|
+
setattr(cfg, "DATA", data)
|
|
245
|
+
|
|
246
|
+
common = _ensure_child(data, "common")
|
|
247
|
+
if isinstance(common, dict):
|
|
248
|
+
common["num_classes"] = int(num_classes)
|
|
249
|
+
else:
|
|
250
|
+
setattr(common, "num_classes", int(num_classes))
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
def get_data_runtime(cfg: Any) -> dict[str, Any]:
|
|
254
|
+
data = _as_dict(getattr(cfg, "DATA", None))
|
|
255
|
+
common = _as_dict(data.get("common"))
|
|
256
|
+
runtime = _as_dict(common.get("runtime"))
|
|
257
|
+
return runtime
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
def set_data_runtime_value(cfg: Any, key: str, value: Any) -> None:
|
|
261
|
+
data = getattr(cfg, "DATA", None)
|
|
262
|
+
if data is None:
|
|
263
|
+
data = SimpleNamespace()
|
|
264
|
+
setattr(cfg, "DATA", data)
|
|
265
|
+
|
|
266
|
+
common = _ensure_child(data, "common")
|
|
267
|
+
runtime = _ensure_child(common, "runtime")
|
|
268
|
+
if isinstance(runtime, dict):
|
|
269
|
+
runtime[key] = value
|
|
270
|
+
else:
|
|
271
|
+
setattr(runtime, key, value)
|
|
227
272
|
|
|
228
273
|
|
|
229
274
|
def get_input_cfg(cfg: Any, input_name: str | None = None) -> dict[str, Any]:
|
|
@@ -1219,6 +1219,11 @@ class Trainer_Classification:
|
|
|
1219
1219
|
sid = item["id"]
|
|
1220
1220
|
gt_label = item["labels"]["action"]["label"]
|
|
1221
1221
|
if gt_label not in exclude_labels:
|
|
1222
|
+
if gt_label not in label_to_idx:
|
|
1223
|
+
raise ValueError(
|
|
1224
|
+
"Ground-truth label is not present in the resolved inference class list: "
|
|
1225
|
+
f"{gt_label!r}."
|
|
1226
|
+
)
|
|
1222
1227
|
gt_dict[sid] = label_to_idx[gt_label]
|
|
1223
1228
|
|
|
1224
1229
|
preds = []
|
|
@@ -1230,6 +1235,11 @@ class Trainer_Classification:
|
|
|
1230
1235
|
continue
|
|
1231
1236
|
|
|
1232
1237
|
pred_label = item["labels"]["action"]["label"]
|
|
1238
|
+
if pred_label not in label_to_idx:
|
|
1239
|
+
raise ValueError(
|
|
1240
|
+
"Predicted label is not present in the resolved inference class list: "
|
|
1241
|
+
f"{pred_label!r}."
|
|
1242
|
+
)
|
|
1233
1243
|
|
|
1234
1244
|
preds.append(label_to_idx[pred_label])
|
|
1235
1245
|
labels.append(gt_dict[sid])
|
|
@@ -2,11 +2,20 @@ import os
|
|
|
2
2
|
import re
|
|
3
3
|
import json
|
|
4
4
|
import gzip
|
|
5
|
+
import logging
|
|
5
6
|
try:
|
|
6
7
|
import yaml
|
|
7
8
|
except ModuleNotFoundError: # pragma: no cover - runtime compatibility
|
|
8
9
|
import yaml_compat as yaml
|
|
9
10
|
|
|
11
|
+
from opensportslib.core.config.accessors import (
|
|
12
|
+
get_data_classes,
|
|
13
|
+
get_data_num_classes,
|
|
14
|
+
get_data_runtime,
|
|
15
|
+
set_data_classes,
|
|
16
|
+
set_data_num_classes,
|
|
17
|
+
set_data_runtime_value,
|
|
18
|
+
)
|
|
10
19
|
from opensportslib.core.config import (
|
|
11
20
|
load_config as _load_config,
|
|
12
21
|
load_config_omega as _load_config_omega,
|
|
@@ -225,6 +234,108 @@ def is_local_path(p):
|
|
|
225
234
|
)
|
|
226
235
|
|
|
227
236
|
|
|
237
|
+
def _extract_class_metadata(data_section):
|
|
238
|
+
if not isinstance(data_section, dict):
|
|
239
|
+
return None, None
|
|
240
|
+
|
|
241
|
+
common = data_section.get("common", {}) if isinstance(data_section.get("common", {}), dict) else {}
|
|
242
|
+
classes = common.get("classes")
|
|
243
|
+
if classes is not None:
|
|
244
|
+
classes = list(classes)
|
|
245
|
+
|
|
246
|
+
num_classes = common.get("num_classes")
|
|
247
|
+
if num_classes is None:
|
|
248
|
+
inputs = data_section.get("inputs", {})
|
|
249
|
+
if isinstance(inputs, dict):
|
|
250
|
+
for input_cfg in inputs.values():
|
|
251
|
+
if not isinstance(input_cfg, dict):
|
|
252
|
+
continue
|
|
253
|
+
params = input_cfg.get("params", {})
|
|
254
|
+
if isinstance(params, dict) and params.get("num_classes") is not None:
|
|
255
|
+
num_classes = params.get("num_classes")
|
|
256
|
+
break
|
|
257
|
+
|
|
258
|
+
if num_classes is None and classes is not None:
|
|
259
|
+
num_classes = len(classes)
|
|
260
|
+
|
|
261
|
+
return classes, num_classes
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
def _cache_pretrained_class_metadata(target_dict, loaded_dict):
|
|
265
|
+
if not isinstance(target_dict, dict) or not isinstance(loaded_dict, dict):
|
|
266
|
+
return
|
|
267
|
+
|
|
268
|
+
loaded_data = loaded_dict.get("DATA", {})
|
|
269
|
+
pretrained_classes, pretrained_num_classes = _extract_class_metadata(loaded_data)
|
|
270
|
+
if pretrained_classes is None and pretrained_num_classes is None:
|
|
271
|
+
return
|
|
272
|
+
|
|
273
|
+
data = target_dict.setdefault("DATA", {})
|
|
274
|
+
if not isinstance(data, dict):
|
|
275
|
+
return
|
|
276
|
+
common = data.setdefault("common", {})
|
|
277
|
+
if not isinstance(common, dict):
|
|
278
|
+
return
|
|
279
|
+
runtime = common.setdefault("runtime", {})
|
|
280
|
+
if not isinstance(runtime, dict):
|
|
281
|
+
return
|
|
282
|
+
|
|
283
|
+
if pretrained_classes is not None:
|
|
284
|
+
runtime["pretrained_classes"] = list(pretrained_classes)
|
|
285
|
+
if pretrained_num_classes is not None:
|
|
286
|
+
runtime["pretrained_num_classes"] = int(pretrained_num_classes)
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
def resolve_inference_class_metadata(cfg):
|
|
290
|
+
runtime = get_data_runtime(cfg)
|
|
291
|
+
pretrained_classes = runtime.get("pretrained_classes")
|
|
292
|
+
pretrained_num_classes = runtime.get("pretrained_num_classes")
|
|
293
|
+
|
|
294
|
+
local_classes = get_data_classes(cfg)
|
|
295
|
+
local_num_classes = get_data_num_classes(cfg, default=0)
|
|
296
|
+
|
|
297
|
+
chosen_classes = None
|
|
298
|
+
chosen_num_classes = None
|
|
299
|
+
source = None
|
|
300
|
+
|
|
301
|
+
if pretrained_classes:
|
|
302
|
+
chosen_classes = list(pretrained_classes)
|
|
303
|
+
chosen_num_classes = len(chosen_classes)
|
|
304
|
+
source = "model"
|
|
305
|
+
if local_classes and list(local_classes) != chosen_classes:
|
|
306
|
+
logging.warning(
|
|
307
|
+
"Inference class mismatch: local config classes differ from pretrained model classes. "
|
|
308
|
+
"Using pretrained model classes."
|
|
309
|
+
)
|
|
310
|
+
elif pretrained_num_classes is not None:
|
|
311
|
+
chosen_num_classes = int(pretrained_num_classes)
|
|
312
|
+
source = "model"
|
|
313
|
+
if local_num_classes and int(local_num_classes) != chosen_num_classes:
|
|
314
|
+
logging.warning(
|
|
315
|
+
"Inference class-count mismatch: local config num_classes=%s, pretrained model num_classes=%s. "
|
|
316
|
+
"Using pretrained model class count.",
|
|
317
|
+
local_num_classes,
|
|
318
|
+
chosen_num_classes,
|
|
319
|
+
)
|
|
320
|
+
elif local_classes:
|
|
321
|
+
chosen_classes = list(local_classes)
|
|
322
|
+
chosen_num_classes = len(chosen_classes)
|
|
323
|
+
source = "local"
|
|
324
|
+
elif local_num_classes:
|
|
325
|
+
chosen_num_classes = int(local_num_classes)
|
|
326
|
+
source = "local"
|
|
327
|
+
else:
|
|
328
|
+
source = "annotation"
|
|
329
|
+
|
|
330
|
+
if chosen_classes is not None:
|
|
331
|
+
set_data_classes(cfg, chosen_classes)
|
|
332
|
+
if chosen_num_classes is not None:
|
|
333
|
+
set_data_num_classes(cfg, chosen_num_classes)
|
|
334
|
+
set_data_runtime_value(cfg, "inference_class_source", source)
|
|
335
|
+
set_data_runtime_value(cfg, "inference_model_classes_authoritative", source == "model")
|
|
336
|
+
return cfg
|
|
337
|
+
|
|
338
|
+
|
|
228
339
|
def fetch_and_merge_config_from_HF(
|
|
229
340
|
target_config, weights, hf_token=None, merge_policy="full"
|
|
230
341
|
):
|
|
@@ -275,6 +386,7 @@ def fetch_and_merge_config_from_HF(
|
|
|
275
386
|
loaded_dict = namespace_to_dict(loaded_cfg)
|
|
276
387
|
|
|
277
388
|
_warn_critical_config_conflicts(target_dict, loaded_dict)
|
|
389
|
+
_cache_pretrained_class_metadata(target_dict, loaded_dict)
|
|
278
390
|
|
|
279
391
|
if merge_policy == "compatibility":
|
|
280
392
|
# Keep local runtime config as source of truth. Pull only compatibility-
|
|
@@ -315,8 +427,6 @@ def fetch_and_merge_config_from_HF(
|
|
|
315
427
|
|
|
316
428
|
|
|
317
429
|
def _warn_critical_config_conflicts(target_dict, loaded_dict):
|
|
318
|
-
import logging
|
|
319
|
-
|
|
320
430
|
local_data = target_dict.get("DATA", {}) if isinstance(target_dict, dict) else {}
|
|
321
431
|
hf_data = loaded_dict.get("DATA", {}) if isinstance(loaded_dict, dict) else {}
|
|
322
432
|
|
|
@@ -335,7 +445,7 @@ def _warn_critical_config_conflicts(target_dict, loaded_dict):
|
|
|
335
445
|
):
|
|
336
446
|
logging.warning(
|
|
337
447
|
"Config mismatch: DATA.num_classes local=%s hf=%s. "
|
|
338
|
-
"
|
|
448
|
+
"Inference may use pretrained model class metadata.",
|
|
339
449
|
local_num_classes,
|
|
340
450
|
hf_num_classes,
|
|
341
451
|
)
|
|
@@ -355,9 +465,12 @@ def _warn_critical_config_conflicts(target_dict, loaded_dict):
|
|
|
355
465
|
):
|
|
356
466
|
logging.warning(
|
|
357
467
|
"Config mismatch: DATA.classes differs between local and HF config. "
|
|
358
|
-
"
|
|
468
|
+
"Inference may use pretrained model classes.",
|
|
359
469
|
)
|
|
360
470
|
|
|
471
|
+
|
|
472
|
+
fetch_and_merge_pretrained_config = fetch_and_merge_config_from_HF
|
|
473
|
+
|
|
361
474
|
def save_config(config_obj, path):
|
|
362
475
|
"""Save the configuration object to a YAML file."""
|
|
363
476
|
from omegaconf import DictConfig, OmegaConf
|
|
@@ -13,6 +13,7 @@ label mapping, and class-weight computation.
|
|
|
13
13
|
|
|
14
14
|
import os
|
|
15
15
|
import random
|
|
16
|
+
import logging
|
|
16
17
|
|
|
17
18
|
import numpy as np
|
|
18
19
|
import torch
|
|
@@ -27,16 +28,19 @@ from opensportslib.core.config.accessors import (
|
|
|
27
28
|
get_component_provider_by_kind,
|
|
28
29
|
get_data_classes,
|
|
29
30
|
get_data_modality,
|
|
31
|
+
get_data_runtime,
|
|
30
32
|
get_data_augmentations,
|
|
31
33
|
get_data_params,
|
|
32
34
|
get_data_sampling,
|
|
33
35
|
set_data_classes,
|
|
36
|
+
set_data_num_classes,
|
|
34
37
|
get_data_transform,
|
|
35
38
|
get_split_source_path,
|
|
36
39
|
)
|
|
37
40
|
|
|
38
41
|
|
|
39
42
|
H5_TRACKING_MODALITIES = {"player_centroids_h5", "player_joints_h5", "tracking_h5"}
|
|
43
|
+
logger = logging.getLogger(__name__)
|
|
40
44
|
|
|
41
45
|
|
|
42
46
|
# -------------------------------------------------------------
|
|
@@ -145,14 +149,34 @@ class ClassificationDataset(Dataset):
|
|
|
145
149
|
|
|
146
150
|
# invert to id -> name and propagate into the config so
|
|
147
151
|
# downstream components (metrics, logging) can look it up.
|
|
148
|
-
|
|
149
|
-
|
|
152
|
+
annotation_label_map = {v: k for k, v in self.label_map.items()}
|
|
153
|
+
runtime = get_data_runtime(self.config)
|
|
154
|
+
inference_source = str(runtime.get("inference_class_source") or "").strip().lower()
|
|
155
|
+
configured_classes = list(get_data_classes(self.config))
|
|
156
|
+
configured_label_map = {idx: name for idx, name in enumerate(configured_classes)}
|
|
157
|
+
|
|
158
|
+
if split in {"test", "infer"} and inference_source in {"model", "local"} and configured_classes:
|
|
159
|
+
self.label_map = configured_label_map
|
|
160
|
+
set_data_num_classes(self.config, len(configured_classes))
|
|
161
|
+
|
|
162
|
+
annotation_classes = [annotation_label_map[idx] for idx in sorted(annotation_label_map.keys())]
|
|
163
|
+
if annotation_classes != configured_classes:
|
|
164
|
+
logger.warning(
|
|
165
|
+
"Inference annotation labels differ from resolved %s classes. "
|
|
166
|
+
"Using resolved runtime classes for predictions.",
|
|
167
|
+
inference_source,
|
|
168
|
+
)
|
|
169
|
+
for sample in self.samples:
|
|
170
|
+
sample.pop("label", None)
|
|
171
|
+
self.has_labels = len(self.samples) > 0 and "label" in self.samples[0]
|
|
172
|
+
else:
|
|
173
|
+
self.label_map = annotation_label_map
|
|
174
|
+
set_data_classes(self.config, list(self.label_map.values()))
|
|
175
|
+
self.has_labels = len(self.samples) > 0 and "label" in self.samples[0]
|
|
150
176
|
|
|
151
177
|
print(len(get_data_classes(self.config)), "classes:", get_data_classes(self.config))
|
|
152
178
|
print("Label Map : ", self.label_map)
|
|
153
179
|
|
|
154
|
-
self.has_labels = len(self.samples) > 0 and "label" in self.samples[0]
|
|
155
|
-
|
|
156
180
|
# -- Sampling / loss weights ------------------------------------------
|
|
157
181
|
|
|
158
182
|
def _normalized_label_tensor(self):
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import json
|
|
6
|
+
import logging
|
|
6
7
|
import os
|
|
7
8
|
import pickle
|
|
8
9
|
import random
|
|
@@ -22,6 +23,8 @@ from opensportslib.core.config.accessors import (
|
|
|
22
23
|
from opensportslib.models.utils.vqa_prediction_priors import build_prediction_prior_text
|
|
23
24
|
from opensportslib.models.utils.xvars_clip_index import load_feature_index, load_prediction_index, validate_xvars_feature_tensor
|
|
24
25
|
|
|
26
|
+
logger = logging.getLogger(__name__)
|
|
27
|
+
|
|
25
28
|
|
|
26
29
|
class VQADataset(Dataset):
|
|
27
30
|
"""Flatten VQA annotations into single question-answer training samples."""
|
|
@@ -66,16 +69,18 @@ class VQADataset(Dataset):
|
|
|
66
69
|
feature_source = get_vqa_feature_source(config, default="indexed")
|
|
67
70
|
if not self.native_vl and feature_backend != "xvars_clip":
|
|
68
71
|
raise ValueError(f"Unsupported VQA feature backend '{feature_backend}'. Expected 'xvars_clip'.")
|
|
69
|
-
|
|
70
|
-
|
|
72
|
+
strict_feature_index = (not self.native_vl) and feature_source in {"indexed", ""}
|
|
73
|
+
fallback_feature_index = (not self.native_vl) and feature_source in {"indexed_or_raw", "indexed_or_raw_clip"}
|
|
74
|
+
if strict_feature_index and not feature_index_path:
|
|
71
75
|
raise ValueError("Missing required config key DATA.common.feature_index for VQA xvars_clip mode.")
|
|
72
76
|
self.feature_source = feature_source
|
|
73
77
|
self.feature_mode = get_vqa_xvars_feature_mode(config, default="strict_xvars")
|
|
74
78
|
self.expected_feature_tokens = get_xvars_train_video_token_len(config)
|
|
75
|
-
self.feature_index = (
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
+
self.feature_index = self._load_feature_index(
|
|
80
|
+
feature_index_path,
|
|
81
|
+
split=split,
|
|
82
|
+
strict=strict_feature_index,
|
|
83
|
+
allow_missing=fallback_feature_index,
|
|
79
84
|
)
|
|
80
85
|
self.prediction_index = (
|
|
81
86
|
load_prediction_index(os.path.abspath(os.path.expanduser(prediction_index_path)), split=split)
|
|
@@ -94,7 +99,7 @@ class VQADataset(Dataset):
|
|
|
94
99
|
frame_paths = self._resolve_frame_paths(item, source_root)
|
|
95
100
|
|
|
96
101
|
feature_candidates = self.feature_index.get(item_id_str, [])
|
|
97
|
-
if
|
|
102
|
+
if strict_feature_index and not feature_candidates:
|
|
98
103
|
raise ValueError(
|
|
99
104
|
f"Missing feature index entry for sample id '{item_id_str}'. "
|
|
100
105
|
"Provide DATA.common.feature_index mapping with feature_paths or feature_dir/path."
|
|
@@ -136,6 +141,43 @@ class VQADataset(Dataset):
|
|
|
136
141
|
"Expected video_path, frame_paths, or video_frames."
|
|
137
142
|
)
|
|
138
143
|
|
|
144
|
+
def _load_feature_index(
|
|
145
|
+
self,
|
|
146
|
+
feature_index_path: str,
|
|
147
|
+
*,
|
|
148
|
+
split: str,
|
|
149
|
+
strict: bool,
|
|
150
|
+
allow_missing: bool,
|
|
151
|
+
) -> dict[str, list[str]]:
|
|
152
|
+
if not feature_index_path:
|
|
153
|
+
return {}
|
|
154
|
+
|
|
155
|
+
resolved_path = os.path.abspath(os.path.expanduser(feature_index_path))
|
|
156
|
+
if allow_missing and not os.path.exists(resolved_path):
|
|
157
|
+
logger.warning(
|
|
158
|
+
"VQA feature index unavailable; falling back to raw-video extraction | "
|
|
159
|
+
"feature_source=%s | split=%s | feature_index=%s",
|
|
160
|
+
self.feature_source,
|
|
161
|
+
split,
|
|
162
|
+
resolved_path,
|
|
163
|
+
)
|
|
164
|
+
return {}
|
|
165
|
+
|
|
166
|
+
try:
|
|
167
|
+
return load_feature_index(resolved_path, split=split)
|
|
168
|
+
except Exception:
|
|
169
|
+
if strict or not allow_missing:
|
|
170
|
+
raise
|
|
171
|
+
logger.warning(
|
|
172
|
+
"VQA feature index unreadable; falling back to raw-video extraction | "
|
|
173
|
+
"feature_source=%s | split=%s | feature_index=%s",
|
|
174
|
+
self.feature_source,
|
|
175
|
+
split,
|
|
176
|
+
resolved_path,
|
|
177
|
+
exc_info=True,
|
|
178
|
+
)
|
|
179
|
+
return {}
|
|
180
|
+
|
|
139
181
|
def __len__(self) -> int:
|
|
140
182
|
return len(self.samples)
|
|
141
183
|
|
{opensportslib-0.3.0.dev7 → opensportslib-0.3.0.dev8}/opensportslib/models/base/qwen_xvars.py
RENAMED
|
@@ -482,7 +482,7 @@ class QwenXVarsModel(nn.Module):
|
|
|
482
482
|
self.raw_extractor = XVarsStrictRawVideoFeatureExtractor(
|
|
483
483
|
weights_path=self.vision_weights_path,
|
|
484
484
|
vision_tower=self.vision_tower_name,
|
|
485
|
-
prefer_cuda=get_hf_prefer_cuda(config, hf_cfg),
|
|
485
|
+
prefer_cuda=get_hf_prefer_cuda(self.config, hf_cfg),
|
|
486
486
|
start_frame=self.strict_sampling_cfg.get("start_frame"),
|
|
487
487
|
end_frame=self.strict_sampling_cfg.get("end_frame"),
|
|
488
488
|
input_fps=self.strict_sampling_cfg.get("input_fps"),
|
|
@@ -492,7 +492,7 @@ class QwenXVarsModel(nn.Module):
|
|
|
492
492
|
else:
|
|
493
493
|
self.raw_extractor = XVarsRawVideoFeatureExtractor(
|
|
494
494
|
vision_tower=self.vision_tower_name,
|
|
495
|
-
prefer_cuda=get_hf_prefer_cuda(config, hf_cfg),
|
|
495
|
+
prefer_cuda=get_hf_prefer_cuda(self.config, hf_cfg),
|
|
496
496
|
)
|
|
497
497
|
if isinstance(self.raw_extractor, XVarsStrictRawVideoFeatureExtractor):
|
|
498
498
|
features, classifier_prior = self.raw_extractor.extract_with_prior(video_path)
|