torch-em 0.9.0__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 (303) hide show
  1. torch_em/__init__.py +11 -0
  2. torch_em/__version__.py +1 -0
  3. torch_em/classification/__init__.py +6 -0
  4. torch_em/classification/classification.py +126 -0
  5. torch_em/classification/classification_dataset.py +65 -0
  6. torch_em/classification/classification_logger.py +137 -0
  7. torch_em/classification/classification_trainer.py +42 -0
  8. torch_em/cli.py +413 -0
  9. torch_em/data/__init__.py +18 -0
  10. torch_em/data/concat_dataset.py +39 -0
  11. torch_em/data/dataset_wrapper.py +23 -0
  12. torch_em/data/datasets/__init__.py +13 -0
  13. torch_em/data/datasets/electron_microscopy/__init__.py +48 -0
  14. torch_em/data/datasets/electron_microscopy/aimseg.py +159 -0
  15. torch_em/data/datasets/electron_microscopy/asem.py +256 -0
  16. torch_em/data/datasets/electron_microscopy/astih.py +340 -0
  17. torch_em/data/datasets/electron_microscopy/axondeepseg.py +277 -0
  18. torch_em/data/datasets/electron_microscopy/axonem.py +150 -0
  19. torch_em/data/datasets/electron_microscopy/betaseg.py +166 -0
  20. torch_em/data/datasets/electron_microscopy/cellmap.py +550 -0
  21. torch_em/data/datasets/electron_microscopy/cem.py +382 -0
  22. torch_em/data/datasets/electron_microscopy/cremi.py +251 -0
  23. torch_em/data/datasets/electron_microscopy/deepict.py +178 -0
  24. torch_em/data/datasets/electron_microscopy/densecell.py +197 -0
  25. torch_em/data/datasets/electron_microscopy/emneuron.py +153 -0
  26. torch_em/data/datasets/electron_microscopy/emps.py +185 -0
  27. torch_em/data/datasets/electron_microscopy/fafb.py +241 -0
  28. torch_em/data/datasets/electron_microscopy/fafb_nuclei.py +116 -0
  29. torch_em/data/datasets/electron_microscopy/fib25.py +215 -0
  30. torch_em/data/datasets/electron_microscopy/hemibrain.py +243 -0
  31. torch_em/data/datasets/electron_microscopy/human_cortex_h01.py +242 -0
  32. torch_em/data/datasets/electron_microscopy/human_organoids.py +179 -0
  33. torch_em/data/datasets/electron_microscopy/hydra_vulgaris.py +299 -0
  34. torch_em/data/datasets/electron_microscopy/isbi2012.py +121 -0
  35. torch_em/data/datasets/electron_microscopy/kasthuri.py +173 -0
  36. torch_em/data/datasets/electron_microscopy/lucchi.py +174 -0
  37. torch_em/data/datasets/electron_microscopy/malecns.py +214 -0
  38. torch_em/data/datasets/electron_microscopy/manc.py +197 -0
  39. torch_em/data/datasets/electron_microscopy/microns.py +527 -0
  40. torch_em/data/datasets/electron_microscopy/microns_nuclei.py +119 -0
  41. torch_em/data/datasets/electron_microscopy/mitoem.py +274 -0
  42. torch_em/data/datasets/electron_microscopy/mitoemv2.py +309 -0
  43. torch_em/data/datasets/electron_microscopy/mousecc.py +180 -0
  44. torch_em/data/datasets/electron_microscopy/nisb.py +283 -0
  45. torch_em/data/datasets/electron_microscopy/nuc_mm.py +159 -0
  46. torch_em/data/datasets/electron_microscopy/platynereis.py +448 -0
  47. torch_em/data/datasets/electron_microscopy/probtem.py +179 -0
  48. torch_em/data/datasets/electron_microscopy/snemi.py +135 -0
  49. torch_em/data/datasets/electron_microscopy/sponge_em.py +137 -0
  50. torch_em/data/datasets/electron_microscopy/synapseweb_hippocampus.py +200 -0
  51. torch_em/data/datasets/electron_microscopy/uro_cell.py +226 -0
  52. torch_em/data/datasets/electron_microscopy/vnc.py +163 -0
  53. torch_em/data/datasets/electron_microscopy/waenet.py +293 -0
  54. torch_em/data/datasets/electron_microscopy/wildenberg.py +384 -0
  55. torch_em/data/datasets/electron_microscopy/zebrafinch.py +312 -0
  56. torch_em/data/datasets/histopathology/__init__.py +23 -0
  57. torch_em/data/datasets/histopathology/bcss.py +243 -0
  58. torch_em/data/datasets/histopathology/conic.py +234 -0
  59. torch_em/data/datasets/histopathology/consep.py +209 -0
  60. torch_em/data/datasets/histopathology/cpm.py +221 -0
  61. torch_em/data/datasets/histopathology/cryonuseg.py +186 -0
  62. torch_em/data/datasets/histopathology/cytodark0.py +211 -0
  63. torch_em/data/datasets/histopathology/glas.py +172 -0
  64. torch_em/data/datasets/histopathology/glysac.py +182 -0
  65. torch_em/data/datasets/histopathology/hest.py +735 -0
  66. torch_em/data/datasets/histopathology/janowczyk.py +231 -0
  67. torch_em/data/datasets/histopathology/lizard.py +194 -0
  68. torch_em/data/datasets/histopathology/lynsec.py +222 -0
  69. torch_em/data/datasets/histopathology/monusac.py +294 -0
  70. torch_em/data/datasets/histopathology/monuseg.py +248 -0
  71. torch_em/data/datasets/histopathology/nuclick.py +149 -0
  72. torch_em/data/datasets/histopathology/nuinsseg.py +128 -0
  73. torch_em/data/datasets/histopathology/orion_crc.py +526 -0
  74. torch_em/data/datasets/histopathology/pannuke.py +277 -0
  75. torch_em/data/datasets/histopathology/panoptils.py +195 -0
  76. torch_em/data/datasets/histopathology/pcns.py +325 -0
  77. torch_em/data/datasets/histopathology/puma.py +345 -0
  78. torch_em/data/datasets/histopathology/segpath.py +336 -0
  79. torch_em/data/datasets/histopathology/srsanet.py +167 -0
  80. torch_em/data/datasets/histopathology/tnbc.py +200 -0
  81. torch_em/data/datasets/light_microscopy/__init__.py +83 -0
  82. torch_em/data/datasets/light_microscopy/aisegcell.py +210 -0
  83. torch_em/data/datasets/light_microscopy/arvidsson.py +179 -0
  84. torch_em/data/datasets/light_microscopy/bac_mother.py +136 -0
  85. torch_em/data/datasets/light_microscopy/balf.py +268 -0
  86. torch_em/data/datasets/light_microscopy/bbbc030.py +214 -0
  87. torch_em/data/datasets/light_microscopy/bbbc034.py +155 -0
  88. torch_em/data/datasets/light_microscopy/bccd.py +206 -0
  89. torch_em/data/datasets/light_microscopy/bitdepth_nucseg.py +156 -0
  90. torch_em/data/datasets/light_microscopy/blastospim.py +139 -0
  91. torch_em/data/datasets/light_microscopy/bmgd.py +236 -0
  92. torch_em/data/datasets/light_microscopy/brain_organoids.py +131 -0
  93. torch_em/data/datasets/light_microscopy/brifiseg.py +166 -0
  94. torch_em/data/datasets/light_microscopy/cartocell.py +145 -0
  95. torch_em/data/datasets/light_microscopy/celegans_atlas.py +134 -0
  96. torch_em/data/datasets/light_microscopy/cellbindb.py +166 -0
  97. torch_em/data/datasets/light_microscopy/cellpose.py +176 -0
  98. torch_em/data/datasets/light_microscopy/cellseg_3d.py +126 -0
  99. torch_em/data/datasets/light_microscopy/cisd.py +278 -0
  100. torch_em/data/datasets/light_microscopy/covid_if.py +166 -0
  101. torch_em/data/datasets/light_microscopy/cshaper.py +231 -0
  102. torch_em/data/datasets/light_microscopy/ctc.py +226 -0
  103. torch_em/data/datasets/light_microscopy/cvz_fluo.py +172 -0
  104. torch_em/data/datasets/light_microscopy/deepbacs.py +213 -0
  105. torch_em/data/datasets/light_microscopy/deepseas.py +142 -0
  106. torch_em/data/datasets/light_microscopy/dic_hepg2.py +190 -0
  107. torch_em/data/datasets/light_microscopy/dsb.py +248 -0
  108. torch_em/data/datasets/light_microscopy/dynamicnuclearnet.py +170 -0
  109. torch_em/data/datasets/light_microscopy/e11bio.py +259 -0
  110. torch_em/data/datasets/light_microscopy/embedseg_data.py +147 -0
  111. torch_em/data/datasets/light_microscopy/enseg.py +234 -0
  112. torch_em/data/datasets/light_microscopy/evican.py +335 -0
  113. torch_em/data/datasets/light_microscopy/glioma_c6.py +234 -0
  114. torch_em/data/datasets/light_microscopy/gonuclear.py +245 -0
  115. torch_em/data/datasets/light_microscopy/hpa.py +453 -0
  116. torch_em/data/datasets/light_microscopy/idr0095.py +274 -0
  117. torch_em/data/datasets/light_microscopy/ifnuclei.py +107 -0
  118. torch_em/data/datasets/light_microscopy/liconn.py +271 -0
  119. torch_em/data/datasets/light_microscopy/livecell.py +305 -0
  120. torch_em/data/datasets/light_microscopy/lpc_nucseg.py +201 -0
  121. torch_em/data/datasets/light_microscopy/lsm_mouse_embryo.py +210 -0
  122. torch_em/data/datasets/light_microscopy/medussa.py +228 -0
  123. torch_em/data/datasets/light_microscopy/microbeseg.py +174 -0
  124. torch_em/data/datasets/light_microscopy/mndino.py +230 -0
  125. torch_em/data/datasets/light_microscopy/morphonet.py +247 -0
  126. torch_em/data/datasets/light_microscopy/morphoseg.py +216 -0
  127. torch_em/data/datasets/light_microscopy/mouse_embryo.py +153 -0
  128. torch_em/data/datasets/light_microscopy/mucic.py +484 -0
  129. torch_em/data/datasets/light_microscopy/neurips_cell_seg.py +361 -0
  130. torch_em/data/datasets/light_microscopy/neurosphere.py +176 -0
  131. torch_em/data/datasets/light_microscopy/nis3d.py +156 -0
  132. torch_em/data/datasets/light_microscopy/nisnet3d.py +191 -0
  133. torch_em/data/datasets/light_microscopy/nuc_morph.py +238 -0
  134. torch_em/data/datasets/light_microscopy/omnipose.py +171 -0
  135. torch_em/data/datasets/light_microscopy/oocyteseg.py +234 -0
  136. torch_em/data/datasets/light_microscopy/orgaextractor.py +160 -0
  137. torch_em/data/datasets/light_microscopy/organoid.py +270 -0
  138. torch_em/data/datasets/light_microscopy/organoidnet.py +148 -0
  139. torch_em/data/datasets/light_microscopy/orgasegment.py +144 -0
  140. torch_em/data/datasets/light_microscopy/orgline.py +282 -0
  141. torch_em/data/datasets/light_microscopy/parhyale_regen.py +140 -0
  142. torch_em/data/datasets/light_microscopy/phmamm.py +154 -0
  143. torch_em/data/datasets/light_microscopy/plantseg.py +244 -0
  144. torch_em/data/datasets/light_microscopy/pnas_arabidopsis.py +140 -0
  145. torch_em/data/datasets/light_microscopy/scaffold_a549.py +171 -0
  146. torch_em/data/datasets/light_microscopy/segpc.py +175 -0
  147. torch_em/data/datasets/light_microscopy/slimia.py +235 -0
  148. torch_em/data/datasets/light_microscopy/spheroids_hepg2.py +139 -0
  149. torch_em/data/datasets/light_microscopy/synthmt.py +191 -0
  150. torch_em/data/datasets/light_microscopy/tissuenet.py +192 -0
  151. torch_em/data/datasets/light_microscopy/toiam.py +111 -0
  152. torch_em/data/datasets/light_microscopy/u20s.py +159 -0
  153. torch_em/data/datasets/light_microscopy/usiigaci.py +124 -0
  154. torch_em/data/datasets/light_microscopy/vgg_hela.py +160 -0
  155. torch_em/data/datasets/light_microscopy/vibrio_cholerae.py +137 -0
  156. torch_em/data/datasets/light_microscopy/vicar.py +152 -0
  157. torch_em/data/datasets/light_microscopy/wing_disc.py +198 -0
  158. torch_em/data/datasets/light_microscopy/xpress.py +149 -0
  159. torch_em/data/datasets/light_microscopy/yeastcellseg.py +187 -0
  160. torch_em/data/datasets/light_microscopy/yeastms.py +196 -0
  161. torch_em/data/datasets/light_microscopy/yeastsam.py +131 -0
  162. torch_em/data/datasets/light_microscopy/yeaz.py +181 -0
  163. torch_em/data/datasets/medical/__init__.py +60 -0
  164. torch_em/data/datasets/medical/abus.py +165 -0
  165. torch_em/data/datasets/medical/acdc.py +162 -0
  166. torch_em/data/datasets/medical/acouslic_ai.py +125 -0
  167. torch_em/data/datasets/medical/amd_sd.py +190 -0
  168. torch_em/data/datasets/medical/amos.py +179 -0
  169. torch_em/data/datasets/medical/autopet.py +152 -0
  170. torch_em/data/datasets/medical/btcv.py +229 -0
  171. torch_em/data/datasets/medical/busi.py +142 -0
  172. torch_em/data/datasets/medical/camus.py +141 -0
  173. torch_em/data/datasets/medical/cbis_ddsm.py +195 -0
  174. torch_em/data/datasets/medical/chaos.py +236 -0
  175. torch_em/data/datasets/medical/cholecseg8k.py +203 -0
  176. torch_em/data/datasets/medical/covid19_seg.py +171 -0
  177. torch_em/data/datasets/medical/covid_qu_ex.py +190 -0
  178. torch_em/data/datasets/medical/ct_cadaiver.py +131 -0
  179. torch_em/data/datasets/medical/curvas.py +194 -0
  180. torch_em/data/datasets/medical/dca1.py +149 -0
  181. torch_em/data/datasets/medical/drive.py +176 -0
  182. torch_em/data/datasets/medical/dsad.py +154 -0
  183. torch_em/data/datasets/medical/duke_liver.py +208 -0
  184. torch_em/data/datasets/medical/feta24.py +144 -0
  185. torch_em/data/datasets/medical/fundus_avseg.py +180 -0
  186. torch_em/data/datasets/medical/han_seg.py +166 -0
  187. torch_em/data/datasets/medical/hil_toothseg.py +174 -0
  188. torch_em/data/datasets/medical/idrid.py +164 -0
  189. torch_em/data/datasets/medical/ircadb.py +201 -0
  190. torch_em/data/datasets/medical/isic.py +190 -0
  191. torch_em/data/datasets/medical/isles.py +141 -0
  192. torch_em/data/datasets/medical/jnuifm.py +122 -0
  193. torch_em/data/datasets/medical/jsrt.py +179 -0
  194. torch_em/data/datasets/medical/kits.py +303 -0
  195. torch_em/data/datasets/medical/kvasir.py +147 -0
  196. torch_em/data/datasets/medical/leg_3d_us.py +190 -0
  197. torch_em/data/datasets/medical/lgg_mri.py +183 -0
  198. torch_em/data/datasets/medical/m2caiseg.py +213 -0
  199. torch_em/data/datasets/medical/mbh_seg.py +125 -0
  200. torch_em/data/datasets/medical/mice_tumseg.py +157 -0
  201. torch_em/data/datasets/medical/micro_usp.py +141 -0
  202. torch_em/data/datasets/medical/montgomery.py +155 -0
  203. torch_em/data/datasets/medical/motum.py +161 -0
  204. torch_em/data/datasets/medical/msd.py +180 -0
  205. torch_em/data/datasets/medical/oasis.py +162 -0
  206. torch_em/data/datasets/medical/oimhs.py +205 -0
  207. torch_em/data/datasets/medical/osic_pulmofib.py +234 -0
  208. torch_em/data/datasets/medical/palm.py +174 -0
  209. torch_em/data/datasets/medical/panorama.py +193 -0
  210. torch_em/data/datasets/medical/papila.py +205 -0
  211. torch_em/data/datasets/medical/pengwin.py +168 -0
  212. torch_em/data/datasets/medical/piccolo.py +149 -0
  213. torch_em/data/datasets/medical/plethora.py +238 -0
  214. torch_em/data/datasets/medical/psfhs.py +148 -0
  215. torch_em/data/datasets/medical/ravir.py +133 -0
  216. torch_em/data/datasets/medical/sa_med2d.py +431 -0
  217. torch_em/data/datasets/medical/sega.py +201 -0
  218. torch_em/data/datasets/medical/segthy.py +204 -0
  219. torch_em/data/datasets/medical/siim_acr.py +179 -0
  220. torch_em/data/datasets/medical/spider.py +142 -0
  221. torch_em/data/datasets/medical/toothfairy.py +223 -0
  222. torch_em/data/datasets/medical/uwaterloo_skin.py +161 -0
  223. torch_em/data/datasets/medical/verse.py +142 -0
  224. torch_em/data/datasets/util.py +593 -0
  225. torch_em/data/image_collection_dataset.py +264 -0
  226. torch_em/data/pseudo_label_dataset.py +86 -0
  227. torch_em/data/raw_dataset.py +383 -0
  228. torch_em/data/raw_image_collection_dataset.py +187 -0
  229. torch_em/data/sampler.py +233 -0
  230. torch_em/data/segmentation_dataset.py +287 -0
  231. torch_em/data/tensor_dataset.py +90 -0
  232. torch_em/loss/__init__.py +15 -0
  233. torch_em/loss/affinity_side_loss.py +172 -0
  234. torch_em/loss/cldice.py +216 -0
  235. torch_em/loss/combined_loss.py +38 -0
  236. torch_em/loss/contrastive.py +169 -0
  237. torch_em/loss/contrastive_impl.py +272 -0
  238. torch_em/loss/dice.py +256 -0
  239. torch_em/loss/distance_based.py +69 -0
  240. torch_em/loss/spoco_loss.py +643 -0
  241. torch_em/loss/wrapper.py +183 -0
  242. torch_em/metric/__init__.py +8 -0
  243. torch_em/metric/cldice.py +63 -0
  244. torch_em/metric/instance_segmentation_metric.py +483 -0
  245. torch_em/model/__init__.py +8 -0
  246. torch_em/model/probabilistic_unet.py +475 -0
  247. torch_em/model/resnet3d.py +518 -0
  248. torch_em/model/unet.py +728 -0
  249. torch_em/model/unetr.py +1018 -0
  250. torch_em/model/vim.py +267 -0
  251. torch_em/model/vit.py +1017 -0
  252. torch_em/multi_gpu_training.py +190 -0
  253. torch_em/segmentation.py +574 -0
  254. torch_em/self_training/__init__.py +13 -0
  255. torch_em/self_training/augmentations.py +4 -0
  256. torch_em/self_training/fix_match.py +689 -0
  257. torch_em/self_training/logger.py +404 -0
  258. torch_em/self_training/loss.py +406 -0
  259. torch_em/self_training/mean_teacher.py +723 -0
  260. torch_em/self_training/probabilistic_unet_trainer.py +117 -0
  261. torch_em/self_training/pseudo_labeling.py +397 -0
  262. torch_em/self_training/uni_match_v2.py +435 -0
  263. torch_em/shallow2deep/__init__.py +8 -0
  264. torch_em/shallow2deep/prepare_shallow2deep.py +880 -0
  265. torch_em/shallow2deep/pseudolabel_training.py +162 -0
  266. torch_em/shallow2deep/shallow2deep_dataset.py +403 -0
  267. torch_em/shallow2deep/shallow2deep_eval.py +231 -0
  268. torch_em/shallow2deep/shallow2deep_model.py +205 -0
  269. torch_em/shallow2deep/transform.py +86 -0
  270. torch_em/trainer/__init__.py +3 -0
  271. torch_em/trainer/default_trainer.py +852 -0
  272. torch_em/trainer/flashoptim_trainer.py +111 -0
  273. torch_em/trainer/logger_base.py +18 -0
  274. torch_em/trainer/spoco_trainer.py +152 -0
  275. torch_em/trainer/tensorboard_logger.py +162 -0
  276. torch_em/trainer/wandb_logger.py +118 -0
  277. torch_em/transform/__init__.py +8 -0
  278. torch_em/transform/augmentation.py +302 -0
  279. torch_em/transform/defect.py +245 -0
  280. torch_em/transform/generic.py +235 -0
  281. torch_em/transform/invertible_augmentations.py +199 -0
  282. torch_em/transform/label.py +633 -0
  283. torch_em/transform/nnunet_raw.py +96 -0
  284. torch_em/transform/raw.py +389 -0
  285. torch_em/util/__init__.py +21 -0
  286. torch_em/util/debug.py +178 -0
  287. torch_em/util/grid_search.py +232 -0
  288. torch_em/util/image.py +115 -0
  289. torch_em/util/modelzoo.py +893 -0
  290. torch_em/util/prediction.py +320 -0
  291. torch_em/util/reporting.py +77 -0
  292. torch_em/util/segmentation.py +233 -0
  293. torch_em/util/submit_slurm.py +103 -0
  294. torch_em/util/test.py +59 -0
  295. torch_em/util/training.py +19 -0
  296. torch_em/util/util.py +486 -0
  297. torch_em/util/validation.py +265 -0
  298. torch_em-0.9.0.dist-info/METADATA +27 -0
  299. torch_em-0.9.0.dist-info/RECORD +303 -0
  300. torch_em-0.9.0.dist-info/WHEEL +5 -0
  301. torch_em-0.9.0.dist-info/entry_points.txt +7 -0
  302. torch_em-0.9.0.dist-info/licenses/LICENSE +21 -0
  303. torch_em-0.9.0.dist-info/top_level.txt +1 -0
