pytinytensor 0.1.4__tar.gz → 0.1.6__tar.gz

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. {pytinytensor-0.1.4/pytinytensor.egg-info → pytinytensor-0.1.6}/PKG-INFO +1 -1
  2. {pytinytensor-0.1.4 → pytinytensor-0.1.6/pytinytensor.egg-info}/PKG-INFO +1 -1
  3. {pytinytensor-0.1.4 → pytinytensor-0.1.6}/pytinytensor.egg-info/SOURCES.txt +7 -0
  4. {pytinytensor-0.1.4 → pytinytensor-0.1.6}/setup.py +1 -2
  5. {pytinytensor-0.1.4 → pytinytensor-0.1.6}/tinytensor/core/tensor.py +14 -0
  6. pytinytensor-0.1.6/tinytensor/nn/__init__.py +16 -0
  7. pytinytensor-0.1.6/tinytensor/nn/batchnorm.py +78 -0
  8. pytinytensor-0.1.6/tinytensor/nn/conv.py +84 -0
  9. pytinytensor-0.1.6/tinytensor/nn/flatten.py +9 -0
  10. pytinytensor-0.1.6/tinytensor/nn/functional.py +54 -0
  11. {pytinytensor-0.1.4 → pytinytensor-0.1.6}/tinytensor/nn/modules.py +32 -1
  12. pytinytensor-0.1.6/tinytensor/nn/pooling.py +113 -0
  13. pytinytensor-0.1.6/tinytensor/nn/utils.py +23 -0
  14. {pytinytensor-0.1.4 → pytinytensor-0.1.6}/tinytensor/optim/__init__.py +6 -3
  15. pytinytensor-0.1.6/tinytensor/optim/lr_scheduler.py +13 -0
  16. pytinytensor-0.1.4/tinytensor/nn/__init__.py +0 -0
  17. {pytinytensor-0.1.4 → pytinytensor-0.1.6}/LICENSE +0 -0
  18. {pytinytensor-0.1.4 → pytinytensor-0.1.6}/README.md +0 -0
  19. {pytinytensor-0.1.4 → pytinytensor-0.1.6}/pyproject.toml +0 -0
  20. {pytinytensor-0.1.4 → pytinytensor-0.1.6}/pytinytensor.egg-info/dependency_links.txt +0 -0
  21. {pytinytensor-0.1.4 → pytinytensor-0.1.6}/pytinytensor.egg-info/requires.txt +0 -0
  22. {pytinytensor-0.1.4 → pytinytensor-0.1.6}/pytinytensor.egg-info/top_level.txt +0 -0
  23. {pytinytensor-0.1.4 → pytinytensor-0.1.6}/setup.cfg +0 -0
  24. {pytinytensor-0.1.4 → pytinytensor-0.1.6}/tests/test_autograd.py +0 -0
  25. {pytinytensor-0.1.4 → pytinytensor-0.1.6}/tests/test_data.py +0 -0
  26. {pytinytensor-0.1.4 → pytinytensor-0.1.6}/tests/test_losses.py +0 -0
  27. {pytinytensor-0.1.4 → pytinytensor-0.1.6}/tests/test_nn.py +0 -0
  28. {pytinytensor-0.1.4 → pytinytensor-0.1.6}/tests/test_optim.py +0 -0
  29. {pytinytensor-0.1.4 → pytinytensor-0.1.6}/tests/test_tensor_math.py +0 -0
  30. {pytinytensor-0.1.4 → pytinytensor-0.1.6}/tinytensor/__init__.py +0 -0
  31. {pytinytensor-0.1.4 → pytinytensor-0.1.6}/tinytensor/backends/__init__.py +0 -0
  32. {pytinytensor-0.1.4 → pytinytensor-0.1.6}/tinytensor/backends/cpu_numpy.py +0 -0
  33. {pytinytensor-0.1.4 → pytinytensor-0.1.6}/tinytensor/backends/cuda_binding.cpp +0 -0
  34. {pytinytensor-0.1.4 → pytinytensor-0.1.6}/tinytensor/backends/cuda_gpu.cu +0 -0
  35. {pytinytensor-0.1.4 → pytinytensor-0.1.6}/tinytensor/backends/cuda_gpu.py +0 -0
  36. {pytinytensor-0.1.4 → pytinytensor-0.1.6}/tinytensor/config.py +0 -0
  37. {pytinytensor-0.1.4 → pytinytensor-0.1.6}/tinytensor/core/__init__.py +0 -0
  38. {pytinytensor-0.1.4 → pytinytensor-0.1.6}/tinytensor/core/autograd.py +0 -0
  39. {pytinytensor-0.1.4 → pytinytensor-0.1.6}/tinytensor/core/ops.py +0 -0
  40. {pytinytensor-0.1.4 → pytinytensor-0.1.6}/tinytensor/data/__init__.py +0 -0
  41. {pytinytensor-0.1.4 → pytinytensor-0.1.6}/tinytensor/data/dataloader.py +0 -0
  42. {pytinytensor-0.1.4 → pytinytensor-0.1.6}/tinytensor/data/dataset.py +0 -0
  43. {pytinytensor-0.1.4 → pytinytensor-0.1.6}/tinytensor/nn/activations.py +0 -0
  44. {pytinytensor-0.1.4 → pytinytensor-0.1.6}/tinytensor/nn/dropout.py +0 -0
  45. {pytinytensor-0.1.4 → pytinytensor-0.1.6}/tinytensor/nn/linear.py +0 -0
  46. {pytinytensor-0.1.4 → pytinytensor-0.1.6}/tinytensor/nn/losses.py +0 -0
  47. {pytinytensor-0.1.4 → pytinytensor-0.1.6}/tinytensor/optim/optimizer.py +0 -0
  48. {pytinytensor-0.1.4 → pytinytensor-0.1.6}/tinytensor/utils/__init__.py +0 -0
  49. {pytinytensor-0.1.4 → pytinytensor-0.1.6}/tinytensor/utils/bar.py +0 -0
  50. {pytinytensor-0.1.4 → pytinytensor-0.1.6}/tinytensor/utils/early_stopping.py +0 -0
  51. {pytinytensor-0.1.4 → pytinytensor-0.1.6}/tinytensor/utils/summary.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pytinytensor
