homa 0.1.1__py3-none-any.whl → 0.2.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 (51) hide show
  1. homa/activations/classes/APLU.py +69 -31
  2. homa/activations/classes/GALU.py +44 -28
  3. homa/activations/classes/MELU.py +51 -31
  4. homa/activations/classes/PDELU.py +33 -18
  5. homa/activations/classes/SReLU.py +46 -26
  6. homa/activations/classes/SmallGALU.py +37 -18
  7. homa/activations/classes/WideMELU.py +71 -42
  8. homa/activations/classes/__init__.py +0 -1
  9. homa/ensemble/Ensemble.py +2 -4
  10. homa/ensemble/concerns/CalculatesMetricNecessities.py +14 -10
  11. homa/ensemble/concerns/PredictsProbabilities.py +4 -0
  12. homa/ensemble/concerns/ReportsClassificationMetrics.py +1 -1
  13. homa/ensemble/concerns/ReportsEnsembleAccuracy.py +3 -2
  14. homa/ensemble/concerns/ReportsLogits.py +4 -0
  15. homa/ensemble/concerns/ReportsSize.py +2 -2
  16. homa/ensemble/concerns/StoresModels.py +29 -0
  17. homa/ensemble/concerns/__init__.py +1 -2
  18. homa/loss/LogitNormLoss.py +12 -0
  19. homa/loss/Loss.py +2 -0
  20. homa/loss/__init__.py +2 -0
  21. homa/torch/__init__.py +0 -1
  22. homa/vision/ClassificationModel.py +5 -0
  23. homa/vision/Resnet.py +6 -5
  24. homa/vision/StochasticClassifier.py +28 -0
  25. homa/vision/StochasticResnet.py +6 -5
  26. homa/vision/StochasticSwin.py +9 -0
  27. homa/vision/Swin.py +12 -0
  28. homa/vision/__init__.py +1 -0
  29. homa/vision/concerns/HasLabels.py +13 -0
  30. homa/vision/concerns/HasLogits.py +12 -0
  31. homa/vision/concerns/HasProbabilities.py +9 -0
  32. homa/vision/concerns/ReportsAccuracy.py +27 -0
  33. homa/vision/concerns/ReportsMetrics.py +6 -0
  34. homa/vision/concerns/Trainable.py +5 -2
  35. homa/vision/concerns/__init__.py +5 -0
  36. homa/vision/modules/SwinModule.py +23 -0
  37. homa/vision/modules/__init__.py +1 -1
  38. homa-0.2.0.dist-info/METADATA +75 -0
  39. homa-0.2.0.dist-info/RECORD +58 -0
  40. homa/activations/classes/StochasticActivation.py +0 -20
  41. homa/ensemble/concerns/HasNetwork.py +0 -5
  42. homa/ensemble/concerns/HasStateDicts.py +0 -8
  43. homa/ensemble/concerns/RecordsStateDictionaries.py +0 -23
  44. homa/torch/Module.py +0 -8
  45. homa/vision/modules/StochasticResnetModule.py +0 -9
  46. homa/vision/utils.py +0 -21
  47. homa-0.1.1.dist-info/METADATA +0 -21
  48. homa-0.1.1.dist-info/RECORD +0 -51
  49. {homa-0.1.1.dist-info → homa-0.2.0.dist-info}/WHEEL +0 -0
  50. {homa-0.1.1.dist-info → homa-0.2.0.dist-info}/entry_points.txt +0 -0
  51. {homa-0.1.1.dist-info → homa-0.2.0.dist-info}/top_level.txt +0 -0
@@ -1,45 +1,76 @@
1
1
  import torch
2
+ from torch import nn
3
+ import torch.nn.functional as F
2
4
 
3
5
 
4
- class WideMELU(torch.nn.Module):
6
+ class WideMELU(nn.Module):
5
7
  def __init__(self, maxInput: float = 1.0):
6
8
  super().__init__()
7
9
  self.maxInput = float(maxInput)