torch_em/__init__.py ADDED
@@ -0,0 +1,11 @@
1
+ """
2
+ .. include:: ../doc/start_page.md
3
+ .. include:: ../doc/datasets_and_dataloaders.md
4
+ """
5
+ from .segmentation import (
6
+ default_segmentation_dataset,
7
+ default_segmentation_loader,
8
+ default_segmentation_trainer,
9
+ get_data_loader,
10
+ )
11
+ from .__version__ import __version__
@@ -0,0 +1 @@
1
+ __version__ = "0.9.0"
@@ -0,0 +1,6 @@
1
+ """Dataset, DataLoader and Trainer implementations for image classification tasks.
2
+ """
3
+ from .classification import default_classification_trainer, default_classification_loader
4
+
5
+ from .classification_logger import ClassificationLogger
6
+ from .classification_trainer import ClassificationTrainer
@@ -0,0 +1,126 @@
1
+ from functools import partial
2
+ from typing import Optional, Sequence, Tuple, Union
3
+
4
+ import numpy as np
5
+ import sklearn.metrics as metrics
6
+ import torch
7
+ import torch_em
8
+ from numpy.typing import ArrayLike
9
+
10
+ from .classification_dataset import ClassificationDataset
11
+ from .classification_logger import ClassificationLogger
12
+ from .classification_trainer import ClassificationTrainer
13
+
14
+
15
+ class ClassificationMetric:
16
+ """Metric for classification training.
17
+
18
+ Args:
19
+ metric_name: The name of the metrics. The name will be looked up in `sklearn.metrics`,
20
+ so it must be a valid identifier in that python package.
21
+ metric_kwargs: Keyword arguments for the metric.
22
+ """
23
+ def __init__(self, metric_name: str = "accuracy_score", **metric_kwargs):
24
+ if not hasattr(metrics, metric_name):
25
+ raise ValueError(f"Invalid metric_name {metric_name}.")
26
+ self.metric = getattr(metrics, metric_name)
27
+ self.metric_kwargs = metric_kwargs
28
+
29
+ def __call__(self, y_true: np.ndarray, y_pred: np.ndarray) -> float:
30
+ """Evaluate model prediction against classification labels.
31
+
32
+ Args:
33
+ y_true: The classification labels.
34
+ y_pred: The model predictions.
35
+
36
+ Returns:
37
+ The metric value.
38
+ """
39
+ metric_error = 1.0 - self.metric(y_true, y_pred, **self.metric_kwargs)
40
+ return metric_error
41
+
42
+
43
+ def default_classification_loader(
44
+ data: Sequence[ArrayLike],
45
+ target: Sequence[ArrayLike],
46
+ batch_size: int,
47
+ normalization: Optional[callable] = None,
48
+ augmentation: Optional[callable] = None,
49
+ image_shape: Optional[Tuple[int, ...]] = None,
50
+ **loader_kwargs,
51
+ ) -> torch.utils.data.DataLoader:
52
+ """Get a data loader for classification training.
53
+
54
+ Args:
55
+ data: The input data for classification. Expects a sequence of array-like data.
56
+ The data can be two or three dimensional.
57
+ target: The target data for classification. Expects a sequence of the same length as `data`.
58
+ Each value in the sequence must be a scalar.
59
+ batch_size: The batch size for the data loader.
60
+ normalization: The normalization function. If None, data standardization will be used.
61
+ augmentation: The augmentation function. If None, the default augmentations will be used.
62
+ image_shape: The target shape of the data. If given, each sample will be resampled to this size.
63
+ loader_kwargs: Additional keyword arguments for `torch.utils.data.DataLoader`.
64
+
65
+ Returns:
66
+ The data loader.
67
+ """
68
+ ndim = data[0].ndim - 1
69
+ if ndim not in (2, 3):
70
+ raise ValueError(f"Expect input data of dimensionality 2 or 3, got {ndim}")
71
+
72
+ if normalization is None:
73
+ axis = (1, 2) if ndim == 2 else (1, 2, 3)
74
+ normalization = partial(torch_em.transform.raw.standardize, axis=axis)
75
+
76
+ if augmentation is None:
77
+ augmentation = torch_em.transform.get_augmentations(ndim=ndim)
78
+
79
+ dataset = ClassificationDataset(data, target, normalization, augmentation, image_shape)
80
+ loader = torch_em.segmentation.get_data_loader(dataset, batch_size, **loader_kwargs)
81
+ return loader
82
+
83
+
84
+ def default_classification_trainer(
85
+ name: str,
86
+ model: torch.nn.Module,
87
+ train_loader: torch.utils.data.DataLoader,
88
+ val_loader: torch.utils.data.DataLoader,
89
+ loss: Optional[Union[torch.nn.Module, callable]] = None,
90
+ metric: Optional[Union[torch.nn.Module, callable]] = None,
91
+ logger=ClassificationLogger,
92
+ trainer_class=ClassificationTrainer,
93
+ **kwargs,
94
+ ):
95
+ """Get a trainer for a classification task.
96
+
97
+ This will create an instance of `torch_em.classification.ClassificationTrainer`.
98
+ Check out its documentation string for details on how to configure and use the trainer.
99
+
100
+ Args:
101
+ name: The name for the checkpoint created by the trainer.
102
+ model: The classification model to train.
103
+ train_loader: The data loader for training.
104
+ val_loader: The data loader for validation.
105
+ loss: The loss function. If None, will use cross entropy.
106
+ metric: The metric function. If None, will use the accuracy error.
107
+ logger: The logger for keeping track of the training progress.
108
+ trainer_class: The trainer class.
109
+ kwargs: Keyword arguments for the trainer class.
110
+
111
+ Returns:
112
+ The classification trainer.
113
+ """
114
+ # Set the default loss and metric (if no values where passed).
115
+ loss = torch.nn.CrossEntropyLoss() if loss is None else loss
116
+ metric = ClassificationMetric() if metric is None else metric
117
+
118
+ # Metric: Note that we use lower metric = better.
119
+ # So we record the accuracy error instead of the accuracy..
120
+ trainer = torch_em.default_segmentation_trainer(
121
+ name, model, train_loader, val_loader,
122
+ loss=loss, metric=metric,
123
+ logger=logger, trainer_class=trainer_class,
124
+ **kwargs,
125
+ )
126
+ return trainer
@@ -0,0 +1,65 @@
1
+ from typing import Sequence, Tuple
2
+
3
+ import numpy as np
4
+ import torch
5
+
6
+ from numpy.typing import ArrayLike
7
+ from skimage.transform import resize
8
+
9
+
10
+ class ClassificationDataset(torch.utils.data.Dataset):
11
+ """Dataset for classification training.
12
+
13
+ Args:
14
+ data: The input data for classification. Expects a sequence of array-like data.
15
+ The data can be two or three dimensional.
16
+ target: The target data for classification. Expects a sequence of the same length as `data`.
17
+ Each value in the sequence must be a scalar.
18
+ normalization: The normalization function.
19
+ augmentation: The augmentation function.
20
+ image_shape: The target shape of the data. If given, each sample will be resampled to this size.
21
+ """
22
+ def __init__(
23
+ self,
24
+ data: Sequence[ArrayLike],
25
+ target: Sequence[ArrayLike],
26
+ normalization: callable,
27
+ augmentation: callable,
28
+ image_shape: Tuple[int, ...],
29
+ ):
30
+ if len(data) != len(target):
31
+ raise ValueError(f"Length of data and target don't agree: {len(data)} != {len(target)}")
32
+ self.data = data
33
+ self.target = target
34
+ self.normalization = normalization
35
+ self.augmentation = augmentation
36
+ self.image_shape = image_shape
37
+
38
+ def __len__(self):
39
+ return len(self.data)
40
+
41
+ def resize(self, x):
42
+ """@private
43
+ """
44
+ out = [resize(channel, self.image_shape, preserve_range=True)[None] for channel in x]
45
+ return np.concatenate(out, axis=0)
46
+
47
+ def __getitem__(self, index):
48
+ x, y = self.data[index], self.target[index]
49
+
50
+ # apply normalization
51
+ if self.normalization is not None:
52
+ x = self.normalization(x)
53
+
54
+ # resize to sample shape if it was given
55
+ if self.image_shape is not None:
56
+ x = self.resize(x)
57
+
58
+ # apply augmentations (if any)
59
+ if self.augmentation is not None:
60
+ _shape = x.shape
61
+ # adds unwanted batch axis
62
+ x = self.augmentation(x)[0][0]
63
+ assert x.shape == _shape
64
+
65
+ return x, y
@@ -0,0 +1,137 @@
1
+ import os
2
+
3
+ import matplotlib.pyplot as plt
4
+ import numpy as np
5
+
6
+ from matplotlib.backends.backend_agg import FigureCanvasAgg
7
+ from sklearn.metrics import ConfusionMatrixDisplay
8
+ from torch.utils.tensorboard import SummaryWriter
9
+ from torch_em.trainer.logger_base import TorchEmLogger
10
+ from torch_em.transform.raw import normalize
11
+
12
+
13
+ def confusion_matrix(y_true, y_pred, class_labels=None, title=None, save_path=None, **plot_kwargs):
14
+ """@private
15
+ """
16
+ fig, ax = plt.subplots(1)
17
+
18
+ if save_path is None:
19
+ canvas = FigureCanvasAgg(fig)
20
+
21
+ disp = ConfusionMatrixDisplay.from_predictions(
22
+ y_true, y_pred, normalize="true", display_labels=class_labels
23
+ )
24
+ disp.plot(ax=ax, **plot_kwargs)
25
+
26
+ if title is not None:
27
+ ax.set_title(title)
28
+ if save_path is not None:
29
+ plt.savefig(save_path)
30
+ return
31
+
32
+ canvas.draw()
33
+ image = np.asarray(canvas.buffer_rgba())[..., :3]
34
+ image = image.transpose((2, 0, 1))
35
+ plt.close()
36
+ return image
37
+
38
+
39
+ def make_grid(images, target=None, prediction=None, images_per_row=8, **kwargs):
40
+ """@private
41
+ """
42
+ assert images.ndim in (4, 5)
43
+ assert images.shape[1] in (1, 3), f"{images.shape}"
44
+
45
+ if images.ndim == 5:
46
+ is_3d = True
47
+ z = images.shape[2] // 2
48
+ else:
49
+ is_3d = False
50
+
51
+ n_images = images.shape[0]
52
+ n_rows = n_images // images_per_row
53
+ if n_images % images_per_row != 0:
54
+ n_rows += 1
55
+
56
+ images = images.detach().cpu().numpy()
57
+ if target is not None:
58
+ target = target.detach().cpu().numpy()
59
+ if prediction is not None:
60
+ prediction = prediction.max(1)[1].detach().cpu().numpy()
61
+
62
+ fig, axes = plt.subplots(n_rows, images_per_row)
63
+ canvas = FigureCanvasAgg(fig)
64
+ for r in range(n_rows):
65
+ for c in range(images_per_row):
66
+ i = r * images_per_row + c
67
+ if i == len(images):
68
+ break
69
+ ax = axes[r, c] if n_rows > 1 else axes[r]
70
+ ax.set_axis_off()
71
+ im = images[i, :, z] if is_3d else images[i]
72
+ im = im.transpose((1, 2, 0))
73
+ im = normalize(im, axis=(0, 1))
74
+ if im.shape[-1] == 3: # rgb
75
+ ax.imshow(im)
76
+ else:
77
+ ax.imshow(im[..., 0], cmap="gray")
78
+
79
+ if target is None and prediction is None:
80
+ continue
81
+
82
+ # TODO get the class name, and if we have both target
83
+ # and prediction check whether they agree or not and do stuff
84
+ title = ""
85
+ if target is not None:
86
+ title += f"t: {target[i]} "
87
+ if prediction is not None:
88
+ title += f"p: {prediction[i]}"
89
+ ax.set_title(title, fontsize=8)
90
+
91
+ canvas.draw()
92
+ image = np.asarray(canvas.buffer_rgba())[..., :3]
93
+ image = image.transpose((2, 0, 1))
94
+ plt.close()
95
+ return image
96
+
97
+
98
+ class ClassificationLogger(TorchEmLogger):
99
+ """Logger for classification trainer.
100
+
101
+ Args:
102
+ trainer: The trainer instance.
103
+ save_root: Root folder for saving the checkpoints and logs.
104
+ """
105
+ def __init__(self, trainer, save_root: str, **unused_kwargs):
106
+ super().__init__(trainer, save_root)
107
+ self.log_dir = f"./logs/{trainer.name}" if save_root is None else\
108
+ os.path.join(save_root, "logs", trainer.name)
109
+ os.makedirs(self.log_dir, exist_ok=True)
110
+
111
+ self.tb = SummaryWriter(self.log_dir)
112
+ self.log_image_interval = trainer.log_image_interval
113
+
114
+ def add_image(self, x, y, pred, name, step):
115
+ """@private
116
+ """
117
+ scale_each = False
118
+ grid = make_grid(x, y, pred, padding=4, normalize=True, scale_each=scale_each)
119
+ self.tb.add_image(tag=f"{name}/images_and_predictions", img_tensor=grid, global_step=step)
120
+
121
+ def log_train(self, step, loss, lr, x, y, prediction, log_gradients=False):
122
+ """@private
123
+ """
124
+ self.tb.add_scalar(tag="train/loss", scalar_value=loss, global_step=step)
125
+ self.tb.add_scalar(tag="train/learning_rate", scalar_value=lr, global_step=step)
126
+ if step % self.log_image_interval == 0:
127
+ self.add_image(x, y, prediction, "train", step)
128
+
129
+ def log_validation(self, step, metric, loss, x, y, prediction, y_true=None, y_pred=None):
130
+ """@private
131
+ """
132
+ self.tb.add_scalar(tag="validation/loss", scalar_value=loss, global_step=step)
133
+ self.tb.add_scalar(tag="validation/metric", scalar_value=metric, global_step=step)
134
+ self.add_image(x, y, prediction, "validation", step)
135
+ if y_true is not None and y_pred is not None:
136
+ cm = confusion_matrix(y_true, y_pred)
137
+ self.tb.add_image(tag="validation/confusion_matrix", img_tensor=cm, global_step=step)
@@ -0,0 +1,42 @@
1
+ import warnings
2
+
3
+ import numpy as np
4
+ import torch
5
+ import torch_em
6
+
7
+
8
+ class ClassificationTrainer(torch_em.trainer.DefaultTrainer):
9
+ """Trainer for classification tasks.
10
+
11
+ This class inherits from `torch_em.trainer.DefaultTrainer` with minor changes for
12
+ classification instead of segmentation training. Check out the documentation of
13
+ the default trainer class for details on how to configure and use the trainer
14
+ """
15
+ def _validate_impl(self, forward_context):
16
+ self.model.eval()
17
+
18
+ loss_val = 0.0
19
+
20
+ # we use the syntax from sklearn.metrics to compute metrics
21
+ # over all the preditions
22
+ y_true, y_pred = [], []
23
+
24
+ with torch.no_grad():
25
+ for x, y in self.val_loader:
26
+ x, y = x.to(self.device), y.to(self.device)
27
+ with forward_context():
28
+ pred, loss = self._forward_and_loss(x, y)
29
+ loss_val += loss.item()
30
+ y_true.append(y.detach().cpu().numpy())
31
+ y_pred.append(pred.max(1)[1].detach().cpu().numpy())
32
+
33
+ if torch.isnan(pred).any():
34
+ warnings.warn("Predictions are NaN")
35
+ loss_val /= len(self.val_loader)
36
+
37
+ y_true, y_pred = np.concatenate(y_true), np.concatenate(y_pred)
38
+ metric_val = self.metric(y_true, y_pred)
39
+
40
+ if self.logger is not None:
41
+ self.logger.log_validation(self._iteration, metric_val, loss_val, x, y, pred, y_true, y_pred)
42
+ return metric_val