3
- Version: 0.1.4
3
+ Version: 0.1.6
4
4
  Summary: мини ИИ фреймворк от IbrokimN ( github/IbrokhimN )
5
5
  Home-page: https://github.com/IbrokhimN/tinytensor
6
6
  Author: IbrokhimN
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pytinytensor
3
- Version: 0.1.4
3
+ Version: 0.1.6
4
4
  Summary: мини ИИ фреймворк от IbrokimN ( github/IbrokhimN )
5
5
  Home-page: https://github.com/IbrokhimN/tinytensor
6
6
  Author: IbrokhimN
@@ -29,11 +29,18 @@ tinytensor/data/dataloader.py
29
29
  tinytensor/data/dataset.py
30
30
  tinytensor/nn/__init__.py
31
31
  tinytensor/nn/activations.py
32
+ tinytensor/nn/batchnorm.py
33
+ tinytensor/nn/conv.py
32
34
  tinytensor/nn/dropout.py
35
+ tinytensor/nn/flatten.py
36
+ tinytensor/nn/functional.py
33
37
  tinytensor/nn/linear.py
34
38
  tinytensor/nn/losses.py
35
39
  tinytensor/nn/modules.py
40
+ tinytensor/nn/pooling.py
41
+ tinytensor/nn/utils.py
36
42
  tinytensor/optim/__init__.py
43
+ tinytensor/optim/lr_scheduler.py
37
44
  tinytensor/optim/optimizer.py
38
45
  tinytensor/utils/__init__.py
39
46
  tinytensor/utils/bar.py
@@ -35,7 +35,6 @@ def find_cuda_lib_dirs():
35
35
  found.append(lib_dir)
36
36
  return found
37
37
 
38
-
39
38
  def check_cuda():
40
39
  try:
41
40
  subprocess.check_output(["nvcc", "--version"])
@@ -113,7 +112,7 @@ else:
113
112
 
