froog 0.3.2__tar.gz → 0.4.2__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.
- {froog-0.3.2 → froog-0.4.2}/PKG-INFO +23 -94
- {froog-0.3.2 → froog-0.4.2}/README.md +21 -88
- {froog-0.3.2 → froog-0.4.2}/froog/ops.py +74 -0
- {froog-0.3.2 → froog-0.4.2}/froog/ops_gpu.py +114 -10
- {froog-0.3.2 → froog-0.4.2}/froog/optim.py +1 -1
- {froog-0.3.2 → froog-0.4.2}/froog.egg-info/PKG-INFO +23 -94
- {froog-0.3.2 → froog-0.4.2}/froog.egg-info/SOURCES.txt +0 -1
- {froog-0.3.2 → froog-0.4.2}/froog.egg-info/requires.txt +0 -1
- {froog-0.3.2 → froog-0.4.2}/setup.py +3 -4
- {froog-0.3.2 → froog-0.4.2}/tests/test_models.py +1 -1
- froog-0.3.2/froog/nn.py +0 -60
- {froog-0.3.2 → froog-0.4.2}/LICENSE +0 -0
- {froog-0.3.2 → froog-0.4.2}/froog/__init__.py +0 -0
- {froog-0.3.2 → froog-0.4.2}/froog/gradcheck.py +0 -0
- {froog-0.3.2 → froog-0.4.2}/froog/tensor.py +0 -0
- {froog-0.3.2 → froog-0.4.2}/froog/utils.py +0 -0
- {froog-0.3.2 → froog-0.4.2}/froog.egg-info/dependency_links.txt +0 -0
- {froog-0.3.2 → froog-0.4.2}/froog.egg-info/top_level.txt +0 -0
- {froog-0.3.2 → froog-0.4.2}/setup.cfg +0 -0
- {froog-0.3.2 → froog-0.4.2}/tests/test_conv_speed.py +0 -0
- {froog-0.3.2 → froog-0.4.2}/tests/test_ops.py +0 -0
- {froog-0.3.2 → froog-0.4.2}/tests/test_optim.py +0 -0
- {froog-0.3.2 → froog-0.4.2}/tests/test_tensor.py +0 -0
@@ -1,7 +1,7 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: froog
|
3
|
-
Version: 0.
|
4
|
-
Summary: a
|
3
|
+
Version: 0.4.2
|
4
|
+
Summary: a toy tensor library with opencl support
|
5
5
|
Author: Kevin Buhler
|
6
6
|
License: MIT
|
7
7
|
Classifier: Programming Language :: Python :: 3
|
@@ -9,10 +9,6 @@ Classifier: License :: OSI Approved :: MIT License
|
|
9
9
|
Requires-Python: >=3.8
|
10
10
|
Description-Content-Type: text/markdown
|
11
11
|
License-File: LICENSE
|
12
|
-
Requires-Dist: numpy
|
13
|
-
Requires-Dist: requests
|
14
|
-
Requires-Dist: matplotlib
|
15
|
-
Requires-Dist: urllib
|
16
12
|
|
17
13
|
# froog <img src="https://github.com/kevbuh/froog/actions/workflows/test.yml/badge.svg" alt="unit test badge" > <img src="https://static.pepy.tech/badge/froog" alt="num downloads badge">
|
18
14
|
<div align="center" >
|
@@ -27,9 +23,10 @@ Requires-Dist: urllib
|
|
27
23
|
<br/>
|
28
24
|
</div>
|
29
25
|
|
30
|
-
```froog``` is an easy-to-read tensor library (<a href="https://www.pepy.tech/projects/froog">
|
26
|
+
```froog``` is an easy-to-read tensor library (<a href="https://www.pepy.tech/projects/froog">25k pip installs!</a>) with OpenCL support for GPU acceleration. Inspired by pytorch, tinygrad, and micrograd.
|
31
27
|
|
32
|
-
|
28
|
+
|
29
|
+
<!-- ```froog``` encapsulates everything from <a href="https://github.com/kevbuh/froog/blob/main/models/linear_regression.py">linear regression</a> to <a href="https://github.com/kevbuh/froog/blob/main/models/efficientnet.py">convolutional neural networks </a> in under 2000 lines. -->
|
33
30
|
|
34
31
|
# Installation
|
35
32
|
```bash
|
@@ -85,7 +82,7 @@ from froog.tensor import Tensor
|
|
85
82
|
my_tensor = Tensor([1,2,3])
|
86
83
|
```
|
87
84
|
|
88
|
-
Notice how we had to import
|
85
|
+
Notice how we had to import NumPy. If you want to create a Tensor manually, make sure that it is a NumPy array!
|
89
86
|
|
90
87
|
<!-- Learn more about ```froog``` Tensors <a href="https://github.com/kevbuh/froog/blob/main/docs/tensors.md">here</a>. -->
|
91
88
|
|
@@ -95,13 +92,10 @@ Tensors are the fundamental datatype in froog, and one of the two main classes.
|
|
95
92
|
|
96
93
|
- ```def __init__(self, data)```:
|
97
94
|
|
98
|
-
- Tensor takes in one param, which is the data. Since froog has a
|
99
|
-
|
95
|
+
- Tensor takes in one param, which is the data. Since ```froog``` has a NumPy backend, the input data into tensors has to be a NumPy array.
|
100
96
|
- Tensor has a ```self.data``` state that it holds. this contains the data inside of the tensor.
|
101
|
-
|
102
97
|
- In addition, it has ```self.grad```. this is to hold what the gradients of the tensor is.
|
103
|
-
|
104
|
-
- Lastly, it has ```self._ctx```. theser are the internal vairables used for autograd graph construction. put more simply, this is where the backward gradient computations are saved.
|
98
|
+
- Lastly, it has ```self._ctx```. These are the internal variables used for autograd graph construction. This is where the backward gradient computations are saved.
|
105
99
|
|
106
100
|
*Properties*
|
107
101
|
|
@@ -109,38 +103,34 @@ Tensors are the fundamental datatype in froog, and one of the two main classes.
|
|
109
103
|
|
110
104
|
*Methods*
|
111
105
|
- ```def zeros(*shape)```: this returns a tensor full of zeros with any shape that you pass in. Defaults to np.float32
|
112
|
-
|
113
106
|
- ```def ones(*shape)```: this returns a tensor full of ones with any shape that you pass in. Defaults to np.float32
|
114
|
-
|
115
107
|
- ```def randn(*shape):```: this returns a randomly initialized Tensor of *shape
|
116
108
|
|
117
109
|
*Gradient calculations*
|
118
110
|
|
119
|
-
- ```froog``` computes gradients automatically through a process called automatic differentiation. it has a variable ```_ctx```, which stores the chain of operations.
|
111
|
+
- ```froog``` computes gradients automatically through a process called automatic differentiation. it has a variable ```_ctx```, which stores the chain of operations. It will take the current operation, let's say a dot product, and go to the dot product definition in ```froog/ops.py```, which contains a backward pass specifically for dot products. all methods, from add to 2x2 maxpools, have this backward pass implemented.
|
120
112
|
|
121
113
|
*Functions*
|
122
114
|
|
123
115
|
The other base class in froog is the class ```Function```. It keeps track of input tensors and tensors that need to be saved for backward passes
|
124
116
|
|
125
117
|
- ```def __init__(self, *tensors)```: takes in an argument of tensors, which are then saved.
|
126
|
-
|
127
118
|
- ```def save_for_backward(self, *x)```: saves Tensors that are necessary to compute for the computation of gradients in the backward pass.
|
128
|
-
|
129
|
-
- ```def apply(self, arg, *x)```: This is what makes everything work. The apply() method takes care of the forward pass, applying the operation to the inputs.
|
119
|
+
- ```def apply(self, arg, *x)```: takes care of the forward pass, applying the operation to the inputs.
|
130
120
|
|
131
121
|
*Register*
|
132
122
|
|
133
|
-
```def register(name, fxn)```:
|
123
|
+
- ```def register(name, fxn)```: allows you to add a method to a Tensor. This allows you to chain any operations, e.g. x.dot(w).relu(), where w is a tensor
|
134
124
|
|
135
125
|
# Creating a model
|
136
126
|
|
137
127
|
Okay cool, so now you know that ```froog```'s main datatype is a Tensor and uses NumPy in the background. How do I actually build a model?
|
138
128
|
|
139
|
-
Here's an example of how to create an MNIST multi-layer perceptron (MLP). We wanted to make it as simple as possible for you to do so
|
129
|
+
Here's an example of how to create an MNIST multi-layer perceptron (MLP). We wanted to make it as simple as possible for you to do so it resembles very basic Python concepts like classes. There are really only two methods you need to define:
|
140
130
|
1. ```__init__``` that defines layers of the model (here we use ```Linear```)
|
141
131
|
2. ```forward``` which defines how the input should flow through your model. We use a simple dot product with a ```Linear``` layer with a <a href="https://en.wikipedia.org/wiki/Rectifier_(neural_networks)">```ReLU```</a> activation.
|
142
132
|
|
143
|
-
|
133
|
+
To create an instance of the ```mnistMLP``` model, do the same as you would in Python: ```model = mnistMLP()```.
|
144
134
|
|
145
135
|
We support a few different optimizers, <a href="https://github.com/kevbuh/froog/blob/main/froog/optim.py">here</a> which include:
|
146
136
|
- <a href="https://en.wikipedia.org/wiki/Stochastic_gradient_descent">Stochastic Gradient Descent (SGD)</a>
|
@@ -199,9 +189,9 @@ So there are two quick examples to get you up and running. You might have notice
|
|
199
189
|
- ```.max_pool2d()```
|
200
190
|
- ```.avg_pool2d()```
|
201
191
|
|
202
|
-
|
192
|
+
# GPU Support
|
203
193
|
|
204
|
-
Have a GPU and need a speedup? You're in good luck because we have GPU support
|
194
|
+
Have a GPU and need a speedup? You're in good luck because we have GPU support via OpenCL for our operations defined in <a href="https://github.com/kevbuh/froog/blob/main/froog/ops_gpu.py">```ops_gpu.py```</a>.
|
205
195
|
|
206
196
|
Here's how you can send data to the GPU during a forward pass and bring it back to the CPU.
|
207
197
|
|
@@ -212,75 +202,19 @@ if GPU:
|
|
212
202
|
out = model.forward(Tensor(img).to_gpu()).cpu()
|
213
203
|
```
|
214
204
|
|
215
|
-
|
205
|
+
# EfficientNet in froog!
|
206
|
+
|
207
|
+
<img src="assets/efficientnet_pug.png" alt="pug" height="300">
|
216
208
|
|
217
209
|
We have a really cool finished implementation of EfficientNet built entirely in ```froog```!
|
218
210
|
|
219
211
|
In order to run EfficientNet inference:
|
220
212
|
|
221
213
|
```bash
|
222
|
-
VIZ=1
|
214
|
+
VIZ=1 python3 models/efficientnet.py <https://put_your_image_url_here>
|
223
215
|
```
|
224
216
|
|
225
|
-
I would recommend checking out the <a href="https://github.com/kevbuh/froog/blob/main/models/efficientnet.py">code</a>, it's highly documented and pretty cool.
|
226
|
-
```
|
227
|
-
Paper : https://arxiv.org/abs/1905.11946
|
228
|
-
PyTorch version : https://github.com/lukemelas/EfficientNet-PyTorch/blob/master/efficientnet_pytorch/model.py
|
229
|
-
|
230
|
-
ConvNets are commonly developed at a fixed resource cost, and then scaled up in order to achieve better accuracy when more resources are made available
|
231
|
-
The scaling method was found by performing a grid search to find the relationship between different scaling dimensions of the baseline network under a fixed resource constraint
|
232
|
-
"SE" stands for "Squeeze-and-Excitation." Introduced by the "Squeeze-and-Excitation Networks" paper by Jie Hu, Li Shen, and Gang Sun (CVPR 2018).
|
233
|
-
|
234
|
-
Environment Variables:
|
235
|
-
VIZ=1 --> plots processed image and output probabilities
|
236
|
-
|
237
|
-
How to Run:
|
238
|
-
'VIZ=1 python models/efficientnet.py https://your_image_url'
|
239
|
-
|
240
|
-
EfficientNet Hyper-Parameters and Weights:
|
241
|
-
url_map = {
|
242
|
-
'efficientnet-b0': 'https://github.com/lukemelas/EfficientNet-PyTorch/releases/download/1.0/efficientnet-b0-355c32eb.pth',
|
243
|
-
'efficientnet-b1': 'https://github.com/lukemelas/EfficientNet-PyTorch/releases/download/1.0/efficientnet-b1-f1951068.pth',
|
244
|
-
'efficientnet-b2': 'https://github.com/lukemelas/EfficientNet-PyTorch/releases/download/1.0/efficientnet-b2-8bb594d6.pth',
|
245
|
-
'efficientnet-b3': 'https://github.com/lukemelas/EfficientNet-PyTorch/releases/download/1.0/efficientnet-b3-5fb5a3c3.pth',
|
246
|
-
'efficientnet-b4': 'https://github.com/lukemelas/EfficientNet-PyTorch/releases/download/1.0/efficientnet-b4-6ed6700e.pth',
|
247
|
-
'efficientnet-b5': 'https://github.com/lukemelas/EfficientNet-PyTorch/releases/download/1.0/efficientnet-b5-b6417697.pth',
|
248
|
-
'efficientnet-b6': 'https://github.com/lukemelas/EfficientNet-PyTorch/releases/download/1.0/efficientnet-b6-c76e70fd.pth',
|
249
|
-
'efficientnet-b7': 'https://github.com/lukemelas/EfficientNet-PyTorch/releases/download/1.0/efficientnet-b7-dcc49843.pth',
|
250
|
-
}
|
251
|
-
|
252
|
-
params_dict = {
|
253
|
-
# Coefficients: width,depth,res,dropout
|
254
|
-
'efficientnet-b0': (1.0, 1.0, 224, 0.2),
|
255
|
-
'efficientnet-b1': (1.0, 1.1, 240, 0.2),
|
256
|
-
'efficientnet-b2': (1.1, 1.2, 260, 0.3),
|
257
|
-
'efficientnet-b3': (1.2, 1.4, 300, 0.3),
|
258
|
-
'efficientnet-b4': (1.4, 1.8, 380, 0.4),
|
259
|
-
'efficientnet-b5': (1.6, 2.2, 456, 0.4),
|
260
|
-
'efficientnet-b6': (1.8, 2.6, 528, 0.5),
|
261
|
-
'efficientnet-b7': (2.0, 3.1, 600, 0.5),
|
262
|
-
'efficientnet-b8': (2.2, 3.6, 672, 0.5),
|
263
|
-
'efficientnet-l2': (4.3, 5.3, 800, 0.5),
|
264
|
-
}
|
265
|
-
|
266
|
-
blocks_args = [
|
267
|
-
'r1_k3_s11_e1_i32_o16_se0.25',
|
268
|
-
'r2_k3_s22_e6_i16_o24_se0.25',
|
269
|
-
'r2_k5_s22_e6_i24_o40_se0.25',
|
270
|
-
'r3_k3_s22_e6_i40_o80_se0.25',
|
271
|
-
'r3_k5_s11_e6_i80_o112_se0.25',
|
272
|
-
'r4_k5_s22_e6_i112_o192_se0.25',
|
273
|
-
'r1_k3_s11_e6_i192_o320_se0.25',
|
274
|
-
]
|
275
|
-
```
|
276
|
-
|
277
|
-
## Linear regression
|
278
|
-
|
279
|
-
Doing linear regression in ```froog``` is pretty easy, check out the entire <a href="https://github.com/kevbuh/froog/blob/main/models/linear_regression.py">code</a>.
|
280
|
-
|
281
|
-
```bash
|
282
|
-
VIZ=1 python3 linear_regression.py
|
283
|
-
```
|
217
|
+
I would recommend checking out the <a href="https://github.com/kevbuh/froog/blob/main/models/efficientnet.py">code</a>, it's highly documented and pretty cool.
|
284
218
|
|
285
219
|
# Contributing
|
286
220
|
<!-- THERES LOT OF STUFF TO WORK ON! VISIT THE <a href="https://github.com/kevbuh/froog/blob/main/docs/bounties.md">BOUNTY SHOP</a> -->
|
@@ -290,12 +224,7 @@ Pull requests will be merged if they:
|
|
290
224
|
* increase functionality
|
291
225
|
* increase efficiency
|
292
226
|
|
293
|
-
More info on <a href="https://github.com/kevbuh/froog/blob/main/docs/contributing.md">contributing</a>.
|
294
|
-
|
295
|
-
# Documentation
|
296
|
-
|
297
|
-
Need more information about how ```froog``` works? Visit the <a href="https://github.com/kevbuh/froog/tree/main/docs">documentation</a>.
|
298
|
-
|
299
|
-
# Interested in more?
|
227
|
+
More info on <a href="https://github.com/kevbuh/froog/blob/main/docs/contributing.md">contributing</a>. Make sure to run ```python -m pytest``` before creating a PR.
|
300
228
|
|
301
|
-
|
229
|
+
<!-- # Documentation
|
230
|
+
Need more information about how ```froog``` works? Visit the <a href="https://github.com/kevbuh/froog/tree/main/docs">documentation</a>. -->
|
@@ -11,9 +11,10 @@
|
|
11
11
|
<br/>
|
12
12
|
</div>
|
13
13
|
|
14
|
-
```froog``` is an easy-to-read tensor library (<a href="https://www.pepy.tech/projects/froog">
|
14
|
+
```froog``` is an easy-to-read tensor library (<a href="https://www.pepy.tech/projects/froog">25k pip installs!</a>) with OpenCL support for GPU acceleration. Inspired by pytorch, tinygrad, and micrograd.
|
15
15
|
|
16
|
-
|
16
|
+
|
17
|
+
<!-- ```froog``` encapsulates everything from <a href="https://github.com/kevbuh/froog/blob/main/models/linear_regression.py">linear regression</a> to <a href="https://github.com/kevbuh/froog/blob/main/models/efficientnet.py">convolutional neural networks </a> in under 2000 lines. -->
|
17
18
|
|
18
19
|
# Installation
|
19
20
|
```bash
|
@@ -69,7 +70,7 @@ from froog.tensor import Tensor
|
|
69
70
|
my_tensor = Tensor([1,2,3])
|
70
71
|
```
|
71
72
|
|
72
|
-
Notice how we had to import
|
73
|
+
Notice how we had to import NumPy. If you want to create a Tensor manually, make sure that it is a NumPy array!
|
73
74
|
|
74
75
|
<!-- Learn more about ```froog``` Tensors <a href="https://github.com/kevbuh/froog/blob/main/docs/tensors.md">here</a>. -->
|
75
76
|
|
@@ -79,13 +80,10 @@ Tensors are the fundamental datatype in froog, and one of the two main classes.
|
|
79
80
|
|
80
81
|
- ```def __init__(self, data)```:
|
81
82
|
|
82
|
-
- Tensor takes in one param, which is the data. Since froog has a
|
83
|
-
|
83
|
+
- Tensor takes in one param, which is the data. Since ```froog``` has a NumPy backend, the input data into tensors has to be a NumPy array.
|
84
84
|
- Tensor has a ```self.data``` state that it holds. this contains the data inside of the tensor.
|
85
|
-
|
86
85
|
- In addition, it has ```self.grad```. this is to hold what the gradients of the tensor is.
|
87
|
-
|
88
|
-
- Lastly, it has ```self._ctx```. theser are the internal vairables used for autograd graph construction. put more simply, this is where the backward gradient computations are saved.
|
86
|
+
- Lastly, it has ```self._ctx```. These are the internal variables used for autograd graph construction. This is where the backward gradient computations are saved.
|
89
87
|
|
90
88
|
*Properties*
|
91
89
|
|
@@ -93,38 +91,34 @@ Tensors are the fundamental datatype in froog, and one of the two main classes.
|
|
93
91
|
|
94
92
|
*Methods*
|
95
93
|
- ```def zeros(*shape)```: this returns a tensor full of zeros with any shape that you pass in. Defaults to np.float32
|
96
|
-
|
97
94
|
- ```def ones(*shape)```: this returns a tensor full of ones with any shape that you pass in. Defaults to np.float32
|
98
|
-
|
99
95
|
- ```def randn(*shape):```: this returns a randomly initialized Tensor of *shape
|
100
96
|
|
101
97
|
*Gradient calculations*
|
102
98
|
|
103
|
-
- ```froog``` computes gradients automatically through a process called automatic differentiation. it has a variable ```_ctx```, which stores the chain of operations.
|
99
|
+
- ```froog``` computes gradients automatically through a process called automatic differentiation. it has a variable ```_ctx```, which stores the chain of operations. It will take the current operation, let's say a dot product, and go to the dot product definition in ```froog/ops.py```, which contains a backward pass specifically for dot products. all methods, from add to 2x2 maxpools, have this backward pass implemented.
|
104
100
|
|
105
101
|
*Functions*
|
106
102
|
|
107
103
|
The other base class in froog is the class ```Function```. It keeps track of input tensors and tensors that need to be saved for backward passes
|
108
104
|
|
109
105
|
- ```def __init__(self, *tensors)```: takes in an argument of tensors, which are then saved.
|
110
|
-
|
111
106
|
- ```def save_for_backward(self, *x)```: saves Tensors that are necessary to compute for the computation of gradients in the backward pass.
|
112
|
-
|
113
|
-
- ```def apply(self, arg, *x)```: This is what makes everything work. The apply() method takes care of the forward pass, applying the operation to the inputs.
|
107
|
+
- ```def apply(self, arg, *x)```: takes care of the forward pass, applying the operation to the inputs.
|
114
108
|
|
115
109
|
*Register*
|
116
110
|
|
117
|
-
```def register(name, fxn)```:
|
111
|
+
- ```def register(name, fxn)```: allows you to add a method to a Tensor. This allows you to chain any operations, e.g. x.dot(w).relu(), where w is a tensor
|
118
112
|
|
119
113
|
# Creating a model
|
120
114
|
|
121
115
|
Okay cool, so now you know that ```froog```'s main datatype is a Tensor and uses NumPy in the background. How do I actually build a model?
|
122
116
|
|
123
|
-
Here's an example of how to create an MNIST multi-layer perceptron (MLP). We wanted to make it as simple as possible for you to do so
|
117
|
+
Here's an example of how to create an MNIST multi-layer perceptron (MLP). We wanted to make it as simple as possible for you to do so it resembles very basic Python concepts like classes. There are really only two methods you need to define:
|
124
118
|
1. ```__init__``` that defines layers of the model (here we use ```Linear```)
|
125
119
|
2. ```forward``` which defines how the input should flow through your model. We use a simple dot product with a ```Linear``` layer with a <a href="https://en.wikipedia.org/wiki/Rectifier_(neural_networks)">```ReLU```</a> activation.
|
126
120
|
|
127
|
-
|
121
|
+
To create an instance of the ```mnistMLP``` model, do the same as you would in Python: ```model = mnistMLP()```.
|
128
122
|
|
129
123
|
We support a few different optimizers, <a href="https://github.com/kevbuh/froog/blob/main/froog/optim.py">here</a> which include:
|
130
124
|
- <a href="https://en.wikipedia.org/wiki/Stochastic_gradient_descent">Stochastic Gradient Descent (SGD)</a>
|
@@ -183,9 +177,9 @@ So there are two quick examples to get you up and running. You might have notice
|
|
183
177
|
- ```.max_pool2d()```
|
184
178
|
- ```.avg_pool2d()```
|
185
179
|
|
186
|
-
|
180
|
+
# GPU Support
|
187
181
|
|
188
|
-
Have a GPU and need a speedup? You're in good luck because we have GPU support
|
182
|
+
Have a GPU and need a speedup? You're in good luck because we have GPU support via OpenCL for our operations defined in <a href="https://github.com/kevbuh/froog/blob/main/froog/ops_gpu.py">```ops_gpu.py```</a>.
|
189
183
|
|
190
184
|
Here's how you can send data to the GPU during a forward pass and bring it back to the CPU.
|
191
185
|
|
@@ -196,75 +190,19 @@ if GPU:
|
|
196
190
|
out = model.forward(Tensor(img).to_gpu()).cpu()
|
197
191
|
```
|
198
192
|
|
199
|
-
|
193
|
+
# EfficientNet in froog!
|
194
|
+
|
195
|
+
<img src="assets/efficientnet_pug.png" alt="pug" height="300">
|
200
196
|
|
201
197
|
We have a really cool finished implementation of EfficientNet built entirely in ```froog```!
|
202
198
|
|
203
199
|
In order to run EfficientNet inference:
|
204
200
|
|
205
201
|
```bash
|
206
|
-
VIZ=1
|
202
|
+
VIZ=1 python3 models/efficientnet.py <https://put_your_image_url_here>
|
207
203
|
```
|
208
204
|
|
209
|
-
I would recommend checking out the <a href="https://github.com/kevbuh/froog/blob/main/models/efficientnet.py">code</a>, it's highly documented and pretty cool.
|
210
|
-
```
|
211
|
-
Paper : https://arxiv.org/abs/1905.11946
|
212
|
-
PyTorch version : https://github.com/lukemelas/EfficientNet-PyTorch/blob/master/efficientnet_pytorch/model.py
|
213
|
-
|
214
|
-
ConvNets are commonly developed at a fixed resource cost, and then scaled up in order to achieve better accuracy when more resources are made available
|
215
|
-
The scaling method was found by performing a grid search to find the relationship between different scaling dimensions of the baseline network under a fixed resource constraint
|
216
|
-
"SE" stands for "Squeeze-and-Excitation." Introduced by the "Squeeze-and-Excitation Networks" paper by Jie Hu, Li Shen, and Gang Sun (CVPR 2018).
|
217
|
-
|
218
|
-
Environment Variables:
|
219
|
-
VIZ=1 --> plots processed image and output probabilities
|
220
|
-
|
221
|
-
How to Run:
|
222
|
-
'VIZ=1 python models/efficientnet.py https://your_image_url'
|
223
|
-
|
224
|
-
EfficientNet Hyper-Parameters and Weights:
|
225
|
-
url_map = {
|
226
|
-
'efficientnet-b0': 'https://github.com/lukemelas/EfficientNet-PyTorch/releases/download/1.0/efficientnet-b0-355c32eb.pth',
|
227
|
-
'efficientnet-b1': 'https://github.com/lukemelas/EfficientNet-PyTorch/releases/download/1.0/efficientnet-b1-f1951068.pth',
|
228
|
-
'efficientnet-b2': 'https://github.com/lukemelas/EfficientNet-PyTorch/releases/download/1.0/efficientnet-b2-8bb594d6.pth',
|
229
|
-
'efficientnet-b3': 'https://github.com/lukemelas/EfficientNet-PyTorch/releases/download/1.0/efficientnet-b3-5fb5a3c3.pth',
|
230
|
-
'efficientnet-b4': 'https://github.com/lukemelas/EfficientNet-PyTorch/releases/download/1.0/efficientnet-b4-6ed6700e.pth',
|
231
|
-
'efficientnet-b5': 'https://github.com/lukemelas/EfficientNet-PyTorch/releases/download/1.0/efficientnet-b5-b6417697.pth',
|
232
|
-
'efficientnet-b6': 'https://github.com/lukemelas/EfficientNet-PyTorch/releases/download/1.0/efficientnet-b6-c76e70fd.pth',
|
233
|
-
'efficientnet-b7': 'https://github.com/lukemelas/EfficientNet-PyTorch/releases/download/1.0/efficientnet-b7-dcc49843.pth',
|
234
|
-
}
|
235
|
-
|
236
|
-
params_dict = {
|
237
|
-
# Coefficients: width,depth,res,dropout
|
238
|
-
'efficientnet-b0': (1.0, 1.0, 224, 0.2),
|
239
|
-
'efficientnet-b1': (1.0, 1.1, 240, 0.2),
|
240
|
-
'efficientnet-b2': (1.1, 1.2, 260, 0.3),
|
241
|
-
'efficientnet-b3': (1.2, 1.4, 300, 0.3),
|
242
|
-
'efficientnet-b4': (1.4, 1.8, 380, 0.4),
|
243
|
-
'efficientnet-b5': (1.6, 2.2, 456, 0.4),
|
244
|
-
'efficientnet-b6': (1.8, 2.6, 528, 0.5),
|
245
|
-
'efficientnet-b7': (2.0, 3.1, 600, 0.5),
|
246
|
-
'efficientnet-b8': (2.2, 3.6, 672, 0.5),
|
247
|
-
'efficientnet-l2': (4.3, 5.3, 800, 0.5),
|
248
|
-
}
|
249
|
-
|
250
|
-
blocks_args = [
|
251
|
-
'r1_k3_s11_e1_i32_o16_se0.25',
|
252
|
-
'r2_k3_s22_e6_i16_o24_se0.25',
|
253
|
-
'r2_k5_s22_e6_i24_o40_se0.25',
|
254
|
-
'r3_k3_s22_e6_i40_o80_se0.25',
|
255
|
-
'r3_k5_s11_e6_i80_o112_se0.25',
|
256
|
-
'r4_k5_s22_e6_i112_o192_se0.25',
|
257
|
-
'r1_k3_s11_e6_i192_o320_se0.25',
|
258
|
-
]
|
259
|
-
```
|
260
|
-
|
261
|
-
## Linear regression
|
262
|
-
|
263
|
-
Doing linear regression in ```froog``` is pretty easy, check out the entire <a href="https://github.com/kevbuh/froog/blob/main/models/linear_regression.py">code</a>.
|
264
|
-
|
265
|
-
```bash
|
266
|
-
VIZ=1 python3 linear_regression.py
|
267
|
-
```
|
205
|
+
I would recommend checking out the <a href="https://github.com/kevbuh/froog/blob/main/models/efficientnet.py">code</a>, it's highly documented and pretty cool.
|
268
206
|
|
269
207
|
# Contributing
|
270
208
|
<!-- THERES LOT OF STUFF TO WORK ON! VISIT THE <a href="https://github.com/kevbuh/froog/blob/main/docs/bounties.md">BOUNTY SHOP</a> -->
|
@@ -274,12 +212,7 @@ Pull requests will be merged if they:
|
|
274
212
|
* increase functionality
|
275
213
|
* increase efficiency
|
276
214
|
|
277
|
-
More info on <a href="https://github.com/kevbuh/froog/blob/main/docs/contributing.md">contributing</a>.
|
278
|
-
|
279
|
-
# Documentation
|
280
|
-
|
281
|
-
Need more information about how ```froog``` works? Visit the <a href="https://github.com/kevbuh/froog/tree/main/docs">documentation</a>.
|
282
|
-
|
283
|
-
# Interested in more?
|
215
|
+
More info on <a href="https://github.com/kevbuh/froog/blob/main/docs/contributing.md">contributing</a>. Make sure to run ```python -m pytest``` before creating a PR.
|
284
216
|
|
285
|
-
|
217
|
+
<!-- # Documentation
|
218
|
+
Need more information about how ```froog``` works? Visit the <a href="https://github.com/kevbuh/froog/tree/main/docs">documentation</a>. -->
|
@@ -9,6 +9,7 @@
|
|
9
9
|
import numpy as np
|
10
10
|
from froog.tensor import Function, register
|
11
11
|
from froog.utils import im2col, col2im
|
12
|
+
from froog.tensor import Tensor
|
12
13
|
|
13
14
|
# *****************************************************
|
14
15
|
# ____ ___ _____ __________ ____ ____ _____
|
@@ -142,6 +143,29 @@ class Sigmoid(Function):
|
|
142
143
|
return grad_input
|
143
144
|
register("sigmoid", Sigmoid)
|
144
145
|
|
146
|
+
# class Dropout(Function):
|
147
|
+
# """
|
148
|
+
# Randomly zeroes some of the elements of the input tensor with probability p during training.
|
149
|
+
# The elements to zero are randomized on every forward call.
|
150
|
+
# During inference, dropout is disabled and the input is scaled by (1-p) to maintain the expected value.
|
151
|
+
# """
|
152
|
+
# @staticmethod
|
153
|
+
# def forward(ctx, input, p=0.5, training=True):
|
154
|
+
# if training:
|
155
|
+
# # Create a binary mask with probability (1-p) of being 1
|
156
|
+
# mask = (np.random.random(input.shape) > p).astype(np.float32)
|
157
|
+
# ctx.save_for_backward(mask)
|
158
|
+
# return input * mask
|
159
|
+
# else:
|
160
|
+
# # during inference, scale the input by (1-p)
|
161
|
+
# return input * (1-p)
|
162
|
+
|
163
|
+
# @staticmethod
|
164
|
+
# def backward(ctx, grad_output):
|
165
|
+
# mask, = ctx.saved_tensors
|
166
|
+
# return grad_output * mask
|
167
|
+
# register("dropout", Dropout)
|
168
|
+
|
145
169
|
class Reshape(Function):
|
146
170
|
@staticmethod
|
147
171
|
def forward(ctx, x, shape):
|
@@ -358,3 +382,53 @@ class AvgPool2D(Function):
|
|
358
382
|
ret[:, :, Y:my:py, X:mx:px] = grad_output / py / px # divide by avg of pool, e.g. for 2x2 pool /= 4
|
359
383
|
return ret
|
360
384
|
register('avg_pool2d', AvgPool2D)
|
385
|
+
|
386
|
+
# *************************************
|
387
|
+
# _ ___ __ ____ ____ _____
|
388
|
+
# / | / / | / / / __ \/ __ \/ ___/
|
389
|
+
# / |/ / |/ / / / / / /_/ /\__ \
|
390
|
+
# / /| / /| / / /_/ / ____/___/ /
|
391
|
+
# /_/ |_/_/ |_/ \____/_/ /____/
|
392
|
+
#
|
393
|
+
# ************* nn ops ************
|
394
|
+
|
395
|
+
def Linear(*x):
|
396
|
+
# random Glorot initialization
|
397
|
+
ret = np.random.uniform(-1., 1., size=x)/np.sqrt(np.prod(x))
|
398
|
+
return ret.astype(np.float32)
|
399
|
+
|
400
|
+
def swish(x):
|
401
|
+
return x.mul(x.sigmoid())
|
402
|
+
|
403
|
+
class BatchNorm2D:
|
404
|
+
"""
|
405
|
+
__call__ follows the formula from the link below
|
406
|
+
pytorch version: https://pytorch.org/docs/stable/generated/torch.nn.BatchNorm2d.html
|
407
|
+
|
408
|
+
self.weight = γ
|
409
|
+
self.bias = β
|
410
|
+
self.running_mean = E[x]
|
411
|
+
self.running_var = Var[x]
|
412
|
+
|
413
|
+
the reshaping step ensures that each channel of the input has its
|
414
|
+
own separate set of parameters (mean, variance, weight, and bias)
|
415
|
+
|
416
|
+
self.running_mean has shape [num_channels].
|
417
|
+
self.running_mean.reshape(shape=[1, -1, 1, 1]) reshapes it to [1, num_channels, 1, 1]
|
418
|
+
"""
|
419
|
+
def __init__(self, sz, eps=0.001):
|
420
|
+
self.eps = eps
|
421
|
+
self.weight = Tensor.zeros(sz)
|
422
|
+
self.bias = Tensor.zeros(sz)
|
423
|
+
|
424
|
+
# TODO: need running_mean and running_var
|
425
|
+
self.running_mean = Tensor.zeros(sz)
|
426
|
+
self.running_var = Tensor.zeros(sz)
|
427
|
+
self.num_batches_tracked = Tensor.zeros(1)
|
428
|
+
|
429
|
+
def __call__(self, x):
|
430
|
+
x = x.sub(self.running_mean.reshape(shape=[1, -1, 1, 1]))
|
431
|
+
x = x.mul(self.weight.reshape(shape=[1, -1, 1, 1]))
|
432
|
+
x = x.div(self.running_var.add(Tensor([self.eps], gpu=x.gpu)).reshape(shape=[1, -1, 1, 1]).sqrt())
|
433
|
+
x = x.add(self.bias.reshape(shape=[1, -1, 1, 1]))
|
434
|
+
return x
|
@@ -303,23 +303,42 @@ register('relu', ReLU, gpu=True)
|
|
303
303
|
class LogSoftmax(Function):
|
304
304
|
@staticmethod
|
305
305
|
def forward(ctx, input):
|
306
|
+
# first find max values for numerical stability
|
307
|
+
max_vals = buffer_new(ctx, (input.shape[0],))
|
308
|
+
prg = clbuild(ctx.cl_ctx, """
|
309
|
+
__kernel void max_vals(
|
310
|
+
__global const float *a_g, int sz, __global float *res_g)
|
311
|
+
{
|
312
|
+
int gid = get_global_id(0);
|
313
|
+
int gidsz = gid*sz;
|
314
|
+
float max_val = -INFINITY;
|
315
|
+
for (int x = 0; x < sz; x++) {
|
316
|
+
max_val = max(max_val, a_g[gidsz+x]);
|
317
|
+
}
|
318
|
+
res_g[gid] = max_val;
|
319
|
+
}
|
320
|
+
""")
|
321
|
+
prg.max_vals(ctx.cl_queue, [input.shape[0]], None, input, np.int32(input.shape[1]), max_vals)
|
322
|
+
|
323
|
+
# compute exp(x - max) and sum
|
306
324
|
lsum = buffer_new(ctx, (input.shape[0],))
|
307
325
|
prg = clbuild(ctx.cl_ctx, """
|
308
326
|
__kernel void logsoftmax(
|
309
|
-
__global const float *a_g, int sz, __global float *res_g)
|
327
|
+
__global const float *a_g, __global const float *max_vals, int sz, __global float *res_g)
|
310
328
|
{
|
311
329
|
int gid = get_global_id(0);
|
312
330
|
int gidsz = gid*sz;
|
313
|
-
|
331
|
+
float max_val = max_vals[gid];
|
314
332
|
float out = 0.0;
|
315
333
|
for (int x = 0; x < sz; x++) {
|
316
|
-
out += exp(a_g[gidsz+x]);
|
334
|
+
out += exp(a_g[gidsz+x] - max_val);
|
317
335
|
}
|
318
|
-
res_g[gid] = log(out);
|
336
|
+
res_g[gid] = log(out) + max_val;
|
319
337
|
}
|
320
338
|
""")
|
321
|
-
prg.logsoftmax(ctx.cl_queue, [input.shape[0]], None, input, np.int32(input.shape[1]), lsum)
|
339
|
+
prg.logsoftmax(ctx.cl_queue, [input.shape[0]], None, input, max_vals, np.int32(input.shape[1]), lsum)
|
322
340
|
|
341
|
+
# compute final output
|
323
342
|
output = buffer_like(ctx, input)
|
324
343
|
prg = clbuild(ctx.cl_ctx, """
|
325
344
|
__kernel void lsmsub(
|
@@ -475,8 +494,38 @@ class AvgPool2D(Function):
|
|
475
494
|
|
476
495
|
@staticmethod
|
477
496
|
def backward(ctx, grad_output):
|
478
|
-
#
|
479
|
-
|
497
|
+
# for average pooling, we need to distribute the gradient evenly across all elements in the pooling window
|
498
|
+
input_shape = ctx.data.shape
|
499
|
+
N, C, Y, X = input_shape
|
500
|
+
py, px = ctx.kernel_size
|
501
|
+
ret = buffer_zeros(ctx, input_shape)
|
502
|
+
|
503
|
+
prg = clbuild(ctx.cl_ctx, """
|
504
|
+
__kernel void avgpool_backward(
|
505
|
+
__global float *grad_input, __global const float *grad_output,
|
506
|
+
uint2 osize, uint2 isize, uint2 kernel_size, int nelem
|
507
|
+
) {
|
508
|
+
int3 gid = (int3)(get_global_id(2), get_global_id(1), get_global_id(0));
|
509
|
+
int oid = gid.x + osize.x*(gid.y + osize.y*gid.z);
|
510
|
+
float grad = grad_output[oid] / (kernel_size.x * kernel_size.y);
|
511
|
+
|
512
|
+
for (uint j=0; j<kernel_size.y; ++j) {
|
513
|
+
for (uint i=0; i<kernel_size.x; ++i) {
|
514
|
+
int iid = (gid.x*kernel_size.x+i) + isize.x*((gid.y*kernel_size.y+j) + isize.y*gid.z);
|
515
|
+
if (iid < nelem)
|
516
|
+
grad_input[iid] += grad;
|
517
|
+
}
|
518
|
+
}
|
519
|
+
}
|
520
|
+
""")
|
521
|
+
|
522
|
+
osize = np.array((X//px, Y//py), dtype=cl.cltypes.uint2)
|
523
|
+
isize = np.array((X, Y), dtype=cl.cltypes.uint2)
|
524
|
+
ksize = np.array((px,py), dtype=cl.cltypes.uint2)
|
525
|
+
|
526
|
+
prg.avgpool_backward(ctx.cl_queue, (N*C, Y//py, X//px), None, ret, grad_output, osize, isize, ksize, np.int32(input_shape.size))
|
527
|
+
|
528
|
+
return ret
|
480
529
|
register('avg_pool2d', AvgPool2D, gpu=True)
|
481
530
|
|
482
531
|
class MaxPool2D(Function):
|
@@ -485,10 +534,65 @@ class MaxPool2D(Function):
|
|
485
534
|
init_val = "FLT_MIN"
|
486
535
|
iter_op = "group_res = max(group_res, input[iid])"
|
487
536
|
result_op = "group_res"
|
488
|
-
|
537
|
+
ret = pooling_op(ctx, input, kernel_size, iter_op, result_op, init_val=init_val)
|
538
|
+
|
539
|
+
# save indices of max elements for backward pass
|
540
|
+
indices = buffer_new(ctx, ret.shape)
|
541
|
+
prg = clbuild(ctx.cl_ctx, """
|
542
|
+
__kernel void maxpool_indices(
|
543
|
+
__global const float *input, __global float *output, __global int *indices,
|
544
|
+
uint2 osize, uint2 isize, uint2 kernel_size, int nelem
|
545
|
+
) {
|
546
|
+
int3 gid = (int3)(get_global_id(2), get_global_id(1), get_global_id(0));
|
547
|
+
int oid = gid.x + osize.x*(gid.y + osize.y*gid.z);
|
548
|
+
float max_val = -INFINITY;
|
549
|
+
int max_idx = 0;
|
550
|
+
|
551
|
+
for (uint j=0; j<kernel_size.y; ++j) {
|
552
|
+
for (uint i=0; i<kernel_size.x; ++i) {
|
553
|
+
int iid = (gid.x*kernel_size.x+i) + isize.x*((gid.y*kernel_size.y+j) + isize.y*gid.z);
|
554
|
+
if (iid < nelem) {
|
555
|
+
float val = input[iid];
|
556
|
+
if (val > max_val) {
|
557
|
+
max_val = val;
|
558
|
+
max_idx = iid;
|
559
|
+
}
|
560
|
+
}
|
561
|
+
}
|
562
|
+
}
|
563
|
+
indices[oid] = max_idx;
|
564
|
+
}
|
565
|
+
""")
|
566
|
+
|
567
|
+
N, C, Y, X = input.shape
|
568
|
+
py, px = kernel_size
|
569
|
+
osize = np.array((X//px, Y//py), dtype=cl.cltypes.uint2)
|
570
|
+
isize = np.array((X, Y), dtype=cl.cltypes.uint2)
|
571
|
+
ksize = np.array((px,py), dtype=cl.cltypes.uint2)
|
572
|
+
|
573
|
+
prg.maxpool_indices(ctx.cl_queue, (N*C, Y//py, X//px), None, input, ret, indices, osize, isize, ksize, np.int32(input.size))
|
574
|
+
|
575
|
+
ctx.save_for_backward(indices)
|
576
|
+
return ret
|
489
577
|
|
490
578
|
@staticmethod
|
491
579
|
def backward(ctx, grad_output):
|
492
|
-
|
493
|
-
|
580
|
+
indices, = ctx.saved_tensors
|
581
|
+
input_shape = ctx.data.shape
|
582
|
+
ret = buffer_zeros(ctx, input_shape)
|
583
|
+
prg = clbuild(ctx.cl_ctx, """
|
584
|
+
__kernel void maxpool_backward(
|
585
|
+
__global float *grad_input, __global const float *grad_output,
|
586
|
+
__global const int *indices, int nelem
|
587
|
+
) {
|
588
|
+
int gid = get_global_id(0);
|
589
|
+
if (gid < nelem) {
|
590
|
+
int idx = indices[gid];
|
591
|
+
grad_input[idx] += grad_output[gid];
|
592
|
+
}
|
593
|
+
}
|
594
|
+
""")
|
595
|
+
|
596
|
+
prg.maxpool_backward(ctx.cl_queue, [np.prod(grad_output.shape)], None, ret, grad_output, indices, np.int32(grad_output.size))
|
597
|
+
return ret
|
494
598
|
register('max_pool2d', MaxPool2D, gpu=True)
|
@@ -57,7 +57,7 @@ class RMSprop(Optimizer):
|
|
57
57
|
RMSprop divides the learning rate by an exponentially decaying average of squared gradients.
|
58
58
|
|
59
59
|
Notes:
|
60
|
-
The reason RPROP doesn
|
60
|
+
The reason RPROP doesn't work is that it violates the central idea behind stochastic gradient descent,
|
61
61
|
which is when we have small enough learning rate, it averages the gradients over successive mini-batches.
|
62
62
|
"""
|
63
63
|
def __init__(self, params, decay=0.9, lr=0.001, eps=1e-8):
|
@@ -1,7 +1,7 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: froog
|
3
|
-
Version: 0.
|
4
|
-
Summary: a
|
3
|
+
Version: 0.4.2
|
4
|
+
Summary: a toy tensor library with opencl support
|
5
5
|
Author: Kevin Buhler
|
6
6
|
License: MIT
|
7
7
|
Classifier: Programming Language :: Python :: 3
|
@@ -9,10 +9,6 @@ Classifier: License :: OSI Approved :: MIT License
|
|
9
9
|
Requires-Python: >=3.8
|
10
10
|
Description-Content-Type: text/markdown
|
11
11
|
License-File: LICENSE
|
12
|
-
Requires-Dist: numpy
|
13
|
-
Requires-Dist: requests
|
14
|
-
Requires-Dist: matplotlib
|
15
|
-
Requires-Dist: urllib
|
16
12
|
|
17
13
|
# froog <img src="https://github.com/kevbuh/froog/actions/workflows/test.yml/badge.svg" alt="unit test badge" > <img src="https://static.pepy.tech/badge/froog" alt="num downloads badge">
|
18
14
|
<div align="center" >
|
@@ -27,9 +23,10 @@ Requires-Dist: urllib
|
|
27
23
|
<br/>
|
28
24
|
</div>
|
29
25
|
|
30
|
-
```froog``` is an easy-to-read tensor library (<a href="https://www.pepy.tech/projects/froog">
|
26
|
+
```froog``` is an easy-to-read tensor library (<a href="https://www.pepy.tech/projects/froog">25k pip installs!</a>) with OpenCL support for GPU acceleration. Inspired by pytorch, tinygrad, and micrograd.
|
31
27
|
|
32
|
-
|
28
|
+
|
29
|
+
<!-- ```froog``` encapsulates everything from <a href="https://github.com/kevbuh/froog/blob/main/models/linear_regression.py">linear regression</a> to <a href="https://github.com/kevbuh/froog/blob/main/models/efficientnet.py">convolutional neural networks </a> in under 2000 lines. -->
|
33
30
|
|
34
31
|
# Installation
|
35
32
|
```bash
|
@@ -85,7 +82,7 @@ from froog.tensor import Tensor
|
|
85
82
|
my_tensor = Tensor([1,2,3])
|
86
83
|
```
|
87
84
|
|
88
|
-
Notice how we had to import
|
85
|
+
Notice how we had to import NumPy. If you want to create a Tensor manually, make sure that it is a NumPy array!
|
89
86
|
|
90
87
|
<!-- Learn more about ```froog``` Tensors <a href="https://github.com/kevbuh/froog/blob/main/docs/tensors.md">here</a>. -->
|
91
88
|
|
@@ -95,13 +92,10 @@ Tensors are the fundamental datatype in froog, and one of the two main classes.
|
|
95
92
|
|
96
93
|
- ```def __init__(self, data)```:
|
97
94
|
|
98
|
-
- Tensor takes in one param, which is the data. Since froog has a
|
99
|
-
|
95
|
+
- Tensor takes in one param, which is the data. Since ```froog``` has a NumPy backend, the input data into tensors has to be a NumPy array.
|
100
96
|
- Tensor has a ```self.data``` state that it holds. this contains the data inside of the tensor.
|
101
|
-
|
102
97
|
- In addition, it has ```self.grad```. this is to hold what the gradients of the tensor is.
|
103
|
-
|
104
|
-
- Lastly, it has ```self._ctx```. theser are the internal vairables used for autograd graph construction. put more simply, this is where the backward gradient computations are saved.
|
98
|
+
- Lastly, it has ```self._ctx```. These are the internal variables used for autograd graph construction. This is where the backward gradient computations are saved.
|
105
99
|
|
106
100
|
*Properties*
|
107
101
|
|
@@ -109,38 +103,34 @@ Tensors are the fundamental datatype in froog, and one of the two main classes.
|
|
109
103
|
|
110
104
|
*Methods*
|
111
105
|
- ```def zeros(*shape)```: this returns a tensor full of zeros with any shape that you pass in. Defaults to np.float32
|
112
|
-
|
113
106
|
- ```def ones(*shape)```: this returns a tensor full of ones with any shape that you pass in. Defaults to np.float32
|
114
|
-
|
115
107
|
- ```def randn(*shape):```: this returns a randomly initialized Tensor of *shape
|
116
108
|
|
117
109
|
*Gradient calculations*
|
118
110
|
|
119
|
-
- ```froog``` computes gradients automatically through a process called automatic differentiation. it has a variable ```_ctx```, which stores the chain of operations.
|
111
|
+
- ```froog``` computes gradients automatically through a process called automatic differentiation. it has a variable ```_ctx```, which stores the chain of operations. It will take the current operation, let's say a dot product, and go to the dot product definition in ```froog/ops.py```, which contains a backward pass specifically for dot products. all methods, from add to 2x2 maxpools, have this backward pass implemented.
|
120
112
|
|
121
113
|
*Functions*
|
122
114
|
|
123
115
|
The other base class in froog is the class ```Function```. It keeps track of input tensors and tensors that need to be saved for backward passes
|
124
116
|
|
125
117
|
- ```def __init__(self, *tensors)```: takes in an argument of tensors, which are then saved.
|
126
|
-
|
127
118
|
- ```def save_for_backward(self, *x)```: saves Tensors that are necessary to compute for the computation of gradients in the backward pass.
|
128
|
-
|
129
|
-
- ```def apply(self, arg, *x)```: This is what makes everything work. The apply() method takes care of the forward pass, applying the operation to the inputs.
|
119
|
+
- ```def apply(self, arg, *x)```: takes care of the forward pass, applying the operation to the inputs.
|
130
120
|
|
131
121
|
*Register*
|
132
122
|
|
133
|
-
```def register(name, fxn)```:
|
123
|
+
- ```def register(name, fxn)```: allows you to add a method to a Tensor. This allows you to chain any operations, e.g. x.dot(w).relu(), where w is a tensor
|
134
124
|
|
135
125
|
# Creating a model
|
136
126
|
|
137
127
|
Okay cool, so now you know that ```froog```'s main datatype is a Tensor and uses NumPy in the background. How do I actually build a model?
|
138
128
|
|
139
|
-
Here's an example of how to create an MNIST multi-layer perceptron (MLP). We wanted to make it as simple as possible for you to do so
|
129
|
+
Here's an example of how to create an MNIST multi-layer perceptron (MLP). We wanted to make it as simple as possible for you to do so it resembles very basic Python concepts like classes. There are really only two methods you need to define:
|
140
130
|
1. ```__init__``` that defines layers of the model (here we use ```Linear```)
|
141
131
|
2. ```forward``` which defines how the input should flow through your model. We use a simple dot product with a ```Linear``` layer with a <a href="https://en.wikipedia.org/wiki/Rectifier_(neural_networks)">```ReLU```</a> activation.
|
142
132
|
|
143
|
-
|
133
|
+
To create an instance of the ```mnistMLP``` model, do the same as you would in Python: ```model = mnistMLP()```.
|
144
134
|
|
145
135
|
We support a few different optimizers, <a href="https://github.com/kevbuh/froog/blob/main/froog/optim.py">here</a> which include:
|
146
136
|
- <a href="https://en.wikipedia.org/wiki/Stochastic_gradient_descent">Stochastic Gradient Descent (SGD)</a>
|
@@ -199,9 +189,9 @@ So there are two quick examples to get you up and running. You might have notice
|
|
199
189
|
- ```.max_pool2d()```
|
200
190
|
- ```.avg_pool2d()```
|
201
191
|
|
202
|
-
|
192
|
+
# GPU Support
|
203
193
|
|
204
|
-
Have a GPU and need a speedup? You're in good luck because we have GPU support
|
194
|
+
Have a GPU and need a speedup? You're in good luck because we have GPU support via OpenCL for our operations defined in <a href="https://github.com/kevbuh/froog/blob/main/froog/ops_gpu.py">```ops_gpu.py```</a>.
|
205
195
|
|
206
196
|
Here's how you can send data to the GPU during a forward pass and bring it back to the CPU.
|
207
197
|
|
@@ -212,75 +202,19 @@ if GPU:
|
|
212
202
|
out = model.forward(Tensor(img).to_gpu()).cpu()
|
213
203
|
```
|
214
204
|
|
215
|
-
|
205
|
+
# EfficientNet in froog!
|
206
|
+
|
207
|
+
<img src="assets/efficientnet_pug.png" alt="pug" height="300">
|
216
208
|
|
217
209
|
We have a really cool finished implementation of EfficientNet built entirely in ```froog```!
|
218
210
|
|
219
211
|
In order to run EfficientNet inference:
|
220
212
|
|
221
213
|
```bash
|
222
|
-
VIZ=1
|
214
|
+
VIZ=1 python3 models/efficientnet.py <https://put_your_image_url_here>
|
223
215
|
```
|
224
216
|
|
225
|
-
I would recommend checking out the <a href="https://github.com/kevbuh/froog/blob/main/models/efficientnet.py">code</a>, it's highly documented and pretty cool.
|
226
|
-
```
|
227
|
-
Paper : https://arxiv.org/abs/1905.11946
|
228
|
-
PyTorch version : https://github.com/lukemelas/EfficientNet-PyTorch/blob/master/efficientnet_pytorch/model.py
|
229
|
-
|
230
|
-
ConvNets are commonly developed at a fixed resource cost, and then scaled up in order to achieve better accuracy when more resources are made available
|
231
|
-
The scaling method was found by performing a grid search to find the relationship between different scaling dimensions of the baseline network under a fixed resource constraint
|
232
|
-
"SE" stands for "Squeeze-and-Excitation." Introduced by the "Squeeze-and-Excitation Networks" paper by Jie Hu, Li Shen, and Gang Sun (CVPR 2018).
|
233
|
-
|
234
|
-
Environment Variables:
|
235
|
-
VIZ=1 --> plots processed image and output probabilities
|
236
|
-
|
237
|
-
How to Run:
|
238
|
-
'VIZ=1 python models/efficientnet.py https://your_image_url'
|
239
|
-
|
240
|
-
EfficientNet Hyper-Parameters and Weights:
|
241
|
-
url_map = {
|
242
|
-
'efficientnet-b0': 'https://github.com/lukemelas/EfficientNet-PyTorch/releases/download/1.0/efficientnet-b0-355c32eb.pth',
|
243
|
-
'efficientnet-b1': 'https://github.com/lukemelas/EfficientNet-PyTorch/releases/download/1.0/efficientnet-b1-f1951068.pth',
|
244
|
-
'efficientnet-b2': 'https://github.com/lukemelas/EfficientNet-PyTorch/releases/download/1.0/efficientnet-b2-8bb594d6.pth',
|
245
|
-
'efficientnet-b3': 'https://github.com/lukemelas/EfficientNet-PyTorch/releases/download/1.0/efficientnet-b3-5fb5a3c3.pth',
|
246
|
-
'efficientnet-b4': 'https://github.com/lukemelas/EfficientNet-PyTorch/releases/download/1.0/efficientnet-b4-6ed6700e.pth',
|
247
|
-
'efficientnet-b5': 'https://github.com/lukemelas/EfficientNet-PyTorch/releases/download/1.0/efficientnet-b5-b6417697.pth',
|
248
|
-
'efficientnet-b6': 'https://github.com/lukemelas/EfficientNet-PyTorch/releases/download/1.0/efficientnet-b6-c76e70fd.pth',
|
249
|
-
'efficientnet-b7': 'https://github.com/lukemelas/EfficientNet-PyTorch/releases/download/1.0/efficientnet-b7-dcc49843.pth',
|
250
|
-
}
|
251
|
-
|
252
|
-
params_dict = {
|
253
|
-
# Coefficients: width,depth,res,dropout
|
254
|
-
'efficientnet-b0': (1.0, 1.0, 224, 0.2),
|
255
|
-
'efficientnet-b1': (1.0, 1.1, 240, 0.2),
|
256
|
-
'efficientnet-b2': (1.1, 1.2, 260, 0.3),
|
257
|
-
'efficientnet-b3': (1.2, 1.4, 300, 0.3),
|
258
|
-
'efficientnet-b4': (1.4, 1.8, 380, 0.4),
|
259
|
-
'efficientnet-b5': (1.6, 2.2, 456, 0.4),
|
260
|
-
'efficientnet-b6': (1.8, 2.6, 528, 0.5),
|
261
|
-
'efficientnet-b7': (2.0, 3.1, 600, 0.5),
|
262
|
-
'efficientnet-b8': (2.2, 3.6, 672, 0.5),
|
263
|
-
'efficientnet-l2': (4.3, 5.3, 800, 0.5),
|
264
|
-
}
|
265
|
-
|
266
|
-
blocks_args = [
|
267
|
-
'r1_k3_s11_e1_i32_o16_se0.25',
|
268
|
-
'r2_k3_s22_e6_i16_o24_se0.25',
|
269
|
-
'r2_k5_s22_e6_i24_o40_se0.25',
|
270
|
-
'r3_k3_s22_e6_i40_o80_se0.25',
|
271
|
-
'r3_k5_s11_e6_i80_o112_se0.25',
|
272
|
-
'r4_k5_s22_e6_i112_o192_se0.25',
|
273
|
-
'r1_k3_s11_e6_i192_o320_se0.25',
|
274
|
-
]
|
275
|
-
```
|
276
|
-
|
277
|
-
## Linear regression
|
278
|
-
|
279
|
-
Doing linear regression in ```froog``` is pretty easy, check out the entire <a href="https://github.com/kevbuh/froog/blob/main/models/linear_regression.py">code</a>.
|
280
|
-
|
281
|
-
```bash
|
282
|
-
VIZ=1 python3 linear_regression.py
|
283
|
-
```
|
217
|
+
I would recommend checking out the <a href="https://github.com/kevbuh/froog/blob/main/models/efficientnet.py">code</a>, it's highly documented and pretty cool.
|
284
218
|
|
285
219
|
# Contributing
|
286
220
|
<!-- THERES LOT OF STUFF TO WORK ON! VISIT THE <a href="https://github.com/kevbuh/froog/blob/main/docs/bounties.md">BOUNTY SHOP</a> -->
|
@@ -290,12 +224,7 @@ Pull requests will be merged if they:
|
|
290
224
|
* increase functionality
|
291
225
|
* increase efficiency
|
292
226
|
|
293
|
-
More info on <a href="https://github.com/kevbuh/froog/blob/main/docs/contributing.md">contributing</a>.
|
294
|
-
|
295
|
-
# Documentation
|
296
|
-
|
297
|
-
Need more information about how ```froog``` works? Visit the <a href="https://github.com/kevbuh/froog/tree/main/docs">documentation</a>.
|
298
|
-
|
299
|
-
# Interested in more?
|
227
|
+
More info on <a href="https://github.com/kevbuh/froog/blob/main/docs/contributing.md">contributing</a>. Make sure to run ```python -m pytest``` before creating a PR.
|
300
228
|
|
301
|
-
|
229
|
+
<!-- # Documentation
|
230
|
+
Need more information about how ```froog``` works? Visit the <a href="https://github.com/kevbuh/froog/tree/main/docs">documentation</a>. -->
|
@@ -1,4 +1,3 @@
|
|
1
|
-
|
2
1
|
#!/usr/bin/env python3
|
3
2
|
# this file specifies how the froog package is installed, including any necessary dependencies required to run
|
4
3
|
|
@@ -10,8 +9,8 @@ with open(os.path.join(directory, 'README.md'), encoding='utf-8') as f:
|
|
10
9
|
long_description = f.read()
|
11
10
|
|
12
11
|
setup(name='froog',
|
13
|
-
version='0.
|
14
|
-
description='a
|
12
|
+
version='0.4.2',
|
13
|
+
description='a toy tensor library with opencl support',
|
15
14
|
author='Kevin Buhler',
|
16
15
|
license='MIT',
|
17
16
|
long_description=long_description,
|
@@ -21,6 +20,6 @@ setup(name='froog',
|
|
21
20
|
"Programming Language :: Python :: 3",
|
22
21
|
"License :: OSI Approved :: MIT License"
|
23
22
|
],
|
24
|
-
install_requires=['numpy', 'requests', 'matplotlib'
|
23
|
+
install_requires=['numpy', 'requests', 'matplotlib'],
|
25
24
|
python_requires='>=3.8',
|
26
25
|
include_package_data=True)
|
froog-0.3.2/froog/nn.py
DELETED
@@ -1,60 +0,0 @@
|
|
1
|
-
# _______ ______ _______ _______ _______
|
2
|
-
# | || _ | | || || |
|
3
|
-
# | ___|| | || | _ || _ || ___|
|
4
|
-
# | |___ | |_||_ | | | || | | || | __
|
5
|
-
# | ___|| __ || |_| || |_| || || |
|
6
|
-
# | | | | | || || || |_| |
|
7
|
-
# |___| |___| |_||_______||_______||_______|
|
8
|
-
|
9
|
-
from froog.tensor import Tensor
|
10
|
-
import numpy as np
|
11
|
-
|
12
|
-
def Linear(*x):
|
13
|
-
# random Glorot initialization
|
14
|
-
ret = np.random.uniform(-1., 1., size=x)/np.sqrt(np.prod(x))
|
15
|
-
return ret.astype(np.float32)
|
16
|
-
|
17
|
-
def swish(x):
|
18
|
-
return x.mul(x.sigmoid())
|
19
|
-
|
20
|
-
# *************************************
|
21
|
-
# _ ___ __ ____ ____ _____
|
22
|
-
# / | / / | / / / __ \/ __ \/ ___/
|
23
|
-
# / |/ / |/ / / / / / /_/ /\__ \
|
24
|
-
# / /| / /| / / /_/ / ____/___/ /
|
25
|
-
# /_/ |_/_/ |_/ \____/_/ /____/
|
26
|
-
#
|
27
|
-
# ************* nn ops ************
|
28
|
-
|
29
|
-
class BatchNorm2D:
|
30
|
-
"""
|
31
|
-
__call__ follows the formula from the link below
|
32
|
-
pytorch version: https://pytorch.org/docs/stable/generated/torch.nn.BatchNorm2d.html
|
33
|
-
|
34
|
-
self.weight = γ
|
35
|
-
self.bias = β
|
36
|
-
self.running_mean = E[x]
|
37
|
-
self.running_var = Var[x]
|
38
|
-
|
39
|
-
the reshaping step ensures that each channel of the input has its
|
40
|
-
own separate set of parameters (mean, variance, weight, and bias)
|
41
|
-
|
42
|
-
self.running_mean has shape [num_channels].
|
43
|
-
self.running_mean.reshape(shape=[1, -1, 1, 1]) reshapes it to [1, num_channels, 1, 1]
|
44
|
-
"""
|
45
|
-
def __init__(self, sz, eps=0.001):
|
46
|
-
self.eps = eps
|
47
|
-
self.weight = Tensor.zeros(sz)
|
48
|
-
self.bias = Tensor.zeros(sz)
|
49
|
-
|
50
|
-
# TODO: need running_mean and running_var
|
51
|
-
self.running_mean = Tensor.zeros(sz)
|
52
|
-
self.running_var = Tensor.zeros(sz)
|
53
|
-
self.num_batches_tracked = Tensor.zeros(1)
|
54
|
-
|
55
|
-
def __call__(self, x):
|
56
|
-
x = x.sub(self.running_mean.reshape(shape=[1, -1, 1, 1]))
|
57
|
-
x = x.mul(self.weight.reshape(shape=[1, -1, 1, 1]))
|
58
|
-
x = x.div(self.running_var.add(Tensor([self.eps], gpu=x.gpu)).reshape(shape=[1, -1, 1, 1]).sqrt())
|
59
|
-
x = x.add(self.bias.reshape(shape=[1, -1, 1, 1]))
|
60
|
-
return x
|
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
|