dslighting 1.7.1__py3-none-any.whl → 1.7.6__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.6.dist-info}/METADATA +1 -1
- {dslighting-1.7.1.dist-info → dslighting-1.7.6.dist-info}/RECORD +352 -7
- {dslighting-1.7.1.dist-info → dslighting-1.7.6.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.6.dist-info}/WHEEL +0 -0
- {dslighting-1.7.1.dist-info → dslighting-1.7.6.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import shutil
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
import pandas as pd
|
|
5
|
+
from sklearn.model_selection import train_test_split
|
|
6
|
+
from tqdm import tqdm
|
|
7
|
+
|
|
8
|
+
from mlebench.utils import read_csv
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def _create_and_populate_split(
|
|
12
|
+
input_df: pd.DataFrame,
|
|
13
|
+
test_size: float,
|
|
14
|
+
random_state: int,
|
|
15
|
+
raw_data_path: Path,
|
|
16
|
+
public_dest_path: Path,
|
|
17
|
+
private_dest_path: Path,
|
|
18
|
+
) -> (pd.DataFrame, pd.DataFrame):
|
|
19
|
+
"""
|
|
20
|
+
Splits a dataframe and populates the corresponding public and private directories.
|
|
21
|
+
|
|
22
|
+
This function performs a train-test split, copies the necessary .npy files,
|
|
23
|
+
creates the ground truth file for the test set, and a sample submission file.
|
|
24
|
+
It's designed to be called multiple times for creating different data splits
|
|
25
|
+
(e.g., train/test and train/validation).
|
|
26
|
+
|
|
27
|
+
Args:
|
|
28
|
+
input_df: The dataframe to be split.
|
|
29
|
+
test_size: The proportion of the dataset to allocate to the test split.
|
|
30
|
+
random_state: The seed used by the random number generator.
|
|
31
|
+
raw_data_path: The path to the raw data directory.
|
|
32
|
+
public_dest_path: The destination path for public-facing files.
|
|
33
|
+
private_dest_path: The destination path for private/solution files.
|
|
34
|
+
|
|
35
|
+
Returns:
|
|
36
|
+
A tuple containing the training and testing dataframes from the split.
|
|
37
|
+
"""
|
|
38
|
+
# Ensure destination directories exist
|
|
39
|
+
public_dest_path.mkdir(parents=True, exist_ok=True)
|
|
40
|
+
private_dest_path.mkdir(parents=True, exist_ok=True)
|
|
41
|
+
|
|
42
|
+
# 1. Create train, test from the input dataframe
|
|
43
|
+
split_train, split_test = train_test_split(
|
|
44
|
+
input_df, test_size=test_size, random_state=random_state
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
# 2. Copy over files
|
|
48
|
+
split_train.to_csv(public_dest_path / "train_labels.csv", index=False)
|
|
49
|
+
split_test.to_csv(private_dest_path / "test.csv", index=False)
|
|
50
|
+
|
|
51
|
+
# Copy shared, non-data-specific files if they exist
|
|
52
|
+
if (raw_data_path / "old_leaky_data").exists():
|
|
53
|
+
shutil.copytree(
|
|
54
|
+
raw_data_path / "old_leaky_data",
|
|
55
|
+
public_dest_path / "old_leaky_data",
|
|
56
|
+
dirs_exist_ok=True,
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
for file_id in tqdm(split_train["id"], desc=f"Copying train files to {public_dest_path.name}"):
|
|
60
|
+
subdir = file_id[0]
|
|
61
|
+
src = raw_data_path / "train" / subdir / f"{file_id}.npy"
|
|
62
|
+
dst = public_dest_path / "train" / subdir / f"{file_id}.npy"
|
|
63
|
+
dst.parent.mkdir(parents=True, exist_ok=True)
|
|
64
|
+
shutil.copy(src, dst)
|
|
65
|
+
|
|
66
|
+
for file_id in tqdm(split_test["id"], desc=f"Copying test files to {public_dest_path.name}"):
|
|
67
|
+
subdir = file_id[0]
|
|
68
|
+
src = raw_data_path / "train" / subdir / f"{file_id}.npy"
|
|
69
|
+
dst = public_dest_path / "test" / subdir / f"{file_id}.npy"
|
|
70
|
+
dst.parent.mkdir(parents=True, exist_ok=True)
|
|
71
|
+
shutil.copy(src, dst)
|
|
72
|
+
|
|
73
|
+
# 3. Create sample submission
|
|
74
|
+
sample_submission = split_test.copy()
|
|
75
|
+
sample_submission["target"] = 0.5 # Overwrite with dummy values
|
|
76
|
+
sample_submission.to_csv(public_dest_path / "sample_submission.csv", index=False)
|
|
77
|
+
|
|
78
|
+
# 4. Perform checks for this specific split
|
|
79
|
+
assert len(sample_submission) == len(
|
|
80
|
+
split_test
|
|
81
|
+
), f"Sample submission length mismatch in {public_dest_path.name}."
|
|
82
|
+
assert not set(split_train["id"]).intersection(
|
|
83
|
+
set(split_test["id"])
|
|
84
|
+
), f"Overlapping IDs in train/test sets for {public_dest_path.name}."
|
|
85
|
+
|
|
86
|
+
train_files = {
|
|
87
|
+
file_path.name
|
|
88
|
+
for file_path in (public_dest_path / "train").rglob("*.npy")
|
|
89
|
+
if file_path.is_file()
|
|
90
|
+
}
|
|
91
|
+
test_files = {
|
|
92
|
+
file_path.name
|
|
93
|
+
for file_path in (public_dest_path / "test").rglob("*.npy")
|
|
94
|
+
if file_path.is_file()
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
assert len(train_files) == len(
|
|
98
|
+
split_train
|
|
99
|
+
), f"Train file count mismatch in {public_dest_path.name}."
|
|
100
|
+
assert len(test_files) == len(
|
|
101
|
+
split_test
|
|
102
|
+
), f"Test file count mismatch in {public_dest_path.name}."
|
|
103
|
+
assert train_files.isdisjoint(
|
|
104
|
+
test_files
|
|
105
|
+
), f"Overlapping files in train/test directories for {public_dest_path.name}."
|
|
106
|
+
|
|
107
|
+
return split_train, split_test
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def prepare(raw: Path, public: Path, private: Path):
|
|
111
|
+
"""
|
|
112
|
+
Prepares the data by creating two parallel splits:
|
|
113
|
+
1. A standard train/test split (outputs to `public` and `private`).
|
|
114
|
+
2. A subsequent train/validation split (outputs to `public_val` and `private_val`).
|
|
115
|
+
"""
|
|
116
|
+
# Read the full raw training data manifest
|
|
117
|
+
full_train_df = read_csv(raw / "train_labels.csv")
|
|
118
|
+
|
|
119
|
+
# --- Stage 1: Create the original train/test split ---
|
|
120
|
+
# This split generates the main competition files in `public` and `private`.
|
|
121
|
+
# The logic and outputs here remain identical to the original script.
|
|
122
|
+
print("--- Creating main train/test split ---")
|
|
123
|
+
new_train, new_test = _create_and_populate_split(
|
|
124
|
+
input_df=full_train_df,
|
|
125
|
+
test_size=0.1,
|
|
126
|
+
random_state=0,
|
|
127
|
+
raw_data_path=raw,
|
|
128
|
+
public_dest_path=public,
|
|
129
|
+
private_dest_path=private,
|
|
130
|
+
)
|
|
131
|
+
print("--- Main train/test split created successfully ---\n")
|
|
132
|
+
|
|
133
|
+
# --- Stage 2: Create the new train/validation split ---
|
|
134
|
+
# This split takes the `new_train` set from Stage 1 and splits it again.
|
|
135
|
+
# The outputs go into new, parallel directories (`public_val`, `private_val`).
|
|
136
|
+
# The number of samples in the validation set (`test_val`) is designed to be
|
|
137
|
+
# the same as the number of samples in the original test set (`new_test`).
|
|
138
|
+
print("--- Creating train/validation split ---")
|
|
139
|
+
public_val = public.parent / "public_val"
|
|
140
|
+
private_val = private.parent / "private_val"
|
|
141
|
+
|
|
142
|
+
# To make the new validation set size equal to the original test set size,
|
|
143
|
+
# we calculate the required proportion.
|
|
144
|
+
# test_size = len(new_test) / len(new_train)
|
|
145
|
+
# Since len(new_test) is 0.1 * total and len(new_train) is 0.9 * total,
|
|
146
|
+
# the ratio is 0.1 / 0.9 = 1/9.
|
|
147
|
+
validation_test_size = 1 / 9
|
|
148
|
+
|
|
149
|
+
# We reuse the same function, ensuring the logic is identical.
|
|
150
|
+
# The returned dataframes are not needed, as this is the final split.
|
|
151
|
+
_create_and_populate_split(
|
|
152
|
+
input_df=new_train, # Use the training set from the first split as input
|
|
153
|
+
test_size=validation_test_size,
|
|
154
|
+
random_state=0, # Use the same random state for consistency
|
|
155
|
+
raw_data_path=raw,
|
|
156
|
+
public_dest_path=public_val,
|
|
157
|
+
private_dest_path=private_val,
|
|
158
|
+
)
|
|
159
|
+
print("--- Train/validation split created successfully ---")
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
from typing import List, Tuple
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
import pandas as pd
|
|
5
|
+
from sklearn.metrics import average_precision_score
|
|
6
|
+
|
|
7
|
+
from mlebench.grade_helpers import InvalidSubmissionError
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def calculate_iou(
|
|
11
|
+
box1: Tuple[float, float, float, float], box2: Tuple[float, float, float, float]
|
|
12
|
+
) -> float:
|
|
13
|
+
"""
|
|
14
|
+
Calculate the Intersection over Union (IoU) of two bounding boxes.
|
|
15
|
+
(this image helps: https://machinelearningspace.com/wp-content/uploads/2023/01/IOU2.jpg)
|
|
16
|
+
"""
|
|
17
|
+
xmin1, ymin1, xmax1, ymax1 = box1
|
|
18
|
+
xmin2, ymin2, xmax2, ymax2 = box2
|
|
19
|
+
|
|
20
|
+
inter_xmin = max(xmin1, xmin2)
|
|
21
|
+
inter_ymin = max(ymin1, ymin2)
|
|
22
|
+
inter_xmax = min(xmax1, xmax2)
|
|
23
|
+
inter_ymax = min(ymax1, ymax2)
|
|
24
|
+
|
|
25
|
+
inter_width = max(0, inter_xmax - inter_xmin)
|
|
26
|
+
inter_height = max(0, inter_ymax - inter_ymin)
|
|
27
|
+
inter_area = inter_width * inter_height
|
|
28
|
+
|
|
29
|
+
box1_area = (xmax1 - xmin1) * (ymax1 - ymin1)
|
|
30
|
+
box2_area = (xmax2 - xmin2) * (ymax2 - ymin2)
|
|
31
|
+
|
|
32
|
+
union_area = box1_area + box2_area - inter_area
|
|
33
|
+
|
|
34
|
+
iou = inter_area / union_area if union_area > 0 else 0.0
|
|
35
|
+
return iou
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def calculate_map(submission_preds: List[List[Tuple]], answers_preds: List[List[Tuple]]) -> float:
|
|
39
|
+
"""
|
|
40
|
+
Calculate mean Average Precision (mAP) for object detection.
|
|
41
|
+
|
|
42
|
+
> The challenge uses the standard PASCAL VOC 2010 mean Average Precision (mAP) at IoU > 0.5.
|
|
43
|
+
Note that the linked document describes VOC 2012, which differs in some minor ways
|
|
44
|
+
(e.g. there is no concept of "difficult" classes in VOC 2010).
|
|
45
|
+
The P/R curve and AP calculations remain the same.
|
|
46
|
+
(www.kaggle.com/competitions/siim-covid19-detection/overview/evaluation)
|
|
47
|
+
|
|
48
|
+
Some choices made here that were not explicitly specified in the challenge description:
|
|
49
|
+
|
|
50
|
+
1. Treating "none" or "negative" as prediction classes of their own, instead of as the non-positive class
|
|
51
|
+
- Justification: Treating them as their own classes is implied by the data format:
|
|
52
|
+
- Study level - train_study_level.csv has 4 binary classes including the "negative" class instead of 3
|
|
53
|
+
- Image level - We're asked to predict "none" with full bounding boxes instead of withholding a prediction
|
|
54
|
+
Also, 3rd place winner says "It probably treats the six classes equally", where the six classes are
|
|
55
|
+
"negative", "typical", "indeterminate", "atypical", "none" and "opacity".
|
|
56
|
+
(https://www.kaggle.com/competitions/siim-covid19-detection/discussion/240363)
|
|
57
|
+
|
|
58
|
+
2. Rules for populating y_pairs (see comments below), in particular the (0, 0) case
|
|
59
|
+
- Justification: The general rules follow the descriptions of the PASCAL VOC 2010 mAP documented online.
|
|
60
|
+
The only custom addition is handling the edge case of (0, 0) false negatives, which was necessary because
|
|
61
|
+
if we don't include (0, 0) pairs, both the sample submission and gold submission end up with all values of
|
|
62
|
+
y_true being 1, so the AP is undefined.
|
|
63
|
+
Behavior of our implementation is consistent with this comment from the organizers:
|
|
64
|
+
https://www.kaggle.com/competitions/siim-covid19-detection/discussion/248467#1362916
|
|
65
|
+
|
|
66
|
+
"""
|
|
67
|
+
aps = []
|
|
68
|
+
|
|
69
|
+
# Group predictions by class - the general idea is to calculate AP for each class separately
|
|
70
|
+
# and then average them to get mAP
|
|
71
|
+
classes = sorted(list(set(pred[0] for preds in answers_preds for pred in preds)))
|
|
72
|
+
|
|
73
|
+
for cls in classes:
|
|
74
|
+
# We will populate y_true and y_scores with (y_true, y_score) of:
|
|
75
|
+
# (1, confidence) for every predicted box that matches a ground truth box
|
|
76
|
+
# (0, confidence) for every predicted box that does not match a ground truth box
|
|
77
|
+
# (1, 0) for every ground truth box that is not matched to a predicted box
|
|
78
|
+
# (0, 0) when there are neither predicted nor ground truth boxes
|
|
79
|
+
y_pairs = [] # List of (y_true, y_score) pairs
|
|
80
|
+
|
|
81
|
+
# Gather all predictions and ground truth boxes related to this class from all samples
|
|
82
|
+
for img_preds, img_gts in zip(submission_preds, answers_preds):
|
|
83
|
+
y_pairs_ = []
|
|
84
|
+
|
|
85
|
+
# Get ground truth boxes for this class
|
|
86
|
+
gt_boxes = [gt[2:] for gt in img_gts if gt[0] == cls]
|
|
87
|
+
|
|
88
|
+
# Sort img_preds by confidence
|
|
89
|
+
img_preds.sort(key=lambda x: x[1], reverse=True)
|
|
90
|
+
|
|
91
|
+
# For each prediction of this class
|
|
92
|
+
matched_gt = [False] * len(gt_boxes) # Initialize all ground truths as unmatched
|
|
93
|
+
for pred in img_preds:
|
|
94
|
+
if pred[0] == cls:
|
|
95
|
+
# Find the best matching ground truth box
|
|
96
|
+
best_iou = 0
|
|
97
|
+
best_gt_idx = -1
|
|
98
|
+
for i, gt in enumerate(gt_boxes):
|
|
99
|
+
if matched_gt[i]: # Don't reuse matched ground truths
|
|
100
|
+
continue
|
|
101
|
+
iou = calculate_iou(pred[2:], gt)
|
|
102
|
+
if iou > best_iou and iou > 0.5:
|
|
103
|
+
best_iou = iou
|
|
104
|
+
best_gt_idx = i
|
|
105
|
+
|
|
106
|
+
pred_confidence = pred[1]
|
|
107
|
+
if best_gt_idx != -1:
|
|
108
|
+
y_pairs_.append((1, pred_confidence)) # True positive
|
|
109
|
+
matched_gt[best_gt_idx] = True
|
|
110
|
+
else:
|
|
111
|
+
y_pairs_.append((0, pred_confidence)) # False positive
|
|
112
|
+
|
|
113
|
+
# Add false negatives for unmatched ground truths
|
|
114
|
+
y_pairs_.extend([(1, 0)] * matched_gt.count(False))
|
|
115
|
+
|
|
116
|
+
if len(y_pairs_) == 0:
|
|
117
|
+
# A true negative
|
|
118
|
+
y_pairs_.append((0, 0))
|
|
119
|
+
|
|
120
|
+
y_pairs.extend(y_pairs_)
|
|
121
|
+
|
|
122
|
+
y_true = [pair[0] for pair in y_pairs]
|
|
123
|
+
y_scores = [pair[1] for pair in y_pairs]
|
|
124
|
+
if len(y_true) > 0:
|
|
125
|
+
assert not all(
|
|
126
|
+
y == 1 for y in y_true
|
|
127
|
+
), "y_true is all 1s; this shouldn't happen and will result in undefined AP"
|
|
128
|
+
ap = average_precision_score(y_true, y_scores)
|
|
129
|
+
aps.append(ap)
|
|
130
|
+
else:
|
|
131
|
+
raise ValueError(f"Unexpected error: y_true is empty for class {cls}")
|
|
132
|
+
|
|
133
|
+
# Calculate mAP
|
|
134
|
+
return np.mean(aps) if aps else 0.0
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def parse_prediction_string(
|
|
138
|
+
prediction_string: str,
|
|
139
|
+
) -> List[Tuple[str, float, float, float, float, float]]:
|
|
140
|
+
"""
|
|
141
|
+
`prediction_string` should have the form "{label} {confidence} {xmin} {ymin} {xmax} {ymax}" for each bounding box
|
|
142
|
+
(so there may be 6 x N space-separated values in total, where N is the number of bounding boxes).
|
|
143
|
+
|
|
144
|
+
Returns a list of tuples, each with the form (label, confidence, xmin, ymin, xmax, ymax).
|
|
145
|
+
"""
|
|
146
|
+
toks = prediction_string.strip().split()
|
|
147
|
+
try:
|
|
148
|
+
return [
|
|
149
|
+
(
|
|
150
|
+
toks[i],
|
|
151
|
+
float(toks[i + 1]),
|
|
152
|
+
float(toks[i + 2]),
|
|
153
|
+
float(toks[i + 3]),
|
|
154
|
+
float(toks[i + 4]),
|
|
155
|
+
float(toks[i + 5]),
|
|
156
|
+
)
|
|
157
|
+
for i in range(0, len(toks), 6)
|
|
158
|
+
]
|
|
159
|
+
except ValueError as e:
|
|
160
|
+
raise InvalidSubmissionError(f"Could not parse PredictionString: {e}")
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def grade(submission: pd.DataFrame, answers: pd.DataFrame) -> float:
|
|
164
|
+
"""
|
|
165
|
+
Grade the submission against the answers.
|
|
166
|
+
|
|
167
|
+
`submission` and `answers` are DataFrames with the following columns:
|
|
168
|
+
- `id` (str): The study ID
|
|
169
|
+
- `PredictionString` (str): Has the form "{label} {confidence} {xmin} {ymin} {xmax} {ymax}" for each bounding box
|
|
170
|
+
(so there may be 6 x N space-separated values in total, where N is the number of bounding boxes).
|
|
171
|
+
"""
|
|
172
|
+
if len(submission) != len(answers):
|
|
173
|
+
raise InvalidSubmissionError("Submission and answers must have the same length")
|
|
174
|
+
|
|
175
|
+
if "id" not in submission.columns:
|
|
176
|
+
raise InvalidSubmissionError("Submission must have an 'Id' column")
|
|
177
|
+
|
|
178
|
+
if "PredictionString" not in submission.columns:
|
|
179
|
+
raise InvalidSubmissionError("Submission must have a 'PredictionString' column")
|
|
180
|
+
|
|
181
|
+
assert "id" in answers.columns, "Answers must have an 'id' column"
|
|
182
|
+
assert "PredictionString" in answers.columns, "Answers must have a 'PredictionString' column"
|
|
183
|
+
|
|
184
|
+
submission = submission.sort_values("id")
|
|
185
|
+
answers = answers.sort_values("id")
|
|
186
|
+
if (submission["id"].values != answers["id"].values).any():
|
|
187
|
+
raise InvalidSubmissionError("Submission and answers must have the same ids")
|
|
188
|
+
|
|
189
|
+
# Attempt to parse the PredictionString
|
|
190
|
+
submission_preds = submission["PredictionString"].apply(parse_prediction_string)
|
|
191
|
+
answers_preds = answers["PredictionString"].apply(parse_prediction_string)
|
|
192
|
+
|
|
193
|
+
# Calculate the mAP
|
|
194
|
+
return calculate_map(submission_preds, answers_preds) if len(submission_preds) > 0 else 0.0
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import shutil
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
import pandas as pd
|
|
5
|
+
from sklearn.model_selection import train_test_split
|
|
6
|
+
from tqdm import tqdm
|
|
7
|
+
|
|
8
|
+
from mlebench.utils import read_csv
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def prepare(raw: Path, public: Path, private: Path):
|
|
12
|
+
"""
|
|
13
|
+
There are two tasks:
|
|
14
|
+
- Image level: Object detection problem - detect the presence of pneumonia in the image using bounding boxes
|
|
15
|
+
- Study level: Classification problem - classify the study into one of the four classes
|
|
16
|
+
|
|
17
|
+
Images in train/ and test/ are stored in paths with the form {study}/{series}/{image}.
|
|
18
|
+
|
|
19
|
+
Original train has 6,334 samples, and test "is of roughly the same scale as the training dataset".
|
|
20
|
+
We'll split the original train into a new train/test split with 90/10 ratio.
|
|
21
|
+
|
|
22
|
+
The split happens at the study level, with image level following accordingly.
|
|
23
|
+
"""
|
|
24
|
+
DEV_MODE = False
|
|
25
|
+
|
|
26
|
+
# Create new train_study_level.csv
|
|
27
|
+
train_study = read_csv(raw / "train_study_level.csv")
|
|
28
|
+
if DEV_MODE:
|
|
29
|
+
# randomly sample 200 rows for development
|
|
30
|
+
train_study = train_study.sample(n=200, random_state=0)
|
|
31
|
+
new_train_study, new_test_study = train_test_split(train_study, test_size=0.1, random_state=0)
|
|
32
|
+
new_train_study = new_train_study.sort_values(by="id")
|
|
33
|
+
new_test_study = new_test_study.sort_values(by="id")
|
|
34
|
+
new_train_study.to_csv(public / "train_study_level.csv", index=False)
|
|
35
|
+
|
|
36
|
+
# Create new train_image_level.csv
|
|
37
|
+
train_image = read_csv(raw / "train_image_level.csv")
|
|
38
|
+
new_train_image = train_image[
|
|
39
|
+
(train_image["StudyInstanceUID"] + "_study").isin(new_train_study["id"])
|
|
40
|
+
]
|
|
41
|
+
new_test_image = train_image[
|
|
42
|
+
(train_image["StudyInstanceUID"] + "_study").isin(new_test_study["id"])
|
|
43
|
+
]
|
|
44
|
+
new_train_image = new_train_image.sort_values(by="id")
|
|
45
|
+
new_test_image = new_test_image.sort_values(by="id")
|
|
46
|
+
if not DEV_MODE:
|
|
47
|
+
assert len(new_train_image) + len(new_test_image) == len(
|
|
48
|
+
train_image
|
|
49
|
+
), f"Expected {len(train_image)} images"
|
|
50
|
+
new_train_image.to_csv(public / "train_image_level.csv", index=False)
|
|
51
|
+
|
|
52
|
+
# Copy data with shutil
|
|
53
|
+
for study_id in tqdm(new_train_study["id"], desc="Copying train data"):
|
|
54
|
+
study_id = study_id.replace("_study", "")
|
|
55
|
+
shutil.copytree(raw / "train" / study_id, public / "train" / study_id)
|
|
56
|
+
for study_id in tqdm(new_test_study["id"], desc="Copying test data"):
|
|
57
|
+
study_id = study_id.replace("_study", "")
|
|
58
|
+
shutil.copytree(raw / "train" / study_id, public / "test" / study_id)
|
|
59
|
+
assert len(list(public.glob("train/*"))) == len(
|
|
60
|
+
new_train_study
|
|
61
|
+
), f"Expected {len(new_train_study)} studies"
|
|
62
|
+
assert len(list(public.glob("test/*"))) == len(
|
|
63
|
+
new_test_study
|
|
64
|
+
), f"Expected {len(new_test_study)} studies"
|
|
65
|
+
|
|
66
|
+
# Create gold answer submission
|
|
67
|
+
rows = []
|
|
68
|
+
|
|
69
|
+
"""
|
|
70
|
+
# new_test_study currently looks like:
|
|
71
|
+
id,Negative for Pneumonia,Typical Appearance,Indeterminate Appearance,Atypical Appearance
|
|
72
|
+
00086460a852_study,0,1,0,0
|
|
73
|
+
000c9c05fd14_study,0,0,0,1
|
|
74
|
+
# but for the submission we need to convert it to the following, where label is one of "negative", "typical", "indeterminate", "atypical"
|
|
75
|
+
id,PredictionString
|
|
76
|
+
00188a671292_study,{label} 1 0 0 1 1
|
|
77
|
+
004bd59708be_study,{label} 1 0 0 1 1
|
|
78
|
+
"""
|
|
79
|
+
for idx, row in new_test_study.iterrows():
|
|
80
|
+
label = ["negative", "typical", "indeterminate", "atypical"][row[1:].argmax()]
|
|
81
|
+
# Study-level task is just a classification task, so set bounding boxes all the same (1 0 0 1 1)
|
|
82
|
+
# then the metric will only care about the label
|
|
83
|
+
# https://www.kaggle.com/competitions/siim-covid19-detection/data
|
|
84
|
+
rows.append({"id": row["id"], "PredictionString": f"{label} 1 0 0 1 1"})
|
|
85
|
+
|
|
86
|
+
# new_test_image currently looks like this, and we only want the "label" column as the PredictionString
|
|
87
|
+
"""
|
|
88
|
+
id,boxes,label,StudyInstanceUID
|
|
89
|
+
000a312787f2_image,"[{'x': 789.28836, 'y': 582.43035, 'width': 1026.65662, 'height': 1917.30292}, {'x': 2245.91208, 'y': 591.20528, 'width': 1094.66162, 'height': 1761.54944}]",opacity 1 789.28836 582.43035 1815.94498 2499.73327 opacity 1 2245.91208 591.20528 3340.5737 2352.75472,5776db0cec75
|
|
90
|
+
000c3a3f293f_image,,none 1 0 0 1 1,ff0879eb20ed
|
|
91
|
+
0012ff7358bc_image,"[{'x': 677.42216, 'y': 197.97662, 'width': 867.79767, 'height': 999.78214}, {'x': 1792.69064, 'y': 402.5525, 'width': 617.02734, 'height': 1204.358}]",opacity 1 677.42216 197.97662 1545.21983 1197.75876 opacity 1 1792.69064 402.5525 2409.71798 1606.9105,9d514ce429a7
|
|
92
|
+
"""
|
|
93
|
+
for idx, row in new_test_image.iterrows():
|
|
94
|
+
rows.append({"id": row["id"], "PredictionString": row["label"]})
|
|
95
|
+
|
|
96
|
+
answers = pd.DataFrame(rows)
|
|
97
|
+
assert len(answers) == len(new_test_study) + len(
|
|
98
|
+
new_test_image
|
|
99
|
+
), f"Expected {len(new_test_study) + len(new_test_image)} answers"
|
|
100
|
+
answers.to_csv(private / "test.csv", index=False)
|
|
101
|
+
|
|
102
|
+
# Create sample submission
|
|
103
|
+
""" Sample submission should look like:
|
|
104
|
+
id,PredictionString
|
|
105
|
+
00188a671292_study,negative 1 0 0 1 1
|
|
106
|
+
004bd59708be_study,negative 1 0 0 1 1
|
|
107
|
+
00508faccd39_study,negative 1 0 0 1 1
|
|
108
|
+
...
|
|
109
|
+
f77d7d1aebab_image,none 1 0 0 1 1
|
|
110
|
+
ccc5b63ca96d_image,none 1 0 0 1 1
|
|
111
|
+
5e8ac1fe2b82_image,none 1 0 0 1 1
|
|
112
|
+
"""
|
|
113
|
+
rows = []
|
|
114
|
+
for idx, row in new_test_study.iterrows():
|
|
115
|
+
rows.append({"id": row["id"], "PredictionString": "negative 1 0 0 1 1"})
|
|
116
|
+
for idx, row in new_test_image.iterrows():
|
|
117
|
+
rows.append({"id": row["id"], "PredictionString": "none 1 0 0 1 1"})
|
|
118
|
+
|
|
119
|
+
sample_submission = pd.DataFrame(rows)
|
|
120
|
+
assert len(sample_submission) == len(new_test_study) + len(
|
|
121
|
+
new_test_image
|
|
122
|
+
), f"Expected {len(new_test_study) + len(new_test_image)} answers"
|
|
123
|
+
sample_submission.to_csv(public / "sample_submission.csv", index=False)
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import shutil
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
import pandas as pd
|
|
5
|
+
from sklearn.model_selection import train_test_split
|
|
6
|
+
from tqdm import tqdm
|
|
7
|
+
|
|
8
|
+
from mlebench.utils import read_csv
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def _process_split(
|
|
12
|
+
train_study_df: pd.DataFrame,
|
|
13
|
+
test_study_df: pd.DataFrame,
|
|
14
|
+
full_image_df: pd.DataFrame,
|
|
15
|
+
raw_data_root: Path,
|
|
16
|
+
output_public_path: Path,
|
|
17
|
+
output_private_path: Path,
|
|
18
|
+
dev_mode: bool,
|
|
19
|
+
):
|
|
20
|
+
"""
|
|
21
|
+
Helper function to process a single data split and generate all required output files.
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
train_study_df: DataFrame of studies for the training set.
|
|
25
|
+
test_study_df: DataFrame of studies for the test set.
|
|
26
|
+
full_image_df: DataFrame of all images, to be filtered for this split.
|
|
27
|
+
raw_data_root: Path to the original raw data.
|
|
28
|
+
output_public_path: Path to the public output directory.
|
|
29
|
+
output_private_path: Path to the private output directory.
|
|
30
|
+
dev_mode: Boolean flag for development mode.
|
|
31
|
+
"""
|
|
32
|
+
# Create output directories if they don't exist
|
|
33
|
+
output_public_path.mkdir(parents=True, exist_ok=True)
|
|
34
|
+
(output_public_path / "train").mkdir(exist_ok=True)
|
|
35
|
+
(output_public_path / "test").mkdir(exist_ok=True)
|
|
36
|
+
output_private_path.mkdir(parents=True, exist_ok=True)
|
|
37
|
+
|
|
38
|
+
# Save the study-level train CSV
|
|
39
|
+
train_study_df.to_csv(output_public_path / "train_study_level.csv", index=False)
|
|
40
|
+
|
|
41
|
+
# Filter and save the image-level CSVs based on the study split
|
|
42
|
+
split_train_image = full_image_df[
|
|
43
|
+
(full_image_df["StudyInstanceUID"] + "_study").isin(train_study_df["id"])
|
|
44
|
+
]
|
|
45
|
+
split_test_image = full_image_df[
|
|
46
|
+
(full_image_df["StudyInstanceUID"] + "_study").isin(test_study_df["id"])
|
|
47
|
+
]
|
|
48
|
+
split_train_image = split_train_image.sort_values(by="id")
|
|
49
|
+
split_test_image = split_test_image.sort_values(by="id")
|
|
50
|
+
if not dev_mode:
|
|
51
|
+
assert len(split_train_image) + len(split_test_image) == len(
|
|
52
|
+
full_image_df[
|
|
53
|
+
(full_image_df["StudyInstanceUID"] + "_study").isin(
|
|
54
|
+
pd.concat([train_study_df["id"], test_study_df["id"]])
|
|
55
|
+
)
|
|
56
|
+
]
|
|
57
|
+
), f"Image split mismatch"
|
|
58
|
+
split_train_image.to_csv(output_public_path / "train_image_level.csv", index=False)
|
|
59
|
+
|
|
60
|
+
# Copy image data for the split
|
|
61
|
+
for study_id in tqdm(train_study_df["id"], desc=f"Copying train data to {output_public_path.name}"):
|
|
62
|
+
study_id = study_id.replace("_study", "")
|
|
63
|
+
shutil.copytree(raw_data_root / "train" / study_id, output_public_path / "train" / study_id, dirs_exist_ok=True)
|
|
64
|
+
for study_id in tqdm(test_study_df["id"], desc=f"Copying test data to {output_public_path.name}"):
|
|
65
|
+
study_id = study_id.replace("_study", "")
|
|
66
|
+
shutil.copytree(raw_data_root / "train" / study_id, output_public_path / "test" / study_id, dirs_exist_ok=True)
|
|
67
|
+
|
|
68
|
+
assert len(list(output_public_path.glob("train/*"))) == len(
|
|
69
|
+
train_study_df
|
|
70
|
+
), f"Expected {len(train_study_df)} studies in {output_public_path.name}/train"
|
|
71
|
+
assert len(list(output_public_path.glob("test/*"))) == len(
|
|
72
|
+
test_study_df
|
|
73
|
+
), f"Expected {len(test_study_df)} studies in {output_public_path.name}/test"
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
# Create gold answer submission for the test set
|
|
77
|
+
rows = []
|
|
78
|
+
for idx, row in test_study_df.iterrows():
|
|
79
|
+
label = ["negative", "typical", "indeterminate", "atypical"][row[1:].argmax()]
|
|
80
|
+
rows.append({"id": row["id"], "PredictionString": f"{label} 1 0 0 1 1"})
|
|
81
|
+
for idx, row in split_test_image.iterrows():
|
|
82
|
+
rows.append({"id": row["id"], "PredictionString": row["label"]})
|
|
83
|
+
|
|
84
|
+
answers = pd.DataFrame(rows)
|
|
85
|
+
assert len(answers) == len(test_study_df) + len(
|
|
86
|
+
split_test_image
|
|
87
|
+
), f"Expected {len(test_study_df) + len(split_test_image)} answers"
|
|
88
|
+
answers.to_csv(output_private_path / "test.csv", index=False)
|
|
89
|
+
|
|
90
|
+
# Create sample submission for the test set
|
|
91
|
+
rows = []
|
|
92
|
+
for idx, row in test_study_df.iterrows():
|
|
93
|
+
rows.append({"id": row["id"], "PredictionString": "negative 1 0 0 1 1"})
|
|
94
|
+
for idx, row in split_test_image.iterrows():
|
|
95
|
+
rows.append({"id": row["id"], "PredictionString": "none 1 0 0 1 1"})
|
|
96
|
+
|
|
97
|
+
sample_submission = pd.DataFrame(rows)
|
|
98
|
+
assert len(sample_submission) == len(test_study_df) + len(
|
|
99
|
+
split_test_image
|
|
100
|
+
), f"Expected {len(test_study_df) + len(split_test_image)} sample answers"
|
|
101
|
+
sample_submission.to_csv(output_public_path / "sample_submission.csv", index=False)
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def prepare(raw: Path, public: Path, private: Path):
|
|
105
|
+
"""
|
|
106
|
+
There are two tasks:
|
|
107
|
+
- Image level: Object detection problem - detect the presence of pneumonia in the image using bounding boxes
|
|
108
|
+
- Study level: Classification problem - classify the study into one of the four classes
|
|
109
|
+
|
|
110
|
+
Images in train/ and test/ are stored in paths with the form {study}/{series}/{image}.
|
|
111
|
+
|
|
112
|
+
Original train has 6,334 samples, and test "is of roughly the same scale as the training dataset".
|
|
113
|
+
We'll split the original train into a new train/test split with 90/10 ratio.
|
|
114
|
+
|
|
115
|
+
The split happens at the study level, with image level following accordingly.
|
|
116
|
+
"""
|
|
117
|
+
DEV_MODE = False
|
|
118
|
+
|
|
119
|
+
# Read the original full datasets
|
|
120
|
+
train_study = read_csv(raw / "train_study_level.csv")
|
|
121
|
+
train_image = read_csv(raw / "train_image_level.csv")
|
|
122
|
+
|
|
123
|
+
if DEV_MODE:
|
|
124
|
+
# randomly sample 200 rows for development
|
|
125
|
+
train_study = train_study.sample(n=200, random_state=0)
|
|
126
|
+
|
|
127
|
+
# --- First Split: Create the main train/test sets ---
|
|
128
|
+
# This split creates the primary competition data, saved to `public` and `private`.
|
|
129
|
+
new_train_study, new_test_study = train_test_split(train_study, test_size=0.1, random_state=0)
|
|
130
|
+
new_train_study = new_train_study.sort_values(by="id").reset_index(drop=True)
|
|
131
|
+
new_test_study = new_test_study.sort_values(by="id").reset_index(drop=True)
|
|
132
|
+
|
|
133
|
+
_process_split(
|
|
134
|
+
train_study_df=new_train_study,
|
|
135
|
+
test_study_df=new_test_study,
|
|
136
|
+
full_image_df=train_image,
|
|
137
|
+
raw_data_root=raw,
|
|
138
|
+
output_public_path=public,
|
|
139
|
+
output_private_path=private,
|
|
140
|
+
dev_mode=DEV_MODE,
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
# --- Second Split: Create the validation train/test sets ---
|
|
144
|
+
# This split takes the *training set* from the first split (`new_train_study`)
|
|
145
|
+
# and splits it again to create a validation set. The outputs are saved to
|
|
146
|
+
# parallel `public_val` and `private_val` directories.
|
|
147
|
+
public_val = public.parent / "public_val"
|
|
148
|
+
private_val = private.parent / "private_val"
|
|
149
|
+
|
|
150
|
+
# We use the exact same splitting parameters to maintain consistency.
|
|
151
|
+
# The new test set (`test_val_study`) will be 10% of the `new_train_study`.
|
|
152
|
+
train_val_study, test_val_study = train_test_split(new_train_study, test_size=0.1, random_state=0)
|
|
153
|
+
train_val_study = train_val_study.sort_values(by="id").reset_index(drop=True)
|
|
154
|
+
test_val_study = test_val_study.sort_values(by="id").reset_index(drop=True)
|
|
155
|
+
|
|
156
|
+
_process_split(
|
|
157
|
+
train_study_df=train_val_study,
|
|
158
|
+
test_study_df=test_val_study,
|
|
159
|
+
full_image_df=train_image, # The full image set is used for filtering
|
|
160
|
+
raw_data_root=raw,
|
|
161
|
+
output_public_path=public_val,
|
|
162
|
+
output_private_path=private_val,
|
|
163
|
+
dev_mode=DEV_MODE,
|
|
164
|
+
)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import pandas as pd
|
|
2
|
+
from sklearn.metrics import roc_auc_score
|
|
3
|
+
|
|
4
|
+
from mlebench.competitions.utils import prepare_for_auroc_metric
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def grade(submission: pd.DataFrame, answers: pd.DataFrame) -> float:
|
|
8
|
+
roc_auc_inputs = prepare_for_auroc_metric(
|
|
9
|
+
submission, answers, id_col="image_name", target_col="target"
|
|
10
|
+
)
|
|
11
|
+
return roc_auc_score(y_true=roc_auc_inputs["y_true"], y_score=roc_auc_inputs["y_score"])
|