8
- self.alpha = None
9
- self.beta = None
10
- self.gamma = None
11
- self.delta = None
12
- self.xi = None
13
- self.psi = None
14
- self.theta = None
15
- self.lam = None
16
- self._initialized = False
17
-
18
- def _initialize_parameters(self, X: torch.Tensor):
19
- if X.dim() != 4:
10
+ self._num_channels = None
11
+ self.register_parameter("alpha", None)
12
+ self.register_parameter("beta", None)
13
+ self.register_parameter("gamma", None)
14
+ self.register_parameter("delta", None)
15
+ self.register_parameter("xi", None)
16
+ self.register_parameter("psi", None)
17
+ self.register_parameter("theta", None)
18
+ self.register_parameter("lam", None)
19
+
20
+ def _ensure_parameters(self, x: torch.Tensor):
21
+ if x.dim() != 4:
20
22
  raise ValueError(
21
- f"Expected 4D input (B, C, H, W), but got {X.dim()}D input."
23
+ f"Expected 4D input (N, C, H, W), got {x.dim()}D with shape {tuple(x.shape)}"
24
+ )
25
+
26
+ c = int(x.shape[1])
27
+ if self._num_channels is None:
28
+ self._num_channels = c
29
+ elif c != self._num_channels:
30
+ raise RuntimeError(
31
+ f"WideMELU was initialized with C={self._num_channels} but got C={c}. "
32
+ "Create a new WideMELU for different channel sizes."
22
33
  )
23
34
 
24
- num_channels = X.shape[1]
25
- shape = (1, num_channels, 1, 1)
26
-
27
- self.alpha = torch.nn.Parameter(torch.zeros(shape))
28
- self.beta = torch.nn.Parameter(torch.zeros(shape))
29
- self.gamma = torch.nn.Parameter(torch.zeros(shape))
30
- self.delta = torch.nn.Parameter(torch.zeros(shape))
31
- self.xi = torch.nn.Parameter(torch.zeros(shape))
32
- self.psi = torch.nn.Parameter(torch.zeros(shape))
33
- self.theta = torch.nn.Parameter(torch.zeros(shape))
34
- self.lam = torch.nn.Parameter(torch.zeros(shape))
35
- self._initialized = True
36
-
37
- def forward(self, X: torch.Tensor) -> torch.Tensor:
38
- if not self._initialized:
39
- self._initialize_parameters(X)
40
- X_norm = X / self.maxInput
35
+ if self.alpha is None:
36
+ shape = (1, c, 1, 1)
37
+ device, dtype = x.device, x.dtype
38
+ for name in (
39
+ "alpha",
40
+ "beta",
41
+ "gamma",
42
+ "delta",
43
+ "xi",
44
+ "psi",
45
+ "theta",
46
+ "lam",
47
+ ):
48
+ param = nn.Parameter(torch.zeros(shape, dtype=dtype, device=device))
49
+ setattr(self, name, param)
50
+
51
+ def reset_parameters(self):
52
+ params = (
53
+ self.alpha,
54
+ self.beta,
55
+ self.gamma,
56
+ self.delta,
57
+ self.xi,
58
+ self.psi,
59
+ self.theta,
60
+ self.lam,
61
+ )
62
+ for p in params:
63
+ if p is not None:
64
+ with torch.no_grad():
65
+ p.zero_()
66
+
67
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
68
+ self._ensure_parameters(x)
69
+
70
+ X_norm = x / self.maxInput
41
71
  Y = torch.roll(X_norm, shifts=-1, dims=1)
42
- term1 = torch.relu(X_norm)
72
+
73
+ term1 = F.relu(X_norm)
43
74
  term2 = self.alpha * torch.clamp(X_norm, max=0)
44
75
  dist_sq_beta = (X_norm - 2) ** 2 + (Y - 2) ** 2
45
76
  dist_sq_gamma = (X_norm - 1) ** 2 + (Y - 1) ** 2
@@ -48,14 +79,12 @@ class WideMELU(torch.nn.Module):
48
79
  dist_sq_psi = (X_norm - 3) ** 2 + (Y - 3) ** 2
49
80
  dist_sq_theta = (X_norm - 1) ** 2 + (Y - 2) ** 2
50
81
  dist_sq_lambda = (X_norm - 3) ** 2 + (Y - 2) ** 2
