dslighting 1.7.1__py3-none-any.whl → 1.7.8__py3-none-any.whl
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.
- dslighting/__init__.py +1 -1
- dslighting/core/agent.py +78 -62
- {dslighting-1.7.1.dist-info → dslighting-1.7.8.dist-info}/METADATA +3 -1
- {dslighting-1.7.1.dist-info → dslighting-1.7.8.dist-info}/RECORD +352 -7
- {dslighting-1.7.1.dist-info → dslighting-1.7.8.dist-info}/top_level.txt +1 -0
- mlebench/README.md +39 -0
- mlebench/__init__.py +0 -0
- mlebench/cli.py +221 -0
- mlebench/competitions/3d-object-detection-for-autonomous-vehicles/grade.py +161 -0
- mlebench/competitions/3d-object-detection-for-autonomous-vehicles/mAP_evaluation.py +425 -0
- mlebench/competitions/3d-object-detection-for-autonomous-vehicles/prepare.py +483 -0
- mlebench/competitions/3d-object-detection-for-autonomous-vehicles/prepare_val.py +719 -0
- mlebench/competitions/AI4Code/grade.py +70 -0
- mlebench/competitions/AI4Code/prepare.py +84 -0
- mlebench/competitions/AI4Code/prepare_val.py +159 -0
- mlebench/competitions/__init__.py +0 -0
- mlebench/competitions/aerial-cactus-identification/grade.py +11 -0
- mlebench/competitions/aerial-cactus-identification/prepare.py +71 -0
- mlebench/competitions/aerial-cactus-identification/prepare_val.py +133 -0
- mlebench/competitions/alaska2-image-steganalysis/grade.py +136 -0
- mlebench/competitions/alaska2-image-steganalysis/prepare.py +88 -0
- mlebench/competitions/alaska2-image-steganalysis/prepare_val.py +148 -0
- mlebench/competitions/aptos2019-blindness-detection/grade.py +35 -0
- mlebench/competitions/aptos2019-blindness-detection/prepare.py +75 -0
- mlebench/competitions/aptos2019-blindness-detection/prepare_val.py +123 -0
- mlebench/competitions/bike-sharing-demand/__init__.py +0 -0
- mlebench/competitions/bike-sharing-demand/grade.py +55 -0
- mlebench/competitions/bike-sharing-demand/prepare.py +37 -0
- mlebench/competitions/billion-word-imputation/grade.py +37 -0
- mlebench/competitions/billion-word-imputation/prepare.py +107 -0
- mlebench/competitions/billion-word-imputation/prepare_val.py +179 -0
- mlebench/competitions/bms-molecular-translation/grade.py +40 -0
- mlebench/competitions/bms-molecular-translation/prepare.py +68 -0
- mlebench/competitions/bms-molecular-translation/prepare_val.py +131 -0
- mlebench/competitions/cassava-leaf-disease-classification/grade.py +12 -0
- mlebench/competitions/cassava-leaf-disease-classification/prepare.py +113 -0
- mlebench/competitions/cassava-leaf-disease-classification/prepare_val.py +186 -0
- mlebench/competitions/cdiscount-image-classification-challenge/grade.py +11 -0
- mlebench/competitions/cdiscount-image-classification-challenge/prepare.py +144 -0
- mlebench/competitions/cdiscount-image-classification-challenge/prepare_val.py +205 -0
- mlebench/competitions/chaii-hindi-and-tamil-question-answering/grade.py +67 -0
- mlebench/competitions/chaii-hindi-and-tamil-question-answering/prepare.py +31 -0
- mlebench/competitions/chaii-hindi-and-tamil-question-answering/prepare_val.py +94 -0
- mlebench/competitions/champs-scalar-coupling/grade.py +60 -0
- mlebench/competitions/champs-scalar-coupling/prepare.py +116 -0
- mlebench/competitions/champs-scalar-coupling/prepare_val.py +155 -0
- mlebench/competitions/conways-reverse-game-of-life-2020/__init__.py +0 -0
- mlebench/competitions/conways-reverse-game-of-life-2020/grade.py +40 -0
- mlebench/competitions/conways-reverse-game-of-life-2020/prepare.py +41 -0
- mlebench/competitions/demand-forecasting-kernels-only/__init__.py +0 -0
- mlebench/competitions/demand-forecasting-kernels-only/grade.py +66 -0
- mlebench/competitions/demand-forecasting-kernels-only/prepare.py +27 -0
- mlebench/competitions/demand_forecasting_kernels_only/__init__.py +0 -0
- mlebench/competitions/demand_forecasting_kernels_only/grade.py +66 -0
- mlebench/competitions/demand_forecasting_kernels_only/prepare.py +27 -0
- mlebench/competitions/denoising-dirty-documents/grade.py +44 -0
- mlebench/competitions/denoising-dirty-documents/prepare.py +134 -0
- mlebench/competitions/denoising-dirty-documents/prepare_val.py +178 -0
- mlebench/competitions/detecting-insults-in-social-commentary/grade.py +11 -0
- mlebench/competitions/detecting-insults-in-social-commentary/prepare.py +72 -0
- mlebench/competitions/detecting-insults-in-social-commentary/prepare_val.py +128 -0
- mlebench/competitions/dog-breed-identification/dogs.py +124 -0
- mlebench/competitions/dog-breed-identification/grade.py +42 -0
- mlebench/competitions/dog-breed-identification/prepare.py +55 -0
- mlebench/competitions/dog-breed-identification/prepare_val.py +104 -0
- mlebench/competitions/dogs-vs-cats-redux-kernels-edition/grade.py +43 -0
- mlebench/competitions/dogs-vs-cats-redux-kernels-edition/prepare.py +70 -0
- mlebench/competitions/dogs-vs-cats-redux-kernels-edition/prepare_val.py +143 -0
- mlebench/competitions/ethanol-concentration/grade.py +23 -0
- mlebench/competitions/ethanol-concentration/prepare.py +90 -0
- mlebench/competitions/facebook-recruiting-iii-keyword-extraction/grade.py +60 -0
- mlebench/competitions/facebook-recruiting-iii-keyword-extraction/prepare.py +41 -0
- mlebench/competitions/facebook-recruiting-iii-keyword-extraction/prepare_val.py +92 -0
- mlebench/competitions/feedback-prize-english-language-learning/__init__.py +0 -0
- mlebench/competitions/feedback-prize-english-language-learning/grade.py +60 -0
- mlebench/competitions/feedback-prize-english-language-learning/prepare.py +39 -0
- mlebench/competitions/freesound-audio-tagging-2019/grade.py +64 -0
- mlebench/competitions/freesound-audio-tagging-2019/prepare.py +94 -0
- mlebench/competitions/freesound-audio-tagging-2019/prepare_val.py +175 -0
- mlebench/competitions/freesound-audio-tagging-2019/vocabulary.py +83 -0
- mlebench/competitions/google-quest-challenge/classes.py +32 -0
- mlebench/competitions/google-quest-challenge/grade.py +45 -0
- mlebench/competitions/google-quest-challenge/prepare.py +58 -0
- mlebench/competitions/google-quest-challenge/prepare_val.py +120 -0
- mlebench/competitions/google-research-identify-contrails-reduce-global-warming/grade.py +77 -0
- mlebench/competitions/google-research-identify-contrails-reduce-global-warming/prepare.py +155 -0
- mlebench/competitions/google-research-identify-contrails-reduce-global-warming/prepare_val.py +211 -0
- mlebench/competitions/h-and-m-personalized-fashion-recommendations/grade.py +42 -0
- mlebench/competitions/h-and-m-personalized-fashion-recommendations/prepare.py +102 -0
- mlebench/competitions/h-and-m-personalized-fashion-recommendations/prepare_val.py +132 -0
- mlebench/competitions/handwriting/grade.py +23 -0
- mlebench/competitions/handwriting/prepare.py +179 -0
- mlebench/competitions/herbarium-2020-fgvc7/grade.py +34 -0
- mlebench/competitions/herbarium-2020-fgvc7/prepare.py +251 -0
- mlebench/competitions/herbarium-2020-fgvc7/prepare_val.py +242 -0
- mlebench/competitions/herbarium-2021-fgvc8/grade.py +34 -0
- mlebench/competitions/herbarium-2021-fgvc8/prepare.py +251 -0
- mlebench/competitions/herbarium-2021-fgvc8/prepare_val.py +222 -0
- mlebench/competitions/herbarium-2022-fgvc9/grade.py +31 -0
- mlebench/competitions/herbarium-2022-fgvc9/prepare.py +233 -0
- mlebench/competitions/herbarium-2022-fgvc9/prepare_val.py +213 -0
- mlebench/competitions/histopathologic-cancer-detection/grade.py +12 -0
- mlebench/competitions/histopathologic-cancer-detection/prepare.py +59 -0
- mlebench/competitions/histopathologic-cancer-detection/prepare_val.py +131 -0
- mlebench/competitions/hms-harmful-brain-activity-classification/constants.py +9 -0
- mlebench/competitions/hms-harmful-brain-activity-classification/grade.py +43 -0
- mlebench/competitions/hms-harmful-brain-activity-classification/kaggle_metric_utilities.py +96 -0
- mlebench/competitions/hms-harmful-brain-activity-classification/kullback_leibler_divergence.py +118 -0
- mlebench/competitions/hms-harmful-brain-activity-classification/prepare.py +121 -0
- mlebench/competitions/hms-harmful-brain-activity-classification/prepare_val.py +190 -0
- mlebench/competitions/hotel-id-2021-fgvc8/grade.py +41 -0
- mlebench/competitions/hotel-id-2021-fgvc8/prepare.py +63 -0
- mlebench/competitions/hotel-id-2021-fgvc8/prepare_val.py +132 -0
- mlebench/competitions/hubmap-kidney-segmentation/grade.py +62 -0
- mlebench/competitions/hubmap-kidney-segmentation/prepare.py +108 -0
- mlebench/competitions/hubmap-kidney-segmentation/prepare_val.py +153 -0
- mlebench/competitions/icecube-neutrinos-in-deep-ice/grade.py +111 -0
- mlebench/competitions/icecube-neutrinos-in-deep-ice/prepare.py +127 -0
- mlebench/competitions/icecube-neutrinos-in-deep-ice/prepare_val.py +183 -0
- mlebench/competitions/ili/grade.py +60 -0
- mlebench/competitions/ili/prepare.py +99 -0
- mlebench/competitions/imet-2020-fgvc7/grade.py +54 -0
- mlebench/competitions/imet-2020-fgvc7/prepare.py +77 -0
- mlebench/competitions/imet-2020-fgvc7/prepare_val.py +157 -0
- mlebench/competitions/inaturalist-2019-fgvc6/grade.py +35 -0
- mlebench/competitions/inaturalist-2019-fgvc6/prepare.py +259 -0
- mlebench/competitions/inaturalist-2019-fgvc6/prepare_val.py +304 -0
- mlebench/competitions/instant-gratification/__init__.py +0 -0
- mlebench/competitions/instant-gratification/grade.py +55 -0
- mlebench/competitions/instant-gratification/prepare.py +25 -0
- mlebench/competitions/instant_gratification/__init__.py +0 -0
- mlebench/competitions/instant_gratification/grade.py +55 -0
- mlebench/competitions/instant_gratification/prepare.py +25 -0
- mlebench/competitions/invasive-species-monitoring/grade.py +11 -0
- mlebench/competitions/invasive-species-monitoring/prepare.py +97 -0
- mlebench/competitions/invasive-species-monitoring/prepare_val.py +164 -0
- mlebench/competitions/iwildcam-2019-fgvc6/grade.py +44 -0
- mlebench/competitions/iwildcam-2019-fgvc6/prepare.py +118 -0
- mlebench/competitions/iwildcam-2019-fgvc6/prepare_val.py +194 -0
- mlebench/competitions/iwildcam-2020-fgvc7/grade.py +11 -0
- mlebench/competitions/iwildcam-2020-fgvc7/prepare.py +164 -0
- mlebench/competitions/iwildcam-2020-fgvc7/prepare_val.py +245 -0
- mlebench/competitions/jigsaw-toxic-comment-classification-challenge/classes.py +1 -0
- mlebench/competitions/jigsaw-toxic-comment-classification-challenge/grade.py +54 -0
- mlebench/competitions/jigsaw-toxic-comment-classification-challenge/prepare.py +42 -0
- mlebench/competitions/jigsaw-toxic-comment-classification-challenge/prepare_val.py +88 -0
- mlebench/competitions/jigsaw-unintended-bias-in-toxicity-classification/grade.py +153 -0
- mlebench/competitions/jigsaw-unintended-bias-in-toxicity-classification/prepare.py +36 -0
- mlebench/competitions/jigsaw-unintended-bias-in-toxicity-classification/prepare_val.py +117 -0
- mlebench/competitions/kuzushiji-recognition/grade.py +58 -0
- mlebench/competitions/kuzushiji-recognition/kuzushiji_metric.py +118 -0
- mlebench/competitions/kuzushiji-recognition/prepare.py +92 -0
- mlebench/competitions/kuzushiji-recognition/prepare_val.py +149 -0
- mlebench/competitions/leaf-classification/classes.py +101 -0
- mlebench/competitions/leaf-classification/grade.py +44 -0
- mlebench/competitions/leaf-classification/prepare.py +60 -0
- mlebench/competitions/leaf-classification/prepare_val.py +116 -0
- mlebench/competitions/learning-agency-lab-automated-essay-scoring-2/grade.py +44 -0
- mlebench/competitions/learning-agency-lab-automated-essay-scoring-2/prepare.py +51 -0
- mlebench/competitions/learning-agency-lab-automated-essay-scoring-2/prepare_val.py +96 -0
- mlebench/competitions/liverpool-ion-switching/__init__.py +0 -0
- mlebench/competitions/liverpool-ion-switching/grade.py +52 -0
- mlebench/competitions/liverpool-ion-switching/prepare.py +27 -0
- mlebench/competitions/liverpool_ion_switching/__init__.py +0 -0
- mlebench/competitions/liverpool_ion_switching/grade.py +52 -0
- mlebench/competitions/liverpool_ion_switching/prepare.py +27 -0
- mlebench/competitions/lmsys-chatbot-arena/grade.py +63 -0
- mlebench/competitions/lmsys-chatbot-arena/prepare.py +52 -0
- mlebench/competitions/lmsys-chatbot-arena/prepare_val.py +115 -0
- mlebench/competitions/mcm_2024_c_test/grade.py +107 -0
- mlebench/competitions/mcm_2024_c_test/prepare.py +2 -0
- mlebench/competitions/ml2021spring-hw2/grade.py +11 -0
- mlebench/competitions/ml2021spring-hw2/prepare.py +58 -0
- mlebench/competitions/ml2021spring-hw2/prepare_val.py +135 -0
- mlebench/competitions/mlsp-2013-birds/grade.py +11 -0
- mlebench/competitions/mlsp-2013-birds/prepare.py +182 -0
- mlebench/competitions/mlsp-2013-birds/prepare_val.py +241 -0
- mlebench/competitions/movie-review-sentiment-analysis-kernels-only/grade.py +11 -0
- mlebench/competitions/movie-review-sentiment-analysis-kernels-only/prepare.py +58 -0
- mlebench/competitions/movie-review-sentiment-analysis-kernels-only/prepare_val.py +120 -0
- mlebench/competitions/multi-modal-gesture-recognition/grade.py +58 -0
- mlebench/competitions/multi-modal-gesture-recognition/prepare.py +85 -0
- mlebench/competitions/multi-modal-gesture-recognition/prepare_val.py +139 -0
- mlebench/competitions/my-custom-task-01/prepare.py +2 -0
- mlebench/competitions/new-my-task-01/prepare.py +2 -0
- mlebench/competitions/new-my-task-03/grade.py +107 -0
- mlebench/competitions/new-my-task-03/prepare.py +2 -0
- mlebench/competitions/new-york-city-taxi-fare-prediction/grade.py +28 -0
- mlebench/competitions/new-york-city-taxi-fare-prediction/prepare.py +44 -0
- mlebench/competitions/new-york-city-taxi-fare-prediction/prepare_val.py +89 -0
- mlebench/competitions/nfl-player-contact-detection/grade.py +36 -0
- mlebench/competitions/nfl-player-contact-detection/prepare.py +101 -0
- mlebench/competitions/nfl-player-contact-detection/prepare_val.py +186 -0
- mlebench/competitions/nomad2018-predict-transparent-conductors/grade.py +47 -0
- mlebench/competitions/nomad2018-predict-transparent-conductors/prepare.py +77 -0
- mlebench/competitions/nomad2018-predict-transparent-conductors/prepare_val.py +144 -0
- mlebench/competitions/osic-pulmonary-fibrosis-progression/grade.py +74 -0
- mlebench/competitions/osic-pulmonary-fibrosis-progression/prepare.py +95 -0
- mlebench/competitions/osic-pulmonary-fibrosis-progression/prepare_val.py +167 -0
- mlebench/competitions/paddy-disease-classification/grade.py +35 -0
- mlebench/competitions/paddy-disease-classification/prepare.py +69 -0
- mlebench/competitions/paddy-disease-classification/prepare_val.py +122 -0
- mlebench/competitions/petfinder-pawpularity-score/grade.py +41 -0
- mlebench/competitions/petfinder-pawpularity-score/prepare.py +76 -0
- mlebench/competitions/petfinder-pawpularity-score/prepare_val.py +154 -0
- mlebench/competitions/plant-pathology-2020-fgvc7/grade.py +41 -0
- mlebench/competitions/plant-pathology-2020-fgvc7/prepare.py +74 -0
- mlebench/competitions/plant-pathology-2020-fgvc7/prepare_val.py +160 -0
- mlebench/competitions/plant-pathology-2021-fgvc8/grade.py +54 -0
- mlebench/competitions/plant-pathology-2021-fgvc8/prepare.py +65 -0
- mlebench/competitions/plant-pathology-2021-fgvc8/prepare_val.py +130 -0
- mlebench/competitions/plant-seedlings-classification/grade.py +39 -0
- mlebench/competitions/plant-seedlings-classification/prepare.py +91 -0
- mlebench/competitions/plant-seedlings-classification/prepare_val.py +158 -0
- mlebench/competitions/playground-series-s3e1/__init__.py +0 -0
- mlebench/competitions/playground-series-s3e1/grade.py +52 -0
- mlebench/competitions/playground-series-s3e1/prepare.py +25 -0
- mlebench/competitions/playground-series-s3e11/__init__.py +0 -0
- mlebench/competitions/playground-series-s3e11/grade.py +55 -0
- mlebench/competitions/playground-series-s3e11/prepare.py +25 -0
- mlebench/competitions/playground-series-s3e18/grade.py +39 -0
- mlebench/competitions/playground-series-s3e18/prepare.py +36 -0
- mlebench/competitions/playground-series-s3e18/prepare_val.py +89 -0
- mlebench/competitions/playground_series_s3e1/__init__.py +0 -0
- mlebench/competitions/playground_series_s3e1/grade.py +52 -0
- mlebench/competitions/playground_series_s3e1/prepare.py +25 -0
- mlebench/competitions/playground_series_s3e11/__init__.py +0 -0
- mlebench/competitions/playground_series_s3e11/grade.py +55 -0
- mlebench/competitions/playground_series_s3e11/prepare.py +25 -0
- mlebench/competitions/predict-volcanic-eruptions-ingv-oe/grade.py +44 -0
- mlebench/competitions/predict-volcanic-eruptions-ingv-oe/prepare.py +68 -0
- mlebench/competitions/predict-volcanic-eruptions-ingv-oe/prepare_val.py +146 -0
- mlebench/competitions/random-acts-of-pizza/grade.py +14 -0
- mlebench/competitions/random-acts-of-pizza/prepare.py +80 -0
- mlebench/competitions/random-acts-of-pizza/prepare_val.py +144 -0
- mlebench/competitions/ranzcr-clip-catheter-line-classification/classes.py +11 -0
- mlebench/competitions/ranzcr-clip-catheter-line-classification/grade.py +31 -0
- mlebench/competitions/ranzcr-clip-catheter-line-classification/prepare.py +53 -0
- mlebench/competitions/ranzcr-clip-catheter-line-classification/prepare_val.py +113 -0
- mlebench/competitions/rsna-2022-cervical-spine-fracture-detection/grade.py +124 -0
- mlebench/competitions/rsna-2022-cervical-spine-fracture-detection/prepare.py +219 -0
- mlebench/competitions/rsna-2022-cervical-spine-fracture-detection/prepare_val.py +257 -0
- mlebench/competitions/rsna-breast-cancer-detection/grade.py +65 -0
- mlebench/competitions/rsna-breast-cancer-detection/prepare.py +141 -0
- mlebench/competitions/rsna-breast-cancer-detection/prepare_val.py +201 -0
- mlebench/competitions/rsna-miccai-brain-tumor-radiogenomic-classification/grade.py +13 -0
- mlebench/competitions/rsna-miccai-brain-tumor-radiogenomic-classification/prepare.py +47 -0
- mlebench/competitions/rsna-miccai-brain-tumor-radiogenomic-classification/prepare_val.py +97 -0
- mlebench/competitions/santander-customer-satisfaction/grade.py +10 -0
- mlebench/competitions/santander-customer-satisfaction/prepare.py +41 -0
- mlebench/competitions/sciencebench-001-clintox-nn/__init__.py +0 -0
- mlebench/competitions/sciencebench-001-clintox-nn/grade.py +56 -0
- mlebench/competitions/sciencebench-001-clintox-nn/prepare.py +75 -0
- mlebench/competitions/sciencebench-015-aai/grade.py +37 -0
- mlebench/competitions/sciencebench-015-aai/prepare.py +102 -0
- mlebench/competitions/sciencebench-051-brain-blood-qsar/grade.py +58 -0
- mlebench/competitions/sciencebench-051-brain-blood-qsar/prepare.py +69 -0
- mlebench/competitions/sciencebench-101-experimental-band-gap-prediction/grade.py +55 -0
- mlebench/competitions/sciencebench-101-experimental-band-gap-prediction/prepare.py +88 -0
- mlebench/competitions/see-click-predict-fix/__init__.py +0 -0
- mlebench/competitions/see-click-predict-fix/grade.py +66 -0
- mlebench/competitions/see-click-predict-fix/prepare.py +25 -0
- mlebench/competitions/see_click_predict_fix/__init__.py +0 -0
- mlebench/competitions/see_click_predict_fix/grade.py +66 -0
- mlebench/competitions/see_click_predict_fix/prepare.py +25 -0
- mlebench/competitions/seti-breakthrough-listen/grade.py +11 -0
- mlebench/competitions/seti-breakthrough-listen/prepare.py +71 -0
- mlebench/competitions/seti-breakthrough-listen/prepare_val.py +159 -0
- mlebench/competitions/siim-covid19-detection/grade.py +194 -0
- mlebench/competitions/siim-covid19-detection/prepare.py +123 -0
- mlebench/competitions/siim-covid19-detection/prepare_val.py +164 -0
- mlebench/competitions/siim-isic-melanoma-classification/grade.py +11 -0
- mlebench/competitions/siim-isic-melanoma-classification/prepare.py +127 -0
- mlebench/competitions/siim-isic-melanoma-classification/prepare_val.py +158 -0
- mlebench/competitions/smartphone-decimeter-2022/grade.py +55 -0
- mlebench/competitions/smartphone-decimeter-2022/notebook.py +86 -0
- mlebench/competitions/smartphone-decimeter-2022/prepare.py +143 -0
- mlebench/competitions/smartphone-decimeter-2022/prepare_val.py +199 -0
- mlebench/competitions/spaceship-titanic/grade.py +11 -0
- mlebench/competitions/spaceship-titanic/prepare.py +23 -0
- mlebench/competitions/spaceship-titanic/prepare_val.py +61 -0
- mlebench/competitions/spooky-author-identification/classes.py +1 -0
- mlebench/competitions/spooky-author-identification/grade.py +38 -0
- mlebench/competitions/spooky-author-identification/prepare.py +40 -0
- mlebench/competitions/spooky-author-identification/prepare_val.py +78 -0
- mlebench/competitions/stanford-covid-vaccine/grade.py +65 -0
- mlebench/competitions/stanford-covid-vaccine/prepare.py +129 -0
- mlebench/competitions/stanford-covid-vaccine/prepare_val.py +199 -0
- mlebench/competitions/statoil-iceberg-classifier-challenge/grade.py +41 -0
- mlebench/competitions/statoil-iceberg-classifier-challenge/prepare.py +105 -0
- mlebench/competitions/statoil-iceberg-classifier-challenge/prepare_val.py +157 -0
- mlebench/competitions/tabular-playground-series-dec-2021/grade.py +11 -0
- mlebench/competitions/tabular-playground-series-dec-2021/prepare.py +39 -0
- mlebench/competitions/tabular-playground-series-dec-2021/prepare_val.py +99 -0
- mlebench/competitions/tabular-playground-series-may-2022/grade.py +9 -0
- mlebench/competitions/tabular-playground-series-may-2022/prepare.py +56 -0
- mlebench/competitions/tabular-playground-series-may-2022/prepare_val.py +116 -0
- mlebench/competitions/tensorflow-speech-recognition-challenge/grade.py +11 -0
- mlebench/competitions/tensorflow-speech-recognition-challenge/prepare.py +90 -0
- mlebench/competitions/tensorflow-speech-recognition-challenge/prepare_val.py +148 -0
- mlebench/competitions/tensorflow2-question-answering/grade.py +122 -0
- mlebench/competitions/tensorflow2-question-answering/prepare.py +122 -0
- mlebench/competitions/tensorflow2-question-answering/prepare_val.py +187 -0
- mlebench/competitions/text-normalization-challenge-english-language/grade.py +49 -0
- mlebench/competitions/text-normalization-challenge-english-language/prepare.py +115 -0
- mlebench/competitions/text-normalization-challenge-english-language/prepare_val.py +213 -0
- mlebench/competitions/text-normalization-challenge-russian-language/grade.py +49 -0
- mlebench/competitions/text-normalization-challenge-russian-language/prepare.py +113 -0
- mlebench/competitions/text-normalization-challenge-russian-language/prepare_val.py +165 -0
- mlebench/competitions/tgs-salt-identification-challenge/grade.py +144 -0
- mlebench/competitions/tgs-salt-identification-challenge/prepare.py +158 -0
- mlebench/competitions/tgs-salt-identification-challenge/prepare_val.py +166 -0
- mlebench/competitions/the-icml-2013-whale-challenge-right-whale-redux/grade.py +11 -0
- mlebench/competitions/the-icml-2013-whale-challenge-right-whale-redux/prepare.py +95 -0
- mlebench/competitions/the-icml-2013-whale-challenge-right-whale-redux/prepare_val.py +141 -0
- mlebench/competitions/tmdb-box-office-prediction/__init__.py +0 -0
- mlebench/competitions/tmdb-box-office-prediction/grade.py +55 -0
- mlebench/competitions/tmdb-box-office-prediction/prepare.py +35 -0
- mlebench/competitions/tweet-sentiment-extraction/grade.py +67 -0
- mlebench/competitions/tweet-sentiment-extraction/prepare.py +36 -0
- mlebench/competitions/tweet-sentiment-extraction/prepare_val.py +106 -0
- mlebench/competitions/us-patent-phrase-to-phrase-matching/grade.py +31 -0
- mlebench/competitions/us-patent-phrase-to-phrase-matching/prepare.py +33 -0
- mlebench/competitions/us-patent-phrase-to-phrase-matching/prepare_val.py +71 -0
- mlebench/competitions/utils.py +266 -0
- mlebench/competitions/uw-madison-gi-tract-image-segmentation/grade.py +158 -0
- mlebench/competitions/uw-madison-gi-tract-image-segmentation/prepare.py +139 -0
- mlebench/competitions/uw-madison-gi-tract-image-segmentation/prepare_val.py +193 -0
- mlebench/competitions/ventilator-pressure-prediction/__init__.py +0 -0
- mlebench/competitions/ventilator-pressure-prediction/grade.py +52 -0
- mlebench/competitions/ventilator-pressure-prediction/prepare.py +27 -0
- mlebench/competitions/ventilator-pressure-prediction/prepare_val.py +142 -0
- mlebench/competitions/ventilator_pressure_prediction/__init__.py +0 -0
- mlebench/competitions/ventilator_pressure_prediction/grade.py +52 -0
- mlebench/competitions/ventilator_pressure_prediction/prepare.py +27 -0
- mlebench/competitions/vesuvius-challenge-ink-detection/grade.py +97 -0
- mlebench/competitions/vesuvius-challenge-ink-detection/prepare.py +122 -0
- mlebench/competitions/vesuvius-challenge-ink-detection/prepare_val.py +170 -0
- mlebench/competitions/vinbigdata-chest-xray-abnormalities-detection/grade.py +220 -0
- mlebench/competitions/vinbigdata-chest-xray-abnormalities-detection/prepare.py +129 -0
- mlebench/competitions/vinbigdata-chest-xray-abnormalities-detection/prepare_val.py +204 -0
- mlebench/competitions/whale-categorization-playground/grade.py +41 -0
- mlebench/competitions/whale-categorization-playground/prepare.py +103 -0
- mlebench/competitions/whale-categorization-playground/prepare_val.py +196 -0
- mlebench/data.py +420 -0
- mlebench/grade.py +209 -0
- mlebench/grade_helpers.py +235 -0
- mlebench/metrics.py +75 -0
- mlebench/registry.py +332 -0
- mlebench/utils.py +346 -0
- {dslighting-1.7.1.dist-info → dslighting-1.7.8.dist-info}/WHEEL +0 -0
- {dslighting-1.7.1.dist-info → dslighting-1.7.8.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
"""Helper classes related to grading"""
|
|
2
|
+
import inspect
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from datetime import datetime
|
|
5
|
+
from typing import Any, Optional, Union
|
|
6
|
+
|
|
7
|
+
import pandas as pd
|
|
8
|
+
|
|
9
|
+
from mlebench.utils import get_logger, import_fn
|
|
10
|
+
|
|
11
|
+
logger = get_logger(__name__)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class Grader:
|
|
15
|
+
def __init__(self, name: str, grade_fn: str) -> None:
|
|
16
|
+
self.name = name
|
|
17
|
+
self.grade_fn = import_fn(grade_fn)
|
|
18
|
+
assert isinstance(self.name, str), "Grader name must be a string."
|
|
19
|
+
assert len(self.name) > 0, "Grader name cannot be empty."
|
|
20
|
+
|
|
21
|
+
def is_lower_better(self, leaderboard: pd.DataFrame) -> bool:
|
|
22
|
+
"""
|
|
23
|
+
Determines if a lower score is better based on the leaderboard.
|
|
24
|
+
Returns True if lower scores are better, False otherwise.
|
|
25
|
+
"""
|
|
26
|
+
scores = leaderboard["score"]
|
|
27
|
+
top_score = scores.iloc[0]
|
|
28
|
+
bottom_score = scores.iloc[-1]
|
|
29
|
+
|
|
30
|
+
return bool(top_score < bottom_score)
|
|
31
|
+
|
|
32
|
+
@staticmethod
|
|
33
|
+
def from_dict(data: dict) -> "Grader":
|
|
34
|
+
if "name" not in data:
|
|
35
|
+
data = data.copy()
|
|
36
|
+
data["name"] = "StandardGrader"
|
|
37
|
+
return Grader(**data)
|
|
38
|
+
|
|
39
|
+
def __call__(self, submission: pd.DataFrame, answers: Any) -> Optional[float]:
|
|
40
|
+
"""
|
|
41
|
+
Runs the grading function on a submission, returning the score rounded to 5 decimal places.
|
|
42
|
+
"""
|
|
43
|
+
try:
|
|
44
|
+
score = self.grade_fn(submission, answers)
|
|
45
|
+
except InvalidSubmissionError as e:
|
|
46
|
+
logger.warning(f"Invalid submission: {e}")
|
|
47
|
+
return None
|
|
48
|
+
except Exception as e:
|
|
49
|
+
try:
|
|
50
|
+
fpath = inspect.getfile(self.grade_fn)
|
|
51
|
+
line_number = inspect.getsourcelines(self.grade_fn)[1]
|
|
52
|
+
fn_info = f"{fpath}:{line_number}"
|
|
53
|
+
except TypeError:
|
|
54
|
+
fn_info = str(self.grade_fn)
|
|
55
|
+
logger.error(f"Unexpected error during grading: {e}. Check {fn_info}")
|
|
56
|
+
return None
|
|
57
|
+
rounded_score = round(score, 5)
|
|
58
|
+
return rounded_score
|
|
59
|
+
|
|
60
|
+
def rank_score(self, score: Optional[float], leaderboard: pd.DataFrame) -> dict:
|
|
61
|
+
"""
|
|
62
|
+
Ranks a score based on the leaderboard.
|
|
63
|
+
Returns a dictionary of bools with the following keys:
|
|
64
|
+
- gold_medal: bool
|
|
65
|
+
- silver_medal: bool
|
|
66
|
+
- bronze_medal: bool
|
|
67
|
+
- above_median: bool
|
|
68
|
+
- gold_threshold: float
|
|
69
|
+
- silver_threshold: float
|
|
70
|
+
- bronze_threshold: float
|
|
71
|
+
- median_threshold: float
|
|
72
|
+
"""
|
|
73
|
+
assert "score" in leaderboard.columns, "Leaderboard must have a `score` column."
|
|
74
|
+
|
|
75
|
+
lower_is_better = self.is_lower_better(leaderboard)
|
|
76
|
+
|
|
77
|
+
num_teams = len(leaderboard)
|
|
78
|
+
scores = leaderboard["score"]
|
|
79
|
+
|
|
80
|
+
def get_score_at_position(position: int) -> float:
|
|
81
|
+
"""
|
|
82
|
+
Returns the score at the given position in the leaderboard.
|
|
83
|
+
Raises an IndexError if the position is out of bounds.
|
|
84
|
+
"""
|
|
85
|
+
if position - 1 >= len(scores) or position < 1:
|
|
86
|
+
raise IndexError("Position out of bounds in the leaderboard.")
|
|
87
|
+
return scores.iloc[position - 1]
|
|
88
|
+
|
|
89
|
+
def get_thresholds(num_teams: int) -> tuple[float, float, float, float]:
|
|
90
|
+
"""
|
|
91
|
+
Returns the thresholds for medals based on kaggle.com/progression
|
|
92
|
+
Returns a tuple of thresholds in the order of gold, silver, bronze, median
|
|
93
|
+
"""
|
|
94
|
+
if 1 <= num_teams < 100:
|
|
95
|
+
gold_threshold = get_score_at_position(max(1, int(num_teams * 0.1)))
|
|
96
|
+
silver_threshold = get_score_at_position(max(1, int(num_teams * 0.2)))
|
|
97
|
+
bronze_threshold = get_score_at_position(max(1, int(num_teams * 0.4)))
|
|
98
|
+
elif 100 <= num_teams < 250:
|
|
99
|
+
gold_threshold = get_score_at_position(10)
|
|
100
|
+
silver_threshold = get_score_at_position(max(1, int(num_teams * 0.2)))
|
|
101
|
+
bronze_threshold = get_score_at_position(max(1, int(num_teams * 0.4)))
|
|
102
|
+
elif 250 <= num_teams < 1000:
|
|
103
|
+
gold_threshold = get_score_at_position(10 + int(num_teams * 0.002))
|
|
104
|
+
silver_threshold = get_score_at_position(50)
|
|
105
|
+
bronze_threshold = get_score_at_position(100)
|
|
106
|
+
elif num_teams >= 1000:
|
|
107
|
+
gold_threshold = get_score_at_position(10 + int(num_teams * 0.002))
|
|
108
|
+
silver_threshold = get_score_at_position(max(1, int(num_teams * 0.05)))
|
|
109
|
+
bronze_threshold = get_score_at_position(max(1, int(num_teams * 0.1)))
|
|
110
|
+
else:
|
|
111
|
+
raise ValueError("Number of teams in leaderboard must be greater than 0.")
|
|
112
|
+
|
|
113
|
+
median_threshold = scores.median()
|
|
114
|
+
|
|
115
|
+
return (
|
|
116
|
+
float(gold_threshold),
|
|
117
|
+
float(silver_threshold),
|
|
118
|
+
float(bronze_threshold),
|
|
119
|
+
float(median_threshold),
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
gold_threshold, silver_threshold, bronze_threshold, median_threshold = get_thresholds(
|
|
123
|
+
num_teams
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
if score is None:
|
|
127
|
+
return {
|
|
128
|
+
"gold_medal": False,
|
|
129
|
+
"silver_medal": False,
|
|
130
|
+
"bronze_medal": False,
|
|
131
|
+
"above_median": False,
|
|
132
|
+
"gold_threshold": gold_threshold,
|
|
133
|
+
"silver_threshold": silver_threshold,
|
|
134
|
+
"bronze_threshold": bronze_threshold,
|
|
135
|
+
"median_threshold": median_threshold,
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
assert isinstance(
|
|
139
|
+
score, (float, int)
|
|
140
|
+
), f"Expected `score` to be a `float` or `int` but got a {type(score)}."
|
|
141
|
+
|
|
142
|
+
gold_medal = score <= gold_threshold if lower_is_better else score >= gold_threshold
|
|
143
|
+
silver_medal = not gold_medal and (
|
|
144
|
+
score <= silver_threshold if lower_is_better else score >= silver_threshold
|
|
145
|
+
)
|
|
146
|
+
bronze_medal = (
|
|
147
|
+
not gold_medal
|
|
148
|
+
and not silver_medal
|
|
149
|
+
and (score <= bronze_threshold if lower_is_better else score >= bronze_threshold)
|
|
150
|
+
)
|
|
151
|
+
above_median = score < median_threshold if lower_is_better else score > median_threshold
|
|
152
|
+
|
|
153
|
+
return {
|
|
154
|
+
"gold_medal": gold_medal,
|
|
155
|
+
"silver_medal": silver_medal,
|
|
156
|
+
"bronze_medal": bronze_medal,
|
|
157
|
+
"above_median": above_median,
|
|
158
|
+
"gold_threshold": gold_threshold,
|
|
159
|
+
"silver_threshold": silver_threshold,
|
|
160
|
+
"bronze_threshold": bronze_threshold,
|
|
161
|
+
"median_threshold": median_threshold,
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
@dataclass(frozen=True)
|
|
166
|
+
class CompetitionReport:
|
|
167
|
+
competition_id: str
|
|
168
|
+
score: Optional[float] # Changed from float | None to Optional[float]
|
|
169
|
+
gold_threshold: float
|
|
170
|
+
silver_threshold: float
|
|
171
|
+
bronze_threshold: float
|
|
172
|
+
median_threshold: float
|
|
173
|
+
any_medal: bool
|
|
174
|
+
gold_medal: bool
|
|
175
|
+
silver_medal: bool
|
|
176
|
+
bronze_medal: bool
|
|
177
|
+
above_median: bool
|
|
178
|
+
submission_exists: bool
|
|
179
|
+
valid_submission: bool
|
|
180
|
+
is_lower_better: bool
|
|
181
|
+
created_at: datetime
|
|
182
|
+
submission_path: str
|
|
183
|
+
|
|
184
|
+
def to_dict(self) -> dict:
|
|
185
|
+
# Convert all values to JSON-compatible types explicitly
|
|
186
|
+
return {
|
|
187
|
+
"competition_id": self.competition_id,
|
|
188
|
+
"score": float(self.score) if self.score is not None else None,
|
|
189
|
+
"gold_threshold": float(self.gold_threshold),
|
|
190
|
+
"silver_threshold": float(self.silver_threshold),
|
|
191
|
+
"bronze_threshold": float(self.bronze_threshold),
|
|
192
|
+
"median_threshold": float(self.median_threshold),
|
|
193
|
+
"any_medal": bool(self.any_medal),
|
|
194
|
+
"gold_medal": bool(self.gold_medal),
|
|
195
|
+
"silver_medal": bool(self.silver_medal),
|
|
196
|
+
"bronze_medal": bool(self.bronze_medal),
|
|
197
|
+
"above_median": bool(self.above_median),
|
|
198
|
+
"submission_exists": bool(self.submission_exists),
|
|
199
|
+
"valid_submission": bool(self.valid_submission),
|
|
200
|
+
"is_lower_better": bool(self.is_lower_better),
|
|
201
|
+
"created_at": self.created_at.isoformat(), # Serialize datetime
|
|
202
|
+
"submission_path": self.submission_path,
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
@classmethod
|
|
206
|
+
def from_dict(cls, data: dict) -> "CompetitionReport":
|
|
207
|
+
data = data.copy() # Avoid accidentally mutating the original dictionary
|
|
208
|
+
typed_data = {
|
|
209
|
+
"competition_id": data["competition_id"],
|
|
210
|
+
"score": float(data["score"]) if data["score"] is not None else None,
|
|
211
|
+
"gold_threshold": float(data["gold_threshold"]),
|
|
212
|
+
"silver_threshold": float(data["silver_threshold"]),
|
|
213
|
+
"bronze_threshold": float(data["bronze_threshold"]),
|
|
214
|
+
"median_threshold": float(data["median_threshold"]),
|
|
215
|
+
"any_medal": bool(data["any_medal"]),
|
|
216
|
+
"gold_medal": bool(data["gold_medal"]),
|
|
217
|
+
"silver_medal": bool(data["silver_medal"]),
|
|
218
|
+
"bronze_medal": bool(data["bronze_medal"]),
|
|
219
|
+
"above_median": bool(data["above_median"]),
|
|
220
|
+
"submission_exists": bool(data["submission_exists"]),
|
|
221
|
+
"valid_submission": bool(data["valid_submission"]),
|
|
222
|
+
"is_lower_better": bool(data["is_lower_better"]),
|
|
223
|
+
"created_at": datetime.fromisoformat(data["created_at"]),
|
|
224
|
+
"submission_path": data["submission_path"],
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
return cls(**typed_data)
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
class InvalidSubmissionError(Exception):
|
|
231
|
+
"""
|
|
232
|
+
A custom exception for when the agent submission cannot be graded.
|
|
233
|
+
"""
|
|
234
|
+
|
|
235
|
+
pass
|
mlebench/metrics.py
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def average_precision_at_k(actual: set, predicted: list, k: int):
|
|
5
|
+
"""
|
|
6
|
+
Computes the average precision at k (AP@k).
|
|
7
|
+
|
|
8
|
+
This function computes the average precision at k between a predicted ranking and a ground truth
|
|
9
|
+
set.
|
|
10
|
+
|
|
11
|
+
Args:
|
|
12
|
+
actual : A set of elements that are to be predicted (order doesn't matter)
|
|
13
|
+
predicted : A list of predicted elements (order does matter, most relevant go first)
|
|
14
|
+
k : The maximum number of predicted elements
|
|
15
|
+
|
|
16
|
+
Adapted from: https://github.com/benhamner/Metrics/blob/master/Python/ml_metrics/average_precision.py
|
|
17
|
+
"""
|
|
18
|
+
if len(predicted) > k:
|
|
19
|
+
predicted = predicted[:k]
|
|
20
|
+
|
|
21
|
+
score = 0.0
|
|
22
|
+
num_hits = 0.0
|
|
23
|
+
|
|
24
|
+
for i, p in enumerate(predicted):
|
|
25
|
+
if p in actual and p not in predicted[:i]:
|
|
26
|
+
num_hits += 1.0
|
|
27
|
+
score += num_hits / (i + 1.0)
|
|
28
|
+
|
|
29
|
+
if not actual:
|
|
30
|
+
return 0.0
|
|
31
|
+
|
|
32
|
+
return score / min(len(actual), k)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def mean_average_precision_at_k(actual: list[set], predicted: list[list], k: int):
|
|
36
|
+
"""
|
|
37
|
+
Computes the MAP@k
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
actual : a list of sets of the elements that are to be predicted (order doesn't matter)
|
|
41
|
+
predicted : a list of lists of predicted elements (order does matter, most relevant go first)
|
|
42
|
+
k : The maximum number of predicted elements
|
|
43
|
+
"""
|
|
44
|
+
return np.mean([average_precision_at_k(a, p, k) for a, p, in zip(actual, predicted)])
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def dice_coefficient(
|
|
48
|
+
predicted_mask: np.ndarray, true_mask: np.ndarray, both_empty_value: float = np.nan
|
|
49
|
+
) -> float:
|
|
50
|
+
"""
|
|
51
|
+
Computes the Dice coefficient between two binary masks (can be multi-dimensional)
|
|
52
|
+
|
|
53
|
+
Args:
|
|
54
|
+
predicted_mask: A binary numpy array indicating where the segmentation is predicted
|
|
55
|
+
true_mask: A binary numpy array indicating where the segmentation is
|
|
56
|
+
both_empty_value: The value to return when both masks are empty
|
|
57
|
+
"""
|
|
58
|
+
assert (
|
|
59
|
+
predicted_mask.shape == true_mask.shape
|
|
60
|
+
), f"Predicted mask shape {predicted_mask.shape} does not match true mask shape {true_mask.shape}"
|
|
61
|
+
# Check if both masks are empty
|
|
62
|
+
if np.sum(predicted_mask) == 0 and np.sum(true_mask) == 0:
|
|
63
|
+
return both_empty_value
|
|
64
|
+
|
|
65
|
+
# Calculate intersection and union
|
|
66
|
+
intersection = np.sum(predicted_mask * true_mask)
|
|
67
|
+
union = np.sum(predicted_mask) + np.sum(true_mask)
|
|
68
|
+
|
|
69
|
+
if union == 0:
|
|
70
|
+
return both_empty_value
|
|
71
|
+
|
|
72
|
+
# Calculate Dice coefficient
|
|
73
|
+
dice_coeff = 2 * intersection / union
|
|
74
|
+
|
|
75
|
+
return dice_coeff
|
mlebench/registry.py
ADDED
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
import importlib
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from typing import Callable
|
|
5
|
+
|
|
6
|
+
from appdirs import user_cache_dir
|
|
7
|
+
|
|
8
|
+
from mlebench.grade_helpers import Grader
|
|
9
|
+
from mlebench.utils import get_logger, get_module_dir, get_repo_dir, import_fn, load_yaml
|
|
10
|
+
|
|
11
|
+
logger = get_logger(__name__)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
DEFAULT_DATA_DIR = (Path(user_cache_dir()) / "mle-bench" / "data").resolve()
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@dataclass(frozen=True)
|
|
18
|
+
class Competition:
|
|
19
|
+
id: str
|
|
20
|
+
name: str
|
|
21
|
+
description: str
|
|
22
|
+
grader: Grader
|
|
23
|
+
answers: Path
|
|
24
|
+
gold_submission: Path
|
|
25
|
+
sample_submission: Path
|
|
26
|
+
competition_type: str
|
|
27
|
+
prepare_fn: Callable[[Path, Path, Path], Path]
|
|
28
|
+
raw_dir: Path
|
|
29
|
+
private_dir: Path
|
|
30
|
+
public_dir: Path
|
|
31
|
+
checksums: Path
|
|
32
|
+
leaderboard: Path
|
|
33
|
+
|
|
34
|
+
def __post_init__(self):
|
|
35
|
+
assert isinstance(self.id, str), "Competition id must be a string."
|
|
36
|
+
assert isinstance(self.name, str), "Competition name must be a string."
|
|
37
|
+
assert isinstance(self.description, str), "Competition description must be a string."
|
|
38
|
+
assert isinstance(self.grader, Grader), "Competition grader must be of type Grader."
|
|
39
|
+
assert isinstance(self.answers, Path), "Competition answers must be a Path."
|
|
40
|
+
assert isinstance(self.gold_submission, Path), "Gold submission must be a Path."
|
|
41
|
+
assert isinstance(self.sample_submission, Path), "Sample submission must be a Path."
|
|
42
|
+
assert isinstance(self.competition_type, str), "Competition type must be a string."
|
|
43
|
+
assert isinstance(self.checksums, Path), "Checksums must be a Path."
|
|
44
|
+
assert isinstance(self.leaderboard, Path), "Leaderboard must be a Path."
|
|
45
|
+
assert len(self.id) > 0, "Competition id cannot be empty."
|
|
46
|
+
assert len(self.name) > 0, "Competition name cannot be empty."
|
|
47
|
+
assert len(self.description) > 0, "Competition description cannot be empty."
|
|
48
|
+
assert len(self.competition_type) > 0, "Competition type cannot be empty."
|
|
49
|
+
|
|
50
|
+
@staticmethod
|
|
51
|
+
def from_dict(data: dict) -> "Competition":
|
|
52
|
+
grader = Grader.from_dict(data["grader"])
|
|
53
|
+
|
|
54
|
+
try:
|
|
55
|
+
return Competition(
|
|
56
|
+
id=data["id"],
|
|
57
|
+
name=data["name"],
|
|
58
|
+
description=data["description"],
|
|
59
|
+
grader=grader,
|
|
60
|
+
answers=data["answers"],
|
|
61
|
+
sample_submission=data["sample_submission"],
|
|
62
|
+
gold_submission=data["gold_submission"],
|
|
63
|
+
competition_type=data["competition_type"],
|
|
64
|
+
prepare_fn=data["prepare_fn"],
|
|
65
|
+
raw_dir=data["raw_dir"],
|
|
66
|
+
public_dir=data["public_dir"],
|
|
67
|
+
private_dir=data["private_dir"],
|
|
68
|
+
checksums=data["checksums"],
|
|
69
|
+
leaderboard=data["leaderboard"],
|
|
70
|
+
)
|
|
71
|
+
except KeyError as e:
|
|
72
|
+
raise ValueError(f"Missing key {e} in competition config!")
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
class Registry:
|
|
76
|
+
def __init__(self, data_dir: Path = DEFAULT_DATA_DIR, registry_dir: Path = None):
|
|
77
|
+
self._data_dir = data_dir.resolve()
|
|
78
|
+
self._custom_registry_dir = registry_dir.resolve() if registry_dir else None
|
|
79
|
+
self.mode = 'test'
|
|
80
|
+
|
|
81
|
+
def _coerce_file_import(
|
|
82
|
+
self, fn_import_string: str, root_dir: Path, competition_id: str
|
|
83
|
+
) -> str:
|
|
84
|
+
if fn_import_string.startswith("file:"):
|
|
85
|
+
return fn_import_string
|
|
86
|
+
|
|
87
|
+
module_name, fn_name = fn_import_string.split(":")
|
|
88
|
+
try:
|
|
89
|
+
importlib.import_module(module_name)
|
|
90
|
+
return fn_import_string
|
|
91
|
+
except ModuleNotFoundError as exc:
|
|
92
|
+
if exc.name != module_name and not module_name.startswith(f"{exc.name}."):
|
|
93
|
+
raise
|
|
94
|
+
|
|
95
|
+
leaf = module_name.split(".")[-1]
|
|
96
|
+
file_module = root_dir / competition_id / f"{leaf}.py"
|
|
97
|
+
if not file_module.exists() and leaf.endswith("_val"):
|
|
98
|
+
fallback = root_dir / competition_id / f"{leaf[:-4]}.py"
|
|
99
|
+
if fallback.exists():
|
|
100
|
+
file_module = fallback
|
|
101
|
+
|
|
102
|
+
if not file_module.exists():
|
|
103
|
+
raise
|
|
104
|
+
|
|
105
|
+
return f"file:{file_module}:{fn_name}"
|
|
106
|
+
|
|
107
|
+
def _resolve_competition_root(self, competition_id: str) -> Path:
|
|
108
|
+
"""
|
|
109
|
+
Resolve where a competition config lives.
|
|
110
|
+
- Prefer custom registry_dir if provided by user.
|
|
111
|
+
- Prefer top-level `dabench/` for DABench-prefixed tasks.
|
|
112
|
+
- Check `data_dir` for user-uploaded tasks.
|
|
113
|
+
- Fallback to legacy `mlebench/competitions/` for everything else.
|
|
114
|
+
"""
|
|
115
|
+
# Priority 1: Use custom registry_dir if provided
|
|
116
|
+
if self._custom_registry_dir:
|
|
117
|
+
if (self._custom_registry_dir / competition_id / "config.yaml").exists():
|
|
118
|
+
return self._custom_registry_dir
|
|
119
|
+
# If custom registry_dir doesn't have config, still try to use it
|
|
120
|
+
# (user might have custom structure)
|
|
121
|
+
return self._custom_registry_dir
|
|
122
|
+
|
|
123
|
+
# Priority 2: DABench tasks
|
|
124
|
+
repo_dir = get_repo_dir()
|
|
125
|
+
dabench_root = repo_dir / "benchmarks" / "dabench" / "competitions"
|
|
126
|
+
if competition_id.startswith("dabench-") and (dabench_root / competition_id).exists():
|
|
127
|
+
return dabench_root
|
|
128
|
+
|
|
129
|
+
# Priority 3: Check if the competition is in the data directory (user uploaded)
|
|
130
|
+
if (self._data_dir / competition_id / "config.yaml").exists():
|
|
131
|
+
return self._data_dir
|
|
132
|
+
|
|
133
|
+
if (legacy_root / competition_id).exists():
|
|
134
|
+
return legacy_root
|
|
135
|
+
if (dabench_root / competition_id).exists():
|
|
136
|
+
return dabench_root
|
|
137
|
+
return legacy_root
|
|
138
|
+
|
|
139
|
+
def set_mode(self, mode: str = 'test'):
|
|
140
|
+
"""Set the mode of the registry.
|
|
141
|
+
Args:
|
|
142
|
+
mode: The mode of the registry. Can be 'test' or 'validation'.
|
|
143
|
+
"""
|
|
144
|
+
assert mode in ['test', 'validation', 'prepare'], "Mode must be in ['test', 'validation', 'prepare']."
|
|
145
|
+
self.mode = mode
|
|
146
|
+
|
|
147
|
+
def get_competition(self, competition_id: str) -> Competition:
|
|
148
|
+
"""Fetch the competition from the registry."""
|
|
149
|
+
|
|
150
|
+
root_dir = self._resolve_competition_root(competition_id)
|
|
151
|
+
is_dabench = root_dir.name == "competitions" and root_dir.parent.name == "dabench"
|
|
152
|
+
|
|
153
|
+
config_path = root_dir / competition_id / "config.yaml"
|
|
154
|
+
config = load_yaml(config_path)
|
|
155
|
+
|
|
156
|
+
checksums_path = root_dir / competition_id / "checksums.yaml"
|
|
157
|
+
leaderboard_path = root_dir / competition_id / "leaderboard.csv"
|
|
158
|
+
|
|
159
|
+
# Resolve description file. DABench configs may still point to legacy paths.
|
|
160
|
+
if root_dir.name == "competitions" and root_dir.parent.name == "dabench":
|
|
161
|
+
description_path = root_dir / competition_id / "description.md"
|
|
162
|
+
else:
|
|
163
|
+
# Try to find description relative to competition dir first
|
|
164
|
+
candidate_desc = root_dir / competition_id / config["description"]
|
|
165
|
+
if candidate_desc.exists():
|
|
166
|
+
description_path = candidate_desc
|
|
167
|
+
else:
|
|
168
|
+
description_path = get_repo_dir() / config["description"]
|
|
169
|
+
if not description_path.exists() and config["description"].startswith("mlebench/"):
|
|
170
|
+
description_path = get_repo_dir() / "benchmarks" / config["description"]
|
|
171
|
+
description = description_path.read_text()
|
|
172
|
+
|
|
173
|
+
# Config for different modes
|
|
174
|
+
base_preparer = config["preparer"]
|
|
175
|
+
base_answers = config["dataset"]["answers"]
|
|
176
|
+
base_sample_submission = config["dataset"]["sample_submission"]
|
|
177
|
+
|
|
178
|
+
config_preparer = base_preparer
|
|
179
|
+
config_answers = base_answers
|
|
180
|
+
config_sample_submission = base_sample_submission
|
|
181
|
+
public_folder = 'public'
|
|
182
|
+
private_folder = 'private'
|
|
183
|
+
|
|
184
|
+
if is_dabench:
|
|
185
|
+
# DABench evaluation should NOT depend on any prepare logic; always use the
|
|
186
|
+
# existing prepared/public + prepared/private folders.
|
|
187
|
+
config_preparer = base_preparer
|
|
188
|
+
config_answers = base_answers
|
|
189
|
+
config_sample_submission = base_sample_submission
|
|
190
|
+
public_folder = "public"
|
|
191
|
+
private_folder = "private"
|
|
192
|
+
else:
|
|
193
|
+
if self.mode == 'prepare':
|
|
194
|
+
config_preparer = config_preparer.replace('prepare:', 'prepare_val:')
|
|
195
|
+
|
|
196
|
+
elif self.mode == 'validation':
|
|
197
|
+
config_preparer = config_preparer.replace('prepare:', 'prepare_val:')
|
|
198
|
+
config_answers = config_answers.replace('/private/', '/private_val/')
|
|
199
|
+
config_sample_submission = config_sample_submission.replace('/public/', '/public_val/')
|
|
200
|
+
public_folder = 'public_val'
|
|
201
|
+
private_folder = 'private_val'
|
|
202
|
+
|
|
203
|
+
# Some benchmarks may not provide *_val splits; if missing, fall back to test artifacts.
|
|
204
|
+
if self.mode == "validation":
|
|
205
|
+
data_dir = self.get_data_dir()
|
|
206
|
+
answers_candidate = data_dir / config_answers
|
|
207
|
+
sample_candidate = data_dir / config_sample_submission
|
|
208
|
+
public_candidate = data_dir / competition_id / "prepared" / public_folder
|
|
209
|
+
private_candidate = data_dir / competition_id / "prepared" / private_folder
|
|
210
|
+
if not (
|
|
211
|
+
answers_candidate.exists()
|
|
212
|
+
and sample_candidate.exists()
|
|
213
|
+
and public_candidate.exists()
|
|
214
|
+
and private_candidate.exists()
|
|
215
|
+
):
|
|
216
|
+
config_preparer = base_preparer
|
|
217
|
+
config_answers = base_answers
|
|
218
|
+
config_sample_submission = base_sample_submission
|
|
219
|
+
public_folder = "public"
|
|
220
|
+
private_folder = "private"
|
|
221
|
+
|
|
222
|
+
# DABench competitions are not importable as Python packages (hyphenated ids).
|
|
223
|
+
# Convert legacy import strings to file-based imports under the resolved root_dir.
|
|
224
|
+
if is_dabench:
|
|
225
|
+
module_str, fn_name = config_preparer.split(":")
|
|
226
|
+
leaf = module_str.split(".")[-1] # prepare or grade
|
|
227
|
+
file_module = root_dir / competition_id / f"{leaf}.py"
|
|
228
|
+
if not file_module.exists() and leaf.endswith("_val"):
|
|
229
|
+
fallback = root_dir / competition_id / f"{leaf[:-4]}.py"
|
|
230
|
+
if fallback.exists():
|
|
231
|
+
file_module = fallback
|
|
232
|
+
config_preparer = f"file:{file_module}:{fn_name}"
|
|
233
|
+
if "grader" in config and "grade_fn" in config["grader"]:
|
|
234
|
+
g_module_str, g_fn_name = config["grader"]["grade_fn"].split(":")
|
|
235
|
+
g_leaf = g_module_str.split(".")[-1]
|
|
236
|
+
g_file_module = root_dir / competition_id / f"{g_leaf}.py"
|
|
237
|
+
if not g_file_module.exists() and g_leaf.endswith("_val"):
|
|
238
|
+
g_fallback = root_dir / competition_id / f"{g_leaf[:-4]}.py"
|
|
239
|
+
if g_fallback.exists():
|
|
240
|
+
g_file_module = g_fallback
|
|
241
|
+
config["grader"]["grade_fn"] = f"file:{g_file_module}:{g_fn_name}"
|
|
242
|
+
else:
|
|
243
|
+
config_preparer = self._coerce_file_import(
|
|
244
|
+
config_preparer, root_dir, competition_id
|
|
245
|
+
)
|
|
246
|
+
if "grader" in config and "grade_fn" in config["grader"]:
|
|
247
|
+
config["grader"]["grade_fn"] = self._coerce_file_import(
|
|
248
|
+
config["grader"]["grade_fn"], root_dir, competition_id
|
|
249
|
+
)
|
|
250
|
+
|
|
251
|
+
if is_dabench:
|
|
252
|
+
def preparer_fn(raw: Path, public: Path, private: Path) -> Path:
|
|
253
|
+
logger.info(
|
|
254
|
+
"DABench prepare disabled; using existing prepared/public + prepared/private."
|
|
255
|
+
)
|
|
256
|
+
return public
|
|
257
|
+
else:
|
|
258
|
+
preparer_fn = import_fn(config_preparer)
|
|
259
|
+
|
|
260
|
+
answers = self.get_data_dir() / config_answers
|
|
261
|
+
gold_submission = answers
|
|
262
|
+
if "gold_submission" in config["dataset"]:
|
|
263
|
+
gold_submission = self.get_data_dir() / config["dataset"]["gold_submission"]
|
|
264
|
+
sample_submission = self.get_data_dir() / config_sample_submission
|
|
265
|
+
|
|
266
|
+
raw_dir = self.get_data_dir() / competition_id / "raw"
|
|
267
|
+
private_dir = self.get_data_dir() / competition_id / "prepared" / private_folder
|
|
268
|
+
public_dir = self.get_data_dir() / competition_id / "prepared" / public_folder
|
|
269
|
+
|
|
270
|
+
return Competition.from_dict(
|
|
271
|
+
{
|
|
272
|
+
**config,
|
|
273
|
+
"description": description,
|
|
274
|
+
"answers": answers,
|
|
275
|
+
"sample_submission": sample_submission,
|
|
276
|
+
"gold_submission": gold_submission,
|
|
277
|
+
"prepare_fn": preparer_fn,
|
|
278
|
+
"raw_dir": raw_dir,
|
|
279
|
+
"private_dir": private_dir,
|
|
280
|
+
"public_dir": public_dir,
|
|
281
|
+
"checksums": checksums_path,
|
|
282
|
+
"leaderboard": leaderboard_path,
|
|
283
|
+
}
|
|
284
|
+
)
|
|
285
|
+
|
|
286
|
+
def get_competitions_dir(self) -> Path:
|
|
287
|
+
"""Retrieves the competition directory within the registry."""
|
|
288
|
+
|
|
289
|
+
return get_module_dir() / "competitions"
|
|
290
|
+
|
|
291
|
+
def get_splits_dir(self) -> Path:
|
|
292
|
+
"""Retrieves the splits directory within the repository."""
|
|
293
|
+
|
|
294
|
+
return get_repo_dir() / "experiments" / "splits"
|
|
295
|
+
|
|
296
|
+
def get_lite_competition_ids(self) -> list[str]:
|
|
297
|
+
"""List all competition IDs for the lite version (low complexity competitions)."""
|
|
298
|
+
|
|
299
|
+
lite_competitions_file = self.get_splits_dir() / "low.txt"
|
|
300
|
+
with open(lite_competitions_file, "r") as f:
|
|
301
|
+
competition_ids = f.read().splitlines()
|
|
302
|
+
return competition_ids
|
|
303
|
+
|
|
304
|
+
def get_data_dir(self) -> Path:
|
|
305
|
+
"""Retrieves the data directory within the registry."""
|
|
306
|
+
|
|
307
|
+
return self._data_dir
|
|
308
|
+
|
|
309
|
+
def set_data_dir(self, new_data_dir: Path) -> "Registry":
|
|
310
|
+
"""Sets the data directory within the registry."""
|
|
311
|
+
|
|
312
|
+
return Registry(new_data_dir)
|
|
313
|
+
|
|
314
|
+
def list_competition_ids(self) -> list[str]:
|
|
315
|
+
"""List all competition IDs available in the registry, sorted alphabetically."""
|
|
316
|
+
|
|
317
|
+
repo_dir = get_repo_dir()
|
|
318
|
+
dabench_root = repo_dir / "dabench" / "competitions"
|
|
319
|
+
|
|
320
|
+
search_roots = [repo_dir / "benchmarks" / "mlebench" / "competitions"]
|
|
321
|
+
if dabench_root.exists():
|
|
322
|
+
search_roots.append(dabench_root)
|
|
323
|
+
|
|
324
|
+
competition_ids: set[str] = set()
|
|
325
|
+
for root in search_roots:
|
|
326
|
+
for cfg in root.rglob("config.yaml"):
|
|
327
|
+
competition_ids.add(cfg.parent.stem)
|
|
328
|
+
|
|
329
|
+
return sorted(competition_ids)
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
registry = Registry()
|