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
mlebench/data.py
ADDED
|
@@ -0,0 +1,420 @@
|
|
|
1
|
+
import functools
|
|
2
|
+
import hashlib
|
|
3
|
+
import inspect
|
|
4
|
+
import os
|
|
5
|
+
import shutil
|
|
6
|
+
import webbrowser
|
|
7
|
+
from datetime import datetime
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from typing import Any, Callable, Optional
|
|
10
|
+
|
|
11
|
+
import diskcache as dc
|
|
12
|
+
import pandas as pd
|
|
13
|
+
import yaml
|
|
14
|
+
from tenacity import retry, retry_if_exception, stop_after_attempt, wait_fixed
|
|
15
|
+
from tqdm.auto import tqdm
|
|
16
|
+
|
|
17
|
+
from mlebench.registry import Competition
|
|
18
|
+
from mlebench.utils import (
|
|
19
|
+
authenticate_kaggle_api,
|
|
20
|
+
extract,
|
|
21
|
+
get_diff,
|
|
22
|
+
get_logger,
|
|
23
|
+
get_path_to_callable,
|
|
24
|
+
is_empty,
|
|
25
|
+
load_yaml,
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
logger = get_logger(__name__)
|
|
29
|
+
#cache = dc.Cache("cache", size_limit=2**26) # 64 MB
|
|
30
|
+
# 修改为
|
|
31
|
+
import tempfile
|
|
32
|
+
cache_dir = os.path.join(tempfile.gettempdir(), f"mlebench_cache_{os.getpid()}")
|
|
33
|
+
cache = dc.Cache(cache_dir, size_limit=2**26) # 64 MB
|
|
34
|
+
|
|
35
|
+
def create_prepared_dir(competition: Competition) -> None:
|
|
36
|
+
competition.public_dir.mkdir(exist_ok=True, parents=True)
|
|
37
|
+
competition.private_dir.mkdir(exist_ok=True, parents=True)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def download_and_prepare_dataset(
|
|
41
|
+
competition: Competition,
|
|
42
|
+
keep_raw: bool = True,
|
|
43
|
+
overwrite_checksums: bool = False,
|
|
44
|
+
overwrite_leaderboard: bool = False,
|
|
45
|
+
skip_verification: bool = False,
|
|
46
|
+
) -> None:
|
|
47
|
+
"""
|
|
48
|
+
Creates a `public` and `private` directory for the competition using the `prepare_fn`,
|
|
49
|
+
downloading the competition's dataset zip file and extracting it into `raw` if needed.
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
assert is_valid_prepare_fn(
|
|
53
|
+
competition.prepare_fn
|
|
54
|
+
), f"Provided `prepare_fn` doesn't take arguments `raw`, `private` and `public`!"
|
|
55
|
+
|
|
56
|
+
ensure_leaderboard_exists(competition, force=overwrite_leaderboard)
|
|
57
|
+
|
|
58
|
+
competition_dir = competition.raw_dir.parent
|
|
59
|
+
|
|
60
|
+
competition.raw_dir.mkdir(exist_ok=True, parents=True)
|
|
61
|
+
create_prepared_dir(competition)
|
|
62
|
+
|
|
63
|
+
zipfile = download_dataset(
|
|
64
|
+
competition_id=competition.id,
|
|
65
|
+
download_dir=competition_dir,
|
|
66
|
+
force=False,
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
if overwrite_checksums or not skip_verification:
|
|
70
|
+
logger.info(f"Generating checksum for `{zipfile}`...")
|
|
71
|
+
actual_zip_checksum = get_checksum(zipfile)
|
|
72
|
+
|
|
73
|
+
if competition.checksums.is_file() and not overwrite_checksums:
|
|
74
|
+
expected_checksums = load_yaml(competition.checksums)
|
|
75
|
+
expected_zip_checksum = expected_checksums["zip"]
|
|
76
|
+
|
|
77
|
+
if actual_zip_checksum != expected_zip_checksum:
|
|
78
|
+
raise ValueError(
|
|
79
|
+
f"Checksum for `{zipfile}` does not match the expected checksum! "
|
|
80
|
+
f"Expected `{expected_zip_checksum}` but got `{actual_zip_checksum}`."
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
logger.info(f"Checksum for `{zipfile}` matches the expected checksum.")
|
|
84
|
+
|
|
85
|
+
if is_empty(competition.raw_dir):
|
|
86
|
+
logger.info(f"Extracting `{zipfile}` to `{competition.raw_dir}`...")
|
|
87
|
+
extract(zipfile, competition.raw_dir, recursive=False)
|
|
88
|
+
logger.info(f"Extracted `{zipfile}` to `{competition.raw_dir}` successfully.")
|
|
89
|
+
|
|
90
|
+
if not is_dataset_prepared(competition) or overwrite_checksums:
|
|
91
|
+
if competition.public_dir.parent.exists() and overwrite_checksums:
|
|
92
|
+
logger.info(
|
|
93
|
+
f"Removing the existing prepared data directory for `{competition.id}` since "
|
|
94
|
+
"`overwrite_checksums` is set to `True`..."
|
|
95
|
+
)
|
|
96
|
+
shutil.rmtree(competition.public_dir.parent)
|
|
97
|
+
create_prepared_dir(competition)
|
|
98
|
+
|
|
99
|
+
logger.info(
|
|
100
|
+
f"Preparing the dataset using `{competition.prepare_fn.__name__}` from "
|
|
101
|
+
f"`{get_path_to_callable(competition.prepare_fn)}`..."
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
competition.prepare_fn(
|
|
105
|
+
raw=competition.raw_dir,
|
|
106
|
+
public=competition.public_dir,
|
|
107
|
+
private=competition.private_dir,
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
logger.info(f"Data for competition `{competition.id}` prepared successfully.")
|
|
111
|
+
|
|
112
|
+
with open(competition.public_dir / "description.md", "w") as f:
|
|
113
|
+
f.write(competition.description)
|
|
114
|
+
|
|
115
|
+
# Also save to public_val directory
|
|
116
|
+
public_val_dir = competition.public_dir.parent / (competition.public_dir.name + "_val")
|
|
117
|
+
if public_val_dir.exists():
|
|
118
|
+
with open(public_val_dir / "description.md", "w") as f:
|
|
119
|
+
f.write(competition.description)
|
|
120
|
+
|
|
121
|
+
if overwrite_checksums or not skip_verification:
|
|
122
|
+
logger.info(f"Generating checksums for files in `{competition_dir}`...")
|
|
123
|
+
|
|
124
|
+
actual_checksums = {
|
|
125
|
+
"zip": actual_zip_checksum,
|
|
126
|
+
"public": generate_checksums(competition.public_dir),
|
|
127
|
+
"private": generate_checksums(competition.private_dir),
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if not competition.checksums.is_file() or overwrite_checksums:
|
|
131
|
+
with open(competition.checksums, "w") as file:
|
|
132
|
+
yaml.dump(actual_checksums, file, default_flow_style=False)
|
|
133
|
+
|
|
134
|
+
logger.info(f"Checksums for `{competition.id}` saved to `{competition.checksums}`.")
|
|
135
|
+
|
|
136
|
+
expected_checksums = load_yaml(competition.checksums)
|
|
137
|
+
|
|
138
|
+
if actual_checksums != expected_checksums:
|
|
139
|
+
logger.error(f"Checksums do not match for `{competition.id}`!")
|
|
140
|
+
|
|
141
|
+
diff = get_diff(
|
|
142
|
+
actual_checksums,
|
|
143
|
+
expected_checksums,
|
|
144
|
+
fromfile="actual_checksums",
|
|
145
|
+
tofile="expected_checksums",
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
raise ValueError(f"Checksums do not match for `{competition.id}`!\n{diff}")
|
|
149
|
+
|
|
150
|
+
logger.info(f"Checksums for files in `{competition_dir}` match the expected checksums.")
|
|
151
|
+
|
|
152
|
+
if not keep_raw:
|
|
153
|
+
logger.info(f"Removing the raw data directory for `{competition.id}`...")
|
|
154
|
+
shutil.rmtree(competition.raw_dir)
|
|
155
|
+
|
|
156
|
+
assert competition.public_dir.is_dir(), f"Public data directory doesn't exist."
|
|
157
|
+
assert competition.private_dir.is_dir(), f"Private data directory doesn't exist."
|
|
158
|
+
assert not is_empty(competition.public_dir), f"Public data directory is empty!"
|
|
159
|
+
assert not is_empty(competition.private_dir), f"Private data directory is empty!"
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def is_dataset_prepared(competition: Competition, grading_only: bool = False) -> bool:
|
|
163
|
+
"""Checks if the competition has non-empty `public` and `private` directories with the expected files."""
|
|
164
|
+
|
|
165
|
+
assert isinstance(
|
|
166
|
+
competition, Competition
|
|
167
|
+
), f"Expected input to be of type `Competition` but got {type(competition)}."
|
|
168
|
+
|
|
169
|
+
public = competition.public_dir
|
|
170
|
+
private = competition.private_dir
|
|
171
|
+
|
|
172
|
+
if not grading_only:
|
|
173
|
+
if not public.is_dir():
|
|
174
|
+
logger.warning("Public directory does not exist.")
|
|
175
|
+
return False
|
|
176
|
+
if is_empty(public):
|
|
177
|
+
logger.warning("Public directory is empty.")
|
|
178
|
+
return False
|
|
179
|
+
|
|
180
|
+
if not private.is_dir():
|
|
181
|
+
logger.warning("Private directory does not exist.")
|
|
182
|
+
return False
|
|
183
|
+
if is_empty(private):
|
|
184
|
+
logger.warning("Private directory is empty.")
|
|
185
|
+
return False
|
|
186
|
+
|
|
187
|
+
if not competition.answers.is_file():
|
|
188
|
+
logger.warning("Answers file does not exist.")
|
|
189
|
+
return False
|
|
190
|
+
|
|
191
|
+
if not competition.sample_submission.is_file() and not grading_only:
|
|
192
|
+
logger.warning("Sample submission file does not exist.")
|
|
193
|
+
return False
|
|
194
|
+
|
|
195
|
+
return True
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
def is_api_exception(exception: Exception) -> bool:
|
|
199
|
+
# only import when necessary; otherwise kaggle asks for API key on import
|
|
200
|
+
#from kaggle.rest import ApiException
|
|
201
|
+
try:
|
|
202
|
+
from kaggle.rest import ApiException
|
|
203
|
+
except ImportError:
|
|
204
|
+
class ApiException(Exception): pass
|
|
205
|
+
|
|
206
|
+
return isinstance(exception, ApiException)
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
@retry(
|
|
210
|
+
retry=retry_if_exception(is_api_exception),
|
|
211
|
+
stop=stop_after_attempt(3), # stop after 3 attempts
|
|
212
|
+
wait=wait_fixed(5), # wait 5 seconds between attempts
|
|
213
|
+
reraise=True,
|
|
214
|
+
)
|
|
215
|
+
def download_dataset(
|
|
216
|
+
competition_id: str,
|
|
217
|
+
download_dir: Path,
|
|
218
|
+
quiet: bool = False,
|
|
219
|
+
force: bool = False,
|
|
220
|
+
) -> Path:
|
|
221
|
+
"""Downloads the competition data as a zip file using the Kaggle API and returns the path to the zip file."""
|
|
222
|
+
|
|
223
|
+
if not download_dir.exists():
|
|
224
|
+
download_dir.mkdir(parents=True)
|
|
225
|
+
|
|
226
|
+
logger.info(f"Downloading the dataset for `{competition_id}` to `{download_dir}`...")
|
|
227
|
+
|
|
228
|
+
api = authenticate_kaggle_api()
|
|
229
|
+
|
|
230
|
+
# only import when necessary; otherwise kaggle asks for API key on import
|
|
231
|
+
from kaggle.rest import ApiException
|
|
232
|
+
|
|
233
|
+
try:
|
|
234
|
+
api.competition_download_files(
|
|
235
|
+
competition=competition_id,
|
|
236
|
+
path=download_dir,
|
|
237
|
+
quiet=quiet,
|
|
238
|
+
force=force,
|
|
239
|
+
)
|
|
240
|
+
except ApiException as e:
|
|
241
|
+
if _need_to_accept_rules(str(e)):
|
|
242
|
+
logger.warning("You must accept the competition rules before downloading the dataset.")
|
|
243
|
+
_prompt_user_to_accept_rules(competition_id)
|
|
244
|
+
download_dataset(competition_id, download_dir, quiet, force)
|
|
245
|
+
else:
|
|
246
|
+
raise e
|
|
247
|
+
|
|
248
|
+
zip_files = list(download_dir.glob("*.zip"))
|
|
249
|
+
|
|
250
|
+
assert (
|
|
251
|
+
len(zip_files) == 1
|
|
252
|
+
), f"Expected to download a single zip file, but found {len(zip_files)} zip files."
|
|
253
|
+
|
|
254
|
+
zip_file = zip_files[0]
|
|
255
|
+
|
|
256
|
+
return zip_file
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
def _need_to_accept_rules(error_msg: str) -> bool:
|
|
260
|
+
return "You must accept this competition" in error_msg
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
def _prompt_user_to_accept_rules(competition_id: str) -> None:
|
|
264
|
+
response = input("Would you like to open the competition page in your browser now? (y/n): ")
|
|
265
|
+
|
|
266
|
+
if response.lower() != "y":
|
|
267
|
+
raise RuntimeError("You must accept the competition rules before downloading the dataset.")
|
|
268
|
+
|
|
269
|
+
webbrowser.open(f"https://www.kaggle.com/c/{competition_id}/rules")
|
|
270
|
+
input("Press Enter to continue after you have accepted the rules...")
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
def is_valid_prepare_fn(preparer_fn: Any) -> bool:
|
|
274
|
+
"""Checks if the `preparer_fn` takes three arguments: `raw`, `public` and `private`, in that order."""
|
|
275
|
+
|
|
276
|
+
try:
|
|
277
|
+
sig = inspect.signature(preparer_fn)
|
|
278
|
+
except (TypeError, ValueError):
|
|
279
|
+
return False
|
|
280
|
+
|
|
281
|
+
actual_params = list(sig.parameters.keys())
|
|
282
|
+
expected_params = ["raw", "public", "private"]
|
|
283
|
+
|
|
284
|
+
return actual_params == expected_params
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
def generate_checksums(
|
|
288
|
+
target_dir: Path,
|
|
289
|
+
exts: Optional[list[str]] = None,
|
|
290
|
+
exclude: Optional[list[Path]] = None,
|
|
291
|
+
) -> dict:
|
|
292
|
+
"""
|
|
293
|
+
Generate checksums for the files directly under the target directory with the specified extensions.
|
|
294
|
+
|
|
295
|
+
Args:
|
|
296
|
+
target_dir: directory to generate checksums for.
|
|
297
|
+
exts: List of file extensions to generate checksums for.
|
|
298
|
+
exclude: List of file paths to exclude from checksum generation.
|
|
299
|
+
|
|
300
|
+
Returns:
|
|
301
|
+
A dictionary of form file: checksum.
|
|
302
|
+
"""
|
|
303
|
+
|
|
304
|
+
if exts is None:
|
|
305
|
+
exts = ["csv", "json", "jsonl", "parquet", "bson"]
|
|
306
|
+
|
|
307
|
+
if exclude is None:
|
|
308
|
+
exclude = []
|
|
309
|
+
|
|
310
|
+
checksums = {}
|
|
311
|
+
|
|
312
|
+
for ext in exts:
|
|
313
|
+
fpaths = target_dir.glob(f"*.{ext}")
|
|
314
|
+
|
|
315
|
+
for fpath in fpaths:
|
|
316
|
+
if not fpath.is_file():
|
|
317
|
+
continue # skip dirs named like `my/dir.csv/`
|
|
318
|
+
|
|
319
|
+
if fpath in exclude:
|
|
320
|
+
continue
|
|
321
|
+
|
|
322
|
+
checksums[fpath.name] = get_checksum(fpath)
|
|
323
|
+
|
|
324
|
+
return checksums
|
|
325
|
+
|
|
326
|
+
|
|
327
|
+
def get_last_modified(fpath: Path) -> datetime:
|
|
328
|
+
"""Return the last modified time of a file."""
|
|
329
|
+
|
|
330
|
+
return datetime.fromtimestamp(fpath.stat().st_mtime)
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
def file_cache(fn: Callable) -> Callable:
|
|
334
|
+
"""A decorator that caches results of a function with a Path argument, invalidating the cache when the file is modified."""
|
|
335
|
+
|
|
336
|
+
sig = inspect.signature(fn)
|
|
337
|
+
params = list(sig.parameters.values())
|
|
338
|
+
|
|
339
|
+
if not (len(params) == 1 and params[0].annotation is Path):
|
|
340
|
+
raise NotImplementedError("Only functions with a single `Path` argument are supported.")
|
|
341
|
+
|
|
342
|
+
# Use `functools.wraps` to preserve the function's metadata, like the name and docstring.
|
|
343
|
+
# Query the cache, but with an additional `last_modified` argument in the key, which has the
|
|
344
|
+
# side effect of invalidating the cache when the file is modified.
|
|
345
|
+
@functools.wraps(fn)
|
|
346
|
+
def wrapper(fpath: Path) -> Any:
|
|
347
|
+
last_modified = get_last_modified(fpath)
|
|
348
|
+
key = (fn.__name__, str(fpath), last_modified)
|
|
349
|
+
|
|
350
|
+
if key not in cache:
|
|
351
|
+
cache[key] = fn(fpath)
|
|
352
|
+
|
|
353
|
+
return cache[key]
|
|
354
|
+
|
|
355
|
+
return wrapper
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
@file_cache
|
|
359
|
+
def get_checksum(fpath: Path) -> str:
|
|
360
|
+
"""Compute MD5 checksum of a file."""
|
|
361
|
+
|
|
362
|
+
assert fpath.is_file(), f"Expected a file at `{fpath}`, but it doesn't exist."
|
|
363
|
+
|
|
364
|
+
hash_md5 = hashlib.md5()
|
|
365
|
+
file_size = os.path.getsize(fpath)
|
|
366
|
+
|
|
367
|
+
# only show progress bar for large files (> ~5 GB)
|
|
368
|
+
show_progress = file_size > 5_000_000_000
|
|
369
|
+
|
|
370
|
+
with open(fpath, "rb") as f:
|
|
371
|
+
for chunk in tqdm(
|
|
372
|
+
iter(lambda: f.read(4_096), b""),
|
|
373
|
+
total=file_size // 4096,
|
|
374
|
+
unit="B",
|
|
375
|
+
unit_scale=True,
|
|
376
|
+
disable=not show_progress,
|
|
377
|
+
):
|
|
378
|
+
hash_md5.update(chunk)
|
|
379
|
+
|
|
380
|
+
return hash_md5.hexdigest()
|
|
381
|
+
|
|
382
|
+
|
|
383
|
+
def ensure_leaderboard_exists(competition: Competition, force: bool = False) -> Path:
|
|
384
|
+
"""
|
|
385
|
+
Ensures the leaderboard for a given competition exists in the competition's
|
|
386
|
+
directory, returning the path to it.
|
|
387
|
+
If `force` is True, the leaderboard is downloaded using the Kaggle API.
|
|
388
|
+
If `force` is `false`, if the leaderboard does not exist, an error is raised.
|
|
389
|
+
"""
|
|
390
|
+
download_dir = competition.leaderboard.parent
|
|
391
|
+
leaderboard_path = competition.leaderboard
|
|
392
|
+
if not force:
|
|
393
|
+
if leaderboard_path.exists():
|
|
394
|
+
return leaderboard_path
|
|
395
|
+
else:
|
|
396
|
+
raise FileNotFoundError(
|
|
397
|
+
f"Leaderboard not found locally for competition `{competition.id}`. Please flag this to the developers."
|
|
398
|
+
)
|
|
399
|
+
api = authenticate_kaggle_api()
|
|
400
|
+
leaderboard = api.competition_leaderboard_view(competition=competition.id)
|
|
401
|
+
if leaderboard:
|
|
402
|
+
leaderboard = [row.__dict__ for row in leaderboard]
|
|
403
|
+
leaderboard_df = pd.DataFrame(leaderboard)
|
|
404
|
+
leaderboard_df.drop(columns=["teamNameNullable", "teamName"], inplace=True)
|
|
405
|
+
leaderboard_df.to_csv(leaderboard_path, index=False)
|
|
406
|
+
logger.info(
|
|
407
|
+
f"Downloaded leaderboard for competition `{competition.id}` to `{download_dir.relative_to(Path.cwd()) / 'leaderboard.csv'}`."
|
|
408
|
+
)
|
|
409
|
+
return leaderboard_path
|
|
410
|
+
else:
|
|
411
|
+
raise RuntimeError(f"Failed to download leaderboard for competition `{competition.id}`.")
|
|
412
|
+
|
|
413
|
+
|
|
414
|
+
def get_leaderboard(competition: Competition) -> pd.DataFrame:
|
|
415
|
+
leaderboard_path = competition.leaderboard
|
|
416
|
+
assert (
|
|
417
|
+
leaderboard_path.exists()
|
|
418
|
+
), f"Leaderboard not found locally for competition `{competition.id}`."
|
|
419
|
+
leaderboard_df = pd.read_csv(leaderboard_path)
|
|
420
|
+
return leaderboard_df
|
mlebench/grade.py
ADDED
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
"""High-level grading functionality"""
|
|
2
|
+
import json
|
|
3
|
+
from datetime import datetime
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
import pandas as pd
|
|
7
|
+
from tqdm import tqdm
|
|
8
|
+
|
|
9
|
+
from mlebench.data import get_leaderboard, is_dataset_prepared
|
|
10
|
+
from mlebench.grade_helpers import CompetitionReport
|
|
11
|
+
from mlebench.registry import Competition, Registry
|
|
12
|
+
from mlebench.registry import registry as DEFAULT_REGISTRY
|
|
13
|
+
from mlebench.utils import get_logger, get_timestamp, load_answers, purple, read_csv, read_jsonl
|
|
14
|
+
|
|
15
|
+
logger = get_logger(__name__)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def grade_jsonl(
|
|
19
|
+
path_to_submissions: Path,
|
|
20
|
+
output_dir: Path,
|
|
21
|
+
registry: Registry = DEFAULT_REGISTRY,
|
|
22
|
+
):
|
|
23
|
+
"""
|
|
24
|
+
Grades multiple submissions stored in a JSONL file.
|
|
25
|
+
Saves the aggregated report as a JSON file.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
submissions = read_jsonl(path_to_submissions, skip_commented_out_lines=True)
|
|
29
|
+
competitions_reports = []
|
|
30
|
+
|
|
31
|
+
for submission in tqdm(submissions, desc="Grading submissions", unit="submission"):
|
|
32
|
+
submission_path = Path(str(submission["submission_path"]))
|
|
33
|
+
competition_id = submission["competition_id"]
|
|
34
|
+
competition = registry.get_competition(competition_id)
|
|
35
|
+
single_report = grade_csv(submission_path, competition)
|
|
36
|
+
competitions_reports.append(single_report)
|
|
37
|
+
|
|
38
|
+
aggregated_report = aggregate_reports(competitions_reports)
|
|
39
|
+
timestamp = get_timestamp()
|
|
40
|
+
save_path = output_dir / f"{timestamp}_grading_report.json"
|
|
41
|
+
logger.info(
|
|
42
|
+
json.dumps(
|
|
43
|
+
{k: v for k, v in aggregated_report.items() if k != "competition_reports"}, indent=4
|
|
44
|
+
)
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
output_dir.mkdir(exist_ok=True)
|
|
48
|
+
with open(save_path, "w") as f:
|
|
49
|
+
json.dump(aggregated_report, f, indent=2)
|
|
50
|
+
logger.info(purple(f"Saved summary report to {save_path}"))
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def grade_csv(path_to_submission: Path, competition: Competition) -> CompetitionReport:
|
|
54
|
+
"""Grades a submission CSV for the given competition."""
|
|
55
|
+
|
|
56
|
+
if not is_dataset_prepared(competition, grading_only=True):
|
|
57
|
+
raise ValueError(
|
|
58
|
+
f"Dataset for competition `{competition.id}` is not prepared! "
|
|
59
|
+
f"Please run `mlebench prepare -c {competition.id}` to prepare the dataset."
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
score = None
|
|
63
|
+
submission_exists = path_to_submission.is_file() and path_to_submission.suffix.lower() == ".csv"
|
|
64
|
+
|
|
65
|
+
if submission_exists:
|
|
66
|
+
submission_df = read_csv(path_to_submission)
|
|
67
|
+
logger.info(purple(f"Load answers from {competition.answers}"))
|
|
68
|
+
answers = load_answers(competition.answers)
|
|
69
|
+
score = competition.grader(submission_df, answers)
|
|
70
|
+
else:
|
|
71
|
+
logger.warning(
|
|
72
|
+
f"Invalid submission file: {path_to_submission}. Please check that the file exists and it is a CSV."
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
valid_submission = score is not None
|
|
76
|
+
competition_leaderboard = get_leaderboard(competition)
|
|
77
|
+
rank_info = competition.grader.rank_score(score, competition_leaderboard)
|
|
78
|
+
is_lower_better = competition.grader.is_lower_better(competition_leaderboard)
|
|
79
|
+
|
|
80
|
+
return CompetitionReport(
|
|
81
|
+
competition_id=competition.id,
|
|
82
|
+
score=score,
|
|
83
|
+
gold_threshold=rank_info["gold_threshold"],
|
|
84
|
+
silver_threshold=rank_info["silver_threshold"],
|
|
85
|
+
bronze_threshold=rank_info["bronze_threshold"],
|
|
86
|
+
median_threshold=rank_info["median_threshold"],
|
|
87
|
+
any_medal=rank_info["gold_medal"] or rank_info["silver_medal"] or rank_info["bronze_medal"],
|
|
88
|
+
gold_medal=rank_info["gold_medal"],
|
|
89
|
+
silver_medal=rank_info["silver_medal"],
|
|
90
|
+
bronze_medal=rank_info["bronze_medal"],
|
|
91
|
+
above_median=rank_info["above_median"],
|
|
92
|
+
submission_exists=submission_exists,
|
|
93
|
+
valid_submission=valid_submission,
|
|
94
|
+
is_lower_better=is_lower_better,
|
|
95
|
+
created_at=datetime.now(),
|
|
96
|
+
submission_path=str(path_to_submission),
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def validate_submission(submission: Path, competition: Competition) -> tuple[bool, str]:
|
|
101
|
+
"""
|
|
102
|
+
Validates a submission for the given competition by actually running the competition grader.
|
|
103
|
+
This is designed for end users, not developers (we assume that the competition grader is
|
|
104
|
+
correctly implemented and use that for validating the submission, not the other way around).
|
|
105
|
+
"""
|
|
106
|
+
if not submission.is_file():
|
|
107
|
+
return False, f"Submission invalid! Submission file {submission} does not exist."
|
|
108
|
+
|
|
109
|
+
if not submission.suffix.lower() == ".csv":
|
|
110
|
+
return False, "Submission invalid! Submission file must be a CSV file."
|
|
111
|
+
|
|
112
|
+
if not is_dataset_prepared(competition, grading_only=True):
|
|
113
|
+
raise ValueError(
|
|
114
|
+
f"Dataset for competition `{competition.id}` is not prepared! "
|
|
115
|
+
f"Please run `mlebench prepare -c {competition.id}` to prepare the dataset."
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
try:
|
|
119
|
+
competition.grader.grade_fn(read_csv(submission), read_csv(competition.answers))
|
|
120
|
+
except Exception as e:
|
|
121
|
+
return (
|
|
122
|
+
False,
|
|
123
|
+
f"Submission invalid! The attempt to grade the submission has resulted in the following error message:\n{e}",
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
return True, "Submission is valid."
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def aggregate_reports(competition_reports: list[CompetitionReport]) -> dict:
|
|
130
|
+
"""
|
|
131
|
+
Builds the summary report from a list of competition reports.
|
|
132
|
+
If pass_at_n is True, then aggregate performence of competitions by selecting the best performance per
|
|
133
|
+
competition, otherwise sum metrics
|
|
134
|
+
"""
|
|
135
|
+
|
|
136
|
+
total_gold_medals = sum(report.gold_medal for report in competition_reports)
|
|
137
|
+
total_silver_medals = sum(report.silver_medal for report in competition_reports)
|
|
138
|
+
total_bronze_medals = sum(report.bronze_medal for report in competition_reports)
|
|
139
|
+
total_above_median = sum(report.above_median for report in competition_reports)
|
|
140
|
+
total_submissions = sum(report.submission_exists for report in competition_reports)
|
|
141
|
+
total_valid_submissions = sum(report.valid_submission for report in competition_reports)
|
|
142
|
+
|
|
143
|
+
summary_report = {
|
|
144
|
+
"total_runs": int(len(competition_reports)),
|
|
145
|
+
"total_runs_with_submissions": int(total_submissions),
|
|
146
|
+
"total_valid_submissions": int(total_valid_submissions),
|
|
147
|
+
"total_medals": int(total_gold_medals + total_silver_medals + total_bronze_medals),
|
|
148
|
+
"total_gold_medals": int(total_gold_medals),
|
|
149
|
+
"total_silver_medals": int(total_silver_medals),
|
|
150
|
+
"total_bronze_medals": int(total_bronze_medals),
|
|
151
|
+
"total_above_median": int(total_above_median),
|
|
152
|
+
"competition_reports": [cr.to_dict() for cr in competition_reports],
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return summary_report
|
|
156
|
+
|
|
157
|
+
def simple_accuracy_grader(submission: pd.DataFrame, answers: pd.DataFrame) -> float:
|
|
158
|
+
"""
|
|
159
|
+
Computes simple accuracy between submission and answers.
|
|
160
|
+
Assumes matching order or joins on an ID column.
|
|
161
|
+
"""
|
|
162
|
+
try:
|
|
163
|
+
# 1. Try to find ID column to merge on
|
|
164
|
+
id_col = None
|
|
165
|
+
common_cols = set(submission.columns).intersection(set(answers.columns))
|
|
166
|
+
for col in common_cols:
|
|
167
|
+
if col.lower() in ['id', 'key', 'index', 'sample_id', 'image_id', 'patient_id']:
|
|
168
|
+
id_col = col
|
|
169
|
+
break
|
|
170
|
+
|
|
171
|
+
if id_col:
|
|
172
|
+
merged = submission.merge(answers, on=id_col, suffixes=('_pred', '_true'))
|
|
173
|
+
# Compare all other columns
|
|
174
|
+
pred_cols = [c for c in submission.columns if c != id_col]
|
|
175
|
+
true_cols = [c for c in answers.columns if c != id_col]
|
|
176
|
+
|
|
177
|
+
# If there's only one other column, compare it
|
|
178
|
+
if len(pred_cols) == 1 and len(true_cols) == 1:
|
|
179
|
+
return float((merged[pred_cols[0]] == merged[true_cols[0]]).mean())
|
|
180
|
+
|
|
181
|
+
# Iterate over shared columns that are NOT id
|
|
182
|
+
shared_content_cols = [c for c in common_cols if c != id_col]
|
|
183
|
+
if shared_content_cols:
|
|
184
|
+
matches = []
|
|
185
|
+
for c in shared_content_cols:
|
|
186
|
+
# In merged df, they are c_pred and c_true
|
|
187
|
+
matches.append((merged[f"{c}_pred"] == merged[f"{c}_true"]).mean())
|
|
188
|
+
if matches:
|
|
189
|
+
return float(sum(matches) / len(matches))
|
|
190
|
+
|
|
191
|
+
# 2. Fallback: Position-based comparison (assuming sorted)
|
|
192
|
+
if len(submission) == len(answers):
|
|
193
|
+
# Compare last column if dimensions match
|
|
194
|
+
if submission.shape[1] == answers.shape[1]:
|
|
195
|
+
return float((submission.iloc[:, -1] == answers.iloc[:, -1]).mean())
|
|
196
|
+
|
|
197
|
+
# Or compare specific common columns
|
|
198
|
+
common_cols = set(submission.columns).intersection(set(answers.columns))
|
|
199
|
+
if common_cols:
|
|
200
|
+
matches = []
|
|
201
|
+
for c in common_cols:
|
|
202
|
+
matches.append((submission[c] == answers[c]).mean())
|
|
203
|
+
if matches:
|
|
204
|
+
return float(sum(matches) / len(matches))
|
|
205
|
+
except Exception as e:
|
|
206
|
+
logger.error(f"simple_accuracy_grader failed: {e}")
|
|
207
|
+
return 0.0
|
|
208
|
+
|
|
209
|
+
return 0.0
|