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.
Files changed (352) hide show
  1. dslighting/__init__.py +1 -1
  2. dslighting/core/agent.py +78 -62
  3. {dslighting-1.7.1.dist-info → dslighting-1.7.8.dist-info}/METADATA +3 -1
  4. {dslighting-1.7.1.dist-info → dslighting-1.7.8.dist-info}/RECORD +352 -7
  5. {dslighting-1.7.1.dist-info → dslighting-1.7.8.dist-info}/top_level.txt +1 -0
  6. mlebench/README.md +39 -0
  7. mlebench/__init__.py +0 -0
  8. mlebench/cli.py +221 -0
  9. mlebench/competitions/3d-object-detection-for-autonomous-vehicles/grade.py +161 -0
  10. mlebench/competitions/3d-object-detection-for-autonomous-vehicles/mAP_evaluation.py +425 -0
  11. mlebench/competitions/3d-object-detection-for-autonomous-vehicles/prepare.py +483 -0
  12. mlebench/competitions/3d-object-detection-for-autonomous-vehicles/prepare_val.py +719 -0
  13. mlebench/competitions/AI4Code/grade.py +70 -0
  14. mlebench/competitions/AI4Code/prepare.py +84 -0
  15. mlebench/competitions/AI4Code/prepare_val.py +159 -0
  16. mlebench/competitions/__init__.py +0 -0
  17. mlebench/competitions/aerial-cactus-identification/grade.py +11 -0
  18. mlebench/competitions/aerial-cactus-identification/prepare.py +71 -0
  19. mlebench/competitions/aerial-cactus-identification/prepare_val.py +133 -0
  20. mlebench/competitions/alaska2-image-steganalysis/grade.py +136 -0
  21. mlebench/competitions/alaska2-image-steganalysis/prepare.py +88 -0
  22. mlebench/competitions/alaska2-image-steganalysis/prepare_val.py +148 -0
  23. mlebench/competitions/aptos2019-blindness-detection/grade.py +35 -0
  24. mlebench/competitions/aptos2019-blindness-detection/prepare.py +75 -0
  25. mlebench/competitions/aptos2019-blindness-detection/prepare_val.py +123 -0
  26. mlebench/competitions/bike-sharing-demand/__init__.py +0 -0
  27. mlebench/competitions/bike-sharing-demand/grade.py +55 -0
  28. mlebench/competitions/bike-sharing-demand/prepare.py +37 -0
  29. mlebench/competitions/billion-word-imputation/grade.py +37 -0
  30. mlebench/competitions/billion-word-imputation/prepare.py +107 -0
  31. mlebench/competitions/billion-word-imputation/prepare_val.py +179 -0
  32. mlebench/competitions/bms-molecular-translation/grade.py +40 -0
  33. mlebench/competitions/bms-molecular-translation/prepare.py +68 -0
  34. mlebench/competitions/bms-molecular-translation/prepare_val.py +131 -0
  35. mlebench/competitions/cassava-leaf-disease-classification/grade.py +12 -0
  36. mlebench/competitions/cassava-leaf-disease-classification/prepare.py +113 -0
  37. mlebench/competitions/cassava-leaf-disease-classification/prepare_val.py +186 -0
  38. mlebench/competitions/cdiscount-image-classification-challenge/grade.py +11 -0
  39. mlebench/competitions/cdiscount-image-classification-challenge/prepare.py +144 -0
  40. mlebench/competitions/cdiscount-image-classification-challenge/prepare_val.py +205 -0
  41. mlebench/competitions/chaii-hindi-and-tamil-question-answering/grade.py +67 -0
  42. mlebench/competitions/chaii-hindi-and-tamil-question-answering/prepare.py +31 -0
  43. mlebench/competitions/chaii-hindi-and-tamil-question-answering/prepare_val.py +94 -0
  44. mlebench/competitions/champs-scalar-coupling/grade.py +60 -0
  45. mlebench/competitions/champs-scalar-coupling/prepare.py +116 -0
  46. mlebench/competitions/champs-scalar-coupling/prepare_val.py +155 -0
  47. mlebench/competitions/conways-reverse-game-of-life-2020/__init__.py +0 -0
  48. mlebench/competitions/conways-reverse-game-of-life-2020/grade.py +40 -0
  49. mlebench/competitions/conways-reverse-game-of-life-2020/prepare.py +41 -0
  50. mlebench/competitions/demand-forecasting-kernels-only/__init__.py +0 -0
  51. mlebench/competitions/demand-forecasting-kernels-only/grade.py +66 -0
  52. mlebench/competitions/demand-forecasting-kernels-only/prepare.py +27 -0
  53. mlebench/competitions/demand_forecasting_kernels_only/__init__.py +0 -0
  54. mlebench/competitions/demand_forecasting_kernels_only/grade.py +66 -0
  55. mlebench/competitions/demand_forecasting_kernels_only/prepare.py +27 -0
  56. mlebench/competitions/denoising-dirty-documents/grade.py +44 -0
  57. mlebench/competitions/denoising-dirty-documents/prepare.py +134 -0
  58. mlebench/competitions/denoising-dirty-documents/prepare_val.py +178 -0
  59. mlebench/competitions/detecting-insults-in-social-commentary/grade.py +11 -0
  60. mlebench/competitions/detecting-insults-in-social-commentary/prepare.py +72 -0
  61. mlebench/competitions/detecting-insults-in-social-commentary/prepare_val.py +128 -0
  62. mlebench/competitions/dog-breed-identification/dogs.py +124 -0
  63. mlebench/competitions/dog-breed-identification/grade.py +42 -0
  64. mlebench/competitions/dog-breed-identification/prepare.py +55 -0
  65. mlebench/competitions/dog-breed-identification/prepare_val.py +104 -0
  66. mlebench/competitions/dogs-vs-cats-redux-kernels-edition/grade.py +43 -0
  67. mlebench/competitions/dogs-vs-cats-redux-kernels-edition/prepare.py +70 -0
  68. mlebench/competitions/dogs-vs-cats-redux-kernels-edition/prepare_val.py +143 -0
  69. mlebench/competitions/ethanol-concentration/grade.py +23 -0
  70. mlebench/competitions/ethanol-concentration/prepare.py +90 -0
  71. mlebench/competitions/facebook-recruiting-iii-keyword-extraction/grade.py +60 -0
  72. mlebench/competitions/facebook-recruiting-iii-keyword-extraction/prepare.py +41 -0
  73. mlebench/competitions/facebook-recruiting-iii-keyword-extraction/prepare_val.py +92 -0
  74. mlebench/competitions/feedback-prize-english-language-learning/__init__.py +0 -0
  75. mlebench/competitions/feedback-prize-english-language-learning/grade.py +60 -0
  76. mlebench/competitions/feedback-prize-english-language-learning/prepare.py +39 -0
  77. mlebench/competitions/freesound-audio-tagging-2019/grade.py +64 -0
  78. mlebench/competitions/freesound-audio-tagging-2019/prepare.py +94 -0
  79. mlebench/competitions/freesound-audio-tagging-2019/prepare_val.py +175 -0
  80. mlebench/competitions/freesound-audio-tagging-2019/vocabulary.py +83 -0
  81. mlebench/competitions/google-quest-challenge/classes.py +32 -0
  82. mlebench/competitions/google-quest-challenge/grade.py +45 -0
  83. mlebench/competitions/google-quest-challenge/prepare.py +58 -0
  84. mlebench/competitions/google-quest-challenge/prepare_val.py +120 -0
  85. mlebench/competitions/google-research-identify-contrails-reduce-global-warming/grade.py +77 -0
  86. mlebench/competitions/google-research-identify-contrails-reduce-global-warming/prepare.py +155 -0
  87. mlebench/competitions/google-research-identify-contrails-reduce-global-warming/prepare_val.py +211 -0
  88. mlebench/competitions/h-and-m-personalized-fashion-recommendations/grade.py +42 -0
  89. mlebench/competitions/h-and-m-personalized-fashion-recommendations/prepare.py +102 -0
  90. mlebench/competitions/h-and-m-personalized-fashion-recommendations/prepare_val.py +132 -0
  91. mlebench/competitions/handwriting/grade.py +23 -0
  92. mlebench/competitions/handwriting/prepare.py +179 -0
  93. mlebench/competitions/herbarium-2020-fgvc7/grade.py +34 -0
  94. mlebench/competitions/herbarium-2020-fgvc7/prepare.py +251 -0
  95. mlebench/competitions/herbarium-2020-fgvc7/prepare_val.py +242 -0
  96. mlebench/competitions/herbarium-2021-fgvc8/grade.py +34 -0
  97. mlebench/competitions/herbarium-2021-fgvc8/prepare.py +251 -0
  98. mlebench/competitions/herbarium-2021-fgvc8/prepare_val.py +222 -0
  99. mlebench/competitions/herbarium-2022-fgvc9/grade.py +31 -0
  100. mlebench/competitions/herbarium-2022-fgvc9/prepare.py +233 -0
  101. mlebench/competitions/herbarium-2022-fgvc9/prepare_val.py +213 -0
  102. mlebench/competitions/histopathologic-cancer-detection/grade.py +12 -0
  103. mlebench/competitions/histopathologic-cancer-detection/prepare.py +59 -0
  104. mlebench/competitions/histopathologic-cancer-detection/prepare_val.py +131 -0
  105. mlebench/competitions/hms-harmful-brain-activity-classification/constants.py +9 -0
  106. mlebench/competitions/hms-harmful-brain-activity-classification/grade.py +43 -0
  107. mlebench/competitions/hms-harmful-brain-activity-classification/kaggle_metric_utilities.py +96 -0
  108. mlebench/competitions/hms-harmful-brain-activity-classification/kullback_leibler_divergence.py +118 -0
  109. mlebench/competitions/hms-harmful-brain-activity-classification/prepare.py +121 -0
  110. mlebench/competitions/hms-harmful-brain-activity-classification/prepare_val.py +190 -0
  111. mlebench/competitions/hotel-id-2021-fgvc8/grade.py +41 -0
  112. mlebench/competitions/hotel-id-2021-fgvc8/prepare.py +63 -0
  113. mlebench/competitions/hotel-id-2021-fgvc8/prepare_val.py +132 -0
  114. mlebench/competitions/hubmap-kidney-segmentation/grade.py +62 -0
  115. mlebench/competitions/hubmap-kidney-segmentation/prepare.py +108 -0
  116. mlebench/competitions/hubmap-kidney-segmentation/prepare_val.py +153 -0
  117. mlebench/competitions/icecube-neutrinos-in-deep-ice/grade.py +111 -0
  118. mlebench/competitions/icecube-neutrinos-in-deep-ice/prepare.py +127 -0
  119. mlebench/competitions/icecube-neutrinos-in-deep-ice/prepare_val.py +183 -0
  120. mlebench/competitions/ili/grade.py +60 -0
  121. mlebench/competitions/ili/prepare.py +99 -0
  122. mlebench/competitions/imet-2020-fgvc7/grade.py +54 -0
  123. mlebench/competitions/imet-2020-fgvc7/prepare.py +77 -0
  124. mlebench/competitions/imet-2020-fgvc7/prepare_val.py +157 -0
  125. mlebench/competitions/inaturalist-2019-fgvc6/grade.py +35 -0
  126. mlebench/competitions/inaturalist-2019-fgvc6/prepare.py +259 -0
  127. mlebench/competitions/inaturalist-2019-fgvc6/prepare_val.py +304 -0
  128. mlebench/competitions/instant-gratification/__init__.py +0 -0
  129. mlebench/competitions/instant-gratification/grade.py +55 -0
  130. mlebench/competitions/instant-gratification/prepare.py +25 -0
  131. mlebench/competitions/instant_gratification/__init__.py +0 -0
  132. mlebench/competitions/instant_gratification/grade.py +55 -0
  133. mlebench/competitions/instant_gratification/prepare.py +25 -0
  134. mlebench/competitions/invasive-species-monitoring/grade.py +11 -0
  135. mlebench/competitions/invasive-species-monitoring/prepare.py +97 -0
  136. mlebench/competitions/invasive-species-monitoring/prepare_val.py +164 -0
  137. mlebench/competitions/iwildcam-2019-fgvc6/grade.py +44 -0
  138. mlebench/competitions/iwildcam-2019-fgvc6/prepare.py +118 -0
  139. mlebench/competitions/iwildcam-2019-fgvc6/prepare_val.py +194 -0
  140. mlebench/competitions/iwildcam-2020-fgvc7/grade.py +11 -0
  141. mlebench/competitions/iwildcam-2020-fgvc7/prepare.py +164 -0
  142. mlebench/competitions/iwildcam-2020-fgvc7/prepare_val.py +245 -0
  143. mlebench/competitions/jigsaw-toxic-comment-classification-challenge/classes.py +1 -0
  144. mlebench/competitions/jigsaw-toxic-comment-classification-challenge/grade.py +54 -0
  145. mlebench/competitions/jigsaw-toxic-comment-classification-challenge/prepare.py +42 -0
  146. mlebench/competitions/jigsaw-toxic-comment-classification-challenge/prepare_val.py +88 -0
  147. mlebench/competitions/jigsaw-unintended-bias-in-toxicity-classification/grade.py +153 -0
  148. mlebench/competitions/jigsaw-unintended-bias-in-toxicity-classification/prepare.py +36 -0
  149. mlebench/competitions/jigsaw-unintended-bias-in-toxicity-classification/prepare_val.py +117 -0
  150. mlebench/competitions/kuzushiji-recognition/grade.py +58 -0
  151. mlebench/competitions/kuzushiji-recognition/kuzushiji_metric.py +118 -0
  152. mlebench/competitions/kuzushiji-recognition/prepare.py +92 -0
  153. mlebench/competitions/kuzushiji-recognition/prepare_val.py +149 -0
  154. mlebench/competitions/leaf-classification/classes.py +101 -0
  155. mlebench/competitions/leaf-classification/grade.py +44 -0
  156. mlebench/competitions/leaf-classification/prepare.py +60 -0
  157. mlebench/competitions/leaf-classification/prepare_val.py +116 -0
  158. mlebench/competitions/learning-agency-lab-automated-essay-scoring-2/grade.py +44 -0
  159. mlebench/competitions/learning-agency-lab-automated-essay-scoring-2/prepare.py +51 -0
  160. mlebench/competitions/learning-agency-lab-automated-essay-scoring-2/prepare_val.py +96 -0
  161. mlebench/competitions/liverpool-ion-switching/__init__.py +0 -0
  162. mlebench/competitions/liverpool-ion-switching/grade.py +52 -0
  163. mlebench/competitions/liverpool-ion-switching/prepare.py +27 -0
  164. mlebench/competitions/liverpool_ion_switching/__init__.py +0 -0
  165. mlebench/competitions/liverpool_ion_switching/grade.py +52 -0
  166. mlebench/competitions/liverpool_ion_switching/prepare.py +27 -0
  167. mlebench/competitions/lmsys-chatbot-arena/grade.py +63 -0
  168. mlebench/competitions/lmsys-chatbot-arena/prepare.py +52 -0
  169. mlebench/competitions/lmsys-chatbot-arena/prepare_val.py +115 -0
  170. mlebench/competitions/mcm_2024_c_test/grade.py +107 -0
  171. mlebench/competitions/mcm_2024_c_test/prepare.py +2 -0
  172. mlebench/competitions/ml2021spring-hw2/grade.py +11 -0
  173. mlebench/competitions/ml2021spring-hw2/prepare.py +58 -0
  174. mlebench/competitions/ml2021spring-hw2/prepare_val.py +135 -0
  175. mlebench/competitions/mlsp-2013-birds/grade.py +11 -0
  176. mlebench/competitions/mlsp-2013-birds/prepare.py +182 -0
  177. mlebench/competitions/mlsp-2013-birds/prepare_val.py +241 -0
  178. mlebench/competitions/movie-review-sentiment-analysis-kernels-only/grade.py +11 -0
  179. mlebench/competitions/movie-review-sentiment-analysis-kernels-only/prepare.py +58 -0
  180. mlebench/competitions/movie-review-sentiment-analysis-kernels-only/prepare_val.py +120 -0
  181. mlebench/competitions/multi-modal-gesture-recognition/grade.py +58 -0
  182. mlebench/competitions/multi-modal-gesture-recognition/prepare.py +85 -0
  183. mlebench/competitions/multi-modal-gesture-recognition/prepare_val.py +139 -0
  184. mlebench/competitions/my-custom-task-01/prepare.py +2 -0
  185. mlebench/competitions/new-my-task-01/prepare.py +2 -0
  186. mlebench/competitions/new-my-task-03/grade.py +107 -0
  187. mlebench/competitions/new-my-task-03/prepare.py +2 -0
  188. mlebench/competitions/new-york-city-taxi-fare-prediction/grade.py +28 -0
  189. mlebench/competitions/new-york-city-taxi-fare-prediction/prepare.py +44 -0
  190. mlebench/competitions/new-york-city-taxi-fare-prediction/prepare_val.py +89 -0
  191. mlebench/competitions/nfl-player-contact-detection/grade.py +36 -0
  192. mlebench/competitions/nfl-player-contact-detection/prepare.py +101 -0
  193. mlebench/competitions/nfl-player-contact-detection/prepare_val.py +186 -0
  194. mlebench/competitions/nomad2018-predict-transparent-conductors/grade.py +47 -0
  195. mlebench/competitions/nomad2018-predict-transparent-conductors/prepare.py +77 -0
  196. mlebench/competitions/nomad2018-predict-transparent-conductors/prepare_val.py +144 -0
  197. mlebench/competitions/osic-pulmonary-fibrosis-progression/grade.py +74 -0
  198. mlebench/competitions/osic-pulmonary-fibrosis-progression/prepare.py +95 -0
  199. mlebench/competitions/osic-pulmonary-fibrosis-progression/prepare_val.py +167 -0
  200. mlebench/competitions/paddy-disease-classification/grade.py +35 -0
  201. mlebench/competitions/paddy-disease-classification/prepare.py +69 -0
  202. mlebench/competitions/paddy-disease-classification/prepare_val.py +122 -0
  203. mlebench/competitions/petfinder-pawpularity-score/grade.py +41 -0
  204. mlebench/competitions/petfinder-pawpularity-score/prepare.py +76 -0
  205. mlebench/competitions/petfinder-pawpularity-score/prepare_val.py +154 -0
  206. mlebench/competitions/plant-pathology-2020-fgvc7/grade.py +41 -0
  207. mlebench/competitions/plant-pathology-2020-fgvc7/prepare.py +74 -0
  208. mlebench/competitions/plant-pathology-2020-fgvc7/prepare_val.py +160 -0
  209. mlebench/competitions/plant-pathology-2021-fgvc8/grade.py +54 -0
  210. mlebench/competitions/plant-pathology-2021-fgvc8/prepare.py +65 -0
  211. mlebench/competitions/plant-pathology-2021-fgvc8/prepare_val.py +130 -0
  212. mlebench/competitions/plant-seedlings-classification/grade.py +39 -0
  213. mlebench/competitions/plant-seedlings-classification/prepare.py +91 -0
  214. mlebench/competitions/plant-seedlings-classification/prepare_val.py +158 -0
  215. mlebench/competitions/playground-series-s3e1/__init__.py +0 -0
  216. mlebench/competitions/playground-series-s3e1/grade.py +52 -0
  217. mlebench/competitions/playground-series-s3e1/prepare.py +25 -0
  218. mlebench/competitions/playground-series-s3e11/__init__.py +0 -0
  219. mlebench/competitions/playground-series-s3e11/grade.py +55 -0
  220. mlebench/competitions/playground-series-s3e11/prepare.py +25 -0
  221. mlebench/competitions/playground-series-s3e18/grade.py +39 -0
  222. mlebench/competitions/playground-series-s3e18/prepare.py +36 -0
  223. mlebench/competitions/playground-series-s3e18/prepare_val.py +89 -0
  224. mlebench/competitions/playground_series_s3e1/__init__.py +0 -0
  225. mlebench/competitions/playground_series_s3e1/grade.py +52 -0
  226. mlebench/competitions/playground_series_s3e1/prepare.py +25 -0
  227. mlebench/competitions/playground_series_s3e11/__init__.py +0 -0
  228. mlebench/competitions/playground_series_s3e11/grade.py +55 -0
  229. mlebench/competitions/playground_series_s3e11/prepare.py +25 -0
  230. mlebench/competitions/predict-volcanic-eruptions-ingv-oe/grade.py +44 -0
  231. mlebench/competitions/predict-volcanic-eruptions-ingv-oe/prepare.py +68 -0
  232. mlebench/competitions/predict-volcanic-eruptions-ingv-oe/prepare_val.py +146 -0
  233. mlebench/competitions/random-acts-of-pizza/grade.py +14 -0
  234. mlebench/competitions/random-acts-of-pizza/prepare.py +80 -0
  235. mlebench/competitions/random-acts-of-pizza/prepare_val.py +144 -0
  236. mlebench/competitions/ranzcr-clip-catheter-line-classification/classes.py +11 -0
  237. mlebench/competitions/ranzcr-clip-catheter-line-classification/grade.py +31 -0
  238. mlebench/competitions/ranzcr-clip-catheter-line-classification/prepare.py +53 -0
  239. mlebench/competitions/ranzcr-clip-catheter-line-classification/prepare_val.py +113 -0
  240. mlebench/competitions/rsna-2022-cervical-spine-fracture-detection/grade.py +124 -0
  241. mlebench/competitions/rsna-2022-cervical-spine-fracture-detection/prepare.py +219 -0
  242. mlebench/competitions/rsna-2022-cervical-spine-fracture-detection/prepare_val.py +257 -0
  243. mlebench/competitions/rsna-breast-cancer-detection/grade.py +65 -0
  244. mlebench/competitions/rsna-breast-cancer-detection/prepare.py +141 -0
  245. mlebench/competitions/rsna-breast-cancer-detection/prepare_val.py +201 -0
  246. mlebench/competitions/rsna-miccai-brain-tumor-radiogenomic-classification/grade.py +13 -0
  247. mlebench/competitions/rsna-miccai-brain-tumor-radiogenomic-classification/prepare.py +47 -0
  248. mlebench/competitions/rsna-miccai-brain-tumor-radiogenomic-classification/prepare_val.py +97 -0
  249. mlebench/competitions/santander-customer-satisfaction/grade.py +10 -0
  250. mlebench/competitions/santander-customer-satisfaction/prepare.py +41 -0
  251. mlebench/competitions/sciencebench-001-clintox-nn/__init__.py +0 -0
  252. mlebench/competitions/sciencebench-001-clintox-nn/grade.py +56 -0
  253. mlebench/competitions/sciencebench-001-clintox-nn/prepare.py +75 -0
  254. mlebench/competitions/sciencebench-015-aai/grade.py +37 -0
  255. mlebench/competitions/sciencebench-015-aai/prepare.py +102 -0
  256. mlebench/competitions/sciencebench-051-brain-blood-qsar/grade.py +58 -0
  257. mlebench/competitions/sciencebench-051-brain-blood-qsar/prepare.py +69 -0
  258. mlebench/competitions/sciencebench-101-experimental-band-gap-prediction/grade.py +55 -0
  259. mlebench/competitions/sciencebench-101-experimental-band-gap-prediction/prepare.py +88 -0
  260. mlebench/competitions/see-click-predict-fix/__init__.py +0 -0
  261. mlebench/competitions/see-click-predict-fix/grade.py +66 -0
  262. mlebench/competitions/see-click-predict-fix/prepare.py +25 -0
  263. mlebench/competitions/see_click_predict_fix/__init__.py +0 -0
  264. mlebench/competitions/see_click_predict_fix/grade.py +66 -0
  265. mlebench/competitions/see_click_predict_fix/prepare.py +25 -0
  266. mlebench/competitions/seti-breakthrough-listen/grade.py +11 -0
  267. mlebench/competitions/seti-breakthrough-listen/prepare.py +71 -0
  268. mlebench/competitions/seti-breakthrough-listen/prepare_val.py +159 -0
  269. mlebench/competitions/siim-covid19-detection/grade.py +194 -0
  270. mlebench/competitions/siim-covid19-detection/prepare.py +123 -0
  271. mlebench/competitions/siim-covid19-detection/prepare_val.py +164 -0
  272. mlebench/competitions/siim-isic-melanoma-classification/grade.py +11 -0
  273. mlebench/competitions/siim-isic-melanoma-classification/prepare.py +127 -0
  274. mlebench/competitions/siim-isic-melanoma-classification/prepare_val.py +158 -0
  275. mlebench/competitions/smartphone-decimeter-2022/grade.py +55 -0
  276. mlebench/competitions/smartphone-decimeter-2022/notebook.py +86 -0
  277. mlebench/competitions/smartphone-decimeter-2022/prepare.py +143 -0
  278. mlebench/competitions/smartphone-decimeter-2022/prepare_val.py +199 -0
  279. mlebench/competitions/spaceship-titanic/grade.py +11 -0
  280. mlebench/competitions/spaceship-titanic/prepare.py +23 -0
  281. mlebench/competitions/spaceship-titanic/prepare_val.py +61 -0
  282. mlebench/competitions/spooky-author-identification/classes.py +1 -0
  283. mlebench/competitions/spooky-author-identification/grade.py +38 -0
  284. mlebench/competitions/spooky-author-identification/prepare.py +40 -0
  285. mlebench/competitions/spooky-author-identification/prepare_val.py +78 -0
  286. mlebench/competitions/stanford-covid-vaccine/grade.py +65 -0
  287. mlebench/competitions/stanford-covid-vaccine/prepare.py +129 -0
  288. mlebench/competitions/stanford-covid-vaccine/prepare_val.py +199 -0
  289. mlebench/competitions/statoil-iceberg-classifier-challenge/grade.py +41 -0
  290. mlebench/competitions/statoil-iceberg-classifier-challenge/prepare.py +105 -0
  291. mlebench/competitions/statoil-iceberg-classifier-challenge/prepare_val.py +157 -0
  292. mlebench/competitions/tabular-playground-series-dec-2021/grade.py +11 -0
  293. mlebench/competitions/tabular-playground-series-dec-2021/prepare.py +39 -0
  294. mlebench/competitions/tabular-playground-series-dec-2021/prepare_val.py +99 -0
  295. mlebench/competitions/tabular-playground-series-may-2022/grade.py +9 -0
  296. mlebench/competitions/tabular-playground-series-may-2022/prepare.py +56 -0
  297. mlebench/competitions/tabular-playground-series-may-2022/prepare_val.py +116 -0
  298. mlebench/competitions/tensorflow-speech-recognition-challenge/grade.py +11 -0
  299. mlebench/competitions/tensorflow-speech-recognition-challenge/prepare.py +90 -0
  300. mlebench/competitions/tensorflow-speech-recognition-challenge/prepare_val.py +148 -0
  301. mlebench/competitions/tensorflow2-question-answering/grade.py +122 -0
  302. mlebench/competitions/tensorflow2-question-answering/prepare.py +122 -0
  303. mlebench/competitions/tensorflow2-question-answering/prepare_val.py +187 -0
  304. mlebench/competitions/text-normalization-challenge-english-language/grade.py +49 -0
  305. mlebench/competitions/text-normalization-challenge-english-language/prepare.py +115 -0
  306. mlebench/competitions/text-normalization-challenge-english-language/prepare_val.py +213 -0
  307. mlebench/competitions/text-normalization-challenge-russian-language/grade.py +49 -0
  308. mlebench/competitions/text-normalization-challenge-russian-language/prepare.py +113 -0
  309. mlebench/competitions/text-normalization-challenge-russian-language/prepare_val.py +165 -0
  310. mlebench/competitions/tgs-salt-identification-challenge/grade.py +144 -0
  311. mlebench/competitions/tgs-salt-identification-challenge/prepare.py +158 -0
  312. mlebench/competitions/tgs-salt-identification-challenge/prepare_val.py +166 -0
  313. mlebench/competitions/the-icml-2013-whale-challenge-right-whale-redux/grade.py +11 -0
  314. mlebench/competitions/the-icml-2013-whale-challenge-right-whale-redux/prepare.py +95 -0
  315. mlebench/competitions/the-icml-2013-whale-challenge-right-whale-redux/prepare_val.py +141 -0
  316. mlebench/competitions/tmdb-box-office-prediction/__init__.py +0 -0
  317. mlebench/competitions/tmdb-box-office-prediction/grade.py +55 -0
  318. mlebench/competitions/tmdb-box-office-prediction/prepare.py +35 -0
  319. mlebench/competitions/tweet-sentiment-extraction/grade.py +67 -0
  320. mlebench/competitions/tweet-sentiment-extraction/prepare.py +36 -0
  321. mlebench/competitions/tweet-sentiment-extraction/prepare_val.py +106 -0
  322. mlebench/competitions/us-patent-phrase-to-phrase-matching/grade.py +31 -0
  323. mlebench/competitions/us-patent-phrase-to-phrase-matching/prepare.py +33 -0
  324. mlebench/competitions/us-patent-phrase-to-phrase-matching/prepare_val.py +71 -0
  325. mlebench/competitions/utils.py +266 -0
  326. mlebench/competitions/uw-madison-gi-tract-image-segmentation/grade.py +158 -0
  327. mlebench/competitions/uw-madison-gi-tract-image-segmentation/prepare.py +139 -0
  328. mlebench/competitions/uw-madison-gi-tract-image-segmentation/prepare_val.py +193 -0
  329. mlebench/competitions/ventilator-pressure-prediction/__init__.py +0 -0
  330. mlebench/competitions/ventilator-pressure-prediction/grade.py +52 -0
  331. mlebench/competitions/ventilator-pressure-prediction/prepare.py +27 -0
  332. mlebench/competitions/ventilator-pressure-prediction/prepare_val.py +142 -0
  333. mlebench/competitions/ventilator_pressure_prediction/__init__.py +0 -0
  334. mlebench/competitions/ventilator_pressure_prediction/grade.py +52 -0
  335. mlebench/competitions/ventilator_pressure_prediction/prepare.py +27 -0
  336. mlebench/competitions/vesuvius-challenge-ink-detection/grade.py +97 -0
  337. mlebench/competitions/vesuvius-challenge-ink-detection/prepare.py +122 -0
  338. mlebench/competitions/vesuvius-challenge-ink-detection/prepare_val.py +170 -0
  339. mlebench/competitions/vinbigdata-chest-xray-abnormalities-detection/grade.py +220 -0
  340. mlebench/competitions/vinbigdata-chest-xray-abnormalities-detection/prepare.py +129 -0
  341. mlebench/competitions/vinbigdata-chest-xray-abnormalities-detection/prepare_val.py +204 -0
  342. mlebench/competitions/whale-categorization-playground/grade.py +41 -0
  343. mlebench/competitions/whale-categorization-playground/prepare.py +103 -0
  344. mlebench/competitions/whale-categorization-playground/prepare_val.py +196 -0
  345. mlebench/data.py +420 -0
  346. mlebench/grade.py +209 -0
  347. mlebench/grade_helpers.py +235 -0
  348. mlebench/metrics.py +75 -0
  349. mlebench/registry.py +332 -0
  350. mlebench/utils.py +346 -0
  351. {dslighting-1.7.1.dist-info → dslighting-1.7.8.dist-info}/WHEEL +0 -0
  352. {dslighting-1.7.1.dist-info → dslighting-1.7.8.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,106 @@
1
+ from pathlib import Path
2
+ import pandas as pd
3
+
4
+ from sklearn.model_selection import train_test_split
5
+
6
+ from mlebench.utils import read_csv
7
+
8
+
9
+ def _split_and_save(
10
+ source_df: pd.DataFrame,
11
+ test_size: float,
12
+ random_state: int,
13
+ public_dir: Path,
14
+ private_dir: Path,
15
+ label_col: str = "selected_text",
16
+ id_col: str = "textID",
17
+ ) -> tuple[pd.DataFrame, pd.DataFrame]:
18
+ """
19
+ Helper function to perform a train/test split and save the results.
20
+
21
+ Args:
22
+ source_df: The DataFrame to split.
23
+ test_size: The proportion of the dataset to allocate to the test split.
24
+ random_state: The seed used by the random number generator.
25
+ public_dir: The directory to save public artifacts (train set, unlabeled test set).
26
+ private_dir: The directory to save private artifacts (labeled test set).
27
+ label_col: The name of the column containing the label.
28
+ id_col: The name of the column containing the unique ID.
29
+
30
+ Returns:
31
+ A tuple containing the created train and test DataFrames.
32
+ """
33
+ # Ensure output directories exist
34
+ public_dir.mkdir(parents=True, exist_ok=True)
35
+ private_dir.mkdir(parents=True, exist_ok=True)
36
+
37
+ # Perform the split
38
+ train_df, test_df = train_test_split(
39
+ source_df, test_size=test_size, random_state=random_state
40
+ )
41
+ test_df_without_labels = test_df.drop(columns=[label_col])
42
+
43
+ # Save the datasets
44
+ train_df.to_csv(public_dir / "train.csv", index=False)
45
+ test_df.to_csv(private_dir / "test.csv", index=False)
46
+ test_df_without_labels.to_csv(public_dir / "test.csv", index=False)
47
+
48
+ assert len(test_df_without_labels) == len(
49
+ test_df
50
+ ), f"Expected test_df_without_labels ({len(test_df_without_labels)}) == test_df ({len(test_df)})"
51
+ assert len(train_df) + len(test_df) == len(
52
+ source_df
53
+ ), f"Expected train_df ({len(train_df)}) + test_df ({len(test_df)}) == source_df ({len(source_df)})"
54
+
55
+ # Create and save a sample submission file
56
+ submission_df = test_df.copy()[[id_col, label_col]]
57
+ submission_df[label_col] = ""
58
+
59
+ submission_df.to_csv(public_dir / "sample_submission.csv", index=False)
60
+ assert len(submission_df) == len(
61
+ test_df
62
+ ), f"Expected submission_df ({len(submission_df)}) == test_df ({len(test_df)})"
63
+
64
+ return train_df, test_df
65
+
66
+
67
+ def prepare(raw: Path, public: Path, private: Path):
68
+ """
69
+ Splits the data in raw into public and private datasets with appropriate test/train splits.
70
+ Also creates a second, parallel split for validation purposes.
71
+ """
72
+ old_train = read_csv(raw / "train.csv")
73
+
74
+ # ---- Original Data Split (for final test set) ----
75
+ # This split creates the main train and test sets for the competition.
76
+ # The outputs in `public` and `private` are left completely unchanged.
77
+ train_for_val_split, _ = _split_and_save(
78
+ source_df=old_train,
79
+ test_size=0.1,
80
+ random_state=0,
81
+ public_dir=public,
82
+ private_dir=private,
83
+ )
84
+
85
+ # ---- New Validation Data Split ----
86
+ # This second split takes the training set created above and splits it *again*
87
+ # to create a new, smaller training set and a validation set. The results are
88
+ # saved to parallel `public_val` and `private_val` directories.
89
+
90
+ # Define paths for the new validation split
91
+ public_val = public.parent / "public_val"
92
+ private_val = private.parent / "private_val"
93
+
94
+ # The original test set size was 0.1 of the total data. The new train set
95
+ # is 0.9 of the total. To make the new validation set (test_val) have
96
+ # roughly the same number of samples as the original test set, we use a
97
+ # test_size of (0.1 / 0.9) = 1/9.
98
+ validation_test_size = 1 / 9
99
+
100
+ _split_and_save(
101
+ source_df=train_for_val_split,
102
+ test_size=validation_test_size,
103
+ random_state=0, # Use same random_state for consistency
104
+ public_dir=public_val,
105
+ private_dir=private_val,
106
+ )
@@ -0,0 +1,31 @@
1
+ import pandas as pd
2
+ from scipy.stats import pearsonr
3
+
4
+ from mlebench.grade_helpers import InvalidSubmissionError
5
+
6
+
7
+ def prepare_for_metric(submission: pd.DataFrame, answers: pd.DataFrame) -> tuple:
8
+ """
9
+ `submission` and `answers` are pd.DataFrames with columns `id` and `score`
10
+ Submissions are evaluated on the Pearson correlation coefficient between the predicted and actual similarity scores.
11
+ """
12
+ if len(submission) != len(answers):
13
+ raise InvalidSubmissionError("Submission and answers must have the same number of rows")
14
+ if not set(["id", "score"]).issubset(submission.columns):
15
+ raise InvalidSubmissionError(
16
+ f"Submission must have columns ['id', 'score'], got {submission.columns}"
17
+ )
18
+
19
+ submission = submission.sort_values("id")
20
+ answers = answers.sort_values("id")
21
+ if (submission["id"].values != answers["id"].values).any():
22
+ raise InvalidSubmissionError("Ids mismatch between submission and answers")
23
+ y_true = answers["score"].to_numpy()
24
+ y_pred = submission["score"].to_numpy()
25
+
26
+ return y_true, y_pred
27
+
28
+
29
+ def grade(submission: pd.DataFrame, answers: pd.DataFrame) -> float:
30
+ y_true, y_pred = prepare_for_metric(submission, answers)
31
+ return pearsonr(y_true, y_pred)[0]
@@ -0,0 +1,33 @@
1
+ from pathlib import Path
2
+
3
+ from sklearn.model_selection import train_test_split
4
+
5
+ from mlebench.utils import read_csv
6
+
7
+
8
+ def prepare(raw: Path, public: Path, private: Path):
9
+ """
10
+ Splits the data in raw into public and private datasets with appropriate test/train splits.
11
+ """
12
+ public.mkdir(exist_ok=True)
13
+ private.mkdir(exist_ok=True)
14
+
15
+ # Create train, test from train split
16
+ old_train = read_csv(raw / "train.csv")
17
+ new_train, new_test = train_test_split(old_train, test_size=0.1, random_state=0)
18
+ new_test_without_labels = new_test.drop(columns=["score"])
19
+
20
+ # Save new train and test
21
+ new_train.to_csv(public / "train.csv", index=False)
22
+ new_test.to_csv(private / "test.csv", index=False)
23
+ new_test_without_labels.to_csv(public / "test.csv", index=False)
24
+
25
+ assert len(new_train) + len(new_test) == len(old_train)
26
+ assert len(new_test) == len(new_test_without_labels)
27
+
28
+ # Create a sample submission file
29
+ submission_df = new_test.copy()[["id", "score"]]
30
+ submission_df["score"] = 0
31
+ submission_df.to_csv(public / "sample_submission.csv", index=False)
32
+
33
+ assert len(submission_df) == len(new_test)
@@ -0,0 +1,71 @@
1
+ from pathlib import Path
2
+
3
+ from sklearn.model_selection import train_test_split
4
+
5
+ from mlebench.utils import read_csv
6
+
7
+
8
+ def prepare(raw: Path, public: Path, private: Path):
9
+ """
10
+ Splits the data in raw into public and private datasets with appropriate test/train splits.
11
+ Additionally, it creates a secondary validation split for model development.
12
+ """
13
+ # Create directories for the primary competition split
14
+ public.mkdir(exist_ok=True)
15
+ private.mkdir(exist_ok=True)
16
+
17
+ # Create directories for the new validation split
18
+ public_val = public.parent / "public_val"
19
+ private_val = private.parent / "private_val"
20
+ public_val.mkdir(exist_ok=True)
21
+ private_val.mkdir(exist_ok=True)
22
+
23
+ # Load raw data
24
+ old_train = read_csv(raw / "train.csv")
25
+
26
+ # --- Block 1: Original Split (for final competition data) ---
27
+ # This block creates the main train/test split. Its output in `public`
28
+ # and `private` must remain unchanged from the original script.
29
+
30
+ # Create train, test from the full raw data
31
+ train, test = train_test_split(old_train, test_size=0.1, random_state=0)
32
+ test_without_labels = test.drop(columns=["score"])
33
+
34
+ # Save new train and test to the original directories
35
+ train.to_csv(public / "train.csv", index=False)
36
+ test.to_csv(private / "test.csv", index=False)
37
+ test_without_labels.to_csv(public / "test.csv", index=False)
38
+
39
+ assert len(train) + len(test) == len(old_train)
40
+ assert len(test) == len(test_without_labels)
41
+
42
+ # Create a sample submission file for the original test set
43
+ submission_df = test.copy()[["id", "score"]]
44
+ submission_df["score"] = 0
45
+ submission_df.to_csv(public / "sample_submission.csv", index=False)
46
+
47
+ assert len(submission_df) == len(test)
48
+
49
+ # --- Block 2: New Validation Split (for model development) ---
50
+ # This block takes the `train` data from the first split and splits it
51
+ # again to create a new, smaller training set and a validation set.
52
+ # The logic and filenames mirror the original split for consistency.
53
+
54
+ # Create a new train/validation split from the main training set
55
+ train_val, test_val = train_test_split(train, test_size=0.1, random_state=0)
56
+ test_val_without_labels = test_val.drop(columns=["score"])
57
+
58
+ # Save the new validation split data into the `_val` directories
59
+ train_val.to_csv(public_val / "train.csv", index=False)
60
+ test_val.to_csv(private_val / "test.csv", index=False)
61
+ test_val_without_labels.to_csv(public_val / "test.csv", index=False)
62
+
63
+ assert len(train_val) + len(test_val) == len(train)
64
+ assert len(test_val) == len(test_val_without_labels)
65
+
66
+ # Create a sample submission file for the new validation set
67
+ submission_val_df = test_val.copy()[["id", "score"]]
68
+ submission_val_df["score"] = 0
69
+ submission_val_df.to_csv(public_val / "sample_submission.csv", index=False)
70
+
71
+ assert len(submission_val_df) == len(test_val)
@@ -0,0 +1,266 @@
1
+ from pathlib import Path
2
+
3
+ import numpy as np
4
+ import pandas as pd
5
+ from numpy import ndarray
6
+ from scipy.special import softmax
7
+
8
+ from mlebench.grade_helpers import InvalidSubmissionError
9
+ from mlebench.utils import get_logger
10
+
11
+ logger = get_logger(__name__)
12
+
13
+
14
+ def df_to_one_hot(
15
+ df: pd.DataFrame, id_column: str, target_column: str, classes: list[str]
16
+ ) -> pd.DataFrame:
17
+ """
18
+ Convert class labels to one-hot encoded vectors.
19
+ """
20
+
21
+ y_onehot = pd.DataFrame(0, index=df.index, columns=[id_column] + classes)
22
+ y_onehot[id_column] = df[id_column]
23
+
24
+ for i, row in df.iterrows():
25
+ y_onehot.loc[i, row[target_column]] = 1
26
+
27
+ return y_onehot
28
+
29
+
30
+ def one_hot_dfs_to_log_loss_inputs(
31
+ submission_one_hot: pd.DataFrame,
32
+ answers_one_hot: pd.DataFrame,
33
+ id_column: str = "id",
34
+ apply_softmax: bool = True,
35
+ ) -> dict:
36
+ """
37
+ Frequently used logic to prepare one-hotted dfs for log loss calculation.
38
+ """
39
+ required_cols = set(answers_one_hot.columns)
40
+ submission_cols = set(submission_one_hot.columns)
41
+
42
+ if not submission_cols.issuperset(required_cols):
43
+ raise InvalidSubmissionError(
44
+ f"The submission DataFrame is missing some columns required by the `answers` DataFrame. "
45
+ f"Missing columns: {required_cols - submission_cols}."
46
+ )
47
+ if id_column not in submission_one_hot.columns:
48
+ raise InvalidSubmissionError(f"Submission is missing id column '{id_column}'.")
49
+
50
+ assert id_column in answers_one_hot.columns, f"Answers is missing id column '{id_column}'."
51
+
52
+ # Filter submission to only include columns that are in the answers
53
+ submission_filtered = submission_one_hot[
54
+ [col for col in answers_one_hot.columns if col in submission_cols]
55
+ ]
56
+
57
+ # Sort submission and answers by id to align them
58
+ submission_sorted = submission_filtered.sort_values(by=id_column).reset_index(drop=True)
59
+ answers_sorted = answers_one_hot.sort_values(by=id_column).reset_index(drop=True)
60
+
61
+ assert submission_sorted[id_column].tolist() == answers_sorted[id_column].tolist(), (
62
+ f"Mismatch in {id_column.capitalize()}s between `submission` and `answers` after sorting. "
63
+ f"Number of mismatched {id_column.capitalize()}s: {len(set(submission_sorted[id_column]) ^ set(answers_sorted[id_column]))}. "
64
+ f"Ensure both DataFrames have the same {id_column.capitalize()}s."
65
+ )
66
+
67
+ assert list(submission_sorted.columns) == list(answers_sorted.columns), (
68
+ "Column order mismatch after filtering and sorting. "
69
+ "Ensure both DataFrames have columns in the same order."
70
+ )
71
+
72
+ y_true = answers_sorted.drop(columns=[id_column]).to_numpy()
73
+ y_pred = submission_sorted.drop(columns=[id_column]).to_numpy()
74
+
75
+ if apply_softmax and is_one_hot_encoded(y_pred):
76
+ logger.warning(
77
+ "The flag `apply_softmax` has been set to `True` but the submission is already "
78
+ "one-hot encoded. Skipping softmax."
79
+ )
80
+
81
+ if apply_softmax and not is_one_hot_encoded(y_pred):
82
+ y_pred = softmax(y_pred, axis=-1)
83
+
84
+ log_loss_inputs = {
85
+ "y_true": y_true,
86
+ "y_pred": y_pred,
87
+ }
88
+
89
+ return log_loss_inputs
90
+
91
+
92
+ def is_one_hot_encoded(xs: ndarray) -> bool:
93
+ """Check if a 2D NumPy array is one-hot encoded."""
94
+
95
+ assert isinstance(xs, ndarray), f"Expected a NumPy array, got {type(xs)}."
96
+ assert xs.ndim == 2, f"Expected a 2D array, got {xs.ndim}D."
97
+
98
+ is_binary_matrix = np.bitwise_or(xs == 0, xs == 1).all()
99
+ is_normalized = np.allclose(xs.sum(axis=-1), 1)
100
+ is_one_hot = bool(is_binary_matrix and is_normalized)
101
+
102
+ assert isinstance(is_one_hot, bool), f"Expected a boolean, got {type(is_one_hot)}."
103
+
104
+ return is_one_hot
105
+
106
+
107
+ def rle_decode(rle_string: str, height: int, width: int) -> ndarray:
108
+ """
109
+ Decode an RLE string into a binary mask. The RLE encoding is top-down, left-right. So 1 is
110
+ (1,1), 2 is (2, 1), etc. The RLE is 1-indexed. Checks that the pairs are sorted, positive, and
111
+ the decoded pixel values do not overlap.
112
+
113
+ Args:
114
+ rle_string (str): The RLE string.
115
+ height (int): The height of the image.
116
+ width (int): The width of the image.
117
+
118
+ Returns:
119
+ np.array: The decoded binary mask.
120
+ """
121
+
122
+ assert isinstance(
123
+ rle_string, str
124
+ ), f"Expected a string, but got {type(rle_string)}: {rle_string}"
125
+ assert isinstance(height, int), f"Expected an integer, but got {type(height)}: {height}"
126
+ assert isinstance(width, int), f"Expected an integer, but got {type(width)}: {width}"
127
+
128
+ if not rle_string.strip(): # Check if the string is empty or contains only whitespace
129
+ return np.zeros((height, width), dtype=bool)
130
+
131
+ s = list(map(int, rle_string.split()))
132
+ starts, lengths = s[0::2], s[1::2]
133
+
134
+ assert starts == sorted(starts), "The pairs in the RLE string must be sorted."
135
+ assert all(x > 0 for x in starts), "All pairs in the RLE string must be positive integers."
136
+ assert all(x > 0 for x in lengths), "All pairs in the RLE string must be positive integers."
137
+
138
+ # Convert to 0-based indices
139
+ starts = np.array(starts) - 1
140
+ ends = starts + lengths
141
+ img = np.zeros(height * width, dtype=bool)
142
+
143
+ for lo, hi in zip(starts, ends):
144
+ assert not img[lo:hi].any(), "Overlapping RLE pairs are not allowed."
145
+ img[lo:hi] = True
146
+
147
+ # reshape appropriately given how the RLE was encoded
148
+ return img.reshape((width, height)).T
149
+
150
+
151
+ # https://www.kaggle.com/code/inversion/contrails-rle-submission
152
+ def rle_encode(x: ndarray, fg_val=1):
153
+ """
154
+ Args:
155
+ x: numpy array of shape (height, width), 1 - mask, 0 - background
156
+ Returns: run length encoding as list
157
+ """
158
+ dots = np.where(x.T.flatten() == fg_val)[0] # .T sets Fortran order down-then-right
159
+ run_lengths = []
160
+ prev = -2
161
+ for b in dots:
162
+ if b > prev + 1:
163
+ run_lengths.extend((b + 1, 0))
164
+ run_lengths[-1] += 1
165
+ prev = b
166
+ return run_lengths
167
+
168
+
169
+ def rles_to_masks(
170
+ rl_encodings: list[str], image_heights: list[int], image_widths: list[int]
171
+ ) -> list[np.ndarray]:
172
+ """
173
+ Performs run-length decoding on a list of run-length encodings to get the binary masks
174
+ """
175
+ masks = [
176
+ rle_decode(encoding, height=image_height, width=image_width)
177
+ for encoding, image_height, image_width in zip(rl_encodings, image_heights, image_widths)
178
+ ]
179
+ return masks
180
+
181
+
182
+ def get_ids_from_tf_records(tf_record_path: Path, id_feature: str = "image_name") -> list[str]:
183
+ import tensorflow as tf # Import only if needed, otherwise it slows down the module import
184
+
185
+ tf_record_dataset = tf.data.TFRecordDataset(tf_record_path.as_posix())
186
+
187
+ ids = []
188
+ for record in tf_record_dataset:
189
+ features = tf.train.Example.FromString(record.numpy())
190
+ id = features.features.feature[id_feature].bytes_list.value[0].decode("utf-8")
191
+ ids.append(id)
192
+
193
+ return ids
194
+
195
+
196
+ def prepare_for_accuracy_metric(
197
+ submission: pd.DataFrame,
198
+ answers: pd.DataFrame,
199
+ target_column: str,
200
+ id_column: str,
201
+ ) -> dict:
202
+
203
+ # Answers checks
204
+ assert target_column in answers.columns, f"Answers must have a `{target_column}` column"
205
+ assert id_column in answers.columns, f"Answers must have a `{id_column}` column"
206
+
207
+ # Submission checks
208
+ if len(submission) != len(answers):
209
+ raise InvalidSubmissionError("Submission must have the same length as the answers.")
210
+ if target_column not in submission.columns:
211
+ raise InvalidSubmissionError(f"Submission must have a `{target_column}` column")
212
+ if id_column not in submission.columns:
213
+ raise InvalidSubmissionError(f"Submission must have a `{id_column}` column")
214
+
215
+ # sort on id to ensure correct order
216
+ submission = submission.sort_values(id_column)
217
+ answers = answers.sort_values(id_column)
218
+
219
+ if (submission[id_column].values != answers[id_column].values).any():
220
+ raise InvalidSubmissionError(f"Submission and Answers `{id_column}`'s do not match")
221
+
222
+ y_pred = submission[target_column].to_numpy()
223
+ y_true = answers[target_column].to_numpy()
224
+
225
+ return {"y_true": y_true, "y_pred": y_pred}
226
+
227
+
228
+ def prepare_for_auroc_metric(
229
+ submission: pd.DataFrame, answers: pd.DataFrame, id_col: str, target_col: str
230
+ ) -> dict:
231
+
232
+ # Answers checks
233
+ assert id_col in answers.columns, f"answers dataframe should have an {id_col} column"
234
+ assert target_col in answers.columns, f"answers dataframe should have a {target_col} column"
235
+
236
+ # Submission checks
237
+ if id_col not in submission.columns:
238
+ raise InvalidSubmissionError(f"Submission should have an {id_col} column")
239
+ if target_col not in submission.columns:
240
+ raise InvalidSubmissionError(f"Submission should have a {target_col} column")
241
+ if len(submission) != len(answers):
242
+ raise InvalidSubmissionError(f"Submission and answers should have the same number of rows")
243
+ try:
244
+ pd.to_numeric(submission[target_col])
245
+ except ValueError:
246
+ raise InvalidSubmissionError(
247
+ f"Expected {target_col} column to be numeric, got {submission[target_col].dtype} instead"
248
+ )
249
+ if submission[target_col].min() < 0 or submission[target_col].max() > 1:
250
+ raise InvalidSubmissionError(
251
+ f"Submission {target_col} column should contain probabilities,"
252
+ " and therefore contain values between 0 and 1 inclusive"
253
+ )
254
+ # Sort
255
+ submission = submission.sort_values(id_col)
256
+ answers = answers.sort_values(id_col)
257
+
258
+ if (submission[id_col].values != answers[id_col].values).any():
259
+ raise InvalidSubmissionError(f"Submission and answers should have the same {id_col} values")
260
+
261
+ roc_auc_inputs = {
262
+ "y_true": answers[target_col].to_numpy(),
263
+ "y_score": submission[target_col].to_numpy(),
264
+ }
265
+
266
+ return roc_auc_inputs
@@ -0,0 +1,158 @@
1
+ import numpy as np
2
+ from pandas import DataFrame
3
+ from scipy.spatial.distance import directed_hausdorff
4
+ from tqdm.auto import tqdm
5
+
6
+ from mlebench.competitions.utils import rles_to_masks
7
+ from mlebench.grade_helpers import InvalidSubmissionError
8
+ from mlebench.metrics import dice_coefficient
9
+
10
+ UNIT_CUBE_DIAGONAL = np.sqrt(3)
11
+
12
+
13
+ def group_masks_by_day(masks: list[np.ndarray], cases_days_slices: list[str]) -> list[np.ndarray]:
14
+ """
15
+ Groups the 2D masks into 3D masks based on the case days
16
+ - We first join masks of the same slice into a single mask with an OR operation
17
+ - We then stack them with all the other slices from the same day in the same case into a 3D image
18
+ """
19
+ case_day_slice_to_masks = {}
20
+ unique_slices = [] # list to keep ordering consistent
21
+ for mask, case_day_slice in sorted(zip(masks, cases_days_slices), key=lambda x: x[1]):
22
+ if case_day_slice not in case_day_slice_to_masks:
23
+ case_day_slice_to_masks[case_day_slice] = []
24
+ unique_slices.append(case_day_slice)
25
+ case_day_slice_to_masks[case_day_slice].append(mask)
26
+
27
+ case_day_to_masks = {}
28
+ case_days = [] # list to keep ordering consistent
29
+ for case_day_slice in unique_slices:
30
+ # go from e.g. "case123_day2_slice_0001" to "case123_day2"
31
+ case_day = case_day_slice.split("_slice_")[0]
32
+ if case_day not in case_day_to_masks:
33
+ case_day_to_masks[case_day] = []
34
+ case_days.append(case_day)
35
+ # OR on the masks from the same case_day_slice
36
+ joined_mask = np.logical_or.reduce(case_day_slice_to_masks[case_day_slice]).astype(np.uint8)
37
+ # add the joined slice to its relevant case_day
38
+ case_day_to_masks[case_day].append(joined_mask)
39
+
40
+ # now we stack the joined masks for each case_day to make a 3d image
41
+ for case_day in case_day_to_masks:
42
+ # make into 3d image
43
+ case_day_to_masks[case_day] = np.stack(case_day_to_masks[case_day], axis=0)
44
+
45
+ # keep the order of the cases consistent
46
+ case_day_masks = [case_day_to_masks[case_day] for case_day in case_days]
47
+ return case_day_masks
48
+
49
+
50
+ def prepare_for_metric(submission: DataFrame, answers: DataFrame):
51
+ """
52
+ Answers dataframe contains image_height and image_width columns necessary for RLE decoding
53
+ """
54
+
55
+ assert "image_height" in answers.columns, "image_height column not found in answers"
56
+ assert "image_width" in answers.columns, "image_width column not found in answers"
57
+ if not {"id", "class", "predicted"}.issubset(set(submission.columns)):
58
+ raise InvalidSubmissionError("Submission must have columns: id, class, predicted")
59
+
60
+ # prepare appropriate types
61
+ submission["predicted"] = submission["predicted"].fillna("")
62
+ answers["predicted"] = answers["predicted"].fillna("")
63
+ answers["image_height"] = answers["image_height"].astype(int)
64
+ answers["image_width"] = answers["image_width"].astype(int)
65
+
66
+ image_heights = answers["image_height"].tolist()
67
+ image_widths = answers["image_width"].tolist()
68
+
69
+ # extract masked images from RLE in the dataframes
70
+ submission_masks = rles_to_masks(submission["predicted"].to_list(), image_heights, image_widths)
71
+ answer_masks = rles_to_masks(answers["predicted"].to_list(), image_heights, image_widths)
72
+
73
+ # group 2d slice masks into 3d case_day masks
74
+ submission_masks_by_day = group_masks_by_day(submission_masks, submission["id"])
75
+ answer_masks_by_day = group_masks_by_day(answer_masks, answers["id"])
76
+
77
+ return submission_masks, answer_masks, submission_masks_by_day, answer_masks_by_day
78
+
79
+
80
+ def hausdorff_distance(predicted_mask: np.ndarray, true_mask: np.ndarray) -> float:
81
+ """
82
+ Computes the hausdorff distance between two 3-dimensional binary masks (H, W, C)
83
+
84
+ Args:
85
+ predicted_mask: A 3D binary numpy array indicating where the segmentation is predicted
86
+ true_mask: A 3D binary numpy array indicating where the segmentation is
87
+ """
88
+ # if both empty, return nan, if identical return 0, if only one is empty, return 1
89
+ if np.sum(predicted_mask) == 0 and np.sum(true_mask) == 0:
90
+ return np.nan
91
+ elif np.array_equal(predicted_mask, true_mask):
92
+ return 0
93
+ elif (np.sum(predicted_mask) == 0 and np.sum(true_mask) > 0) or (
94
+ np.sum(predicted_mask) > 0 and np.sum(true_mask) == 0
95
+ ):
96
+ return 1
97
+
98
+ # if the pred mask is > 1 OOM larger than the true mask, return 1 to avoid unnecess heavy computation
99
+ if predicted_mask.sum() > 10 * true_mask.sum():
100
+ return 1
101
+
102
+ true_coordinates = np.argwhere(true_mask)
103
+ predicted_coordinates = np.argwhere(predicted_mask)
104
+
105
+ # normalize so that the coordinates are in the range [0, 1], to get a unit cube
106
+ normalization_constants = true_mask.shape
107
+ true_coordinates = true_coordinates / normalization_constants
108
+ predicted_coordinates = predicted_coordinates / normalization_constants
109
+
110
+ # Symmetrize Hausdorff distance
111
+ hausdorff_distance1, _, _ = directed_hausdorff(true_coordinates, predicted_coordinates)
112
+ hausdorff_distance2, _, _ = directed_hausdorff(predicted_coordinates, true_coordinates)
113
+ hausdorff_distance = max(hausdorff_distance1, hausdorff_distance2)
114
+
115
+ # normalize by the maximum distance possible in a unit cube, which is the diagonal
116
+ hausdorff_distance = hausdorff_distance / UNIT_CUBE_DIAGONAL
117
+
118
+ return hausdorff_distance
119
+
120
+
121
+ def grade(submission: DataFrame, answers: DataFrame) -> float:
122
+ """
123
+ Computes dice_weight * dice + hausdorff_weight * (1 - hausdorff)
124
+ """
125
+ dice_weight = 0.4
126
+ hausdorff_weight = 0.6
127
+
128
+ (
129
+ submission_masks,
130
+ answer_masks,
131
+ submission_masks_by_day,
132
+ answer_masks_by_day,
133
+ ) = prepare_for_metric(submission, answers)
134
+
135
+ # we skip cases where both masks are empty, so we use nanmean
136
+ # https://www.kaggle.com/competitions/uw-madison-gi-tract-image-segmentation/discussion/324934#1795540
137
+ dice_coeff = np.nanmean(
138
+ [
139
+ dice_coefficient(submission_mask, answer_mask, np.nan)
140
+ for submission_mask, answer_mask in tqdm(
141
+ zip(submission_masks, answer_masks),
142
+ total=len(submission_masks),
143
+ )
144
+ ]
145
+ )
146
+
147
+ # skip cases where both masks are empty, to match behaviour of dice
148
+ hausdorff_dis = np.nanmean(
149
+ [
150
+ hausdorff_distance(submission_mask_by_day, answer_mask_by_day)
151
+ for submission_mask_by_day, answer_mask_by_day in tqdm(
152
+ zip(submission_masks_by_day, answer_masks_by_day),
153
+ total=len(submission_masks_by_day),
154
+ )
155
+ ]
156
+ )
157
+
158
+ return dice_weight * dice_coeff + hausdorff_weight * (1 - hausdorff_dis)