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.
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: froog
3
- Version: 0.3.2
4
- Summary: a beautifully simplistic tensor library
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">16k pip installs!</a>) meant for those looking to get into machine learning and who want to understand how the underlying machine learning framework's code works before they are ultra-optimized (which all modern ml libraries are).
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
- ```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 1000 lines.
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 numpy. If you want to create a Tensor manually, make sure that it is a Numpy array!
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 numpy backend, the input data into tensors has to be a numpy array.
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. it will take the current operation, lets say a dot product, and go to the dot product definition in ```froog/ops.py```, which contains a backward pass specfically for dot products. all methods, from add to 2x2 maxpools, have this backward pass implemented.
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)```: this function 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
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 so it resembles very basic python concepts like classes. There's really only two methods you need to define:
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
- In order to create an instance of the ```mnistMLP``` model, do the same as you would in python: ```model = mnistMLP()``` .
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
- ## GPU Support
192
+ # GPU Support
203
193
 
204
- Have a GPU and need a speedup? You're in good luck because we have GPU support from for our operations defined in <a href="https://github.com/kevbuh/froog/blob/main/froog/ops_gpu.py">```ops_gpu.py```</a>. In order to do this we have a backend built on <a href="https://en.wikipedia.org/wiki/OpenGL">OpenGL</a> that invokes kernel functions that work on the GPU.
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
- ## EfficientNet in froog!
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 python models/efficientnet.py <https://put_your_image_url_here>
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. Here's some of the documentation
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
- If you thought ```froog``` was cool, check out the inspirations for this project: pytorch, tinygrad, and https://github.com/karpathy/micrograd/blob/master/micrograd/engine.py
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">16k pip installs!</a>) meant for those looking to get into machine learning and who want to understand how the underlying machine learning framework's code works before they are ultra-optimized (which all modern ml libraries are).
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
- ```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 1000 lines.
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 numpy. If you want to create a Tensor manually, make sure that it is a Numpy array!
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 numpy backend, the input data into tensors has to be a numpy array.
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. it will take the current operation, lets say a dot product, and go to the dot product definition in ```froog/ops.py```, which contains a backward pass specfically for dot products. all methods, from add to 2x2 maxpools, have this backward pass implemented.
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)```: this function 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
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 so it resembles very basic python concepts like classes. There's really only two methods you need to define:
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
- In order to create an instance of the ```mnistMLP``` model, do the same as you would in python: ```model = mnistMLP()``` .
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
- ## GPU Support
180
+ # GPU Support
187
181
 
188
- Have a GPU and need a speedup? You're in good luck because we have GPU support from for our operations defined in <a href="https://github.com/kevbuh/froog/blob/main/froog/ops_gpu.py">```ops_gpu.py```</a>. In order to do this we have a backend built on <a href="https://en.wikipedia.org/wiki/OpenGL">OpenGL</a> that invokes kernel functions that work on the GPU.
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
- ## EfficientNet in froog!
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 python models/efficientnet.py <https://put_your_image_url_here>
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. Here's some of the documentation
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
- If you thought ```froog``` was cool, check out the inspirations for this project: pytorch, tinygrad, and https://github.com/karpathy/micrograd/blob/master/micrograd/engine.py
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
- // TODO: stability with max
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
- # TODO Finish this
479
- pass
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
- return pooling_op(ctx, input, kernel_size, iter_op, result_op, init_val=init_val)
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
- # TODO Finish this
493
- pass
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 doesnt work is that it violates the central idea behind stochastic gradient descent,
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.3.2
4
- Summary: a beautifully simplistic tensor library
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">16k pip installs!</a>) meant for those looking to get into machine learning and who want to understand how the underlying machine learning framework's code works before they are ultra-optimized (which all modern ml libraries are).
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
- ```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 1000 lines.
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 numpy. If you want to create a Tensor manually, make sure that it is a Numpy array!
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 numpy backend, the input data into tensors has to be a numpy array.
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. it will take the current operation, lets say a dot product, and go to the dot product definition in ```froog/ops.py```, which contains a backward pass specfically for dot products. all methods, from add to 2x2 maxpools, have this backward pass implemented.
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)```: this function 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
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 so it resembles very basic python concepts like classes. There's really only two methods you need to define:
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
- In order to create an instance of the ```mnistMLP``` model, do the same as you would in python: ```model = mnistMLP()``` .
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
- ## GPU Support
192
+ # GPU Support
203
193
 
204
- Have a GPU and need a speedup? You're in good luck because we have GPU support from for our operations defined in <a href="https://github.com/kevbuh/froog/blob/main/froog/ops_gpu.py">```ops_gpu.py```</a>. In order to do this we have a backend built on <a href="https://en.wikipedia.org/wiki/OpenGL">OpenGL</a> that invokes kernel functions that work on the GPU.
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
- ## EfficientNet in froog!
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 python models/efficientnet.py <https://put_your_image_url_here>
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. Here's some of the documentation
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
- If you thought ```froog``` was cool, check out the inspirations for this project: pytorch, tinygrad, and https://github.com/karpathy/micrograd/blob/master/micrograd/engine.py
229
+ <!-- # Documentation
230
+ Need more information about how ```froog``` works? Visit the <a href="https://github.com/kevbuh/froog/tree/main/docs">documentation</a>. -->
@@ -3,7 +3,6 @@ README.md
3
3
  setup.py
4
4
  froog/__init__.py
5
5
  froog/gradcheck.py
6
- froog/nn.py
7
6
  froog/ops.py
8
7
  froog/ops_gpu.py
9
8
  froog/optim.py
@@ -1,4 +1,3 @@
1
1
  numpy
2
2
  requests
3
3
  matplotlib
4
- urllib
@@ -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.3.2',
14
- description='a beautifully simplistic tensor library',
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', 'urllib'],
23
+ install_requires=['numpy', 'requests', 'matplotlib'],
25
24
  python_requires='>=3.8',
26
25
  include_package_data=True)
@@ -2,7 +2,7 @@ import numpy as np
2
2
  from tqdm import trange
3
3
  from froog.tensor import Tensor, GPU
4
4
  from froog.utils import fetch_mnist
5
- from froog.nn import Linear
5
+ from froog.ops import Linear
6
6
  import froog.optim as optim
7
7
  import unittest
8
8
  import os
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