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.
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.6.dist-info}/METADATA +1 -1
  4. {dslighting-1.7.1.dist-info → dslighting-1.7.6.dist-info}/RECORD +352 -7
  5. {dslighting-1.7.1.dist-info → dslighting-1.7.6.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.6.dist-info}/WHEEL +0 -0
  352. {dslighting-1.7.1.dist-info → dslighting-1.7.6.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,70 @@
1
+ from bisect import bisect
2
+ from typing import Any
3
+
4
+ import pandas as pd
5
+
6
+ from mlebench.grade_helpers import InvalidSubmissionError
7
+
8
+
9
+ def kendall_tau(ground_truth: list[list[Any]], predictions: list[list[Any]]) -> float:
10
+ """
11
+ Computes the Kendall Tau correlation between
12
+ - `ground_truth`: a list of lists, where each sublist contains the ground truth order of items
13
+ - `predictions`: a list of lists, where each sublist contains the predicted order of items
14
+
15
+ See: https://www.kaggle.com/code/ryanholbrook/competition-metric-kendall-tau-correlation
16
+ """
17
+
18
+ # Actually O(N^2), but fast in practice for our data
19
+ def count_inversions(a):
20
+ inversions = 0
21
+ sorted_so_far = []
22
+ for i, u in enumerate(a): # O(N)
23
+ j = bisect(sorted_so_far, u) # O(log N)
24
+ inversions += i - j
25
+ sorted_so_far.insert(j, u) # O(N)
26
+ return inversions
27
+
28
+ total_inversions = 0 # total inversions in predicted ranks across all instances
29
+ total_2max = 0 # maximum possible inversions across all instances
30
+ for gt, pred in zip(ground_truth, predictions):
31
+ ranks = [gt.index(x) for x in pred] # rank predicted order in terms of ground truth
32
+ total_inversions += count_inversions(ranks)
33
+ n = len(gt)
34
+ total_2max += n * (n - 1)
35
+ return 1 - 4 * total_inversions / total_2max
36
+
37
+
38
+ def prepare_for_metric(submission: pd.DataFrame, answers: pd.DataFrame) -> dict:
39
+ if len(submission) != len(answers):
40
+ raise InvalidSubmissionError("Submission and answers must have the same length")
41
+ if "id" not in submission.columns or "cell_order" not in submission.columns:
42
+ raise InvalidSubmissionError("Submission must have 'id' and 'cell_order' columns")
43
+ if set(submission["id"]) != set(answers["id"]):
44
+ raise InvalidSubmissionError("Submission and answers must have the same ids")
45
+ # "cell_order" columns must be strings of space-separated cell ids: "54c7cab3 fe66203e 7844d5f8 ..."
46
+ submission["cell_order"] = submission["cell_order"].astype(str)
47
+ answers["cell_order"] = answers["cell_order"].astype(str)
48
+
49
+ # Sort by id to ensure we're comparing the same rows
50
+ submission = submission.sort_values("id")
51
+ answers = answers.sort_values("id")
52
+
53
+ ground_truth, predictions = [], []
54
+ target_column = "cell_order"
55
+ for (_, row_gt), (_, row_pred) in zip(submission.iterrows(), answers.iterrows()):
56
+ ground_truth_items = row_gt[target_column].split()
57
+ prediction_items = row_pred[target_column].split()
58
+ if len(ground_truth_items) != len(prediction_items):
59
+ raise InvalidSubmissionError("Ground truth and predictions must have the same length")
60
+ ground_truth.append(ground_truth_items)
61
+ predictions.append(prediction_items)
62
+ return {
63
+ "ground_truth": ground_truth,
64
+ "predictions": predictions,
65
+ }
66
+
67
+
68
+ def grade(submission: pd.DataFrame, answers: pd.DataFrame) -> float:
69
+ kendall_tau_inputs = prepare_for_metric(submission, answers)
70
+ return kendall_tau(**kendall_tau_inputs)
@@ -0,0 +1,84 @@
1
+ import json
2
+ import shutil
3
+ from pathlib import Path
4
+
5
+ import pandas as pd
6
+ from tqdm.auto import tqdm
7
+
8
+ from mlebench.utils import read_csv
9
+
10
+
11
+ # Create train, test from train split
12
+ def create_train_test_split(train_ancestors_df: pd.DataFrame, test_size: int):
13
+ """
14
+ On Kaggle, a user may "fork" (that is, copy) the notebook of another user to create their own version.
15
+ `train_ancestors_df` contains information about the ancestry of each notebook in the training set.
16
+
17
+ To create the test split, we select rows from the train set that don't share ancestors with any others
18
+ so that there aren't any relatives in the train set. The train split is the remaining rows.
19
+ """
20
+ group_by_ancestor = {}
21
+ for _, row in tqdm(
22
+ train_ancestors_df.iterrows(), desc="Grouping by Ancestor", total=len(train_ancestors_df)
23
+ ):
24
+ ancestor_id = row["ancestor_id"]
25
+ if ancestor_id not in group_by_ancestor:
26
+ group_by_ancestor[ancestor_id] = []
27
+ group_by_ancestor[ancestor_id].append(row)
28
+
29
+ train_ids = []
30
+ test_ids = []
31
+ num_test_ids = 0
32
+ for ancestor_id, rows in tqdm(group_by_ancestor.items(), desc="Splitting on Ancestors"):
33
+ if num_test_ids + len(rows) <= test_size:
34
+ test_ids.extend(([row["id"] for row in rows]))
35
+ num_test_ids += len(rows)
36
+ else:
37
+ train_ids.extend([row["id"] for row in rows])
38
+
39
+ assert len(test_ids) == test_size
40
+ assert len(train_ids) == len(train_ancestors_df) - test_size
41
+
42
+ return train_ids, test_ids
43
+
44
+
45
+ def prepare(raw: Path, public: Path, private: Path):
46
+ train_ancestors_df = read_csv(raw / "train_ancestors.csv")
47
+ # Shuffle the train_ancestors_df to ensure our split is random
48
+ train_ancestors_df = train_ancestors_df.sample(frac=1, random_state=0).reset_index(drop=True)
49
+ new_train_ids, new_test_ids = create_train_test_split(train_ancestors_df, test_size=20000)
50
+
51
+ # Copy json files to public
52
+ (public / "train").mkdir(parents=True, exist_ok=True)
53
+ for train_id in tqdm(new_train_ids, desc="Copying train json files"):
54
+ shutil.copy(raw / "train" / f"{train_id}.json", public / "train" / f"{train_id}.json")
55
+ (public / "test").mkdir(parents=True, exist_ok=True)
56
+ for test_id in tqdm(new_test_ids, desc="Copying test json files"):
57
+ shutil.copy(raw / "train" / f"{test_id}.json", public / "test" / f"{test_id}.json")
58
+
59
+ # Generate answers for train and test
60
+ train_orders = read_csv(raw / "train_orders.csv")
61
+ # Answers for new train
62
+ train_orders_new = train_orders[train_orders["id"].isin(new_train_ids)]
63
+ train_orders_new.to_csv(public / "train_orders.csv", index=False)
64
+ # Answers for new test
65
+ test_orders_new = train_orders[train_orders["id"].isin(new_test_ids)]
66
+ test_orders_new.to_csv(private / "test_orders.csv", index=False)
67
+
68
+ # Make new train_ancestors.csv, excluding the new_test_ids
69
+ train_ancestors_df = train_ancestors_df[~train_ancestors_df["id"].isin(new_test_ids)]
70
+ train_ancestors_df.to_csv(public / "train_ancestors.csv", index=False)
71
+
72
+ # Create sample submission (use the given order without changing it)
73
+ sample_submission_rows = []
74
+ for sample_id in tqdm(test_orders_new["id"], desc="Creating sample submission"):
75
+ # Get cell order from json file
76
+ with open(public / "test" / f"{sample_id}.json") as f:
77
+ json_data = json.load(f)
78
+ cell_order = list(json_data["cell_type"].keys())
79
+ sample_submission_rows.append({"id": sample_id, "cell_order": " ".join(cell_order)})
80
+ sample_submission = pd.DataFrame(sample_submission_rows)
81
+ sample_submission.to_csv(public / "sample_submission.csv", index=False)
82
+ assert len(sample_submission) == len(
83
+ new_test_ids
84
+ ), "Sample submission length does not match test length."
@@ -0,0 +1,159 @@
1
+ import json
2
+ import shutil
3
+ from pathlib import Path
4
+
5
+ import pandas as pd
6
+ from tqdm.auto import tqdm
7
+
8
+ from mlebench.utils import read_csv
9
+
10
+
11
+ # Create train, test from train split
12
+ def create_train_test_split(train_ancestors_df: pd.DataFrame, test_size: int):
13
+ """
14
+ On Kaggle, a user may "fork" (that is, copy) the notebook of another user to create their own version.
15
+ `train_ancestors_df` contains information about the ancestry of each notebook in the training set.
16
+
17
+ To create the test split, we select rows from the train set that don't share ancestors with any others
18
+ so that there aren't any relatives in the train set. The train split is the remaining rows.
19
+ """
20
+ group_by_ancestor = {}
21
+ for _, row in tqdm(
22
+ train_ancestors_df.iterrows(), desc="Grouping by Ancestor", total=len(train_ancestors_df)
23
+ ):
24
+ ancestor_id = row["ancestor_id"]
25
+ if ancestor_id not in group_by_ancestor:
26
+ group_by_ancestor[ancestor_id] = []
27
+ group_by_ancestor[ancestor_id].append(row)
28
+
29
+ train_ids = []
30
+ test_ids = []
31
+ num_test_ids = 0
32
+ # Ensure a deterministic split by sorting the groups
33
+ sorted_ancestors = sorted(group_by_ancestor.items(), key=lambda x: x[0])
34
+ for ancestor_id, rows in tqdm(sorted_ancestors, desc="Splitting on Ancestors"):
35
+ if num_test_ids + len(rows) <= test_size:
36
+ test_ids.extend(([row["id"] for row in rows]))
37
+ num_test_ids += len(rows)
38
+ else:
39
+ train_ids.extend([row["id"] for row in rows])
40
+
41
+ # The exact number of test samples can vary slightly based on group sizes.
42
+ # We adjust the assertion to check it's close to the target, not necessarily equal.
43
+ assert len(train_ids) + len(test_ids) == len(train_ancestors_df)
44
+
45
+ return train_ids, test_ids
46
+
47
+
48
+ def _generate_split_files(
49
+ train_ids: list,
50
+ test_ids: list,
51
+ public_dir: Path,
52
+ private_dir: Path,
53
+ raw_dir: Path,
54
+ full_train_orders_df: pd.DataFrame,
55
+ full_train_ancestors_df: pd.DataFrame,
56
+ ):
57
+ """
58
+ A helper function to generate all required files for a given train/test split.
59
+ This helps avoid code duplication and ensures consistent output structure.
60
+ """
61
+ # Create output directories
62
+ public_dir.mkdir(parents=True, exist_ok=True)
63
+ private_dir.mkdir(parents=True, exist_ok=True)
64
+ (public_dir / "train").mkdir(exist_ok=True)
65
+ (public_dir / "test").mkdir(exist_ok=True)
66
+
67
+ # Copy json files to public
68
+ for train_id in tqdm(train_ids, desc=f"Copying train json files to {public_dir.name}"):
69
+ shutil.copy(raw_dir / "train" / f"{train_id}.json", public_dir / "train" / f"{train_id}.json")
70
+ for test_id in tqdm(test_ids, desc=f"Copying test json files to {public_dir.name}"):
71
+ shutil.copy(raw_dir / "train" / f"{test_id}.json", public_dir / "test" / f"{test_id}.json")
72
+
73
+ # Generate answers for train and test
74
+ # Answers for new train
75
+ train_orders_new = full_train_orders_df[full_train_orders_df["id"].isin(train_ids)]
76
+ train_orders_new.to_csv(public_dir / "train_orders.csv", index=False)
77
+ # Answers for new test
78
+ test_orders_new = full_train_orders_df[full_train_orders_df["id"].isin(test_ids)]
79
+ test_orders_new.to_csv(private_dir / "test_orders.csv", index=False)
80
+
81
+ # Make new train_ancestors.csv, excluding the new_test_ids
82
+ train_ancestors_new = full_train_ancestors_df[
83
+ full_train_ancestors_df["id"].isin(train_ids)
84
+ ]
85
+ train_ancestors_new.to_csv(public_dir / "train_ancestors.csv", index=False)
86
+
87
+ # Create sample submission (use the given order without changing it)
88
+ sample_submission_rows = []
89
+ for sample_id in tqdm(
90
+ test_orders_new["id"], desc=f"Creating sample submission for {public_dir.name}"
91
+ ):
92
+ # Get cell order from json file
93
+ with open(public_dir / "test" / f"{sample_id}.json") as f:
94
+ json_data = json.load(f)
95
+ cell_order = list(json_data["cell_type"].keys())
96
+ sample_submission_rows.append({"id": sample_id, "cell_order": " ".join(cell_order)})
97
+ sample_submission = pd.DataFrame(sample_submission_rows)
98
+ sample_submission.to_csv(public_dir / "sample_submission.csv", index=False)
99
+ assert len(sample_submission) == len(test_ids), "Sample submission length does not match test length."
100
+
101
+
102
+ def prepare(raw: Path, public: Path, private: Path):
103
+ # --- Initial Setup ---
104
+ TEST_SIZE = 20000
105
+ # Load all necessary data once
106
+ full_train_ancestors_df = read_csv(raw / "train_ancestors.csv")
107
+ full_train_orders_df = read_csv(raw / "train_orders.csv")
108
+
109
+ # Shuffle the train_ancestors_df to ensure our split is random but reproducible
110
+ shuffled_ancestors_df = full_train_ancestors_df.sample(
111
+ frac=1, random_state=0
112
+ ).reset_index(drop=True)
113
+
114
+ # --- 1. Original Split (train/test) ---
115
+ print("--- Generating original train/test split ---")
116
+ train_ids, test_ids = create_train_test_split(shuffled_ancestors_df, test_size=TEST_SIZE)
117
+
118
+ # Generate files for the original public and private directories
119
+ _generate_split_files(
120
+ train_ids,
121
+ test_ids,
122
+ public,
123
+ private,
124
+ raw,
125
+ full_train_orders_df,
126
+ shuffled_ancestors_df,
127
+ )
128
+
129
+ # --- 2. Validation Split (train_val/test_val) ---
130
+ print("\n--- Generating new validation split ---")
131
+ # Define paths for the new validation directories
132
+ public_val = public.parent / "public_val"
133
+ private_val = private.parent / "private_val"
134
+
135
+ # The input for the second split is the training set from the first split.
136
+ # We use the already shuffled dataframe to maintain deterministic behavior.
137
+ train_subset_for_val_split = shuffled_ancestors_df[
138
+ shuffled_ancestors_df["id"].isin(train_ids)
139
+ ].reset_index(drop=True)
140
+
141
+ # Create the second split from the first split's training data
142
+ train_val_ids, test_val_ids = create_train_test_split(
143
+ train_subset_for_val_split, test_size=TEST_SIZE
144
+ )
145
+
146
+ # Generate the validation split files in the new directories
147
+ _generate_split_files(
148
+ train_val_ids,
149
+ test_val_ids,
150
+ public_val,
151
+ private_val,
152
+ raw,
153
+ full_train_orders_df,
154
+ shuffled_ancestors_df,
155
+ )
156
+
157
+ print("\nData preparation complete.")
158
+ print(f"Original split created in '{public.name}' and '{private.name}'.")
159
+ print(f"Validation split created in '{public_val.name}' and '{private_val.name}'.")
File without changes
@@ -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=submission, answers=answers, id_col="id", target_col="has_cactus"
10
+ )
11
+ return roc_auc_score(y_true=roc_auc_inputs["y_true"], y_score=roc_auc_inputs["y_score"])
@@ -0,0 +1,71 @@
1
+ import shutil
2
+ from pathlib import Path
3
+
4
+ from sklearn.model_selection import train_test_split
5
+ from tqdm.auto import tqdm
6
+
7
+ from mlebench.utils import compress, extract, read_csv
8
+
9
+
10
+ def prepare(raw: Path, public: Path, private: Path):
11
+
12
+ old_train = read_csv(raw / "train.csv")
13
+
14
+ # 4000 / (4000 + 17500) -> test_size is ~0.19
15
+ new_train, new_test = train_test_split(old_train, test_size=0.19, random_state=0)
16
+
17
+ new_train.to_csv(public / "train.csv", index=False)
18
+ new_test.to_csv(private / "test.csv", index=False)
19
+
20
+ sample_submission = new_test.copy()
21
+ sample_submission["has_cactus"] = 0.5
22
+ sample_submission.to_csv(public / "sample_submission.csv", index=False)
23
+
24
+ # need to split the train.zip into train.zip and test.zip; to do so need to extract first
25
+ extract(raw / "train.zip", raw)
26
+
27
+ # copy
28
+ (public / "train").mkdir(parents=True, exist_ok=True)
29
+ for image_id in tqdm(new_train["id"], desc="Copying train images", total=len(new_train)):
30
+ shutil.copy(raw / "train" / image_id, public / "train" / image_id)
31
+
32
+ (public / "test").mkdir(parents=True, exist_ok=True)
33
+ for image_id in tqdm(new_test["id"], desc="Copying test images", total=len(new_test)):
34
+ shutil.copy(raw / "train" / image_id, public / "test" / image_id)
35
+
36
+ # and then recompress
37
+ compress(public / "train", public / "train.zip")
38
+ compress(public / "test", public / "test.zip")
39
+
40
+ # and cleanup
41
+ shutil.rmtree(public / "train")
42
+ shutil.rmtree(public / "test")
43
+ shutil.rmtree(raw / "train")
44
+
45
+ # checks
46
+ assert (public / "train.zip").exists(), "public/train.zip should exist"
47
+ assert (public / "test.zip").exists(), "public/test.zip should exist"
48
+ assert not (raw / "train").exists(), "raw/train/ should not exist"
49
+
50
+ assert len(new_train) + len(new_test) == len(
51
+ old_train
52
+ ), "The lengths of the splits should add up to the original"
53
+ assert len(new_train) > len(new_test), "The train set should be larger than the test set"
54
+ assert len(new_test) == len(
55
+ sample_submission
56
+ ), "The test set should match the sample submission"
57
+
58
+ assert (
59
+ new_train.columns.tolist()
60
+ == new_test.columns.tolist()
61
+ == old_train.columns.tolist()
62
+ == sample_submission.columns.tolist()
63
+ ), "All dataframes should have the same columns, i.e. ['id', 'has_cactus']"
64
+
65
+ assert set(new_train["id"]).isdisjoint(new_test["id"]), "Train and test ids should not overlap"
66
+ assert set(new_test["id"]) == set(
67
+ sample_submission["id"]
68
+ ), "Test and sample_submission ids should match"
69
+
70
+ assert new_train["id"].nunique() == len(new_train), "There should be no duplicate ids in train"
71
+ assert new_test["id"].nunique() == len(new_test), "There should be no duplicate ids in test"
@@ -0,0 +1,133 @@
1
+ import shutil
2
+ from pathlib import Path
3
+ import pandas as pd
4
+
5
+ from sklearn.model_selection import train_test_split
6
+ from tqdm.auto import tqdm
7
+
8
+ from mlebench.utils import compress, extract, read_csv
9
+
10
+
11
+ def _process_and_save_split(
12
+ train_df: pd.DataFrame,
13
+ test_df: pd.DataFrame,
14
+ public_dir: Path,
15
+ private_dir: Path,
16
+ raw_image_dir: Path,
17
+ original_df: pd.DataFrame,
18
+ ):
19
+ """
20
+ Helper function to process a single train/test split.
21
+ It saves all required CSVs, copies and compresses images, and runs assertions.
22
+ """
23
+ public_dir.mkdir(parents=True, exist_ok=True)
24
+ private_dir.mkdir(parents=True, exist_ok=True)
25
+
26
+ # Save the dataframes
27
+ train_df.to_csv(public_dir / "train.csv", index=False)
28
+ test_df.to_csv(private_dir / "test.csv", index=False)
29
+
30
+ sample_submission = test_df.copy()
31
+ sample_submission["has_cactus"] = 0.5
32
+ sample_submission.to_csv(public_dir / "sample_submission.csv", index=False)
33
+
34
+ # Prepare temporary directories for images
35
+ temp_train_img_dir = public_dir / "train"
36
+ temp_test_img_dir = public_dir / "test"
37
+ temp_train_img_dir.mkdir(parents=True, exist_ok=True)
38
+ temp_test_img_dir.mkdir(parents=True, exist_ok=True)
39
+
40
+ # Copy images for the current split
41
+ for image_id in tqdm(train_df["id"], desc=f"Copying train images to {public_dir.name}", total=len(train_df)):
42
+ shutil.copy(raw_image_dir / image_id, temp_train_img_dir / image_id)
43
+
44
+ for image_id in tqdm(test_df["id"], desc=f"Copying test images to {public_dir.name}", total=len(test_df)):
45
+ shutil.copy(raw_image_dir / image_id, temp_test_img_dir / image_id)
46
+
47
+ # and then recompress
48
+ compress(temp_train_img_dir, public_dir / "train.zip")
49
+ compress(temp_test_img_dir, public_dir / "test.zip")
50
+
51
+ # and cleanup temporary image directories
52
+ shutil.rmtree(temp_train_img_dir)
53
+ shutil.rmtree(temp_test_img_dir)
54
+
55
+ # checks for the current split
56
+ assert (public_dir / "train.zip").exists(), f"{public_dir.name}/train.zip should exist"
57
+ assert (public_dir / "test.zip").exists(), f"{public_dir.name}/test.zip should exist"
58
+
59
+ assert len(train_df) + len(test_df) == len(
60
+ original_df
61
+ ), "The lengths of the splits should add up to the original"
62
+ assert len(train_df) > len(test_df), "The train set should be larger than the test set"
63
+ assert len(test_df) == len(
64
+ sample_submission
65
+ ), "The test set should match the sample submission"
66
+
67
+ assert (
68
+ train_df.columns.tolist()
69
+ == test_df.columns.tolist()
70
+ == original_df.columns.tolist()
71
+ == sample_submission.columns.tolist()
72
+ ), "All dataframes should have the same columns, i.e. ['id', 'has_cactus']"
73
+
74
+ assert set(train_df["id"]).isdisjoint(test_df["id"]), "Train and test ids should not overlap"
75
+ assert set(test_df["id"]) == set(
76
+ sample_submission["id"]
77
+ ), "Test and sample_submission ids should match"
78
+
79
+ assert train_df["id"].nunique() == len(train_df), "There should be no duplicate ids in train"
80
+ assert test_df["id"].nunique() == len(test_df), "There should be no duplicate ids in test"
81
+
82
+
83
+ def prepare(raw: Path, public: Path, private: Path):
84
+
85
+ old_train = read_csv(raw / "train.csv")
86
+
87
+ # need to split the train.zip into train.zip and test.zip; to do so need to extract first
88
+ extract(raw / "train.zip", raw)
89
+ raw_image_dir = raw / "train"
90
+
91
+ # --- 1. Original Split: Create main train and test sets ---
92
+ # This block creates the original public/private outputs, which must remain unchanged.
93
+
94
+ # 4000 / (4000 + 17500) -> test_size is ~0.19
95
+ new_train, new_test = train_test_split(old_train, test_size=0.19, random_state=0)
96
+
97
+ _process_and_save_split(
98
+ train_df=new_train,
99
+ test_df=new_test,
100
+ public_dir=public,
101
+ private_dir=private,
102
+ raw_image_dir=raw_image_dir,
103
+ original_df=old_train,
104
+ )
105
+
106
+ # --- 2. New Validation Split: Create a validation set from the main train set ---
107
+ # This block creates the new public_val/private_val outputs.
108
+
109
+ # Define paths for the new validation split artifacts
110
+ public_val = public.parent / "public_val"
111
+ private_val = private.parent / "private_val"
112
+
113
+ # To make the new validation set (test_val) have the same size as the original
114
+ # test set (new_test), we calculate the required test_size proportion.
115
+ test_size_for_val_split = len(new_test) / len(new_train)
116
+
117
+ # Split the main training set (new_train) into a smaller training set (train_val)
118
+ # and a validation set (test_val), using the same random_state for consistency.
119
+ train_val, test_val = train_test_split(new_train, test_size=test_size_for_val_split, random_state=0)
120
+
121
+ _process_and_save_split(
122
+ train_df=train_val,
123
+ test_df=test_val,
124
+ public_dir=public_val,
125
+ private_dir=private_val,
126
+ raw_image_dir=raw_image_dir,
127
+ original_df=new_train,
128
+ )
129
+
130
+ # --- Final Cleanup ---
131
+ # and cleanup the extracted raw image directory, which is no longer needed
132
+ shutil.rmtree(raw_image_dir)
133
+ assert not (raw / "train").exists(), "raw/train/ should not exist"
@@ -0,0 +1,136 @@
1
+ import numpy as np
2
+ import pandas as pd
3
+ from sklearn import metrics
4
+
5
+ from mlebench.grade_helpers import InvalidSubmissionError
6
+
7
+
8
+ def insert_thresholds(fpr: np.ndarray, tpr: np.ndarray, tpr_thresholds: list) -> tuple:
9
+ """
10
+ Insert tpr_thresholds into the TPR and FPR arrays to ensure that the thresholds are present
11
+ in the TPR array and the corresponding FPR values are interpolated.
12
+
13
+ e.g.
14
+ > tpr = [0.0, 0.25, 0.5, 0.75, 1.0]
15
+ > fpr = [0.0, 0.1, 0.2, 0.3, 0.4]
16
+
17
+ > tpr_thresholds = [0.0, 0.3, 0.4, 1.0]
18
+ > fpr, tpr = insert_thresholds(fpr, tpr, tpr_thresholds)
19
+
20
+ > print(tpr)
21
+ > print(fpr)
22
+ [0.0, 0.25, 0.3, 0.4, 0.5, 0.75, 1.0]
23
+ [0.0, 0.1, 0.12, 0.16, 0.2, 0.3, 0.4]
24
+ """
25
+ fpr_ = fpr.tolist().copy() # Don't modify the input arrays
26
+ tpr_ = tpr.tolist().copy()
27
+ for threshold in tpr_thresholds:
28
+ if threshold not in tpr_:
29
+ # Find the right position within tpr to insert the threshold
30
+ for i, tpr_val in enumerate(tpr_):
31
+ if tpr_val > threshold:
32
+ # Linear interpolation of fpr
33
+ new_fpr = fpr_[i - 1] + (fpr_[i] - fpr_[i - 1]) * (threshold - tpr_[i - 1]) / (
34
+ tpr_[i] - tpr_[i - 1]
35
+ )
36
+
37
+ tpr_.insert(i, threshold)
38
+ fpr_.insert(i, new_fpr)
39
+ break
40
+ return np.array(fpr_), np.array(tpr_)
41
+
42
+
43
+ def alaska_weighted_auc(y_true: np.ndarray, y_pred: np.ndarray) -> float:
44
+ """
45
+ Instead of the standard AUC, the competition uses a weighted AUC where different regions of
46
+ the ROC curve are weighted differently.
47
+
48
+ We compute the area under the curve segment by segment (HORIZONTAL segments between TPR pairs
49
+ on the y-axis), and then compute a weighted average of the segments.
50
+
51
+ For more details, see:
52
+ www.kaggle.com/competitions/alaska2-image-steganalysis/overview/evaluation
53
+
54
+ This particular implementation is adapted from:
55
+ https://www.kaggle.com/code/anokas/weighted-auc-metric-updated
56
+ (Key change vs the above implementation: The above implementation uses the `tpr` and `fpr`
57
+ arrays from metrics.roc_curve as is, neglecting to handle the case where the `tpr` values
58
+ don't line up nicely with the thresholds - leading to a situation where some segments either
59
+ belong partially to the wrong threshold, or get skipped entirely. Our implementation fixes
60
+ this by inserting the thresholds into the `tpr` and `fpr` arrays before computing the AUC.)
61
+ """
62
+ tpr_thresholds = [0.0, 0.4, 1.0]
63
+ weights = [2, 1]
64
+
65
+ fpr, tpr, thresholds = metrics.roc_curve(y_true, y_pred, pos_label=1)
66
+ fpr, tpr = insert_thresholds(fpr, tpr, tpr_thresholds)
67
+
68
+ # size of subsets
69
+ areas = np.array(tpr_thresholds[1:]) - np.array(tpr_thresholds[:-1])
70
+
71
+ competition_metric = 0
72
+ # Compute AUC segment by segment (where each segment is a horizontal slice of the ROC curve
73
+ # between a pair of consecutive TPR thresholds)
74
+ for idx, weight in enumerate(weights):
75
+ y_min = tpr_thresholds[idx]
76
+ y_max = tpr_thresholds[idx + 1]
77
+
78
+ # Here, we're creating new x and y arrays to calculate the AUC for this segment:
79
+
80
+ # The segment arrays consist of the FPR and TPR values in the segment,
81
+ mask = (y_min <= tpr) & (tpr <= y_max)
82
+ if mask.sum() == 0:
83
+ continue
84
+ xs = fpr[mask]
85
+ ys = tpr[mask]
86
+
87
+ # plus a new point [1, y_max] which just closes the shape of this segment (draws a
88
+ # horizontal line from the highest point in this segment to the right of the x-axis)
89
+ xs = np.concatenate([xs, [1]])
90
+ ys = np.concatenate([ys, [y_max]])
91
+ ys = ys - y_min # normalize such that curve starts at y=0
92
+ score = metrics.auc(xs, ys)
93
+ submetric = score * weight
94
+ competition_metric += submetric
95
+
96
+ # The total area is normalized by the sum of weights such that the final weighted AUC is between 0 and 1.
97
+ normalization = np.dot(areas, weights)
98
+
99
+ return competition_metric / normalization
100
+
101
+
102
+ def prepare_for_metric(submission: pd.DataFrame, answers: pd.DataFrame):
103
+ if len(submission) != len(answers):
104
+ raise InvalidSubmissionError("Submission and answers must have the same length")
105
+
106
+ if "Id" not in submission.columns:
107
+ raise InvalidSubmissionError("Submission must have an 'Id' column")
108
+
109
+ if "Label" not in submission.columns:
110
+ raise InvalidSubmissionError("Submission must have a 'Label' column")
111
+
112
+ submission = submission.sort_values("Id")
113
+ answers = answers.sort_values("Id")
114
+
115
+ if (submission["Id"].values != answers["Id"].values).any():
116
+ raise InvalidSubmissionError("Submission and answers must have the same ids")
117
+
118
+ # Answers and submission must be numbers
119
+ try:
120
+ submission["Label"] = submission["Label"].astype(float)
121
+ except ValueError:
122
+ raise InvalidSubmissionError("Labels in submission must be numbers")
123
+ answers["Label"] = answers["Label"].astype(float)
124
+
125
+ # Cannot contain NaNs
126
+ assert not answers["Label"].isnull().any(), "Answers cannot contain NaNs"
127
+ if submission["Label"].isnull().any():
128
+ raise InvalidSubmissionError("Submission cannot contain NaNs")
129
+
130
+ return answers["Label"], submission["Label"]
131
+
132
+
133
+ def grade(submission: pd.DataFrame, answers: pd.DataFrame) -> float:
134
+ y_true, y_pred = prepare_for_metric(submission, answers)
135
+
136
+ return alaska_weighted_auc(np.array(y_true), np.array(y_pred))