114
113
  setup(
115
114
  name="pytinytensor",
116
- version="0.1.4",
115
+ version="0.1.6",
117
116
  description="мини ИИ фреймворк от IbrokimN ( github/IbrokhimN )",
118
117
  long_description=long_description,
119
118
  long_description_content_type="text/markdown",
@@ -184,6 +184,20 @@ class Tensor:
184
184
  out._backward = _backward
185
185
  return out
186
186
 
187
+ def reshape(self, *shape):
188
+ out = Tensor(self.data.reshape(*shape), requires_grad=self.requires_grad, device=self.device)
189
+ if out.requires_grad:
190
+ out._prev = {self}
191
+
192
+ def _backward():
193
+ if self.requires_grad:
194
+ if self.grad is None:
195
+ self.grad = np.zeros_like(self.data, dtype=np.float32)
196
+ self.grad += out.grad.reshape(self.data.shape)
197
+
198
+ out._backward = _backward
199
+ return out
200
+
187
201
  def relu(self):
188
202
  out = Tensor(
189
203
  np.maximum(0, self.data),
@@ -0,0 +1,16 @@
1
+ from tinytensor.nn.modules import Module, Sequential
2
+ from tinytensor.nn.linear import Linear
3
+ from tinytensor.nn.conv import Conv2d
4
+ from tinytensor.nn.pooling import MaxPool2d, AvgPool2d
5
+ from tinytensor.nn.flatten import Flatten
6
+ from tinytensor.nn.batchnorm import BatchNorm2d
7
+ from tinytensor.nn.activations import ReLU, LeReLU, Sigmod, Tanh, GELU
8
+ from tinytensor.nn.dropout import Dropout
9
+ from tinytensor.nn.losses import MSELoss
10
+
11
+ __all__ = [
12
+ "Module", "Sequential",
13
+ "Linear", "Conv2d", "MaxPool2d", "AvgPool2d", "Flatten", "BatchNorm2d",
14
+ "ReLU", "LeReLU", "Sigmod", "Tanh", "GELU",
15
+ "Dropout", "MSELoss"
16
+ ]
@@ -0,0 +1,78 @@
1
+ import numpy as np
2
+ from tinytensor.core.tensor import Tensor
3
+ from tinytensor.nn.modules import Module
4
+
5
+ class BatchNorm2d(Module):
6
+ def __init__(self, num_features, eps=1e-5, momentum=0.1):
7
+ super().__init__()
8
+ self.num_features = num_features
9
+ self.eps = eps
10
+ self.momentum = momentum
11
+
12
+ self.gamma = Tensor(np.ones((1, num_features, 1, 1), dtype=np.float32), requires_grad=True)
13
+ self.beta = Tensor(np.zeros((1, num_features, 1, 1), dtype=np.float32), requires_grad=True)
14
+
15
+ self.running_mean = np.zeros((1, num_features, 1, 1), dtype=np.float32)
16
+ self.running_var = np.ones((1, num_features, 1, 1), dtype=np.float32)
17
+
18
+ def forward(self, x):
19
+ training = self.training
20
+ if training:
21
+ mean = np.mean(x.data, axis=(0, 2, 3), keepdims=True)
22
+ var = np.var(x.data, axis=(0, 2, 3), keepdims=True)
23
+
24
+ self.running_mean = (1 - self.momentum) * self.running_mean + self.momentum * mean
25
+ self.running_var = (1 - self.momentum) * self.running_var + self.momentum * var
26
+ else:
27
+ mean = self.running_mean
28
+ var = self.running_var
29
+
30
+ std_inv = 1.0 / np.sqrt(var + self.eps)
31
+ x_centered = x.data - mean
32
+ x_hat = x_centered * std_inv
33
+
34
+ out_data = self.gamma.data * x_hat + self.beta.data
35
+
36
+ out = Tensor(
37
+ out_data,
38
+ requires_grad=x.requires_grad or self.gamma.requires_grad or self.beta.requires_grad,
39
+ device=x.device,
40
+ )
41
+
42
+ if out.requires_grad:
43
+ out._prev = {x, self.gamma, self.beta}
44
+
45
+ def _backward():
46
+ dout = out.grad
47
+ N, C, H, W = x.data.shape
48
+ m = N * H * W
49
+
50
+ if self.gamma.requires_grad:
51
+ if self.gamma.grad is None:
52
+ self.gamma.grad = np.zeros_like(self.gamma.data, dtype=np.float32)
53
+ self.gamma.grad += np.sum(dout * x_hat, axis=(0, 2, 3), keepdims=True)
54
+
55
+ if self.beta.requires_grad:
56
+ if self.beta.grad is None:
57
+ self.beta.grad = np.zeros_like(self.beta.data, dtype=np.float32)
58
+ self.beta.grad += np.sum(dout, axis=(0, 2, 3), keepdims=True)
59
+
60
+ if x.requires_grad:
61
+ if x.grad is None:
62
+ x.grad = np.zeros_like(x.data, dtype=np.float32)
63
+
64
+ if training:
65
+ dx_hat = dout * self.gamma.data
66
+ dvar = np.sum(dx_hat * x_centered * -0.5 * std_inv ** 3, axis=(0, 2, 3), keepdims=True)
67
+ dmean = np.sum(dx_hat * -std_inv, axis=(0, 2, 3), keepdims=True) + \
68
+ dvar * np.mean(-2.0 * x_centered, axis=(0, 2, 3), keepdims=True)
69
+ dx = dx_hat * std_inv + dvar * 2.0 * x_centered / m + dmean / m
70
+ else:
71
+ dx = dout * self.gamma.data * std_inv
72
+
73
+ x.grad += dx
74
+
75
+ out._backward = _backward
76
+
77
+ return out
78
+
@@ -0,0 +1,84 @@
1
+ import numpy as np
2
+
3
+ from tinytensor.core.tensor import Tensor
4
+ from tinytensor.nn.modules import Module
5
+ from tinytensor.nn.functional import im2col_indices, col2_im_indices
6
+
7
+
8
+ class Conv2d(Module):
9
+ def __init__(self, in_channels, out_channels, kernel_size, stride=1, padding=0):
10
+ super().__init__()
11
+
12
+ self.in_channels = in_channels
13
+ self.out_channels = out_channels
14
+
15
+ # если как число
16
+ if isinstance(kernel_size, int):
17
+ self.kh = self.kw = kernel_size
18
+ #если кортеж
19
+ else:
20
+ self.kh, self.kw = kernel_size
21
+
22
+ self.stride = stride
23
+ self.padding = padding
24
+
25
+ n = in_channels * self.kh * self.kw
26
+ std = np.sqrt(2.0 / n)
27
+
28
+ w_data = np.random.randn(out_channels, in_channels, self.kh, self.kw).astype(np.float32) * std
29
+ self.weight = Tensor(w_data, requires_grad=True)
30
+
31
+ b_data = np.zeros((out_channels, 1), dtype=np.float32)
32
+ self.bias = Tensor(b_data, requires_grad=True)
33
+
34
+ def forward(self, x):
35
+ N, C, H, W = x.data.shape
36
+
37
+ x_col, out_h, out_w = im2col_indices(
38
+ x.data, self.kh, self.kw, padding=self.padding, stride=self.stride
39
+ )
40
+
41
+ w_row = self.weight.data.reshape(self.out_channels, -1)
42
+
43
+ out_data = w_row @ x_col + self.bias.data
44
+
45
+ out_data = out_data.reshape(self.out_channels, out_h, out_w, N)
46
+ out_data = out_data.transpose(3, 0, 1, 2)
47
+
48
+ out = Tensor(
49
+ out_data,
50
+ requires_grad=x.requires_grad or self.weight.requires_grad or self.bias.requires_grad,
51
+ device=x.device,
52
+ )
53
+
54
+ if out.requires_grad:
55
+ out._prev = {x, self.weight, self.bias}
56
+
57
+ def _backward():
58
+ dout = out.grad
59
+ dout_reshaped = dout.transpose(1, 2, 3, 0).reshape(self.out_channels, -1)
60
+
61
+ if self.weight.requires_grad:
62
+ if self.weight.grad is None:
63
+ self.weight.grad = np.zeros_like(self.weight.data, dtype=np.float32)
64
+ dW = dout_reshaped @ x_col.T
65
+ self.weight.grad += dW.reshape(self.weight.data.shape)
66
+
67
+ if self.bias.requires_grad:
68
+ if self.bias.grad is None:
69
+ self.bias.grad = np.zeros_like(self.bias.data, dtype=np.float32)
70
+ self.bias.grad += np.sum(dout_reshaped, axis=1, keepdims=True)
71
+
72
+ if x.requires_grad:
73
+ if x.grad is None:
74
+ x.grad = np.zeros_like(x.data, dtype=np.float32)
75
+ dx_col = w_row.T @ dout_reshaped
76
+ dx = col2_im_indices(
77
+ dx_col, x.data.shape, self.kh, self.kw,
78
+ padding=self.padding, stride=self.stride
79
+ )
80
+ x.grad += dx
81
+
82
+ out._backward = _backward
83
+
84
+ return out
@@ -0,0 +1,9 @@
1
+ from tinytensor.nn.modules import Module
2
+
3
+ #делаем данные более пригодные для методов типо Linear
4
+
5
+ class Flatten(Module):
6
+ def forward(self, x):
7
+ batch_size = x.data.shape[0]
8
+ return x.reshape(batch_size, -1)
9
+
@@ -0,0 +1,54 @@
1
+ import numpy as np
2
+
3
+ # вцелом идея im2col это то что изначально интуитивный метод перебора окна по изображению является просто написать 6 циклов для сдвигов и тд однако это ооочень медленный метод, и поэтому мы преобразовываем в 1 матрицу и умножаем и это все будет в разыыы быстрее чем наивный метод перебора
4
+
5
+ def im2col_indices(x, kh, kw, padding=1, stride=1):
6
+ p = padding
7
+ #делаем паддинг
8
+ x_padded = np.pad(x, ((0, 0), (0, 0), (p, p), (p, p)), mode='constant')
9
+ N, C, H, W = x.shape
10
+ out_h = int((H + 2 * p - kh) / stride + 1)
11
+ out_w = int((W + 2 * p - kw) / stride + 1)
12
+
13
+ i0 = np.repeat(np.arange(kh), kw)
14
+ i0 = np.tile(i0, C)
15
+ i1 = stride * np.repeat(np.arange(out_h), out_w)
16
+ j0 = np.tile(np.arange(kw), kh * C)
17
+ j1 = stride * np.tile(np.arange(out_w), out_h)
18
+
19
+ i = i0.reshape(-1, 1) + i1.reshape(1, -1)
20
+ j = j0.reshape(-1, 1) + j1.reshape(1, -1)
21
+ k = np.repeat(np.arange(C), kh * kw).reshape(-1, 1)
22
+
23
+ cols = x_padded[:, k, i, j]
24
+ cols = cols.transpose(1, 2, 0).reshape(kh * kw * C, -1)
25
+ return cols, out_h, out_w
26
+
27
+ def col2_im_indices(cols, x_shape, kh, kw, padding=1, stride=1):
28
+ N, C, H, W = x_shape
29
+ p = padding
30
+ H_padded, W_padded = H + 2 * p, W + 2 * p
31
+ x_padded = np.zeros((N, C, H_padded, W_padded), dtype=cols.dtype)
32
+
33
+ out_h = int((H + 2 * p - kh) / stride + 1)
34
+ out_w = int((W + 2 * p - kw) / stride + 1)
35
+
36
+ i0 = np.repeat(np.arange(kh), kw)
37
+ i0 = np.tile(i0, C)
38
+ i1 = stride * np.repeat(np.arange(out_h), out_w)
39
+ j0 = np.tile(np.arange(kw), kh * C)
40
+ j1 = stride * np.tile(np.arange(out_w), out_h)
41
+
42
+ i = i0.reshape(-1, 1) + i1.reshape(1, -1)
43
+ j = j0.reshape(-1, 1) + j1.reshape(1, -1)
44
+ k = np.repeat(np.arange(C), kh * kw).reshape(-1, 1)
45
+
46
+ cols_reshaped = cols.reshape(C * kh * kw, -1, N)
47
+ cols_reshaped = cols_reshaped.transpose(2, 0, 1)
48
+
49
+ np.add.at(x_padded, (slice(None), k, i, j), cols_reshaped)
50
+
51
+ if p == 0:
52
+ return x_padded
53
+ return x_padded[:, :, p:-p, p:-p]
54
+
@@ -37,7 +37,7 @@ class Module:
37
37
  sdict = {}
38
38
  for name, param in self._get_named_params().items():
39
39
  sdict[name] = param.data
40
- return sdict
40
+ return sdict
41
41
 
42
42
  def load_state_dict(self, sdict):
43
43
  #запихиваем обратно
@@ -63,3 +63,34 @@ class Module:
63
63
  with open(filepath, "rb") as f:
64
64
  sd = pickle.load(f)
65
65
  self.load_state_dict(sd)
66
+
67
+
68
+ class Sequential(Module):
69
+ def __init__(self, *args):
70
+ super().__init__()
71
+ self.layers = list(args)
72
+
73
+ def parameters(self):
74
+ params = []
75
+ for layer in self.layers:
76
+ params.extend(layer.parameters())
77
+ return params
78
+
79
+ def _get_named_params(self, prefix=""):
80
+ named = {}
81
+ for i, layer in enumerate(self.layers):
82
+ key = f"{prefix}.layers.{i}" if prefix else f"layers.{i}"
83
+ named.update(layer._get_named_params(prefix=key))
84
+ return named
85
+
86
+ def forward(self, x):
87
+ # закидываем x по слоям
88
+ for layer in self.layers:
89
+ x = layer(x)
90
+ return x
91
+
92
+ def __getitem__(self, idx):
93
+ return self.layers[idx]
94
+
95
+ def __len__(self):
96
+ return len(self.layers)
@@ -0,0 +1,113 @@
1
+ import numpy as np
2
+ from tinytensor.core.tensor import Tensor
3
+ from tinytensor.nn.modules import Module
4
+ from tinytensor.nn.functional import im2col_indices, col2_im_indices
5
+
6
+ class MaxPool2d(Module):
7
+ def __init__(self, kernel_size=2, stride=2, padding=0):
8
+ super().__init__()
9
+ if isinstance(kernel_size, int):
10
+ self.kh = self.kw = kernel_size
11
+ # если кортедж
12
+ else:
13
+ self.kh, self.kw = kernel_size
14
+
15
+ self.stride = stride
16
+ self.padding = padding
17
+
18
+ def forward(self,x):
19
+ N, C, H, W = x.data.shape
20
+ # меняем размерность
21
+ x_reshaped = x.data.reshape(N * C, 1, H, W)
22
+ x_col, out_h, out_w = im2col_indices(
23
+ x_reshaped, self.kh, self.kw, padding=self.padding, stride=self.stride
24
+ )
25
+
26
+ #находим максимумы
27
+ max_idx = np.argmax(x_col, axis=0)
28
+ out = x_col[max_idx, np.arange(x_col.shape[1])]
29
+
30
+ #сново меняем размеры
31
+ out = out.reshape(out_h, out_w, N, C)
32
+ out = out.transpose(2, 3, 0, 1)
33
+
34
+ out_t = Tensor(out, requires_grad=x.requires_grad, device=x.device)
35
+
36
+ if out_t.requires_grad:
37
+ out_t._prev = {x}
38
+
39
+ def _backward():
40
+ dout = out_t.grad
41
+ dout_flat = dout.transpose(2, 3, 0, 1).reshape(-1)
42
+
43
+ dx_col = np.zeros_like(x_col)
44
+ dx_col[max_idx, np.arange(max_idx.size)] = dout_flat
45
+
46
+ dx_reshaped = col2_im_indices(
47
+ dx_col, x_reshaped.shape, self.kh, self.kw,
48
+ padding=self.padding, stride=self.stride
49
+ )
50
+ dx = dx_reshaped.reshape(N, C, H, W)
51
+
52
+ if x.grad is None:
53
+ x.grad = np.zeros_like(x.data, dtype=np.float32)
54
+ x.grad += dx
55
+
56
+ out_t._backward = _backward
57
+
58
+ return out_t
59
+
60
+
61
+ class AvgPool2d(Module):
62
+ def __init__(self, kernel_size=2, stride=2, padding=0):
63
+ super().__init__()
64
+ if isinstance(kernel_size, int):
65
+ self.kh = self.kw = kernel_size
66
+ # если кортедж
67
+ else:
68
+ self.kh, self.kw = kernel_size
69
+
70
+ self.stride = stride
71
+ self.padding = padding
72
+
73
+ def forward(self,x):
74
+ N, C, H, W = x.data.shape
75
+ # меняем размерность
76
+ x_reshaped = x.data.reshape(N * C, 1, H, W)
77
+ x_col, out_h, out_w = im2col_indices(
78
+ x_reshaped, self.kh, self.kw, padding=self.padding, stride=self.stride
79
+ )
80
+
81
+ #находим средние
82
+ out = np.mean(x_col, axis=0)
83
+
84
+ #сново меняем размеры
85
+ out = out.reshape(out_h, out_w, N, C)
86
+ out = out.transpose(2, 3, 0, 1)
87
+
88
+ out_t = Tensor(out, requires_grad=x.requires_grad, device=x.device)
89
+
90
+ if out_t.requires_grad:
91
+ out_t._prev = {x}
92
+
93
+ def _backward():
94
+ dout = out_t.grad
95
+ dout_flat = dout.transpose(2, 3, 0, 1).reshape(-1)
96
+
97
+ dx_col = np.repeat((dout_flat / (self.kh * self.kw))[None, :], self.kh * self.kw, axis=0)
98
+
99
+ dx_reshaped = col2_im_indices(
100
+ dx_col, x_reshaped.shape, self.kh, self.kw,
101
+ padding=self.padding, stride=self.stride
102
+ )
103
+ dx = dx_reshaped.reshape(N, C, H, W)
104
+
105
+ if x.grad is None:
106
+ x.grad = np.zeros_like(x.data, dtype=np.float32)
107
+ x.grad += dx
108
+
109
+ out_t._backward = _backward
110
+
111
+ return out_t
112
+
113
+
@@ -0,0 +1,23 @@
1
+ import numpy as np
2
+
3
+ def clip_grad_norm_(parameters, max_norm=1.0):
4
+ if isinstance(parameters, Exception): # тп защита
5
+ return
6
+
7
+ params = [p for p in parameters if p.grad is not None]
8
+ if len(params) == 0:
9
+ return 0.0
10
+
11
+ total_norm_sq = 0.0
12
+ for p in params:
13
+ total_norm_sq += np.sum(p.grad ** 2)
14
+
15
+ total_norm = np.sqrt(total_norm_sq)
16
+
17
+ clip_coef = max_norm / (total_norm + 1e-6)
18
+
19
+ if clip_coef < 1.0:
20
+ for p in params:
21
+ p.grad *= clip_coef
22
+
23
+ return total_norm
@@ -1,6 +1,9 @@
1
1
  from tinytensor.optim.optimizer import Optimizer, SGD, AdamW
2
-
3
- __all__ = ["Optimizer", "SGD", "AdamW"]
2
+ from tinytensor.optim.lr_scheduler import StepLR
3
+ __all__ = [
4
+ "Optimizer", "SGD", "AdamW",
5
+ "StepLR"
6
+ ]
4
7
 
5
8
  #эт для удобства
6
9
  #чтоб можно было писать вот так:
@@ -8,4 +11,4 @@ __all__ = ["Optimizer", "SGD", "AdamW"]
8
11
  from tinytensor.optim import AdamW
9
12
 
10
13
  optimizer = AdamW(model.parameters(), lr=1e-3)
11
- """
14
+ """
@@ -0,0 +1,13 @@
1
+ #уменьшаем lr каждые n эпох чтоб модель обучилась более плавно
2
+ class StepLR:
3
+ def __init__(self, optimizer, step_size: int, gamma: float = 0.1):
4
+ self.optimizer = optimizer
5
+ self.step_size = step_size
6
+ self.gamma = gamma
7
+ self.last_epoch = 0
8
+
9
+ def step(self):
10
+ self.last_epoch += 1
11
+ if self.last_epoch % self.step_size == 0:
12
+ # уменьшаем условно в 10 раз
13
+ self.optimizer.lr *= self.gamma
File without changes
File without changes
File without changes
File without changes