51
-
52
- term3 = self.beta * torch.sqrt(torch.relu(2 - dist_sq_beta))
53
- term4 = self.gamma * torch.sqrt(torch.relu(1 - dist_sq_gamma))
54
- term5 = self.delta * torch.sqrt(torch.relu(1 - dist_sq_delta))
55
- term6 = self.xi * torch.sqrt(torch.relu(1 - dist_sq_xi))
56
- term7 = self.psi * torch.sqrt(torch.relu(1 - dist_sq_psi))
57
- term8 = self.theta * torch.sqrt(torch.relu(1 - dist_sq_theta))
58
- term9 = self.lam * torch.sqrt(torch.relu(1 - dist_sq_lambda))
82
+ term3 = self.beta * torch.sqrt(F.relu(2 - dist_sq_beta))
83
+ term4 = self.gamma * torch.sqrt(F.relu(1 - dist_sq_gamma))
84
+ term5 = self.delta * torch.sqrt(F.relu(1 - dist_sq_delta))
85
+ term6 = self.xi * torch.sqrt(F.relu(1 - dist_sq_xi))
86
+ term7 = self.psi * torch.sqrt(F.relu(1 - dist_sq_psi))
87
+ term8 = self.theta * torch.sqrt(F.relu(1 - dist_sq_theta))
88
+ term9 = self.lam * torch.sqrt(F.relu(1 - dist_sq_lambda))
59
89
  Z_norm = term1 + term2 + term3 + term4 + term5 + term6 + term7 + term8 + term9
60
- Z = Z_norm * self.maxInput
61
- return Z
90
+ return Z_norm * self.maxInput
@@ -5,4 +5,3 @@ from .MELU import MELU
5
5
  from .WideMELU import WideMELU
6
6
  from .PDELU import PDELU
7
7
  from .SReLU import SReLU
8
- from .StochasticActivation import StochasticActivation
homa/ensemble/Ensemble.py CHANGED
@@ -1,8 +1,7 @@
1
1
  from .concerns import (
2
2
  ReportsSize,
3
- RecordsStateDictionaries,
3
+ StoresModels,
4
4
  ReportsClassificationMetrics,
5
- HasNetwork,
6
5
  PredictsProbabilities,
7
6
  )
8
7
 
