pytinytensor 0.1.2__tar.gz → 0.1.3__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 (64) hide show
  1. {pytinytensor-0.1.2/pytinytensor.egg-info → pytinytensor-0.1.3}/PKG-INFO +1 -1
  2. {pytinytensor-0.1.2 → pytinytensor-0.1.3/pytinytensor.egg-info}/PKG-INFO +1 -1
  3. {pytinytensor-0.1.2 → pytinytensor-0.1.3}/pytinytensor.egg-info/SOURCES.txt +1 -22
  4. {pytinytensor-0.1.2 → pytinytensor-0.1.3}/setup.py +1 -1
  5. {pytinytensor-0.1.2/tinytensor → pytinytensor-0.1.3}/tinytensor/nn/activations.py +1 -0
  6. pytinytensor-0.1.3/tinytensor/nn/dropout.py +23 -0
  7. {pytinytensor-0.1.2/tinytensor → pytinytensor-0.1.3}/tinytensor/nn/modules.py +8 -7
  8. {pytinytensor-0.1.2/tinytensor → pytinytensor-0.1.3}/tinytensor/optim/optimizer.py +13 -6
  9. pytinytensor-0.1.2/tinytensor/nn/activations.py +0 -36
  10. pytinytensor-0.1.2/tinytensor/nn/modules.py +0 -63
  11. pytinytensor-0.1.2/tinytensor/optim/optimizer.py +0 -72
  12. pytinytensor-0.1.2/tinytensor/setup.py +0 -81
  13. pytinytensor-0.1.2/tinytensor/tinytensor/__init__.py +0 -0
  14. pytinytensor-0.1.2/tinytensor/tinytensor/backends/__init__.py +0 -0
  15. pytinytensor-0.1.2/tinytensor/tinytensor/backends/cpu_numpy.py +0 -0
  16. pytinytensor-0.1.2/tinytensor/tinytensor/config.py +0 -20
  17. pytinytensor-0.1.2/tinytensor/tinytensor/core/__init__.py +0 -0
  18. pytinytensor-0.1.2/tinytensor/tinytensor/core/autograd.py +0 -22
  19. pytinytensor-0.1.2/tinytensor/tinytensor/core/ops.py +0 -1
  20. pytinytensor-0.1.2/tinytensor/tinytensor/core/tensor.py +0 -288
  21. pytinytensor-0.1.2/tinytensor/tinytensor/data/__init__.py +0 -5
  22. pytinytensor-0.1.2/tinytensor/tinytensor/data/dataloader.py +0 -41
  23. pytinytensor-0.1.2/tinytensor/tinytensor/data/dataset.py +0 -19
  24. pytinytensor-0.1.2/tinytensor/tinytensor/nn/__init__.py +0 -0
  25. pytinytensor-0.1.2/tinytensor/tinytensor/nn/linear.py +0 -18
  26. pytinytensor-0.1.2/tinytensor/tinytensor/nn/losses.py +0 -12
  27. pytinytensor-0.1.2/tinytensor/tinytensor/optim/__init__.py +0 -11
  28. pytinytensor-0.1.2/tinytensor/utils/__init__.py +0 -4
  29. pytinytensor-0.1.2/tinytensor/utils/bar.py +0 -26
  30. pytinytensor-0.1.2/tinytensor/utils/early_stopping.py +0 -64
  31. {pytinytensor-0.1.2 → pytinytensor-0.1.3}/LICENSE +0 -0
  32. {pytinytensor-0.1.2 → pytinytensor-0.1.3}/README.md +0 -0
  33. {pytinytensor-0.1.2 → pytinytensor-0.1.3}/pyproject.toml +0 -0
  34. {pytinytensor-0.1.2 → pytinytensor-0.1.3}/pytinytensor.egg-info/dependency_links.txt +0 -0
  35. {pytinytensor-0.1.2 → pytinytensor-0.1.3}/pytinytensor.egg-info/requires.txt +0 -0
  36. {pytinytensor-0.1.2 → pytinytensor-0.1.3}/pytinytensor.egg-info/top_level.txt +0 -0
  37. {pytinytensor-0.1.2 → pytinytensor-0.1.3}/setup.cfg +0 -0
  38. {pytinytensor-0.1.2 → pytinytensor-0.1.3}/tests/test_autograd.py +0 -0
  39. {pytinytensor-0.1.2 → pytinytensor-0.1.3}/tests/test_data.py +0 -0
  40. {pytinytensor-0.1.2 → pytinytensor-0.1.3}/tests/test_losses.py +0 -0
  41. {pytinytensor-0.1.2 → pytinytensor-0.1.3}/tests/test_nn.py +0 -0
  42. {pytinytensor-0.1.2 → pytinytensor-0.1.3}/tests/test_optim.py +0 -0
  43. {pytinytensor-0.1.2 → pytinytensor-0.1.3}/tests/test_tensor_math.py +0 -0
  44. {pytinytensor-0.1.2 → pytinytensor-0.1.3}/tinytensor/__init__.py +0 -0
  45. {pytinytensor-0.1.2 → pytinytensor-0.1.3}/tinytensor/backends/__init__.py +0 -0
  46. {pytinytensor-0.1.2 → pytinytensor-0.1.3}/tinytensor/backends/cpu_numpy.py +0 -0
  47. {pytinytensor-0.1.2 → pytinytensor-0.1.3}/tinytensor/backends/cuda_binding.cpp +0 -0
  48. {pytinytensor-0.1.2 → pytinytensor-0.1.3}/tinytensor/backends/cuda_gpu.cu +0 -0
  49. {pytinytensor-0.1.2 → pytinytensor-0.1.3}/tinytensor/backends/cuda_gpu.py +0 -0
  50. {pytinytensor-0.1.2 → pytinytensor-0.1.3}/tinytensor/config.py +0 -0
  51. {pytinytensor-0.1.2 → pytinytensor-0.1.3}/tinytensor/core/__init__.py +0 -0
  52. {pytinytensor-0.1.2 → pytinytensor-0.1.3}/tinytensor/core/autograd.py +0 -0
  53. {pytinytensor-0.1.2 → pytinytensor-0.1.3}/tinytensor/core/ops.py +0 -0
  54. {pytinytensor-0.1.2 → pytinytensor-0.1.3}/tinytensor/core/tensor.py +0 -0
  55. {pytinytensor-0.1.2 → pytinytensor-0.1.3}/tinytensor/data/__init__.py +0 -0
  56. {pytinytensor-0.1.2 → pytinytensor-0.1.3}/tinytensor/data/dataloader.py +0 -0
  57. {pytinytensor-0.1.2 → pytinytensor-0.1.3}/tinytensor/data/dataset.py +0 -0
  58. {pytinytensor-0.1.2 → pytinytensor-0.1.3}/tinytensor/nn/__init__.py +0 -0
  59. {pytinytensor-0.1.2 → pytinytensor-0.1.3}/tinytensor/nn/linear.py +0 -0
  60. {pytinytensor-0.1.2 → pytinytensor-0.1.3}/tinytensor/nn/losses.py +0 -0
  61. {pytinytensor-0.1.2 → pytinytensor-0.1.3}/tinytensor/optim/__init__.py +0 -0
  62. {pytinytensor-0.1.2/tinytensor → pytinytensor-0.1.3}/tinytensor/utils/__init__.py +0 -0
  63. {pytinytensor-0.1.2/tinytensor → pytinytensor-0.1.3}/tinytensor/utils/bar.py +0 -0
  64. {pytinytensor-0.1.2/tinytensor → pytinytensor-0.1.3}/tinytensor/utils/early_stopping.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pytinytensor
