gradforge 2.0.1__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 (42) hide show
  1. gradforge/_exceptions/__init__.py +4 -0
  2. gradforge/_exceptions/_errors.py +6 -0
  3. gradforge/_tests/profiling_stats.py +6 -0
  4. gradforge/_tests/test_linear.py +47 -0
  5. gradforge/_tests/test_operation.py +11 -0
  6. gradforge/autograd/__init__.py +2 -0
  7. gradforge/autograd/_operations/add.py +20 -0
  8. gradforge/autograd/_operations/div.py +23 -0
  9. gradforge/autograd/_operations/matmul.py +22 -0
  10. gradforge/autograd/_operations/mul.py +25 -0
  11. gradforge/autograd/_operations/pow.py +26 -0
  12. gradforge/autograd/_operations/sub.py +19 -0
  13. gradforge/autograd/engine.py +23 -0
  14. gradforge/autograd/operation.py +15 -0
  15. gradforge/autograd/standard_engine.py +35 -0
  16. gradforge/backend/__init__.py +5 -0
  17. gradforge/backend/backend.py +85 -0
  18. gradforge/backend/backend_manager.py +13 -0
  19. gradforge/backend/cupy_backend/cuda_backend.py +4 -0
  20. gradforge/backend/numpy_backend/numpy_backend.py +72 -0
  21. gradforge/core/tensor.py +71 -0
  22. gradforge/data/preprocessing/__init__.py +2 -0
  23. gradforge/data/preprocessing/preprocess.py +22 -0
  24. gradforge/metrics/__init__.py +4 -0
  25. gradforge/metrics/std_metrics.py +34 -0
  26. gradforge/optimizers/__init__.py +0 -0
  27. gradforge/optimizers/adam.py +0 -0
  28. gradforge/optimizers/optimizer.py +14 -0
  29. gradforge/optimizers/sgd.py +13 -0
  30. gradforge/training/__init__.py +0 -0
  31. gradforge/training/callbacks/__init__.py +2 -0
  32. gradforge/training/callbacks/std_callbacks.py +38 -0
  33. gradforge/training/layers/__init__.py +0 -0
  34. gradforge/training/layers/layer.py +15 -0
  35. gradforge/training/layers/linear.py +17 -0
  36. gradforge/training/models/model.py +0 -0
  37. gradforge/training/models/sequential.py +10 -0
  38. gradforge/training/trainer.py +2 -0
  39. gradforge-2.0.1.dist-info/METADATA +54 -0
  40. gradforge-2.0.1.dist-info/RECORD +42 -0
  41. gradforge-2.0.1.dist-info/WHEEL +5 -0
  42. gradforge-2.0.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,4 @@