@@ -10,9 +9,8 @@ from .concerns import (
10
9
  class Ensemble(
11
10
  ReportsSize,
12
11
  ReportsClassificationMetrics,
13
- RecordsStateDictionaries,
14
12
  PredictsProbabilities,
15
- HasNetwork,
13
+ StoresModels,
16
14
  ):
17
15
  def __init__(self):
18
16
  super().__init__()
@@ -1,20 +1,24 @@
1
1
  import torch
2
+ from ...device import get_device
2
3
 
3
4
 
4
5
  class CalculatesMetricNecessities:
5
6
  def __init__(self, *args, **kwargs):
6
7
  super().__init__(*args, **kwargs)
7
8
 
9
+ @torch.no_grad()
8
10
  def metric_necessities(self, dataloader):
9
- all_predictions = []
10
- all_labels = []
11
+ predictions, labels = [], []
12
+ device = get_device()
11
13
  for x, y in dataloader:
12
- batch_logits_list = []
14
+ x, y = x.to(device), y.to(device)
15
+ sum_logits = None
13
16
  for model in self.models:
14
- batch_logits_list.append(model(x))
15
- all_batch_logits = torch.stack(batch_logits_list)
16
- avg_logits = torch.mean(all_batch_logits, dim=0)
17
- _, preds = torch.max(avg_logits, 1)
18
- all_predictions.extend(preds.cpu().numpy())
19
- all_labels.extend(y.cpu().numpy())
20
- return all_predictions, all_labels
17
+ model.to(device)
18
+ model.eval()
19
+ logits = model(x)
20
+ sum_logits = logits if sum_logits is None else sum_logits + logits
21
+ batch_predictions = sum_logits.argmax(dim=1)
22
+ predictions.extend(batch_predictions.cpu().numpy())
23
+ labels.extend(y.cpu().numpy())
24
+ return predictions, labels
@@ -9,3 +9,7 @@ class PredictsProbabilities(ReportsLogits):
9
9
  def predict(self, x: torch.Tensor) -> torch.Tensor:
10
10
  logits = self.logits(x)
11
11
  return torch.nn.functional.softmax(logits, dim=1)
12
+
13
+ @torch.no_grad()
14
+ def predict_(self, x: torch.Tensor) -> torch.Tensor:
15
+ return self.predict(x)
@@ -6,8 +6,8 @@ from .CalculatesMetricNecessities import CalculatesMetricNecessities
6
6
 
7
7
  class ReportsClassificationMetrics(
8
8
  CalculatesMetricNecessities,
9
- ReportsEnsembleF1,
10
9
  ReportsEnsembleAccuracy,
10
+ ReportsEnsembleF1,
11
11
  ReportsEnsembleKappa,
12
12
  ):
13
13
  pass
@@ -1,10 +1,11 @@
1
1
  from sklearn.metrics import accuracy_score as accuracy
2
+ from torch.utils.data import DataLoader
2
3
 
3
4
 
4
5
  class ReportsEnsembleAccuracy:
5
6
  def __init__(self, *args, **kwargs):
6
7
  super().__init__(*args, **kwargs)
7
8
 
8
- def accuracy(self) -> float:
9
- predictions, labels = self.metric_necessities()
9
+ def accuracy(self, dataloader: DataLoader) -> float:
10
+ predictions, labels = self.metric_necessities(dataloader)
10
11
  return accuracy(labels, predictions)
@@ -11,3 +11,7 @@ class ReportsLogits:
11
11
  for model in self.models:
12
12
  logits += model(x)
13
13
  return logits
14
+
15
+ @torch.no_grad()
16
+ def logits_(self, *args, **kwargs):
17
+ return self.logits(*args, **kwargs)
@@ -4,8 +4,8 @@ class ReportsSize:
4
4
 
5
5
  @property
6
6
  def size(self):
7
- return len(self.state_dicts)
7
+ return len(self.models)
8
8
 
9
9
  @property
10
10
  def length(self):
11
- return len(self.state_dicts)
11
+ return len(self.models)
@@ -0,0 +1,29 @@
1
+ import torch
2
+ from copy import deepcopy
3
+ from typing import List
4
+ from ...vision import Model
5
+
6
+
7
+ class StoresModels:
8
+ def __init__(self, *args, **kwargs):
9
+ super().__init__(*args, **kwargs)
10
+ self.models: List[torch.nn.Module] = []
11
+
12
+ def record(self, model: Model | torch.nn.Module):
13
+ model_: torch.nn.Module | None = None
14
+ if isinstance(model, Model):
15
+ model_ = deepcopy(model.network)
16
+ elif isinstance(model, torch.nn.Module):
17
+ model_ = deepcopy(model)
18
+ else:
19
+ raise TypeError("Wrong input to ensemble record")
20
+ self.models.append(model_)
21
+
22
+ def push(self, *args, **kwargs):
23
+ self.record(*args, **kwargs)
24
+
25
+ def append(self, *args, **kwargs):
26
+ self.record(*args, **kwargs)
27
+
28
+ def add(self, *args, **kwargs):
29
+ self.record(*args, **kwargs)
@@ -1,10 +1,9 @@
1
1
  from .CalculatesMetricNecessities import CalculatesMetricNecessities
2
- from .HasNetwork import HasNetwork
3
2
  from .PredictsProbabilities import PredictsProbabilities
4
- from .RecordsStateDictionaries import RecordsStateDictionaries
5
3
  from .ReportsClassificationMetrics import ReportsClassificationMetrics
6
4
  from .ReportsEnsembleAccuracy import ReportsEnsembleAccuracy
7
5
  from .ReportsEnsembleF1 import ReportsEnsembleF1
8
6
  from .ReportsEnsembleKappa import ReportsEnsembleKappa
9
7
  from .ReportsLogits import ReportsLogits
10
8
  from .ReportsSize import ReportsSize
9
+ from .StoresModels import StoresModels
@@ -0,0 +1,12 @@
1
+ import torch
2
+ from .Loss import Loss
3
+
4
+
5
+ class LogitNormLoss(Loss):
6
+ def __init__(self, *args, **kwargs):
7
+ super().__init__(*args, **kwargs)
8
+
9
+ def forward(self, logits, target):
10
+ norms = torch.norm(logits, p=2, dim=-1, keepdim=True) + 1e-7
11
+ normalized_logits = torch.div(logits, norms)
12
+ return torch.nn.functional.cross_entropy(normalized_logits, target)
homa/loss/Loss.py ADDED
@@ -0,0 +1,2 @@
1
+ class Loss:
2
+ pass
homa/loss/__init__.py ADDED
@@ -0,0 +1,2 @@
1
+ from .LogitNormLoss import LogitNormLoss
2
+ from .Loss import Loss
homa/torch/__init__.py CHANGED
@@ -1,2 +1 @@
1
- from .Module import Module
2
1
  from .helpers import *
@@ -0,0 +1,5 @@
1
+ from .Model import Model
2
+
3
+
4
+ class ClassificationModel(Model):
5
+ pass
homa/vision/Resnet.py CHANGED
@@ -1,12 +1,13 @@
1
1
  import torch
2
2
  from .modules import ResnetModule
3
- from .Model import Model
4
- from .concerns import Trainable
3
+ from .ClassificationModel import ClassificationModel
4
+ from .concerns import Trainable, ReportsMetrics
5
+ from ..device import get_device
5
6
 
6
7
 
7
- class Resnet(Model, Trainable):
8
- def __init__(self, num_classes: int, lr: float):
8
+ class Resnet(ClassificationModel, Trainable, ReportsMetrics):
9
+ def __init__(self, num_classes: int, lr: float = 0.001):
9
10
  super().__init__()
10
- self.network = ResnetModule(num_classes)
11
+ self.network = ResnetModule(num_classes).to(get_device())
11
12
  self.criterion = torch.nn.CrossEntropyLoss()
12
13
  self.optimizer = torch.optim.SGD(self.network.parameters(), lr=lr, momentum=0.9)
@@ -0,0 +1,28 @@
1
+ import torch
2
+ import random
3
+ from ..activations import APLU, GALU, SmallGALU, MELU, WideMELU, PDELU, SReLU
4
+
5
+
6
+ class StochasticClassifier:
7
+ def __init__(self, *args, **kwargs):
8
+ super().__init__(*args, **kwargs)
9
+ self.pool = [
10
+ APLU,
11
+ GALU,
12
+ SmallGALU,
13
+ MELU,
14
+ WideMELU,
15
+ PDELU,
16
+ SReLU,
17
+ torch.nn.ReLU,
18
+ torch.nn.PReLU,
19
+ torch.nn.LeakyReLU,
20
+ torch.nn.ELU,
21
+ ]
22
+
23
+ def replace_activations(self, needle: torch.Tensor) -> None:
24
+ replacement = random.choice(self.pool)
25
+ for parent in self.network.modules():
26
+ for name, child in list(parent.named_children()):
27
+ if isinstance(child, needle):
28
+ setattr(parent, name, replacement())
@@ -1,8 +1,9 @@
1
- from .modules import StochasticResnetModule
1
+ import torch
2
2
  from .Resnet import Resnet
3
+ from .StochasticClassifier import StochasticClassifier
3
4
 
4
5
 
5
- class StochasticResnet(Resnet):
6
- def __init__(self, **kwargs):
7
- super().__init__(**kwargs)
8
- self.model = StochasticResnetModule(kwargs["num_classes"])
6
+ class StochasticResnet(Resnet, StochasticClassifier):
7
+ def __init__(self, *args, **kwargs):
8
+ super().__init__(*args, **kwargs)
9
+ self.replace_activations(torch.nn.ReLU)
@@ -0,0 +1,9 @@
1
+ import torch
2
+ from .Swin import Swin
3
+ from .StochasticClassifier import StochasticClassifier
4
+
5
+
6
+ class StochasticSwin(Swin, StochasticClassifier):
7
+ def __init__(self, *args, **kwargs):
8
+ super().__init__(*args, **kwargs)
9
+ self.replace_activations(torch.nn.GELU)
homa/vision/Swin.py ADDED
@@ -0,0 +1,12 @@
1
+ import torch
2
+ from .ClassificationModel import ClassificationModel
3
+ from .concerns import Trainable, ReportsMetrics
4
+ from .modules import SwinModule
5
+
6
+
7
+ class Swin(ClassificationModel, Trainable, ReportsMetrics):
8
+ def __init__(self, num_classes: int, lr: float = 0.0001):
9
+ super().__init__()
10
+ self.network = SwinModule(num_classes=num_classes)
11
+ self.optimizer = torch.optim.AdamW(self.network.parameters(), lr=lr)
12
+ self.criterion = torch.nn.CrossEntropyLoss()
homa/vision/__init__.py CHANGED
@@ -1,3 +1,4 @@
1
1
  from .Model import Model
2
2
  from .Resnet import Resnet
3
3
  from .StochasticResnet import StochasticResnet
4
+ from .Swin import Swin
@@ -0,0 +1,13 @@
1
+ import torch
2
+
3
+
4
+ class HasLabels:
5
+ def __init__(self, *args, **kwargs):
6
+ super().__init__(*args, **kwargs)
7
+
8
+ def predict(self, x: torch.Tensor):
9
+ return torch.argmax(self.logits(x), dim=1)
10
+
11
+ @torch.no_grad()
12
+ def predict_(self, x: torch.Tensor):
13
+ return torch.argmax(self.logits(x), dim=1)
@@ -0,0 +1,12 @@
1
+ import torch
2
+
3
+
4
+ class HasLogits:
5
+ def __init__(self, *args, **kwargs):
6
+ super().__init__(*args, **kwargs)
7
+
8
+ def logits(self, x: torch.Tensor) -> torch.Tensor:
9
+ return self.network(x)
10
+
11
+ def logits_(self, x: torch.Tensor) -> torch.Tensor:
12
+ return self.network(x)
@@ -0,0 +1,9 @@
1
+ import torch
2
+
3
+
4
+ class HasProbabilities:
5
+ def __init__(self, *args, **kwargs):
6
+ super().__init__(*args, **kwargs)
7
+
8
+ def probabilities(self, x: torch.Tensor):
9
+ return torch.softmax(self.logits(x), dim=1)
@@ -0,0 +1,27 @@
1
+ from torch import Tensor, no_grad
2
+ from torch.utils.data.dataloader import DataLoader
3
+ from ...device import get_device
4
+
5
+
6
+ class ReportsAccuracy:
7
+ def __init__(self, *args, **kwargs):
8
+ super().__init__(*args, **kwargs)
9
+
10
+ def accuracy_tensors(self, x: Tensor, y: Tensor) -> float:
11
+ predictions = self.predict_(x)
12
+ return (predictions == y).float().mean().item()
13
+
14
+ def accuracy_dataloader(self, dataloader: DataLoader):
15
+ correct, total = 0, 0
16
+ for x, y in dataloader:
17
+ x, y = x.to(get_device()), y.to(get_device())
18
+ predictions = self.predict_(x)
19
+ correct += (predictions == y).sum().item()
20
+ total += y.numel()
21
+ return correct / total if total > 0 else 0.0
22
+
23
+ def accuracy(self, x: Tensor | DataLoader, y: Tensor | None = None) -> float:
24
+ self.network.eval()
25
+ if isinstance(x, DataLoader):
26
+ return self.accuracy_dataloader(x)
27
+ return self.accuracy_tensors(x, y)
@@ -0,0 +1,6 @@
1
+ from .ReportsAccuracy import ReportsAccuracy
2
+
3
+
4
+ class ReportsMetrics(ReportsAccuracy):
5
+ def __init__(self, *args, **kwargs):
6
+ super().__init__(*args, **kwargs)
@@ -1,9 +1,12 @@
1
1
  from torch import Tensor
2
2
  from torch.utils.data.dataloader import DataLoader
3
+ from .HasLogits import HasLogits
4
+ from .HasProbabilities import HasProbabilities
5
+ from .HasLabels import HasLabels
3
6
  from ...device import get_device
4
7
 
5
8
 
6
- class Trainable:
9
+ class Trainable(HasLogits, HasProbabilities, HasLabels):
7
10
  def __init__(self, *args, **kwargs):
8
11
  super().__init__(*args, **kwargs)
9
12
 
@@ -16,7 +19,7 @@ class Trainable:
16
19
  def train_tensors(self, x: Tensor, y: Tensor):
17
20
  self.network.train()
18
21
  self.optimizer.zero_grad()
19
- loss = self.criterion(y, self.network(x).float())
22
+ loss = self.criterion(self.network(x).float(), y)
20
23
  loss.backward()
21
24
  self.optimizer.step()
22
25
 
@@ -1 +1,6 @@
1
+ from .HasLabels import HasLabels
2
+ from .HasLogits import HasLogits
3
+ from .HasProbabilities import HasProbabilities
4
+ from .ReportsAccuracy import ReportsAccuracy
5
+ from .ReportsMetrics import ReportsMetrics
1
6
  from .Trainable import Trainable
@@ -0,0 +1,23 @@
1
+ import torch
2
+ from torchvision.models import swin_v2_b
3
+ from torch.nn.init import kaiming_uniform_ as kaiming
4
+
5
+
6
+ class SwinModule(torch.nn.Module):
7
+ def __init__(self, num_classes: int):
8
+ super().__init__()
9
+ self.num_classes = num_classes
10
+ self._create_encoder()
11
+ self._create_fc()
12
+
13
+ def _create_encoder(self):
14
+ self.encoder = swin_v2_b(weights="DEFAULT")
15
+ self.encoder.head = torch.nn.Identity()
16
+
17
+ def _create_fc(self):
18
+ self.fc = torch.nn.Linear(1024, self.num_classes)
19
+ kaiming(self.fc.weight, mode="fan_in", nonlinearity="relu")
20
+
21
+ def forward(self, images: torch.Tensor):
22
+ features = self.encoder(images)
23
+ return self.fc(features)
@@ -1,2 +1,2 @@
1
1
  from .ResnetModule import ResnetModule
2
- from .StochasticResnetModule import StochasticResnetModule
2
+ from .SwinModule import SwinModule
@@ -0,0 +1,75 @@
1
+ Metadata-Version: 2.4
2
+ Name: homa
3
+ Version: 0.2.0
4
+ Summary: A curated list of machine learning and deep learning helpers.
5
+ Author-email: Taha Shieenavaz <tahashieenavaz@gmail.com>
6
+ Requires-Python: >=3.7
7
+ Description-Content-Type: text/markdown
8
+ Requires-Dist: numpy
9
+ Requires-Dist: torch
10
+ Requires-Dist: fire
11
+
12
+ # Core
13
+
14
+ ### Device Management
15
+
16
+ ```py
17
+ from homa import cpu, mps, cuda, device
18
+
19
+ torch.tensor([1, 2, 3, 4, 5]).to(cpu())
20
+ torch.tensor([1, 2, 3, 4, 5]).to(cuda())
21
+ torch.tensor([1, 2, 3, 4, 5]).to(mps())
22
+ torch.tensor([1, 2, 3, 4, 5]).to(device())
23
+ ```
24
+
25
+ # Vision
26
+
27
+ ## Resnet
28
+
29
+ This is the standard ResNet50 module.
30
+
31
+ You can train the model with a `DataLoader` object.
32
+
33
+ ```py
34
+ from homa.vision import Resnet
35
+
36
+ model = Resnet(num_classes=10, lr=0.001)
37
+ for epoch in range(10):
38
+ model.train(train_dataloader)
39
+ ```
40
+
41
+ Similarly you can manually take care of decomposition of data from the `DataLoader`.
42
+
43
+ ```py
44
+ from homa.vision import Resnet
45
+
46
+ model = Resnet(num_classes=10, lr=0.001)
47
+ for epoch in range(10):
48
+ for x, y in train_dataloader:
49
+ model.train(x, y)
50
+ ```
51
+
52
+ ## StochasticResnet
53
+
54
+ This is a ResNet module whose activation functions are replaced from a pool of different activation functions randomly. Read more on the [(paper)](https://www.mdpi.com/1424-8220/22/16/6129).
55
+
56
+ You can train the model with a `DataLoader` object.
57
+
58
+ ```py
59
+ from homa.vision import StochasticResnet
60
+
61
+ model = StochasticResnet(num_classes=10, lr=0.001)
62
+ for epoch in range(10):
63
+ model.train(train_dataloader)
64
+ ```
65
+
66
+ Similarly you can manually take care of decomposition of data from the `DataLoader`.
67
+
68
+ ```py
69
+ from homa.vision import StochasticResnet
70
+
71
+ model = StochasticResnet(num_classes=10, lr=0.001)
72
+ for epoch in range(10):
73
+ for x, y in train_dataloader:
74
+ model.train(x, y)
75
+ ```