3
- Version: 0.1.2
3
+ Version: 0.1.3
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.2
3
+ Version: 0.1.3
4
4
  Summary: мини ИИ фреймворк от IbrokimN ( github/IbrokhimN )
5
5
  Home-page: https://github.com/IbrokhimN/tinytensor
6
6
  Author: IbrokhimN
@@ -15,7 +15,6 @@ tests/test_optim.py
15
15
  tests/test_tensor_math.py
16
16
  tinytensor/__init__.py
17
17
  tinytensor/config.py
18
- tinytensor/setup.py
19
18
  tinytensor/backends/__init__.py
20
19
  tinytensor/backends/cpu_numpy.py
21
20
  tinytensor/backends/cuda_binding.cpp
@@ -30,32 +29,12 @@ tinytensor/data/dataloader.py
30
29
  tinytensor/data/dataset.py
31
30
  tinytensor/nn/__init__.py
32
31
  tinytensor/nn/activations.py
32
+ tinytensor/nn/dropout.py
33
33
  tinytensor/nn/linear.py
34
34
  tinytensor/nn/losses.py
35
35
  tinytensor/nn/modules.py
36
36
  tinytensor/optim/__init__.py
37
37
  tinytensor/optim/optimizer.py
38
- tinytensor/tinytensor/__init__.py
39
- tinytensor/tinytensor/config.py
40
- tinytensor/tinytensor/backends/__init__.py
41
- tinytensor/tinytensor/backends/cpu_numpy.py
42
- tinytensor/tinytensor/core/__init__.py
43
- tinytensor/tinytensor/core/autograd.py
44
- tinytensor/tinytensor/core/ops.py
45
- tinytensor/tinytensor/core/tensor.py
46
- tinytensor/tinytensor/data/__init__.py
47
- tinytensor/tinytensor/data/dataloader.py
48
- tinytensor/tinytensor/data/dataset.py
49
- tinytensor/tinytensor/nn/__init__.py
50
- tinytensor/tinytensor/nn/activations.py
51
- tinytensor/tinytensor/nn/linear.py
52
- tinytensor/tinytensor/nn/losses.py
53
- tinytensor/tinytensor/nn/modules.py
54
- tinytensor/tinytensor/optim/__init__.py
55
- tinytensor/tinytensor/optim/optimizer.py
56
- tinytensor/tinytensor/utils/__init__.py
57
- tinytensor/tinytensor/utils/bar.py
58
- tinytensor/tinytensor/utils/early_stopping.py
59
38
  tinytensor/utils/__init__.py
60
39
  tinytensor/utils/bar.py
61
40
  tinytensor/utils/early_stopping.py
@@ -113,7 +113,7 @@ else:
113
113
 
