pyzapo 1.0.0__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.
- pyzapo-1.0.0/PKG-INFO +76 -0
- pyzapo-1.0.0/README.md +64 -0
- pyzapo-1.0.0/pyproject.toml +25 -0
- pyzapo-1.0.0/pyzapo/__init__.py +4 -0
- pyzapo-1.0.0/pyzapo/layers.py +145 -0
- pyzapo-1.0.0/pyzapo/losses.py +32 -0
- pyzapo-1.0.0/pyzapo.egg-info/PKG-INFO +76 -0
- pyzapo-1.0.0/pyzapo.egg-info/SOURCES.txt +10 -0
- pyzapo-1.0.0/pyzapo.egg-info/dependency_links.txt +1 -0
- pyzapo-1.0.0/pyzapo.egg-info/requires.txt +1 -0
- pyzapo-1.0.0/pyzapo.egg-info/top_level.txt +1 -0
- pyzapo-1.0.0/setup.cfg +4 -0
pyzapo-1.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pyzapo
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Модульный ООП фреймворк для глубокого обучения на чистом NumPy в стиле PyTorch с оптимизатором Adam
|
|
5
|
+
Author-email: wiffy <melnikarthur280912@gmail.com>
|
|
6
|
+
Classifier: Programming Language :: Python :: 3
|
|
7
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
8
|
+
Classifier: Operating System :: OS Independent
|
|
9
|
+
Requires-Python: >=3.8
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
Requires-Dist: numpy>=1.20.0
|
|
12
|
+
|
|
13
|
+
# PyZapo 🚀
|
|
14
|
+
|
|
15
|
+
**PyZapo** is a lightweight, object-oriented Deep Learning framework written completely from scratch using **pure NumPy** (without PyTorch) [ML / AI Engineering: PyTorch].
|
|
16
|
+
|
|
17
|
+
It features an in-built adaptive **Adam optimizer** right inside the layers, making neural network training fast, clean, and highly efficient without any extra boilerplate code [ML / AI Engineering: PyTorch].
|
|
18
|
+
|
|
19
|
+
## Features ✨
|
|
20
|
+
* **PyTorch-Style Syntax:** Built-in `__call__` allows you to invoke models and layers like functions (`model(X)`) [ML / AI Engineering: PyTorch].
|
|
21
|
+
* **OOP Architecture:** Inherit from `Module` to build complex custom neural networks [ML / AI Engineering: PyTorch].
|
|
22
|
+
* **Built-in Adam Optimizer:** Adaptive learning rate for each weight out of the box.
|
|
23
|
+
* **Modern Activations:** High-performance `ReLU` and `Sigmoid` layers.
|
|
24
|
+
* **Loss Functions:** `MSELoss` and binary cross-entropy (`BCELoss`) with clipping safety.
|
|
25
|
+
* **Weights Management:** Save and load your trained models instantly with `.npz` binary files.
|
|
26
|
+
|
|
27
|
+
## Installation 📦
|
|
28
|
+
```bash
|
|
29
|
+
pip install pyzapo
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Quick Start 💻
|
|
33
|
+
```python
|
|
34
|
+
import numpy as np
|
|
35
|
+
import pyzapo as pz
|
|
36
|
+
|
|
37
|
+
# 1. Define your custom architecture
|
|
38
|
+
class MyCoolAi(pz.Module):
|
|
39
|
+
def __init__(self):
|
|
40
|
+
super().__init__()
|
|
41
|
+
self.fc1 = pz.Linear(2, 8)
|
|
42
|
+
self.relu = pz.ReLU()
|
|
43
|
+
self.fc2 = pz.Linear(8, 1)
|
|
44
|
+
self.sigmoid = pz.Sigmoid()
|
|
45
|
+
|
|
46
|
+
def forward(self, x):
|
|
47
|
+
out = self.fc1(x)
|
|
48
|
+
out = self.relu(out)
|
|
49
|
+
out = self.fc2(out)
|
|
50
|
+
out = self.sigmoid(out)
|
|
51
|
+
return out
|
|
52
|
+
|
|
53
|
+
def backward(self, loss_gradient):
|
|
54
|
+
delta = self.sigmoid.backward(loss_gradient)
|
|
55
|
+
delta = self.fc2.backward(delta)
|
|
56
|
+
delta = self.relu.backward(delta)
|
|
57
|
+
delta = self.fc1.backward(delta)
|
|
58
|
+
return delta
|
|
59
|
+
|
|
60
|
+
# 2. Train and Save
|
|
61
|
+
X = np.array([[5.0, 1.0], [1.0, 50.0]])
|
|
62
|
+
y = np.array([[1.0], [0.0]])
|
|
63
|
+
|
|
64
|
+
model = MyCoolAi()
|
|
65
|
+
criterion = pz.BCELoss()
|
|
66
|
+
|
|
67
|
+
for epoch in range(1000):
|
|
68
|
+
pred = model(X)
|
|
69
|
+
loss = criterion(pred, y)
|
|
70
|
+
|
|
71
|
+
loss_grad = criterion.backward()
|
|
72
|
+
model.backward(loss_grad)
|
|
73
|
+
model.step(lr=0.01)
|
|
74
|
+
|
|
75
|
+
model.save_weights("my_model.npz")
|
|
76
|
+
```
|
pyzapo-1.0.0/README.md
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# PyZapo 🚀
|
|
2
|
+
|
|
3
|
+
**PyZapo** is a lightweight, object-oriented Deep Learning framework written completely from scratch using **pure NumPy** (without PyTorch) [ML / AI Engineering: PyTorch].
|
|
4
|
+
|
|
5
|
+
It features an in-built adaptive **Adam optimizer** right inside the layers, making neural network training fast, clean, and highly efficient without any extra boilerplate code [ML / AI Engineering: PyTorch].
|
|
6
|
+
|
|
7
|
+
## Features ✨
|
|
8
|
+
* **PyTorch-Style Syntax:** Built-in `__call__` allows you to invoke models and layers like functions (`model(X)`) [ML / AI Engineering: PyTorch].
|
|
9
|
+
* **OOP Architecture:** Inherit from `Module` to build complex custom neural networks [ML / AI Engineering: PyTorch].
|
|
10
|
+
* **Built-in Adam Optimizer:** Adaptive learning rate for each weight out of the box.
|
|
11
|
+
* **Modern Activations:** High-performance `ReLU` and `Sigmoid` layers.
|
|
12
|
+
* **Loss Functions:** `MSELoss` and binary cross-entropy (`BCELoss`) with clipping safety.
|
|
13
|
+
* **Weights Management:** Save and load your trained models instantly with `.npz` binary files.
|
|
14
|
+
|
|
15
|
+
## Installation 📦
|
|
16
|
+
```bash
|
|
17
|
+
pip install pyzapo
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Quick Start 💻
|
|
21
|
+
```python
|
|
22
|
+
import numpy as np
|
|
23
|
+
import pyzapo as pz
|
|
24
|
+
|
|
25
|
+
# 1. Define your custom architecture
|
|
26
|
+
class MyCoolAi(pz.Module):
|
|
27
|
+
def __init__(self):
|
|
28
|
+
super().__init__()
|
|
29
|
+
self.fc1 = pz.Linear(2, 8)
|
|
30
|
+
self.relu = pz.ReLU()
|
|
31
|
+
self.fc2 = pz.Linear(8, 1)
|
|
32
|
+
self.sigmoid = pz.Sigmoid()
|
|
33
|
+
|
|
34
|
+
def forward(self, x):
|
|
35
|
+
out = self.fc1(x)
|
|
36
|
+
out = self.relu(out)
|
|
37
|
+
out = self.fc2(out)
|
|
38
|
+
out = self.sigmoid(out)
|
|
39
|
+
return out
|
|
40
|
+
|
|
41
|
+
def backward(self, loss_gradient):
|
|
42
|
+
delta = self.sigmoid.backward(loss_gradient)
|
|
43
|
+
delta = self.fc2.backward(delta)
|
|
44
|
+
delta = self.relu.backward(delta)
|
|
45
|
+
delta = self.fc1.backward(delta)
|
|
46
|
+
return delta
|
|
47
|
+
|
|
48
|
+
# 2. Train and Save
|
|
49
|
+
X = np.array([[5.0, 1.0], [1.0, 50.0]])
|
|
50
|
+
y = np.array([[1.0], [0.0]])
|
|
51
|
+
|
|
52
|
+
model = MyCoolAi()
|
|
53
|
+
criterion = pz.BCELoss()
|
|
54
|
+
|
|
55
|
+
for epoch in range(1000):
|
|
56
|
+
pred = model(X)
|
|
57
|
+
loss = criterion(pred, y)
|
|
58
|
+
|
|
59
|
+
loss_grad = criterion.backward()
|
|
60
|
+
model.backward(loss_grad)
|
|
61
|
+
model.step(lr=0.01)
|
|
62
|
+
|
|
63
|
+
model.save_weights("my_model.npz")
|
|
64
|
+
```
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "pyzapo"
|
|
7
|
+
version = "1.0.0" # Наша первая официальная версия!
|
|
8
|
+
authors = [
|
|
9
|
+
{ name="wiffy", email="melnikarthur280912@gmail.com" },
|
|
10
|
+
]
|
|
11
|
+
description = "Модульный ООП фреймворк для глубокого обучения на чистом NumPy в стиле PyTorch с оптимизатором Adam"
|
|
12
|
+
readme = "README.md"
|
|
13
|
+
requires-python = ">=3.8"
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Programming Language :: Python :: 3",
|
|
16
|
+
"License :: OSI Approved :: MIT License",
|
|
17
|
+
"Operating System :: OS Independent",
|
|
18
|
+
]
|
|
19
|
+
dependencies = [
|
|
20
|
+
"numpy>=1.20.0",
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
[tool.setuptools.packages.find]
|
|
24
|
+
where = ["."]
|
|
25
|
+
include = ["pyzapo*"]
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
class Linear:
|
|
4
|
+
def __init__(self, in_features, out_features):
|
|
5
|
+
self.W = np.random.randn(in_features, out_features) * 0.1
|
|
6
|
+
self.b = np.zeros((1, out_features))
|
|
7
|
+
|
|
8
|
+
self.m_W, self.m_b = np.zeros_like(self.W), np.zeros_like(self.b)
|
|
9
|
+
self.v_W, self.v_b = np.zeros_like(self.W), np.zeros_like(self.b)
|
|
10
|
+
self.t = 0
|
|
11
|
+
|
|
12
|
+
def forward(self, x):
|
|
13
|
+
self.x = x
|
|
14
|
+
|
|
15
|
+
return np.dot(x, self.W) + self.b
|
|
16
|
+
|
|
17
|
+
def backward(self, delta):
|
|
18
|
+
self.dW = np.dot(self.x.T, delta)
|
|
19
|
+
self.db = np.sum(delta, axis=0, keepdims=True)
|
|
20
|
+
|
|
21
|
+
next_delta = np.dot(delta, self.W.T)
|
|
22
|
+
|
|
23
|
+
return next_delta
|
|
24
|
+
|
|
25
|
+
def step(self, lr, beta1=0.9, beta2=0.999, eps=1e-8):
|
|
26
|
+
self.t += 1
|
|
27
|
+
|
|
28
|
+
self.m_W = beta1 * self.m_W + (1 - beta1) * self.dW
|
|
29
|
+
self.m_b = beta1 * self.m_b + (1 - beta1) * self.db
|
|
30
|
+
|
|
31
|
+
self.v_W = beta2 * self.v_W + (1 - beta2) * (self.dW ** 2)
|
|
32
|
+
self.v_b = beta2 * self.v_b + (1 - beta2) * (self.db ** 2)
|
|
33
|
+
|
|
34
|
+
m_W_corrected = self.m_W / (1 - beta1 ** self.t)
|
|
35
|
+
m_b_corrected = self.m_b / (1 - beta1 ** self.t)
|
|
36
|
+
v_W_corrected = self.v_W / (1 - beta2 ** self.t)
|
|
37
|
+
v_b_corrected = self.v_b / (1 - beta2 ** self.t)
|
|
38
|
+
|
|
39
|
+
self.W -= lr * m_W_corrected / (np.sqrt(v_W_corrected) + eps)
|
|
40
|
+
self.b -= lr * m_b_corrected / (np.sqrt(v_b_corrected) + eps)
|
|
41
|
+
|
|
42
|
+
def __call__(self, x):
|
|
43
|
+
return self.forward(x)
|
|
44
|
+
|
|
45
|
+
class Sigmoid:
|
|
46
|
+
def forward(self, x):
|
|
47
|
+
self.y_pred = 1 / (1 + np.exp(-x))
|
|
48
|
+
|
|
49
|
+
return self.y_pred
|
|
50
|
+
|
|
51
|
+
def backward(self, delta):
|
|
52
|
+
return delta * (self.y_pred * (1 - self.y_pred))
|
|
53
|
+
|
|
54
|
+
def __call__(self, x):
|
|
55
|
+
return self.forward(x)
|
|
56
|
+
|
|
57
|
+
class Sequential:
|
|
58
|
+
def __init__(self, layers_list):
|
|
59
|
+
self.layers = layers_list
|
|
60
|
+
|
|
61
|
+
def forward(self, x):
|
|
62
|
+
out = x
|
|
63
|
+
for layer in self.layers:
|
|
64
|
+
out = layer.forward(out)
|
|
65
|
+
|
|
66
|
+
return out
|
|
67
|
+
|
|
68
|
+
def backward(self, loss_gradient):
|
|
69
|
+
delta = loss_gradient
|
|
70
|
+
for layer in reversed(self.layers):
|
|
71
|
+
delta = layer.backward(delta)
|
|
72
|
+
|
|
73
|
+
return delta
|
|
74
|
+
|
|
75
|
+
def step(self, lr):
|
|
76
|
+
for layer in self.layers:
|
|
77
|
+
if hasattr(layer, 'step'):
|
|
78
|
+
layer.step(lr)
|
|
79
|
+
|
|
80
|
+
def save_weight(self, filepath: str):
|
|
81
|
+
weight_dict = {}
|
|
82
|
+
for idx, layer in enumerate(self.layers):
|
|
83
|
+
if hasattr(layer, 'W'):
|
|
84
|
+
weight_dict[f'layer_{idx}_W'] = layer.W
|
|
85
|
+
weight_dict[f'layer_{idx}_b'] = layer.b
|
|
86
|
+
|
|
87
|
+
np.savez(filepath, **weight_dict)
|
|
88
|
+
|
|
89
|
+
def load_weight(self, filepath: str):
|
|
90
|
+
try:
|
|
91
|
+
data = np.load(filepath)
|
|
92
|
+
for idx, layer in enumerate(self.layers):
|
|
93
|
+
if hasattr(layer, 'W'):
|
|
94
|
+
w_key = f'layer_{idx}_W'
|
|
95
|
+
b_key = f'layer_{idx}_b'
|
|
96
|
+
|
|
97
|
+
if w_key in data and b_key in data:
|
|
98
|
+
layer.W = data[w_key]
|
|
99
|
+
layer.b = data[b_key]
|
|
100
|
+
|
|
101
|
+
except FileNotFoundError:
|
|
102
|
+
print(f"❌ Файл {filepath} не найден! Проверь путь.")
|
|
103
|
+
|
|
104
|
+
class ReLU:
|
|
105
|
+
def forward(self, x):
|
|
106
|
+
self.x = x
|
|
107
|
+
|
|
108
|
+
return np.maximum(0, x)
|
|
109
|
+
|
|
110
|
+
def backward(self, delta):
|
|
111
|
+
return delta * (self.x > 0)
|
|
112
|
+
|
|
113
|
+
def __call__(self, x):
|
|
114
|
+
return self.forward(x)
|
|
115
|
+
|
|
116
|
+
class Module:
|
|
117
|
+
def __init__(self):
|
|
118
|
+
pass
|
|
119
|
+
|
|
120
|
+
def __call__(self, x):
|
|
121
|
+
return self.forward(x)
|
|
122
|
+
|
|
123
|
+
def step(self, lr):
|
|
124
|
+
for attr in vars(self).values():
|
|
125
|
+
if hasattr(attr, 'step'):
|
|
126
|
+
attr.step(lr)
|
|
127
|
+
|
|
128
|
+
def save_weights(self, filepath: str):
|
|
129
|
+
weights_dict = {}
|
|
130
|
+
for name, attr in vars(self).items():
|
|
131
|
+
if hasattr(attr, 'W'):
|
|
132
|
+
weights_dict[f"{name}_W"] = attr.W
|
|
133
|
+
weights_dict[f"{name}_b"] = attr.b
|
|
134
|
+
np.savez(filepath, **weights_dict)
|
|
135
|
+
|
|
136
|
+
def load_weights(self, filepath: str):
|
|
137
|
+
try:
|
|
138
|
+
data = np.load(filepath)
|
|
139
|
+
for name, attr in vars(self).items():
|
|
140
|
+
if hasattr(attr, 'W'):
|
|
141
|
+
if f"{name}_W" in data and f"{name}_b" in data:
|
|
142
|
+
attr.W = data[f"{name}_W"]
|
|
143
|
+
attr.b = data[f"{name}_b"]
|
|
144
|
+
except FileNotFoundError:
|
|
145
|
+
print(f"❌ Файл {filepath} не найден!")
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
class MSELoss:
|
|
4
|
+
def forward(self, y_pred, y_true):
|
|
5
|
+
self.y_pred = y_pred
|
|
6
|
+
self.y_true = y_true
|
|
7
|
+
|
|
8
|
+
return np.mean((y_pred - y_true) ** 2)
|
|
9
|
+
|
|
10
|
+
def backward(self):
|
|
11
|
+
return self.y_pred - self.y_true
|
|
12
|
+
|
|
13
|
+
def __call__(self, y_pred, y_true):
|
|
14
|
+
return self.forward(y_pred, y_true)
|
|
15
|
+
|
|
16
|
+
class BCELoss:
|
|
17
|
+
def forward(self, y_pred, y_true):
|
|
18
|
+
y_pred = np.clip(y_pred, 1e-15, 1 - 1e-15)
|
|
19
|
+
loss = -np.mean(y_true * np.log(y_pred) + (1 - y_true) * np.log(1 - y_pred))
|
|
20
|
+
|
|
21
|
+
self.y_pred = y_pred
|
|
22
|
+
self.y_true = y_true
|
|
23
|
+
|
|
24
|
+
return np.mean(loss)
|
|
25
|
+
|
|
26
|
+
def backward(self):
|
|
27
|
+
grad = (self.y_pred - self.y_true) / (self.y_pred * (1 - self.y_pred)) / len(self.y_true)
|
|
28
|
+
|
|
29
|
+
return grad
|
|
30
|
+
|
|
31
|
+
def __call__(self, y_pred, y_true):
|
|
32
|
+
return self.forward(y_pred, y_true)
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pyzapo
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Модульный ООП фреймворк для глубокого обучения на чистом NumPy в стиле PyTorch с оптимизатором Adam
|
|
5
|
+
Author-email: wiffy <melnikarthur280912@gmail.com>
|
|
6
|
+
Classifier: Programming Language :: Python :: 3
|
|
7
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
8
|
+
Classifier: Operating System :: OS Independent
|
|
9
|
+
Requires-Python: >=3.8
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
Requires-Dist: numpy>=1.20.0
|
|
12
|
+
|
|
13
|
+
# PyZapo 🚀
|
|
14
|
+
|
|
15
|
+
**PyZapo** is a lightweight, object-oriented Deep Learning framework written completely from scratch using **pure NumPy** (without PyTorch) [ML / AI Engineering: PyTorch].
|
|
16
|
+
|
|
17
|
+
It features an in-built adaptive **Adam optimizer** right inside the layers, making neural network training fast, clean, and highly efficient without any extra boilerplate code [ML / AI Engineering: PyTorch].
|
|
18
|
+
|
|
19
|
+
## Features ✨
|
|
20
|
+
* **PyTorch-Style Syntax:** Built-in `__call__` allows you to invoke models and layers like functions (`model(X)`) [ML / AI Engineering: PyTorch].
|
|
21
|
+
* **OOP Architecture:** Inherit from `Module` to build complex custom neural networks [ML / AI Engineering: PyTorch].
|
|
22
|
+
* **Built-in Adam Optimizer:** Adaptive learning rate for each weight out of the box.
|
|
23
|
+
* **Modern Activations:** High-performance `ReLU` and `Sigmoid` layers.
|
|
24
|
+
* **Loss Functions:** `MSELoss` and binary cross-entropy (`BCELoss`) with clipping safety.
|
|
25
|
+
* **Weights Management:** Save and load your trained models instantly with `.npz` binary files.
|
|
26
|
+
|
|
27
|
+
## Installation 📦
|
|
28
|
+
```bash
|
|
29
|
+
pip install pyzapo
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Quick Start 💻
|
|
33
|
+
```python
|
|
34
|
+
import numpy as np
|
|
35
|
+
import pyzapo as pz
|
|
36
|
+
|
|
37
|
+
# 1. Define your custom architecture
|
|
38
|
+
class MyCoolAi(pz.Module):
|
|
39
|
+
def __init__(self):
|
|
40
|
+
super().__init__()
|
|
41
|
+
self.fc1 = pz.Linear(2, 8)
|
|
42
|
+
self.relu = pz.ReLU()
|
|
43
|
+
self.fc2 = pz.Linear(8, 1)
|
|
44
|
+
self.sigmoid = pz.Sigmoid()
|
|
45
|
+
|
|
46
|
+
def forward(self, x):
|
|
47
|
+
out = self.fc1(x)
|
|
48
|
+
out = self.relu(out)
|
|
49
|
+
out = self.fc2(out)
|
|
50
|
+
out = self.sigmoid(out)
|
|
51
|
+
return out
|
|
52
|
+
|
|
53
|
+
def backward(self, loss_gradient):
|
|
54
|
+
delta = self.sigmoid.backward(loss_gradient)
|
|
55
|
+
delta = self.fc2.backward(delta)
|
|
56
|
+
delta = self.relu.backward(delta)
|
|
57
|
+
delta = self.fc1.backward(delta)
|
|
58
|
+
return delta
|
|
59
|
+
|
|
60
|
+
# 2. Train and Save
|
|
61
|
+
X = np.array([[5.0, 1.0], [1.0, 50.0]])
|
|
62
|
+
y = np.array([[1.0], [0.0]])
|
|
63
|
+
|
|
64
|
+
model = MyCoolAi()
|
|
65
|
+
criterion = pz.BCELoss()
|
|
66
|
+
|
|
67
|
+
for epoch in range(1000):
|
|
68
|
+
pred = model(X)
|
|
69
|
+
loss = criterion(pred, y)
|
|
70
|
+
|
|
71
|
+
loss_grad = criterion.backward()
|
|
72
|
+
model.backward(loss_grad)
|
|
73
|
+
model.step(lr=0.01)
|
|
74
|
+
|
|
75
|
+
model.save_weights("my_model.npz")
|
|
76
|
+
```
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
numpy>=1.20.0
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
pyzapo
|
pyzapo-1.0.0/setup.cfg
ADDED