1
+ from _errors import DataError, MatchError, ProcessError
2
+ __all__ = ["DataError", "MatchError", "ProcessError"]
3
+
4
+
@@ -0,0 +1,6 @@
1
+ class DataError(Exception):
2
+ pass
3
+ class MatchError(Exception):
4
+ pass
5
+ class ProcessError(Exception):
6
+ pass
@@ -0,0 +1,6 @@
1
+ import pstats
2
+
3
+ stats = pstats.Stats("profile.prof")
4
+
5
+ stats.sort_stats("cumtime")
6
+ stats.print_stats(30)
@@ -0,0 +1,47 @@
1
+ from gradforge.core.tensor import Tensor
2
+ from gradforge.optimizers.sgd import SGD
3
+ from gradforge.autograd.standard_engine import StandardEngine
4
+ from gradforge.backend.backend_manager import BackendManager
5
+ from gradforge.training.layers.linear import Linear
6
+ import tracemalloc
7
+
8
+ #tracemalloc.start()
9
+
10
+ def train(model, x, y, epochs):
11
+ engine = StandardEngine()
12
+ optimizer = SGD(learning_rate=1e-3)
13
+ for epoch in range(epochs):
14
+ y_pred = model.predict(x)
15
+ error = y - y_pred
16
+ loss = error ** 2
17
+
18
+ optimizer.zero_grad(model.params)
19
+ engine.backward(loss)
20
+ print('eror grad: ', error.grad)
21
+ try:
22
+ optimizer.step(model.params)
23
+ except Exception as e:
24
+ print('Error: ', e)
25
+
26
+ print(x.data @ model.w.data)
27
+
28
+ x = Tensor([[4], [8], [9]])
29
+ y = Tensor([[8], [16], [18]])
30
+ test = Tensor([[40], [60]])
31
+ assert x.data.shape == y.data.shape
32
+
33
+ #before = tracemalloc.take_snapshot()
34
+
35
+ model = Linear(1, 1)
36
+ train(model, x, y, epochs=10000)
37
+ # after = tracemalloc.take_snapshot()
38
+
39
+ print(test.data @ model.w.data)
40
+ # print(model.w.data.shape)
41
+
42
+ # stats = after.compare_to(before, "lineno")
43
+ # for result in stats[:50]:
44
+ # print(result)
45
+
46
+ # 0.757 seconds
47
+ # Backend allocations needs to optimize
@@ -0,0 +1,11 @@
1
+ import timeit
2
+
3
+ setup = "from gradforge.core.tensor import Tensor; a = Tensor([5]); b = Tensor([6])"
4
+
5
+ result = timeit.repeat("c = a + b", setup=setup, number=100000, repeat=10)
6
+
7
+ best_time = min(result)
8
+ time_per_op = best_time / 100_000
9
+ print(time_per_op * 1000000)
10
+
11
+ #0.8082507399922179
@@ -0,0 +1,2 @@
1
+ from .operation import Operation
2
+ __all__ = ["Operation"]
@@ -0,0 +1,20 @@
1
+ from ...autograd.operation import Operation
2
+
3
+ class Add(Operation):
4
+ def __init__(self, backend) -> None:
5
+ super().__init__(backend)
6
+
7
+ def forward(self, a, b):
8
+
9
+ result = self._backend.add(a, b)
10
+
11
+ return result
12
+
13
+
14
+ def backward(self, result_grad) -> tuple:
15
+
16
+ a_grad = result_grad
17
+ b_grad = result_grad
18
+
19
+ return (a_grad, b_grad)
20
+
@@ -0,0 +1,23 @@
1
+ from ...autograd.operation import Operation
2
+
3
+ class Div(Operation):
4
+ def __init__(self, backend) -> None:
5
+ super().__init__(backend)
6
+ self.parent_data = (0, 0)
7
+
8
+ def forward(self, a, b):
9
+
10
+ result = self._backend.div(a, b)
11
+ self.parent_data = (a, b)
12
+
13
+ return result
14
+
15
+
16
+ def backward(self, result_grad) -> tuple:
17
+ a_data, b_data = self.parent_data
18
+
19
+ a_grad = result_grad / b_data if b_data != 0 else 0
20
+ b_grad = (- a_data / b_data ^ 2) * result_grad if b_data != 0 else 0
21
+
22
+ return (a_grad, b_grad)
23
+
@@ -0,0 +1,22 @@
1
+ from ...autograd.operation import Operation
2
+ class Matmul(Operation):
3
+ def __init__(self, backend) -> None:
4
+ super().__init__(backend)
5
+ self.parent_data = (0, 0)
6
+
7
+ def forward(self, a, b):
8
+
9
+ self.parent_data = (a, b)
10
+ result = self._backend.matmul(a, b)
11
+
12
+ return result
13
+
14
+
15
+ def backward(self, result_grad) -> tuple:
16
+
17
+ a_data, b_data = self.parent_data
18
+
19
+ a_grad = result_grad @ self._backend.transpose(b_data)
20
+ b_grad = self._backend.transpose(a_data) @ result_grad
21
+
22
+ return (a_grad, b_grad)
@@ -0,0 +1,25 @@
1
+ from ...autograd.operation import Operation
2
+ from typing import TYPE_CHECKING
3
+ if TYPE_CHECKING:
4
+ from ...core.tensor import Tensor
5
+ class Mul(Operation):
6
+ def __init__(self, backend) -> None:
7
+ super().__init__(backend)
8
+ self.parent_data = (0, 0)
9
+
10
+ def forward(self, a, b):
11
+
12
+ self.parent_data = (a, b)
13
+ result = self._backend.mul(a, b)
14
+
15
+ return result
16
+
17
+
18
+ def backward(self, result_grad) -> tuple:
19
+ a_data, b_data = self.parent_data
20
+
21
+ a_grad = b_data * result_grad
22
+ b_grad = a_data * result_grad
23
+
24
+ return (a_grad, b_grad)
25
+
@@ -0,0 +1,26 @@
1
+ from ...autograd.operation import Operation
2
+ class Pow(Operation):
3
+ def __init__(self, backend) -> None:
4
+ super().__init__(backend)
5
+ self.n = 0
6
+ self.parent_data = 0
7
+
8
+ def forward(self, x, n):
9
+
10
+ self.parent_data = x
11
+ self.n = n
12
+
13
+ result = x ** n
14
+
15
+ return result
16
+
17
+
18
+ def backward(self, result_grad) -> list:
19
+ x_data = self.parent_data
20
+ n = self.n
21
+
22
+ x_grad = result_grad * n * x_data**(n - 1)
23
+
24
+ return [x_grad]
25
+
26
+
@@ -0,0 +1,19 @@
1
+ from ...autograd.operation import Operation
2
+ class Sub(Operation):
3
+ def __init__(self, backend) -> None:
4
+ super().__init__(backend)
5
+
6
+ def forward(self, a, b):
7
+
8
+ result = self._backend.sub(a.data, b.data)
9
+
10
+ return result
11
+
12
+
13
+ def backward(self, result_grad) -> tuple:
14
+
15
+ a_grad = result_grad
16
+ b_grad = -result_grad
17
+
18
+ return (a_grad, b_grad)
19
+
@@ -0,0 +1,23 @@
1
+ from abc import ABC, abstractmethod
2
+ from ..backend.backend_manager import BackendManager
3
+
4
+ class Engine(ABC):
5
+ def __init__(self) -> None:
6
+ super().__init__()
7
+ self._backend = BackendManager.get_backend()
8
+
9
+ @abstractmethod
10
+ def _prepare_root_grad():
11
+ pass
12
+
13
+ @abstractmethod
14
+ def _tensor_backward():
15
+ pass
16
+
17
+ @abstractmethod
18
+ def _start_backward_recursion():
19
+ pass
20
+
21
+ @abstractmethod
22
+ def backward():
23
+ pass
@@ -0,0 +1,15 @@
1
+ from __future__ import annotations
2
+ from abc import ABC, abstractmethod
3
+ from ..backend.backend import Backend
4
+ class Operation(ABC):
5
+ def __init__(self, backend: Backend) -> None:
6
+ super().__init__()
7
+ self._backend: Backend = backend
8
+
9
+ @abstractmethod
10
+ def forward(self, a, b):
11
+ pass
12
+
13
+ @abstractmethod
14
+ def backward(self, result_grad) -> tuple:
15
+ pass
@@ -0,0 +1,35 @@
1
+ from .engine import Engine
2
+ from ..core.tensor import Tensor
3
+
4
+ class StandardEngine(Engine):
5
+ def __init__(self) -> None:
6
+ super().__init__()
7
+
8
+ def _prepare_root_grad(self, tensor: Tensor):
9
+ root_grad = self._backend.ones_like(tensor.data)
10
+ return root_grad
11
+
12
+ def _tensor_backward(self, tensor: Tensor, grad):
13
+ if tensor.grad_fn is None:
14
+ return ()
15
+
16
+ parents = tensor.grad_fn[0]
17
+ grads = tensor.grad_fn[1].backward(grad)
18
+
19
+
20
+ return zip(parents, grads)
21
+
22
+ def _start_backward_recursion(self, tensor_backward):
23
+ for parent, parent_grad in tensor_backward:
24
+ if parent.requires_grad:
25
+ parent.grad += parent_grad
26
+
27
+ if parent.grad_fn is not None:
28
+ self.backward(parent, parent.grad)
29
+
30
+ def backward(self, tensor: Tensor, grad=None):
31
+ if grad is None:
32
+ grad = self._prepare_root_grad(tensor)
33
+
34
+ tensor_backward = self._tensor_backward(tensor, grad)
35
+ self._start_backward_recursion(tensor_backward)
@@ -0,0 +1,5 @@
1
+ from .backend_manager import BackendManager
2
+ from .backend import Backend
3
+ from .numpy_backend import numpy_backend
4
+
5
+ __all__ = ["BackendManager", "Backend", "numpy_backend"]
@@ -0,0 +1,85 @@
1
+ from abc import ABC, abstractmethod
2
+ class Backend(ABC):
3
+
4
+ @abstractmethod
5
+ def convert(self, data):
6
+ return data
7
+
8
+ #Binary operations
9
+ @abstractmethod
10
+ def add(self, a, b):
11
+ pass
12
+
13
+ @abstractmethod
14
+ def div(self, a, b):
15
+ pass
16
+
17
+ @abstractmethod
18
+ def mul(self, a, b):
19
+ pass
20
+
21
+ @abstractmethod
22
+ def sub(self, a, b):
23
+ pass
24
+
25
+ #Matrix operations
26
+ @abstractmethod
27
+ def matmul(self, a, b):
28
+ pass
29
+
30
+ @abstractmethod
31
+ def transpose(self, matrix):
32
+ return matrix
33
+
34
+ #Unary operations
35
+ @abstractmethod
36
+ def relu(self, x):
37
+ return x
38
+
39
+ @abstractmethod
40
+ def sigmoid(self, x):
41
+ return x
42
+
43
+ @abstractmethod
44
+ def tanh(self, x):
45
+ return x
46
+
47
+ @abstractmethod
48
+ def softmax(self, x):
49
+ return x
50
+
51
+ @abstractmethod
52
+ def mean(self, array):
53
+ return array
54
+
55
+ @abstractmethod
56
+ def std(self, array):
57
+ return array
58
+
59
+ @abstractmethod
60
+ def abs(self, array):
61
+ return array
62
+
63
+ @abstractmethod
64
+ def zeros_like(self, array):
65
+ return array
66
+
67
+ @abstractmethod
68
+ def ones_like(self, array):
69
+ return array
70
+
71
+ @abstractmethod
72
+ def array_zeros(self, shape):
73
+ return shape
74
+
75
+ @abstractmethod
76
+ def array_ones(self, shape):
77
+ return shape
78
+
79
+ @abstractmethod
80
+ def is_native(self, data) -> bool:
81
+ pass
82
+
83
+
84
+
85
+
@@ -0,0 +1,13 @@
1
+ from .backend import Backend
2
+ from .numpy_backend.numpy_backend import NumpyBackend
3
+ class BackendManager():
4
+ _backend: Backend = NumpyBackend()
5
+
6
+ @staticmethod
7
+ def set_backend(backend_adapter: Backend):
8
+ BackendManager._backend = backend_adapter
9
+
10
+ @staticmethod
11
+ def get_backend() -> Backend:
12
+ return BackendManager._backend
13
+
@@ -0,0 +1,4 @@
1
+ from backend import Backend
2
+
3
+ class CupyBackend(Backend):
4
+ pass
@@ -0,0 +1,72 @@
1
+ from ..backend import Backend
2
+ import numpy as np
3
+
4
+ class NumpyBackend(Backend):
5
+
6
+ def convert(self, data) -> np.ndarray:
7
+ if not self.is_native(data):
8
+ return np.array(data, dtype=np.float32)
9
+
10
+ return data
11
+
12
+ #Binary operations
13
+ def add(self, a, b):
14
+ return np.add(a, b)
15
+
16
+ def div(self, a, b):
17
+ return np.divide(a, b)
18
+
19
+ def mul(self, a, b):
20
+ return np.multiply(a, b)
21
+
22
+ def sub(self, a, b):
23
+ return np.subtract(a, b)
24
+
25
+ #Matrix operations
26
+ def matmul(self, a, b):
27
+ return np.matmul(a, b)
28
+
29
+ def transpose(self, matrix):
30
+ return matrix.T
31
+
32
+ #Unary operations
33
+ def relu(self, x):
34
+ return max(0, x)
35
+
36
+ def sigmoid(self, x):
37
+ pass
38
+
39
+ def tanh(self, x):
40
+ pass
41
+
42
+ def softmax(self, x):
43
+ pass
44
+
45
+ def mean(self, array):
46
+ return np.mean(array)
47
+
48
+ def std(self, array):
49
+ return np.std(array)
50
+
51
+ def abs(self, array):
52
+ return np.abs(array)
53
+
54
+ def zeros_like(self, array):
55
+ return np.zeros_like(array)
56
+
57
+ def ones_like(self, array):
58
+ return np.ones_like(array)
59
+
60
+ def array_zeros(self, shape):
61
+ return np.zeros(shape)
62
+
63
+ def array_ones(self, shape):
64
+ return np.ones(shape)
65
+
66
+ def is_native(self, data) -> bool:
67
+ if type(data) is np.ndarray:
68
+ return True
69
+ else:
70
+ return False
71
+
72
+
@@ -0,0 +1,71 @@
1
+ from __future__ import annotations
2
+ from ..backend.backend_manager import BackendManager
3
+ from ..backend.backend import Backend
4
+ from ..autograd._operations import mul, matmul, sub, div, add, pow
5
+ from typing import Optional
6
+
7
+ class Tensor():
8
+ __slots__ = ['data', 'requires_grad', 'grad', 'grad_fn', 'backend']
9
+
10
+ def __init__(self, data, requires_grad: bool = False):
11
+ self.requires_grad: bool = requires_grad
12
+ self.grad = 0
13
+ self.grad_fn: Optional[list] = None
14
+ self.backend: Backend = BackendManager.get_backend()
15
+ self.data = self.backend.convert(data)
16
+
17
+ def __mul__(self, other):
18
+ mul_op = mul.Mul(self.backend)
19
+ mul_forward = mul_op.forward(self.data, other.data)
20
+
21
+ result = Tensor(mul_forward, requires_grad=self.requires_grad or other.requires_grad)
22
+ result.grad_fn = [[self, other], mul_op]
23
+
24
+ return result
25
+
26
+ def __matmul__(self, other: Tensor):
27
+ mat_mul_op = matmul.Matmul(self.backend)
28
+ mul_forward = mat_mul_op.forward(self.data, other.data)
29
+
30
+ result = Tensor(mul_forward, requires_grad=self.requires_grad or other.requires_grad)
31
+ result.grad_fn = [[self, other], mat_mul_op]
32
+
33
+ return result
34
+
35
+ def __add__(self, other: Tensor):
36
+ add_op = add.Add(self.backend)
37
+ add_forward = add_op.forward(self.data, other.data)
38
+
39
+ result = Tensor(add_forward, requires_grad=self.requires_grad or other.requires_grad)
40
+ result.grad_fn = [[self, other], add_op]
41
+
42
+ return result
43
+
44
+ def __sub__(self, other: Tensor):
45
+ sub_op = sub.Sub(self.backend)
46
+ sub_forward = sub_op.forward(self.data, other.data)
47
+
48
+ result = Tensor(sub_forward, requires_grad=self.requires_grad or other.requires_grad)
49
+ result.grad_fn = [[self, other], sub_op]
50
+
51
+ return result
52
+
53
+ def __truediv__(self, other):
54
+ div_op = div.Div(self.backend)
55
+ div_forward = div_op.forward(self.data, other.data)
56
+
57
+ result = Tensor(div_forward, requires_grad=self.requires_grad or other.requires_grad)
58
+ result.grad_fn = [[self, other], div_op]
59
+
60
+ return result
61
+
62
+ def __pow__(self, other):
63
+ pow_op = pow.Pow(self.backend)
64
+ pow_forward = pow_op.forward(self.data, other)
65
+
66
+ result = Tensor(pow_forward, requires_grad=self.requires_grad or other.requires_grad)
67
+ result.grad_fn = [[self], pow_op]
68
+
69
+ return result
70
+
71
+
@@ -0,0 +1,2 @@
1
+ from .preprocess import preprocessing
2
+ __all__ = ["preprocessing"]
@@ -0,0 +1,22 @@
1
+ from ..._exceptions._errors import DataError
2
+ from ...backend.backend_manager import BackendManager
3
+ class preprocessing():
4
+
5
+ @staticmethod
6
+ def normalize(array, mean=None, std=None):
7
+ backend = BackendManager.get_backend()
8
+ if mean is not None and std is not None:
9
+ arr_mean = mean
10
+ arr_std = std
11
+ elif (mean is None and std is not None) or (mean is not None and std is None):
12
+ raise DataError('one of the normalize components is none, and another is not none')
13
+ else:
14
+ arr_mean = backend.mean(array)
15
+ arr_std = backend.std(array)
16
+ arr_norm = (array-arr_mean)/arr_std
17
+ return arr_norm, arr_mean, arr_std
18
+ @staticmethod
19
+
20
+ def denormalize(normalized, mean, std):
21
+ array = normalized * std + mean
22
+ return array
@@ -0,0 +1,4 @@
1
+ from .std_metrics import metrics
2
+ __all__ = ["metrics"]
3
+
4
+
@@ -0,0 +1,34 @@
1
+ from math import sqrt
2
+ from ..backend.backend_manager import BackendManager
3
+ class metrics():
4
+
5
+ @staticmethod
6
+ def mse(y, y_pred, training=False):
7
+ backend = BackendManager.get_backend()
8
+ y = backend.convert(y)
9
+ y_pred = backend.convert(y_pred)
10
+
11
+ loss = backend.mean((y.flatten()-y_pred.flatten())**2)
12
+ if not training:
13
+ print(f'MSE: {loss}')
14
+ return loss
15
+
16
+ @staticmethod
17
+ def rmse(y, y_pred, training=False):
18
+ y = BackendManager.get_backend().convert(y)
19
+ y_pred = BackendManager.get_backend().convert(y_pred)
20
+
21
+ loss = sqrt(metrics.mse(y, y_pred, training=True))
22
+ if not training:
23
+ print(f'RMSE: {loss}')
24
+ return loss
25
+
26
+ @staticmethod
27
+ def mae(y, y_pred, training=False):
28
+ backend = BackendManager.get_backend()
29
+ mae = backend.mean(backend.abs(y - y_pred))
30
+
31
+ if not training:
32
+ print('MAE:', mae)
33
+
34
+ return mae
File without changes
File without changes
@@ -0,0 +1,14 @@
1
+ from abc import ABC, abstractmethod
2
+
3
+ class Optimizer(ABC):
4
+ def __init__(self, learning_rate=1e-3) -> None:
5
+ super().__init__()
6
+ self.learning_rate = learning_rate
7
+
8
+ @abstractmethod
9
+ def step():
10
+ pass
11
+
12
+ @abstractmethod
13
+ def zero_grad():
14
+ pass
@@ -0,0 +1,13 @@
1
+ from .optimizer import Optimizer
2
+ from ..core.tensor import Tensor
3
+ class SGD(Optimizer):
4
+ def __init__(self, learning_rate=0.001) -> None:
5
+ super().__init__(learning_rate)
6
+
7
+ def step(self, params: list[Tensor]):
8
+ for param in params:
9
+ param.data -= param.grad * self.learning_rate
10
+
11
+ def zero_grad(self, params: list[Tensor]):
12
+ for param in params:
13
+ param.grad = param.backend.zeros_like(param.data)
File without changes
@@ -0,0 +1,2 @@
1
+ from .std_callbacks import callbacks
2
+ __all__ = ["callbacks"]
@@ -0,0 +1,38 @@
1
+ class callbacks():
2
+
3
+ class EarlyStop():
4
+ def __init__(self, patience=10, delta=1e-3):
5
+ self.best_loss = None
6
+ self.delta = delta
7
+ self.patience = patience
8
+ self.wait = 0
9
+ def __call__(self, model, log):
10
+ val_loss = log.get('val_loss')
11
+ if val_loss is None:
12
+ return
13
+
14
+ if self.best_loss is None:
15
+ self.best_loss = val_loss
16
+
17
+ else:
18
+ if val_loss < self.best_loss - self.delta:
19
+ self.best_loss = val_loss
20
+ self.wait = 0
21
+ else:
22
+ self.wait += 1
23
+
24
+ if self.wait >= self.patience:
25
+ model.stop_training = True
26
+ else:
27
+ model.stop_training = False
28
+
29
+ class History():
30
+ def __init__(self):
31
+ self.history = {'epoch': [], 'loss': [], 'val_loss': []}
32
+ def __call__(self, model, log):
33
+ epoch = log.get('epoch')
34
+ loss = log.get('loss')
35
+ val_loss = log.get('val_loss')
36
+ self.history['epoch'].append(epoch)
37
+ self.history['loss'].append(loss)
38
+ self.history['val_loss'].append(val_loss)
File without changes
@@ -0,0 +1,15 @@
1
+ from abc import ABC, abstractmethod
2
+
3
+ class Layer(ABC):
4
+ def __init__(self) -> None:
5
+ super().__init__()
6
+
7
+ @abstractmethod
8
+ def predict():
9
+ pass
10
+
11
+ @abstractmethod
12
+ def params() -> list:
13
+ pass
14
+
15
+
@@ -0,0 +1,17 @@
1
+ from .layer import Layer
2
+ from ...core.tensor import Tensor
3
+ from ...backend.backend_manager import BackendManager
4
+ class Linear(Layer):
5
+ def __init__(self, in_shape, out_shape) -> None:
6
+ super().__init__()
7
+ self._backend = BackendManager.get_backend()
8
+ self.w: Tensor = Tensor(self._backend.array_zeros((in_shape, out_shape)), requires_grad=True)
9
+
10
+ def predict(self, x: Tensor) -> Tensor:
11
+ return x @ self.w
12
+
13
+ @property
14
+ def params(self) -> list[Tensor]:
15
+ return [attr_val\
16
+ for attr_val in self.__dict__.values()\
17
+ if (type(attr_val) is Tensor and attr_val.requires_grad)]
File without changes
@@ -0,0 +1,10 @@
1
+ from ..layers.layer import Layer
2
+ from ...core.tensor import Tensor
3
+ class Sequential:
4
+ def __init__(self, *layers: list[Layer]):
5
+ self.layers: list[Layer] = layers
6
+
7
+ @property
8
+ def params(self):
9
+ for layer in self.layers:
10
+ yield layer.params
@@ -0,0 +1,2 @@
1
+ class Trainer:
2
+ pass
@@ -0,0 +1,54 @@
1
+ Metadata-Version: 2.4
2
+ Name: gradforge
3
+ Version: 2.0.1
4
+ Summary: Machinelearning library
5
+ Author-email: insane-machines <forshnikita2@gmail.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/nikitaforsh/gradforge
8
+ Requires-Python: >=3.11
9
+ Description-Content-Type: text/markdown
10
+ Requires-Dist: numpy
11
+ Requires-Dist: pytest>=9.1.1
12
+ Provides-Extra: cuda
13
+ Requires-Dist: cupy; extra == "cuda"
14
+
15
+ <h1 align="center">
16
+ <img src="https://github.com/insane-machines/fsh/blob/main/fsh/fsh.egg-info/logo.jpg"></img>
17
+ </h1>
18
+ <h1 align="center">
19
+ <img src="https://readme-typing-svg.herokuapp.com?font=Fira+Code&pause=1000&color=00FFAA&center=true&vCenter=true&width=500&lines=Hi,+I'm+nikitaforsh!;Welcome+to++our+machinelearning+library;named+GradForge!" alt="Typing SVG" />
20
+ </h1>
21
+
22
+ <p align="center">
23
+ <a href="https://t.me/insane_machines" target="_blank">
24
+ <img src="https://img.shields.io/badge/Insane%20Machines-Telegram-blue?style=for-the-badge&logo=telegram" alt="Telegram link" />
25
+ </a>
26
+ </p>
27
+ Features
28
+
29
+ Linear model with:
30
+ • **Callbacks**
31
+ • **Metrics**
32
+ • **Preprocessing functions**
33
+ • **Simple integration**
34
+
35
+ ---
36
+
37
+ Quick Start
38
+
39
+ ```python
40
+ import fsh
41
+
42
+ X = [[1, 2], [3, 4]]
43
+ y = [[5], [6]]
44
+
45
+ #array converting is integrated! but you can do it yourself!
46
+ X = fsh.fsh.preprocessing.to_array(X)
47
+ y = fsh.fsh.preprocessing.to_array(y)
48
+
49
+ callback = fsh.fsh.callbacks.History()
50
+ model = fsh.fsh.Linear(n_features=2, lr=0.01)
51
+
52
+ # Training
53
+ model.train(X, y, epochs=100, callbacks=[callback], loss_fn=fsh.fsh.metrics.mse)
54
+ model.predict(X)
@@ -0,0 +1,42 @@
1
+ gradforge/_exceptions/__init__.py,sha256=LtRrFhT5HtNY26bJ6nLUEehTv-OWoC4SiPxOQ3P18_s,116
2
+ gradforge/_exceptions/_errors.py,sha256=KsMfZqaMmgk1lYLzhMOsRPvsxg0ol9iaH_Su1_6X4_M,121
3
+ gradforge/_tests/profiling_stats.py,sha256=Xv1BDXfRDWnHh0cqIlJqXRV9UYoXImpetGIUvTq1em4,102
4
+ gradforge/_tests/test_linear.py,sha256=Z3rMx4ba9XSbJxxbdJG3VDRPptTQtQNffEMJlXvw2LY,1276
5
+ gradforge/_tests/test_operation.py,sha256=StwDlxEizx8FfX70kTo9eOnHbwG87ykMpwYsIDmOObY,294
6
+ gradforge/autograd/__init__.py,sha256=F98aOrZZmLxzVZeR51XnIMGidAv72y-YT-5jXuldBQw,56
7
+ gradforge/autograd/engine.py,sha256=3iFUx0FAe-ygV6NTh5eXWifPouiG6lGSwZ71Oe0KAPU,475
8
+ gradforge/autograd/operation.py,sha256=nd2y9OofeLYlhA6_j11cLm8Va9vXY6UhegKZbPiFRNU,394
9
+ gradforge/autograd/standard_engine.py,sha256=nFchbdkcSYkkEW0xzyVCsaVakBOLkiBbB7CxOolOcQE,1068
10
+ gradforge/autograd/_operations/add.py,sha256=1bNpCs7aQSlAnDdj1-7VhkpFWRs4dtHrmt6x8lRTFs8,406
11
+ gradforge/autograd/_operations/div.py,sha256=EZ2IkIKe6wv5GNSwkDSJx_oXtH-80qfgIfEX2Jj6NTs,589
12
+ gradforge/autograd/_operations/matmul.py,sha256=TOz-yX0rMYR27B8TkPI_rpXk5y8Q-aG1g_wQ-T-whWo,579
13
+ gradforge/autograd/_operations/mul.py,sha256=yZz9cW3PU-XjcUkVl_IGsXkssTSH6CZJUE3dCOk1iG8,606
14
+ gradforge/autograd/_operations/pow.py,sha256=zY4FFDKWBri7hp7lxWKFxUkpHt3SIKy2Ohbn23IA8i8,515
15
+ gradforge/autograd/_operations/sub.py,sha256=n543ZqspB99EB3YP6ccHFrMFT8VOK3v0-5oxEnWj9tA,408
16
+ gradforge/backend/__init__.py,sha256=pkTWhqZ7U9fLeUIa36vEdUKkoPA79D4hJno8xC9g5ro,171
17
+ gradforge/backend/backend.py,sha256=_Z6Tkx-_9ModqJyl0uEuJxrbwcbT7DMH8thhcHoym9c,1404
18
+ gradforge/backend/backend_manager.py,sha256=_IO9Pp8MHyWQ-7WpXxbMI524oLceX8dw8RfMbR6ed0U,362
19
+ gradforge/backend/cupy_backend/cuda_backend.py,sha256=SKwM4W96FvmBVp5665DtlNWtmiBI0BHEdjXpycwV6TY,65
20
+ gradforge/backend/numpy_backend/numpy_backend.py,sha256=zpSvBVqi8w5fEbF-9C7umSV5h_I32MJsnqg2WO_CaUc,1407
21
+ gradforge/core/tensor.py,sha256=wLkhUvlSTFDPT6xlq7Kha-tYrQFYIeIHpEkXk8IjqY0,2496
22
+ gradforge/data/preprocessing/__init__.py,sha256=gBoGfS38ZaSRBpgdYFayKEhiNIkzQiKIM26HgPqtaAg,65
23
+ gradforge/data/preprocessing/preprocess.py,sha256=scp38nnvgkZyQeT2SMQuhRReaZns0Xk2DQblPTBYGI0,860
24
+ gradforge/metrics/__init__.py,sha256=GqFRSHuvlP-5feyRqZzMPWR_DbEFiGiTlJ3kBepbpg4,61
25
+ gradforge/metrics/std_metrics.py,sha256=G6qqrvql415LfG_Fzmgz1OwDVonk70uDY16HIPvpY1c,1016
26
+ gradforge/optimizers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
27
+ gradforge/optimizers/adam.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
28
+ gradforge/optimizers/optimizer.py,sha256=ceuydMqwgOvSUWPGNMcPCOlo-QigO0hvfatAqEU0nnA,298
29
+ gradforge/optimizers/sgd.py,sha256=Oazimj6oBrNc1YiOA4nqk1XRoOh6f8CYvaoqYFgXi_A,452
30
+ gradforge/training/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
31
+ gradforge/training/trainer.py,sha256=7glIrU3FZJXDViB8TRoSiUblmmu8pF4kPVJTnvB_9Ls,23
32
+ gradforge/training/callbacks/__init__.py,sha256=8jUNKZaX0RRYCFYaa3knWpxa6OjcfTW8V401ClXY1QE,60
33
+ gradforge/training/callbacks/std_callbacks.py,sha256=S-XxqVT31wQQwlziyuZe-QhcKxS0knqrqRATOp-5vKg,1283
34
+ gradforge/training/layers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
35
+ gradforge/training/layers/layer.py,sha256=xXo3u8vmIydFddHwlE-aUwkWc3V9JKUYSr5GigDMnYo,232
36
+ gradforge/training/layers/linear.py,sha256=QIqmlrZ0qc1V5EGm2IsdvUlNsBr6NfshniXrPb09RbU,674
37
+ gradforge/training/models/model.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
38
+ gradforge/training/models/sequential.py,sha256=vmIyMMriQMPnO3TRPkfwI4RmEIyX3d8WWMyYZXb5aUA,278
39
+ gradforge-2.0.1.dist-info/METADATA,sha256=KhOf7goGlV5FD1pxp2oZ5alNWSrNsuOeLYYEyUJBqEg,1529
40
+ gradforge-2.0.1.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
41
+ gradforge-2.0.1.dist-info/top_level.txt,sha256=TPldOw70ltnRhalaxduzn67NgsiDip_VRbLqiscrUlI,10
42
+ gradforge-2.0.1.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (84.0.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1 @@
1
+ gradforge