114
114
  setup(
115
115
  name="pytinytensor",
116
- version="0.1.2",
116
+ version="0.1.3",
117
117
  description="мини ИИ фреймворк от IbrokimN ( github/IbrokhimN )",
118
118
  long_description=long_description,
119
119
  long_description_content_type="text/markdown",
@@ -7,6 +7,7 @@ class ReLU(Module):
7
7
  class LeReLU(Module):
8
8
  # у нас есть тут альфа
9
9
  def __init__(self, alpha=0.01):
10
+ super().__init__()
10
11
  self.alpha = alpha
11
12
 
12
13
  def forward(self, x):
@@ -0,0 +1,23 @@
1
+ #функция дропаута это короче нужно чтоб вырубать нейроны во время обучения чтоб остальные нейроны обучились хорошо тоже
2
+
3
+ import numpy as np
4
+ from tinytensor.nn.modules import Module
5
+ from tinytensor.core.tensor import Tensor
6
+
7
+ class Dropout(Module):
8
+ def __init__(self, p=0.5):
9
+ super().__init__()
10
+ # p это вероятност типа 0.5 это половина нейронов вырубается
11
+ self.p = p
12
+
13
+ def forward(self, x):
14
+ # если не обучаемся то скип
15
+ if not self.training or self.p == 0:
16
+ return x
17
+ mask_data = (np.random.rand(*x.data.shape) > self.p) / (1.0 - self.p)
18
+
19
+ #маску в тензор превращаем
20
+ mask = Tensor(mask_data, requires_grad=False)
21
+
22
+ #тк маска состоит из 0 и 1 умножение как раз некоторые нейроны вырубит
23
+ return x * mask
@@ -1,6 +1,5 @@
1
1
  from tinytensor.core.tensor import Tensor
2
2
  import pickle
3
-
4
3
  #кароч модуль от которого будут наследоваться все слои
5
4
  class Module:
6
5
  def __init__(self):
@@ -8,27 +7,31 @@ class Module:
8
7
 
9
8
  def __call__(self, *args, **kwargs):
10
9
  return self.forward(*args, **kwargs)
11
-
12
10
  #щас это просто заглушка для прямого вызова, а в реале у всех должны быть свои реализации forward, так что это роль не играет
13
11
  def forward(self, *args, **kwargs):
14
12
  raise NotImplementedError(...)
15
-
16
13
  # сохраняет обучаемые веса, и если в модуле есть еще какие то модули то он их тоже открывает
17
14
  def parameters(self):
18
15
  params = []
19
16
  for atr in self.__dict__.values():
20
17
  if isinstance(atr, Tensor) and atr.requires_grad == True:
21
18
  params.append(atr)
22
-
23
19
  elif isinstance(atr, Module):
24
20
  params.extend(atr.parameters())
25
21
  return params
26
-
27
22
  #обнуляет градиенты
28
23
  def zero_grad(self):
29
24
  for atr in self.parameters():
30
25
  atr.grad = None
31
26
 
27
+ def train(self, mode=True):
28
+ self.training = mode
29
+ for atr in self.__dict__.values():
30
+ if isinstance(atr, Module):
31
+ atr.train(mode)
32
+ return self
33
+ def eval(self):
34
+ return self.train(False)
32
35
  def state_dict(self):
33
36
  #вытащим все веса параметров
34
37
  sdict = {}
@@ -41,7 +44,6 @@ class Module:
41
44
  for name, param in self._get_named_params().items():
42
45
  if name in sdict:
43
46
  param.data = sdict[name]
44
-
45
47
  def _get_named_params(self, prefix=""):
46
48
  named = {}
47
49
  for attr_name, attr in self.__dict__.items():
@@ -56,7 +58,6 @@ class Module:
56
58
  def save(self,filepath):
57
59
  with open(filepath, "wb") as f:
58
60
  pickle.dump(self.state_dict(), f)
59
-
60
61
  # загрузка весов обратно
61
62
  def load(self, filepath):
62
63
  with open(filepath, "rb") as f:
@@ -17,27 +17,30 @@ class Optimizer:
17
17
  # SGD
18
18
  # w = w - lr*dw
19
19
  class SGD(Optimizer):
20
- def __init__(self, parameters, lr = 0.01, momentum = 0.0):
20
+ def __init__(self, parameters, lr = 0.01, momentum = 0.0, weight_decay = 0.0):
21
21
  super().__init__(parameters)
22
22
  self.lr = lr
23
23
  self.momentum = momentum
24
+ self.weight_decay = weight_decay
24
25
  # буфера
25
26
  self.velocities = [np.zeros_like(p.data) for p in self.parameters] if momentum > 0 else None
26
27
 
27
28
  def step(self):
28
- for i,p in enumerate(self.parameters):
29
+ for i, p in enumerate(self.parameters):
29
30
  if p.grad is None:
30
31
  continue
31
- grad = p.grad
32
+ grad = p.grad
33
+ if self.weight_decay != 0:
34
+ grad = grad + self.weight_decay * p.data
32
35
 
33
- if self.momentum>0:
36
+ if self.momentum > 0:
34
37
  self.velocities[i] = self.momentum * self.velocities[i] + grad
35
38
  grad = self.velocities[i]
39
+
36
40
  # шаг
37
41
  p.data -= self.lr * grad
38
42
 
39
43
 
40
-
41
44
  #Adamw
42
45
  # слишком много формул мне впадлу писать
43
46
  class AdamW(Optimizer):
@@ -69,4 +72,8 @@ class AdamW(Optimizer):
69
72
  v_hat = self.v[i] / (1.0 - self.beta2 ** self.t)
70
73
  # адапт шаг и разделение затухания весов
71
74
  denom = np.sqrt(v_hat) + self.eps
72
- p.data -= self.lr * (m_hat / denom + self.weight_decay * p.data)
75
+
76
+ if self.weight_decay != 0:
77
+ p.data -= self.lr * self.weight_decay * p.data
78
+
79
+ p.data -= self.lr * (m_hat / denom)
@@ -1,36 +0,0 @@
1
- from tinytensor.nn.modules import Module
2
-
3
- class ReLU(Module):
4
- def forward(self, x):
5
- return x.relu()
6
-
7
- class LeReLU(Module):
8
- # у нас есть тут альфа
9
- def __init__(self, alpha=0.01):
10
- self.alpha = alpha
11
-
12
- def forward(self, x):
13
- return x.leaky_relu(alpha=self.alpha)
14
-
15
- class Sigmod(Module):
16
- def forward(self, x):
17
- return x.sigmoid()
18
-
19
- class Tanh(Module):
20
- def forward(self, x):
21
- return x.tanh()
22
-
23
- class GELU(Module):
24
- def forward(self, x):
25
- return x.gelu()
26
-
27
-
28
-
29
-
30
- # ToDo:
31
- # ReLU [x]
32
- # LeReLU [x]
33
- # Sigmoid [x]
34
- # Tanh [x]
35
- # GELU [x]
36
- # kama soska
@@ -1,63 +0,0 @@
1
- from tinytensor.core.tensor import Tensor
2
- import pickle
3
-
4
- #кароч модуль от которого будут наследоваться все слои
5
- class Module:
6
- def __init__(self):
7
- self.training = True
8
-
9
- def __call__(self, *args, **kwargs):
10
- return self.forward(*args, **kwargs)
11
-
12
- #щас это просто заглушка для прямого вызова, а в реале у всех должны быть свои реализации forward, так что это роль не играет
13
- def forward(self, *args, **kwargs):
14
- raise NotImplementedError(...)
15
-
16
- # сохраняет обучаемые веса, и если в модуле есть еще какие то модули то он их тоже открывает
17
- def parameters(self):
18
- params = []
19
- for atr in self.__dict__.values():
20
- if isinstance(atr, Tensor) and atr.requires_grad == True:
21
- params.append(atr)
22
-
23
- elif isinstance(atr, Module):
24
- params.extend(atr.parameters())
25
- return params
26
-
27
- #обнуляет градиенты
28
- def zero_grad(self):
29
- for atr in self.parameters():
30
- atr.grad = None
31
-
32
- def state_dict(self):
33
- #вытащим все веса параметров
34
- sdict = {}
35
- for name, param in self._get_named_params().items():
36
- sdict[name] = param.data
37
-
38
- def load_state_dict(self, sdict):
39
- #запихиваем обратно
40
- for name, param in self._get_named_params().items():
41
- if name in sdict:
42
- param.data = sdict[name]
43
-
44
- def _get_named_params(self, prefix=""):
45
- named = {}
46
- for attr_name, attr in self.__dict__.items():
47
- key = f"{prefix}.{attr_name}" if prefix else attr_name
48
- if isinstance(attr, Tensor):
49
- named[key] = attr
50
- elif isinstance(attr, Module):
51
- named.update(attr._get_named_params(prefix=key))
52
- return named
53
-
54
- #сохранение модели
55
- def save(self,filepath):
56
- with open(filepath, "wb") as f:
57
- pickle.dump(self.state_dict(), f)
58
-
59
- # загрузка весов обратно
60
- def load(self, filepath):
61
- with open(filepath, "wb") as f:
62
- sd = pickle.load(f)
63
- self.load_state_dict(sd)
@@ -1,72 +0,0 @@
1
- # я допил свой чай, теперь хочу еще но мне лень вставать
2
- import numpy as np
3
-
4
- class Optimizer:
5
- def __init__ (self, parameters):
6
- # в лист если через генератор model параметры выдано
7
- self.parameters = list(parameters)
8
-
9
- def step(self):
10
- #у каждого свой
11
- raise NotImplementedError
12
-
13
- def zero_grad(self):
14
- for p in self.parameters:
15
- p.grad = None
16
-
17
- # SGD
18
- # w = w - lr*dw
19
- class SGD(Optimizer):
20
- def __init__(self, parameters, lr = 0.01, momentum = 0.0):
21
- super().__init__(parameters)
22
- self.lr = lr
23
- self.momentum = momentum
24
- # буфера
25
- self.velocities = [np.zeros_like(p.data) for p in self.parameters] if momentum > 0 else None
26
-
27
- def step(self):
28
- for i,p in enumerate(self.parameters):
29
- if p.grad is None:
30
- continue
31
- grad = p.grad
32
-
33
- if self.momentum>0:
34
- self.velocities[i] = self.momentum * self.velocities[i] + grad
35
- grad = self.velocities[i]
36
- # шаг
37
- p.data -= self.lr * grad
38
-
39
-
40
-
41
- #Adamw
42
- # слишком много формул мне впадлу писать
43
- class AdamW(Optimizer):
44
- def __init__(self, parameters, lr=0.001, betas=(0.9, 0.999), eps=1e-8, weight_decay=0.01):
45
- super().__init__(parameters)
46
- self.lr = lr
47
- self.beta1, self.beta2 = betas
48
- self.eps = eps
49
- self.weight_decay = weight_decay
50
-
51
- self.t = 0
52
-
53
- self.m = [np.zeros_like(p.data) for p in self.parameters]
54
- self.v = [np.zeros_like(p.data) for p in self.parameters]
55
-
56
- def step(self):
57
- self.t += 1
58
-
59
- for i, p in enumerate(self.parameters):
60
- if p.grad is None:
61
- continue
62
-
63
- grad = p.grad
64
- # обновка m и v мометы
65
- self.m[i] = self.beta1 * self.m[i] + (1.0 - self.beta1) * grad
66
- self.v[i] = self.beta2 * self.v[i] + (1.0 - self.beta2) * (grad ** 2)
67
- # корекция баяса
68
- m_hat = self.m[i] / (1.0 - self.beta1 ** self.t)
69
- v_hat = self.v[i] / (1.0 - self.beta2 ** self.t)
70
- # адапт шаг и разделение затухания весов
71
- denom = np.sqrt(v_hat) + self.eps
72
- p.data -= self.lr * (m_hat / denom + self.weight_decay * p.data)
@@ -1,81 +0,0 @@
1
- import os
2
- import subprocess
3
- import pybind11
4
- from setuptools import setup, find_packages, Extension
5
- from setuptools.command.build_ext import build_ext
6
-
7
- def check_cuda():
8
- try:
9
- subprocess.check_output(["nvcc", "--version"])
10
- return True
11
- except (FileNotFoundError, subprocess.CalledProcessError):
12
- return False
13
-
14
- class CUDABuildExt(build_ext):
15
- def build_extensions(self):
16
- self.compiler.src_extensions.append('.cu')
17
- original_compile = self.compiler._compile
18
-
19
- def custom_compile(obj, src, ext, cc_args, extra_postargs, pp_opts):
20
- # extra_postargs может приходить как список или словарь — обрабатываем оба случая
21
- if isinstance(extra_postargs, dict):
22
- gcc_postargs = extra_postargs.get('gcc', [])
23
- nvcc_postargs = extra_postargs.get('nvcc', [])
24
- else:
25
- gcc_postargs = extra_postargs or []
26
- nvcc_postargs = []
27
-
28
- if os.path.splitext(src)[1] == '.cu':
29
- # nvcc собирает .cu файл
30
- inc_flags = [f"-I{inc}" for inc in self.compiler.include_dirs]
31
- cmd = ['nvcc', '-c', src, '-o', obj] + inc_flags + nvcc_postargs
32
- self.spawn(cmd)
33
- else:
34
- # g++ собирает .cpp файл (с pybind11)
35
- original_compile(obj, src, ext, cc_args, gcc_postargs, pp_opts)
36
-
37
- self.compiler._compile = custom_compile
38
- super().build_extensions()
39
-
40
- ext_modules = []
41
-
42
- if check_cuda():
43
- cuda_module = Extension(
44
- 'tinytensor.cuda_ops',
45
- sources=[
46
- 'tinytensor/backends/cuda_gpu.cu', # Компилируется nvcc
47
- 'tinytensor/backends/cuda_binding.cpp' # Компилируется g++
48
- ],
49
- include_dirs=[
50
- pybind11.get_include(),
51
- '/usr/local/cuda/include',
52
- os.path.expanduser('~/.local/include')
53
- ],
54
- library_dirs=['/usr/local/cuda/lib64'],
55
- libraries=['cudart', 'cublas'],
56
- extra_compile_args={
57
- 'gcc': ['-O3', '-fPIC', '-std=c++17'],
58
- 'nvcc': ['-O3', '-Xcompiler', '-fPIC']
59
- }
60
- )
61
- ext_modules.append(cuda_module)
62
- print("🔥 CUDA найдена! Собираем cuBLAS бэкенд...")
63
- else:
64
- print("⚠️ CUDA не найдена. Сборка продолжится на CPU (NumPy).")
65
-
66
- setup(
67
- name="tinytensor",
68
- version="0.1.0",
69
- description="мини ИИ фреймворк от IbrokimN ( github/IbrokhimN )",
70
- packages=find_packages(include=["tinytensor", "tinytensor.*"]),
71
- ext_modules=ext_modules,
72
- cmdclass={'build_ext': CUDABuildExt},
73
- install_requires=[
74
- "numpy>=1.23",
75
- "pybind11>=2.10",
76
- ],
77
- extras_require={
78
- "dev": ["pytest>=7.0"],
79
- },
80
- python_requires=">=3.9",
81
- )
File without changes
@@ -1,20 +0,0 @@
1
- from dataclasses import dataclass
2
- import numpy as np
3
-
4
-
5
- @dataclass
6
- class Config:
7
- # базовый сид будет 67
8
- seed: int = 67
9
-
10
-
11
- config = Config()
12
-
13
-
14
- def set_seed(seed: int):
15
- # автоматически устанавливаем сид для воспроизведения и тд
16
- config.seed = seed
17
- np.random.seed(seed)
18
-
19
- # ну все при импорте будет устанавливаться
20
- np.random.seed(config.seed)
File without changes
@@ -1,22 +0,0 @@
1
- import numpy as np
2
-
3
-
4
- def backward(target_tensor):
5
- # эт я вообще сделал чтоб файл не пустовал, но это архитектура micrograd как у Андрея Карпатова,
6
- # если кто то шарит за нормальный движок autograd, то PRните
7
- topo = []
8
- visited = set()
9
-
10
- def build_topo(v):
11
- if v not in visited:
12
- visited.add(v)
13
- for child in v._prev:
14
- build_topo(child)
15
- topo.append(v)
16
-
17
- build_topo(target_tensor)
18
-
19
- target_tensor.grad = np.ones_like(target_tensor.data, dtype=np.float32)
20
-
21
- for v in reversed(topo):
22
- v._backward()
@@ -1 +0,0 @@
1
- # пока что побудет пустым
@@ -1,288 +0,0 @@
1
- import numpy as np
2
-
3
- from tinytensor.core.autograd import backward as run_backward
4
-
5
- #чекаем ес можно на cuda матричные умножения сделать
6
- try:
7
- from tinytensor import cuda_ops
8
- HAS_CUDA = True
9
- except ImportError:
10
- HAS_CUDA = False
11
-
12
-
13
- def _unbroadcast(grad, target):
14
- while grad.ndim > len(target):
15
- grad = grad.sum(axis=0)
16
-
17
- for i, dim in enumerate(target):
18
- if dim == 1:
19
- grad = grad.sum(axis=i, keepdims=True)
20
- return grad
21
-
22
-
23
- # этот мир жесток
24
- class Tensor:
25
- def __init__(self, data, requires_grad=False, device="cpu"):
26
- # кароч проверка если нампай массив то оставляем а если нет то делаем нампаем
27
- if isinstance(data, np.ndarray):
28
- self.data = data.astype(np.float32)
29
- else:
30
- self.data = np.array(data, dtype=np.float32)
31
-
32
- self.grad = None
33
- self._backward = lambda: None
34
- self._prev = set()
35
- self.requires_grad = requires_grad
36
- self.device = device
37
-
38
- def to(self, device):
39
- # перекидываем тензор на cuda или cpu
40
- self.device = device
41
- return self
42
-
43
- def __repr__(self):
44
- return f"tensor({self.data}, device='{self.device}', requires_grad={self.requires_grad})"
45
-
46
- @property
47
- def shape(self):
48
- return self.data.shape
49
-
50
- # сложение
51
- def __add__(self, other):
52
- other = other if isinstance(other, Tensor) else Tensor(other, device=self.device)
53
- out = Tensor(
54
- self.data + other.data,
55
- requires_grad=self.requires_grad or other.requires_grad,
56
- device=self.device,
57
- )
58
-
59
- if out.requires_grad:
60
- out._prev = {self, other}
61
-
62
- def _backward():
63
- if self.requires_grad:
64
- if self.grad is None:
65
- self.grad = np.zeros_like(self.data, dtype=np.float32)
66
-
67
- grad_self = out.grad * 1.0
68
- self.grad += _unbroadcast(grad_self, self.data.shape)
69
-
70
- # градиент для 2 параметра
71
- if other.requires_grad:
72
- if other.grad is None:
73
- other.grad = np.zeros_like(other.data, dtype=np.float32)
74
-
75
- grad_other = out.grad * 1.0
76
- other.grad += _unbroadcast(grad_other, other.data.shape)
77
-
78
- out._backward = _backward
79
-
80
- return out
81
-
82
- def __radd__(self, other):
83
- # эт если пользователь решит написать не Tensor + 5 а 5 + Tensor
84
- return self + other
85
-
86
- # умножение
87
- def __mul__(self, other):
88
- other = other if isinstance(other, Tensor) else Tensor(other, device=self.device)
89
- out = Tensor(
90
- self.data * other.data,
91
- requires_grad=self.requires_grad or other.requires_grad,
92
- device=self.device,
93
- )
94
-
95
- if out.requires_grad:
96
- out._prev = {self, other}
97
-
98
- def _backward():
99
- if self.requires_grad:
100
- if self.grad is None:
101
- self.grad = np.zeros_like(self.data, dtype=np.float32)
102
- grad_self = out.grad * other.data
103
- self.grad += _unbroadcast(grad_self, self.data.shape)
104
-
105
- if other.requires_grad:
106
- if other.grad is None:
107
- other.grad = np.zeros_like(other.data, dtype=np.float32)
108
- grad_other = out.grad * self.data
109
- other.grad += _unbroadcast(grad_other, other.data.shape)
110
-
111
- out._backward = _backward
112
-
113
- return out
114
-
115
- def __rmul__(self, other):
116
- return self * other
117
-
118
- # матричное умножение
119
- def __matmul__(self, other):
120
- other = other if isinstance(other, Tensor) else Tensor(other, device=self.device)
121
-
122
- # если девайс куда и бэкенд собрался то гоним через кублас а если нет то обычный нампай
123
- if (self.device == "cuda" or other.device == "cuda") and HAS_CUDA:
124
- res_data = cuda_ops.matmul(self.data, other.data)
125
- else:
126
- res_data = np.matmul(self.data, other.data)
127
-
128
- out = Tensor(
129
- res_data,
130
- requires_grad=self.requires_grad or other.requires_grad,
131
- device=self.device,
132
- )
133
-
134
- if out.requires_grad:
135
- out._prev = {self, other}
136
-
137
- def _backward():
138
- if self.requires_grad:
139
- if self.grad is None:
140
- self.grad = np.zeros_like(self.data, dtype=np.float32)
141
- self.grad += np.matmul(out.grad, other.data.T)
142
-
143
- if other.requires_grad:
144
- if other.grad is None:
145
- other.grad = np.zeros_like(other.data, dtype=np.float32)
146
- other.grad += np.matmul(self.data.T, out.grad)
147
-
148
- out._backward = _backward
149
-
150
- return out
151
-
152
- # вычитание
153
- def __sub__(self, other):
154
- return self + (other * -1)
155
-
156
- def __rsub__(self, other):
157
- return (self * -1) + other
158
-
159
- def __pow__(self, power):
160
- out = Tensor(self.data ** power, requires_grad=self.requires_grad, device=self.device)
161
- if out.requires_grad:
162
- out._prev = {self}
163
-
164
- def _backward():
165
- if self.requires_grad:
166
- if self.grad is None:
167
- self.grad = np.zeros_like(self.data, dtype=np.float32)
168
- self.grad += out.grad * (power * (self.data ** (power - 1)))
169
-
170
- out._backward = _backward
171
- return out
172
-
173
- def sum(self):
174
- out = Tensor(self.data.sum(), requires_grad=self.requires_grad, device=self.device)
175
- if out.requires_grad:
176
- out._prev = {self}
177
-
178
- def _backward():
179
- if self.requires_grad:
180
- if self.grad is None:
181
- self.grad = np.zeros_like(self.data, dtype=np.float32)
182
- self.grad += out.grad * np.ones_like(self.data)
183
-
184
- out._backward = _backward
185
- return out
186
-
187
- def relu(self):
188
- out = Tensor(
189
- np.maximum(0, self.data),
190
- requires_grad=self.requires_grad,
191
- device=self.device,
192
- )
193
-
194
- if out.requires_grad:
195
- out._prev = {self}
196
-
197
- def _backward():
198
- if self.requires_grad:
199
- if self.grad is None:
200
- self.grad = np.zeros_like(self.data, dtype=np.float32)
201
- self.grad += out.grad * (self.data > 0)
202
-
203
- out._backward = _backward
204
-
205
- return out
206
-
207
- def leaky_relu(self, alpha=0.01):
208
- out_data = np.where(self.data > 0, self.data, self.data * alpha)
209
- out = Tensor(out_data, requires_grad=self.requires_grad, device=self.device)
210
- if out.requires_grad:
211
- out._prev = {self}
212
-
213
- def _backward():
214
- if self.requires_grad:
215
- if self.grad is None:
216
- self.grad = np.zeros_like(self.data, dtype=np.float32)
217
- dx = np.where(self.data > 0, 1.0, alpha)
218
- self.grad += out.grad * dx
219
-
220
- out._backward = _backward
221
- return out
222
-
223
- def sigmoid(self):
224
- sig = 1.0 / (1.0 + np.exp(-np.clip(self.data, -50, 50)))
225
- out = Tensor(sig, requires_grad=self.requires_grad, device=self.device)
226
- if out.requires_grad:
227
- out._prev = {self}
228
-
229
- def _backward():
230
- if self.requires_grad:
231
- if self.grad is None:
232
- self.grad = np.zeros_like(self.data, dtype=np.float32)
233
- self.grad += out.grad * (sig * (1.0 - sig))
234
-
235
- out._backward = _backward
236
- return out
237
-
238
- def tanh(self):
239
- t = np.tanh(self.data)
240
- out = Tensor(t, requires_grad=self.requires_grad, device=self.device)
241
- if out.requires_grad:
242
- out._prev = {self}
243
-
244
- def _backward():
245
- if self.requires_grad:
246
- if self.grad is None:
247
- self.grad = np.zeros_like(self.data, dtype=np.float32)
248
- self.grad += out.grad * (1.0 - t ** 2)
249
-
250
- out._backward = _backward
251
- return out
252
-
253
- def gelu(self):
254
- x = self.data
255
- cdf = 0.5 * (1.0 + np.tanh(np.sqrt(2.0 / np.pi) * (x + 0.044715 * (x ** 3))))
256
- out = Tensor(x * cdf, requires_grad=self.requires_grad, device=self.device)
257
- if out.requires_grad:
258
- out._prev = {self}
259
-
260
- def _backward():
261
- if self.requires_grad:
262
- if self.grad is None:
263
- self.grad = np.zeros_like(self.data, dtype=np.float32)
264
- pdf = np.exp(-0.5 * (x ** 2)) / np.sqrt(2.0 * np.pi)
265
- d_gelu = cdf + x * pdf
266
- self.grad += out.grad * d_gelu
267
-
268
- out._backward = _backward
269
- return out
270
-
271
- def backward(self):
272
- run_backward(self)
273
-
274
-
275
- # ⣇⣿⠘⣿⣿⣿⡿⡿⣟⣟⢟⢟⢝⠵⡝⣿⡿⢂⣼⣿⣷⣌⠩⡫⡻⣝⠹⢿⣿⣷
276
- # ⡆⣿⣆⠱⣝⡵⣝⢅⠙⣿⢕⢕⢕⢕⢝⣥⢒⠅⣿⣿⣿⡿⣳⣌⠪⡪⣡⢑⢝⣇
277
- # ⡆⣿⣿⣦⠹⣳⣳⣕⢅⠈⢗⢕⢕⢕⢕⢕⢈⢆⠟⠋⠉⠁⠉⠉⠁⠈⠼⢐⢕⢽
278
- # ⡗⢰⣶⣶⣦⣝⢝⢕⢕⠅⡆⢕⢕⢕⢕⢕⣴⠏⣠⡶⠛⡉⡉⡛⢶⣦⡀⠐⣕⢕
279
- # ⡝⡄⢻⢟⣿⣿⣷⣕⣕⣅⣿⣔⣕⣵⣵⣿⣿⢠⣿⢠⣮⡈⣌⠨⠅⠹⣷⡀⢱⢕
280
- # ⡝⡵⠟⠈⢀⣀⣀⡀⠉⢿⣿⣿⣿⣿⣿⣿⣿⣼⣿⢈⡋⠴⢿⡟⣡⡇⣿⡇⡀⢕
281
- # ⡝⠁⣠⣾⠟⡉⡉⡉⠻⣦⣻⣿⣿⣿⣿⣿⣿⣿⣿⣧⠸⣿⣦⣥⣿⡇⡿⣰⢗⢄
282
- # ⠁⢰⣿⡏⣴⣌⠈⣌⠡⠈⢻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣬⣉⣉⣁⣄⢖⢕⢕⢕
283
- # ⡀⢻⣿⡇⢙⠁⠴⢿⡟⣡⡆⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣵⣵⣿
284
- # ⡻⣄⣻⣿⣌⠘⢿⣷⣥⣿⠇⣿⣿⣿⣿⣿⣿⠛⠻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
285
- # ⣷⢄⠻⣿⣟⠿⠦⠍⠉⣡⣾⣿⣿⣿⣿⣿⣿⢸⣿⣦⠙⣿⣿⣿⣿⣿⣿⣿⣿⠟
286
- # ⡕⡑⣑⣈⣻⢗⢟⢞⢝⣻⣿⣿⣿⣿⣿⣿⣿⠸⣿⠿⠃⣿⣿⣿⣿⣿⣿⡿⠁⣠
287
- # ⡝⡵⢟⢕⢕⢕⢕⣵⣿⣿⣿⣿⣿⣿⣿⣿⣿⣶⣶⣿⣿⣿⣿⣿⠿⠋⣀⣈⠙
288
- # ⡝⡵⡕⡀⠑⠳⠿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠿⠛⢉⡠⡲⡫⡪⡪⡣
@@ -1,5 +0,0 @@
1
- from tinytensor.data.dataset import Dataset, TensorDataset
2
- from tinytensor.data.dataloader import DataLoader
3
-
4
- __all__ = ["Dataset", "TensorDataset", "DataLoader"]
5
- # для крастоы :3
@@ -1,41 +0,0 @@
1
- import numpy as np
2
- from tinytensor.core.tensor import Tensor
3
-
4
- class DataLoader:
5
- def __init__(self, dataset, batch_size=32, shuffle=True):
6
- self.dataset = dataset
7
- self.batch_size = batch_size
8
- self.shuffle = shuffle
9
-
10
- def __len__(self):
11
- #колво батчей за 1 эпоху
12
- return (len(self.dataset) + self.batch_size - 1) // self.batch_size
13
-
14
- def __iter__(self):
15
- self.indices = np.arange(len(self.dataset))
16
-
17
- # перемешкиваем если шафл есть
18
- if self.shuffle:
19
- np.random.shuffle(self.indices)
20
-
21
- self.current_idx = 0
22
- return self
23
-
24
- def __next__(self):
25
- # выдает след батч
26
- # останавливаемся если дошли до конца датасета
27
- if self.current_idx >= len(self.dataset):
28
- raise StopIteration
29
-
30
- batch_indices = self.indices[self.current_idx : self.current_idx + self.batch_size]
31
- self.current_idx += self.batch_size
32
-
33
- #cбор
34
- batch_x, batch_y = [], []
35
- for i in batch_indices:
36
- x, y = self.dataset[i]
37
- batch_x.append(x.data if isinstance(x, Tensor) else x)
38
- batch_y.append(y.data if isinstance(y, Tensor) else y)
39
-
40
- # батч в нампай и потом в тензо
41
- return Tensor(np.array(batch_x)), Tensor(np.array(batch_y))
@@ -1,19 +0,0 @@
1
- #влом коменты ставить тут и так все понятно
2
- class Dataset:
3
- def __len__(self):
4
- raise NotImplementedError
5
-
6
- def __getitem__(self, idx):
7
- raise NotImplementedError
8
-
9
- class TensorDataset(Dataset):
10
- def __init__(self, x, y):
11
- assert len(x) == len(y)
12
- self.x = x
13
- self.y = y
14
-
15
- def __len__(self):
16
- return len(self.x)
17
-
18
- def __getitem__(self, idx):
19
- return self.x[idx], self.y[idx]
File without changes
@@ -1,18 +0,0 @@
1
- import numpy as np
2
-
3
- from tinytensor.core.tensor import Tensor
4
- from tinytensor.nn.modules import Module
5
-
6
- class Linear(Module):
7
- def __init__(self,in_features, out_features):
8
- super().__init__()
9
- std = np.sqrt(2.0 / in_features)
10
- weightd = np.random.randn(in_features, out_features).astype(np.float32) * std
11
- self.weight = Tensor(weightd, requires_grad=True)
12
-
13
- bias_d = np.zeros((1, out_features), dtype=np.float32)
14
- self.bias = Tensor(bias_d, requires_grad=True)
15
-
16
- def forward(self, x):
17
- # кароч обычная формула y = x@w + b
18
- return (x @ self.weight ) + self.bias
@@ -1,12 +0,0 @@
1
- import numpy as np
2
- from tinytensor.nn.modules import Module
3
- # 1/n * sum((n, i = 1), yi - y`i)^2
4
- class MSELoss(Module):
5
- def forward(self, y_pred, y_true):
6
- diff = y_pred - y_true
7
- sq_diff = diff ** 2
8
- return sq_diff.sum() * (1.0/y_pred.data.size)
9
-
10
-
11
-
12
- # мб в будущем добавлю cross entropy loss
@@ -1,11 +0,0 @@
1
- from tinytensor.optim.optimizer import Optimizer, SGD, AdamW
2
-
3
- __all__ = ["Optimizer", "SGD", "AdamW"]
4
-
5
- #эт для удобства
6
- #чтоб можно было писать вот так:
7
- """
8
- from tinytensor.optim import AdamW
9
-
10
- optimizer = AdamW(model.parameters(), lr=1e-3)
11
- """
@@ -1,4 +0,0 @@
1
- from tinytensor.utils.bar import progress_bar, train_bar
2
- from tinytensor.utils.early_stopping import EarlyStopping
3
- __all__ = ["progress_bar", "train_bar",
4
- "EarlyStopping"]
@@ -1,26 +0,0 @@
1
- import time
2
-
3
-
4
- def progress_bar(iterable, prefix="", length=30):
5
- total = len(iterable)
6
- start_time = time.time()
7
- for i, item in enumerate(iterable):
8
- yield item # ИСПРАВЛЕНО: возвращаем элемент, а не модуль time
9
- percent = (i + 1) / total
10
- filled = int(length * percent)
11
- bar = "█" * filled + "-" * (length - filled)
12
- elapsed = time.time() - start_time
13
-
14
- print(f"\r{prefix} |{bar}| {percent*100:.1f}% [{elapsed:.1f}s]", end="")
15
- print()
16
-
17
-
18
- #алиас для тех кто привык train_bar писать
19
- train_bar = progress_bar
20
-
21
-
22
- """
23
- пользоваться надо крч вот так:
24
- for epoch in train_bar(range(100), prefix="обучение"):
25
- ...
26
- """
@@ -1,64 +0,0 @@
1
- import copy
2
-
3
-
4
- class EarlyStopping:
5
- def __init__(self, model, patience=5, min_delta=0.0, restore_best_weights=True):
6
- self.model = model
7
- self.patience = patience
8
- self.min_delta = min_delta
9
- self.restore_best_weights = restore_best_weights
10
-
11
- self.counter = 0
12
- self.best_loss = None
13
- self.early_stop = False
14
- self.best_state_dict = None
15
-
16
- def __call__(self, val_loss):
17
- if hasattr(val_loss, "data"):
18
- val_loss = float(val_loss.data)
19
-
20
- #если это была первая эпоха
21
- if self.best_loss is None:
22
- self.best_loss = val_loss
23
- self._save_checkpoint()
24
-
25
- elif val_loss < self.best_loss - self.min_delta:
26
- self.best_loss = val_loss
27
- self.counter = 0
28
- self._save_checkpoint()
29
-
30
- else:
31
- self.counter += 1
32
- if self.counter >= self.patience:
33
- self.early_stop = True
34
- if self.restore_best_weights and self.best_state_dict is not None:
35
- # восстанавливаем лучшие веса
36
- self.model.load_state_dict(self.best_state_dict)
37
-
38
- return self.early_stop
39
-
40
- def _save_checkpoint(self):
41
- if self.restore_best_weights and hasattr(self.model, "state_dict"):
42
- self.best_state_dict = copy.deepcopy(self.model.state_dict())
43
-
44
-
45
- '''пример кода
46
-
47
- from tinytensor.utils import EarlyStopping
48
-
49
- model = MLP()
50
- early_stopping = EarlyStopping(model, patience=7, min_delta=0.01)
51
-
52
- for epoch in range(100):
53
- #обучение
54
- train_loss = train_one_epoch(model)
55
-
56
- #валидация
57
- val_loss = evaluate(model)
58
-
59
- #проверка остановки
60
- if early_stopping(val_loss):
61
- print(f"обучение прекратилось на эпохе {epoch+1}")
62
- break
63
-
64
- '''
File without changes
File without changes
File without changes