pytinytensor 0.1.5__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.
- {pytinytensor-0.1.5/pytinytensor.egg-info → pytinytensor-0.1.6}/PKG-INFO +1 -1
- {pytinytensor-0.1.5 → pytinytensor-0.1.6/pytinytensor.egg-info}/PKG-INFO +1 -1
- {pytinytensor-0.1.5 → pytinytensor-0.1.6}/pytinytensor.egg-info/SOURCES.txt +5 -0
- {pytinytensor-0.1.5 → pytinytensor-0.1.6}/setup.py +1 -1
- {pytinytensor-0.1.5 → pytinytensor-0.1.6}/tinytensor/core/tensor.py +14 -0
- pytinytensor-0.1.6/tinytensor/nn/__init__.py +16 -0
- pytinytensor-0.1.6/tinytensor/nn/batchnorm.py +78 -0
- pytinytensor-0.1.6/tinytensor/nn/conv.py +84 -0
- pytinytensor-0.1.6/tinytensor/nn/flatten.py +9 -0
- pytinytensor-0.1.6/tinytensor/nn/functional.py +54 -0
- pytinytensor-0.1.6/tinytensor/nn/pooling.py +113 -0
- pytinytensor-0.1.5/tinytensor/nn/__init__.py +0 -14
- {pytinytensor-0.1.5 → pytinytensor-0.1.6}/LICENSE +0 -0
- {pytinytensor-0.1.5 → pytinytensor-0.1.6}/README.md +0 -0
- {pytinytensor-0.1.5 → pytinytensor-0.1.6}/pyproject.toml +0 -0
- {pytinytensor-0.1.5 → pytinytensor-0.1.6}/pytinytensor.egg-info/dependency_links.txt +0 -0
- {pytinytensor-0.1.5 → pytinytensor-0.1.6}/pytinytensor.egg-info/requires.txt +0 -0
- {pytinytensor-0.1.5 → pytinytensor-0.1.6}/pytinytensor.egg-info/top_level.txt +0 -0
- {pytinytensor-0.1.5 → pytinytensor-0.1.6}/setup.cfg +0 -0
- {pytinytensor-0.1.5 → pytinytensor-0.1.6}/tests/test_autograd.py +0 -0
- {pytinytensor-0.1.5 → pytinytensor-0.1.6}/tests/test_data.py +0 -0
- {pytinytensor-0.1.5 → pytinytensor-0.1.6}/tests/test_losses.py +0 -0
- {pytinytensor-0.1.5 → pytinytensor-0.1.6}/tests/test_nn.py +0 -0
- {pytinytensor-0.1.5 → pytinytensor-0.1.6}/tests/test_optim.py +0 -0
- {pytinytensor-0.1.5 → pytinytensor-0.1.6}/tests/test_tensor_math.py +0 -0
- {pytinytensor-0.1.5 → pytinytensor-0.1.6}/tinytensor/__init__.py +0 -0
- {pytinytensor-0.1.5 → pytinytensor-0.1.6}/tinytensor/backends/__init__.py +0 -0
- {pytinytensor-0.1.5 → pytinytensor-0.1.6}/tinytensor/backends/cpu_numpy.py +0 -0
- {pytinytensor-0.1.5 → pytinytensor-0.1.6}/tinytensor/backends/cuda_binding.cpp +0 -0
- {pytinytensor-0.1.5 → pytinytensor-0.1.6}/tinytensor/backends/cuda_gpu.cu +0 -0
- {pytinytensor-0.1.5 → pytinytensor-0.1.6}/tinytensor/backends/cuda_gpu.py +0 -0
- {pytinytensor-0.1.5 → pytinytensor-0.1.6}/tinytensor/config.py +0 -0
- {pytinytensor-0.1.5 → pytinytensor-0.1.6}/tinytensor/core/__init__.py +0 -0
- {pytinytensor-0.1.5 → pytinytensor-0.1.6}/tinytensor/core/autograd.py +0 -0
- {pytinytensor-0.1.5 → pytinytensor-0.1.6}/tinytensor/core/ops.py +0 -0
- {pytinytensor-0.1.5 → pytinytensor-0.1.6}/tinytensor/data/__init__.py +0 -0
- {pytinytensor-0.1.5 → pytinytensor-0.1.6}/tinytensor/data/dataloader.py +0 -0
- {pytinytensor-0.1.5 → pytinytensor-0.1.6}/tinytensor/data/dataset.py +0 -0
- {pytinytensor-0.1.5 → pytinytensor-0.1.6}/tinytensor/nn/activations.py +0 -0
- {pytinytensor-0.1.5 → pytinytensor-0.1.6}/tinytensor/nn/dropout.py +0 -0
- {pytinytensor-0.1.5 → pytinytensor-0.1.6}/tinytensor/nn/linear.py +0 -0
- {pytinytensor-0.1.5 → pytinytensor-0.1.6}/tinytensor/nn/losses.py +0 -0
- {pytinytensor-0.1.5 → pytinytensor-0.1.6}/tinytensor/nn/modules.py +0 -0
- {pytinytensor-0.1.5 → pytinytensor-0.1.6}/tinytensor/nn/utils.py +0 -0
- {pytinytensor-0.1.5 → pytinytensor-0.1.6}/tinytensor/optim/__init__.py +0 -0
- {pytinytensor-0.1.5 → pytinytensor-0.1.6}/tinytensor/optim/lr_scheduler.py +0 -0
- {pytinytensor-0.1.5 → pytinytensor-0.1.6}/tinytensor/optim/optimizer.py +0 -0
- {pytinytensor-0.1.5 → pytinytensor-0.1.6}/tinytensor/utils/__init__.py +0 -0
- {pytinytensor-0.1.5 → pytinytensor-0.1.6}/tinytensor/utils/bar.py +0 -0
- {pytinytensor-0.1.5 → pytinytensor-0.1.6}/tinytensor/utils/early_stopping.py +0 -0
- {pytinytensor-0.1.5 → pytinytensor-0.1.6}/tinytensor/utils/summary.py +0 -0
|
@@ -29,10 +29,15 @@ 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
|
|
36
41
|
tinytensor/nn/utils.py
|
|
37
42
|
tinytensor/optim/__init__.py
|
|
38
43
|
tinytensor/optim/lr_scheduler.py
|
|
@@ -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,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
|
+
|
|
@@ -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
|
+
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
from tinytensor.nn.modules import Module, Sequential
|
|
2
|
-
from tinytensor.nn.linear import Linear
|
|
3
|
-
from tinytensor.nn.activations import ReLU, LeReLU, Sigmod, Tanh, GELU
|
|
4
|
-
from tinytensor.nn.dropout import Dropout
|
|
5
|
-
from tinytensor.nn.losses import MSELoss
|
|
6
|
-
|
|
7
|
-
__all__ = [
|
|
8
|
-
"Module",
|
|
9
|
-
"Sequential",
|
|
10
|
-
"Linear",
|
|
11
|
-
"ReLU", "LeReLU", "Sigmod", "Tanh", "GELU",
|
|
12
|
-
"Dropout",
|
|
13
|
-
"MSELoss"
|
|
14
|
-
]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|