froog 0.2.8__tar.gz → 0.3.1__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.1/PKG-INFO ADDED
@@ -0,0 +1,301 @@
1
+ Metadata-Version: 2.1
2
+ Name: froog
3
+ Version: 0.3.1
4
+ Summary: a beautifully simplistic tensor library
5
+ Author: Kevin Buhler
6
+ License: MIT
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: License :: OSI Approved :: MIT License
9
+ Requires-Python: >=3.8
10
+ Description-Content-Type: text/markdown
11
+ License-File: LICENSE
12
+ Requires-Dist: numpy
13
+ Requires-Dist: requests
14
+ Requires-Dist: matplotlib
15
+ Requires-Dist: urllib
16
+
17
+ # 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
+ <div align="center" >
19
+ <img src="https://raw.githubusercontent.com/kevbuh/froog/main/assets/froog.png" alt="froog the frog" height="200">
20
+ <br/>
21
+ froog: fast real-time optimization of gradients
22
+ <br/>
23
+ a beautifully compact tensor library
24
+ <br/>
25
+ <a href="https://github.com/kevbuh/froog">homepage</a> | <a href="https://github.com/kevbuh/froog/tree/main/docs">documentation</a> | <a href="https://pypi.org/project/froog/">pip</a>
26
+ <br/>
27
+ <br/>
28
+ </div>
29
+
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).
31
+
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.
33
+
34
+ # Installation
35
+ ```bash
36
+ pip install froog
37
+ ```
38
+
39
+ More information on downloading ```froog``` in the <a href="https://github.com/kevbuh/froog/blob/main/docs/install.md">installation</a> docs.
40
+
41
+ # Features
42
+ - <a href="https://github.com/kevbuh/froog/blob/main/froog/tensor.py">Custom Tensors</a>
43
+ - Backpropagation
44
+ - Automatic Differentiation (autograd)
45
+ - Forward and backward passes
46
+ - <a href="https://github.com/kevbuh/froog/blob/main/froog/ops.py">ML Operations</a>
47
+ - 2D Convolutions (im2col)
48
+ - Numerical gradient checking
49
+ - Acceleration methods (Adam)
50
+ - Avg & Max pooling
51
+ - <a href="https://github.com/kevbuh/froog/blob/main/models/efficientnet.py">EfficientNet</a> inference
52
+ - <a href="https://github.com/kevbuh/froog/blob/main/froog/ops_gpu.py">GPU Support</a>
53
+ - and a bunch <a href="https://github.com/kevbuh/froog/tree/main/froog">more</a>
54
+
55
+ # Sneak Peek
56
+
57
+ Here's how you set up a simple multilayer perceptron for classification on MNIST. Looks pretty similar to pytorch, right?
58
+
59
+ ```python
60
+ from froog.tensor import Tensor
61
+ from froog.nn import Linear
62
+ import froog.optim as optim
63
+
64
+ class mnistMLP:
65
+ def __init__(self):
66
+ self.l1 = Tensor(Linear(784, 128)) # layer 1
67
+ self.l2 = Tensor(Linear(128, 10)) # layer 2
68
+
69
+ def forward(self, x):
70
+ # forward pass through both layers and softmax for output probabilities
71
+ return x.dot(self.l1).relu().dot(self.l2).logsoftmax()
72
+
73
+ model = mnistMLP() # create model
74
+ optim = optim.SGD([model.l1, model.l2], lr=0.001) # stochastic gradient descent optimizer
75
+ ```
76
+
77
+ # Overview
78
+
79
+ The most fundamental concept in all of ```froog``` and machine learning frameworks is the <a href="https://github.com/kevbuh/froog/blob/977b09caf32f21904768b08b2772139596604603/froog/tensor.py#L47">Tensor</a>. A <a href="https://en.wikipedia.org/wiki/Tensor_(machine_learning)">tensor</a> is simply a matrix of matrices (more accurately a multi-dimensional array).
80
+
81
+ You can create a Tensor in ```froog``` with:
82
+ ```python
83
+ import numpy as np
84
+ from froog.tensor import Tensor
85
+ my_tensor = Tensor([1,2,3])
86
+ ```
87
+
88
+ Notice how we had to import numpy. If you want to create a Tensor manually, make sure that it is a Numpy array!
89
+
90
+ <!-- Learn more about ```froog``` Tensors <a href="https://github.com/kevbuh/froog/blob/main/docs/tensors.md">here</a>. -->
91
+
92
+ # Tensors
93
+
94
+ Tensors are the fundamental datatype in froog, and one of the two main classes.
95
+
96
+ - ```def __init__(self, data)```:
97
+
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
+
100
+ - Tensor has a ```self.data``` state that it holds. this contains the data inside of the tensor.
101
+
102
+ - 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.
105
+
106
+ *Properties*
107
+
108
+ - ```shape(self)```: this returns the tensor shape
109
+
110
+ *Methods*
111
+ - ```def zeros(*shape)```: this returns a tensor full of zeros with any shape that you pass in. Defaults to np.float32
112
+
113
+ - ```def ones(*shape)```: this returns a tensor full of ones with any shape that you pass in. Defaults to np.float32
114
+
115
+ - ```def randn(*shape):```: this returns a randomly initialized Tensor of *shape
116
+
117
+ *Gradient calculations*
118
+
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.
120
+
121
+ *Functions*
122
+
123
+ 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
+
125
+ - ```def __init__(self, *tensors)```: takes in an argument of tensors, which are then saved.
126
+
127
+ - ```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.
130
+
131
+ *Register*
132
+
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
134
+
135
+ # Creating a model
136
+
137
+ 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
+
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:
140
+ 1. ```__init__``` that defines layers of the model (here we use ```Linear```)
141
+ 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
+
143
+ In order to create an instance of the ```mnistMLP``` model, do the same as you would in python: ```model = mnistMLP()``` .
144
+
145
+ We support a few different optimizers, <a href="https://github.com/kevbuh/froog/blob/main/froog/optim.py">here</a> which include:
146
+ - <a href="https://en.wikipedia.org/wiki/Stochastic_gradient_descent">Stochastic Gradient Descent (SGD)</a>
147
+ - <a href="https://en.wikipedia.org/wiki/Stochastic_gradient_descent#Adam">Adaptive Moment Estimation (Adam)</a>
148
+ - <a href="https://en.wikipedia.org/wiki/Stochastic_gradient_descent#RMSProp">Root Mean Square Propagation (RMSProp)</a>
149
+
150
+ ```python
151
+ from froog.tensor import Tensor
152
+ import froog.optim as optim
153
+ from froog.nn import Linear
154
+
155
+ class mnistMLP:
156
+ def __init__(self):
157
+ self.l1 = Tensor(Linear(784, 128))
158
+ self.l2 = Tensor(Linear(128, 10))
159
+
160
+ def forward(self, x):
161
+ return x.dot(self.l1).relu().dot(self.l2).logsoftmax()
162
+
163
+ model = mnistMLP()
164
+ optim = optim.SGD([model.l1, model.l2], lr=0.001)
165
+ ```
166
+
167
+ You can also create a convolutional neural net by
168
+
169
+ ```python
170
+ class SimpleConvNet:
171
+ def __init__(self):
172
+ conv_size = 5
173
+ channels = 17
174
+ self.c1 = Tensor(Linear(channels,1,conv_size,conv_size)) # (num_filters, color_channels, kernel_h, kernel_w)
175
+ self.l1 = Tensor(Linear((28-conv_size+1)**2*channels, 128)) # (28-conv+1)(28-conv+1) since kernel isn't padded
176
+ self.l2 = Tensor(Linear(128, 10)) # MNIST output is 10 classes
177
+
178
+ def forward(self, x):
179
+ x.data = x.data.reshape((-1, 1, 28, 28)) # get however many number of imgs in batch
180
+ x = x.conv2d(self.c1).relu() # pass through conv first
181
+ x = x.reshape(shape=(x.shape[0], -1))
182
+ return x.dot(self.l1).relu().dot(self.l2).logsoftmax()
183
+ ```
184
+
185
+ So there are two quick examples to get you up and running. You might have noticed some operations like ```reshape``` and were wondering what else you can do with ```froog```. We have many more operations that you can apply on tensors:
186
+ - ```.add()```
187
+ - ```.sub()```
188
+ - ```.mul()```
189
+ - ```.sum()```
190
+ - ```.pow()```
191
+ - ```.dot()```
192
+ - ```.relu()```
193
+ - ```.sigmoid()```
194
+ - ```.reshape()```
195
+ - ```.pad2d()```
196
+ - ```.logsoftmax()```
197
+ - ```.conv2d()```
198
+ - ```.im2col2dconv()```
199
+ - ```.max_pool2d()```
200
+ - ```.avg_pool2d()```
201
+
202
+ ## GPU Support
203
+
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.
205
+
206
+ Here's how you can send data to the GPU during a forward pass and bring it back to the CPU.
207
+
208
+ ```python
209
+ # ...
210
+ GPU = os.getenv("GPU", None) is not None
211
+ if GPU:
212
+ out = model.forward(Tensor(img).to_gpu()).cpu()
213
+ ```
214
+
215
+ ## EfficientNet in froog!
216
+
217
+ We have a really cool finished implementation of EfficientNet built entirely in ```froog```!
218
+
219
+ In order to run EfficientNet inference:
220
+
221
+ ```bash
222
+ VIZ=1 python models/efficientnet.py <https://put_your_image_url_here>
223
+ ```
224
+
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
+ ```
284
+
285
+ # Contributing
286
+ <!-- THERES LOT OF STUFF TO WORK ON! VISIT THE <a href="https://github.com/kevbuh/froog/blob/main/docs/bounties.md">BOUNTY SHOP</a> -->
287
+
288
+ Pull requests will be merged if they:
289
+ * increase simplicity
290
+ * increase functionality
291
+ * increase efficiency
292
+
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?
300
+
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
froog-0.3.1/README.md ADDED
@@ -0,0 +1,285 @@
1
+ # 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">
2
+ <div align="center" >
3
+ <img src="https://raw.githubusercontent.com/kevbuh/froog/main/assets/froog.png" alt="froog the frog" height="200">
4
+ <br/>
5
+ froog: fast real-time optimization of gradients
6
+ <br/>
7
+ a beautifully compact tensor library
8
+ <br/>
9
+ <a href="https://github.com/kevbuh/froog">homepage</a> | <a href="https://github.com/kevbuh/froog/tree/main/docs">documentation</a> | <a href="https://pypi.org/project/froog/">pip</a>
10
+ <br/>
11
+ <br/>
12
+ </div>
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).
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.
17
+
18
+ # Installation
19
+ ```bash
20
+ pip install froog
21
+ ```
22
+
23
+ More information on downloading ```froog``` in the <a href="https://github.com/kevbuh/froog/blob/main/docs/install.md">installation</a> docs.
24
+
25
+ # Features
26
+ - <a href="https://github.com/kevbuh/froog/blob/main/froog/tensor.py">Custom Tensors</a>
27
+ - Backpropagation
28
+ - Automatic Differentiation (autograd)
29
+ - Forward and backward passes
30
+ - <a href="https://github.com/kevbuh/froog/blob/main/froog/ops.py">ML Operations</a>
31
+ - 2D Convolutions (im2col)
32
+ - Numerical gradient checking
33
+ - Acceleration methods (Adam)
34
+ - Avg & Max pooling
35
+ - <a href="https://github.com/kevbuh/froog/blob/main/models/efficientnet.py">EfficientNet</a> inference
36
+ - <a href="https://github.com/kevbuh/froog/blob/main/froog/ops_gpu.py">GPU Support</a>
37
+ - and a bunch <a href="https://github.com/kevbuh/froog/tree/main/froog">more</a>
38
+
39
+ # Sneak Peek
40
+
41
+ Here's how you set up a simple multilayer perceptron for classification on MNIST. Looks pretty similar to pytorch, right?
42
+
43
+ ```python
44
+ from froog.tensor import Tensor
45
+ from froog.nn import Linear
46
+ import froog.optim as optim
47
+
48
+ class mnistMLP:
49
+ def __init__(self):
50
+ self.l1 = Tensor(Linear(784, 128)) # layer 1
51
+ self.l2 = Tensor(Linear(128, 10)) # layer 2
52
+
53
+ def forward(self, x):
54
+ # forward pass through both layers and softmax for output probabilities
55
+ return x.dot(self.l1).relu().dot(self.l2).logsoftmax()
56
+
57
+ model = mnistMLP() # create model
58
+ optim = optim.SGD([model.l1, model.l2], lr=0.001) # stochastic gradient descent optimizer
59
+ ```
60
+
61
+ # Overview
62
+
63
+ The most fundamental concept in all of ```froog``` and machine learning frameworks is the <a href="https://github.com/kevbuh/froog/blob/977b09caf32f21904768b08b2772139596604603/froog/tensor.py#L47">Tensor</a>. A <a href="https://en.wikipedia.org/wiki/Tensor_(machine_learning)">tensor</a> is simply a matrix of matrices (more accurately a multi-dimensional array).
64
+
65
+ You can create a Tensor in ```froog``` with:
66
+ ```python
67
+ import numpy as np
68
+ from froog.tensor import Tensor
69
+ my_tensor = Tensor([1,2,3])
70
+ ```
71
+
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
+
74
+ <!-- Learn more about ```froog``` Tensors <a href="https://github.com/kevbuh/froog/blob/main/docs/tensors.md">here</a>. -->
75
+
76
+ # Tensors
77
+
78
+ Tensors are the fundamental datatype in froog, and one of the two main classes.
79
+
80
+ - ```def __init__(self, data)```:
81
+
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
+
84
+ - Tensor has a ```self.data``` state that it holds. this contains the data inside of the tensor.
85
+
86
+ - 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.
89
+
90
+ *Properties*
91
+
92
+ - ```shape(self)```: this returns the tensor shape
93
+
94
+ *Methods*
95
+ - ```def zeros(*shape)```: this returns a tensor full of zeros with any shape that you pass in. Defaults to np.float32
96
+
97
+ - ```def ones(*shape)```: this returns a tensor full of ones with any shape that you pass in. Defaults to np.float32
98
+
99
+ - ```def randn(*shape):```: this returns a randomly initialized Tensor of *shape
100
+
101
+ *Gradient calculations*
102
+
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.
104
+
105
+ *Functions*
106
+
107
+ 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
+
109
+ - ```def __init__(self, *tensors)```: takes in an argument of tensors, which are then saved.
110
+
111
+ - ```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.
114
+
115
+ *Register*
116
+
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
118
+
119
+ # Creating a model
120
+
121
+ 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
+
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:
124
+ 1. ```__init__``` that defines layers of the model (here we use ```Linear```)
125
+ 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
+
127
+ In order to create an instance of the ```mnistMLP``` model, do the same as you would in python: ```model = mnistMLP()``` .
128
+
129
+ We support a few different optimizers, <a href="https://github.com/kevbuh/froog/blob/main/froog/optim.py">here</a> which include:
130
+ - <a href="https://en.wikipedia.org/wiki/Stochastic_gradient_descent">Stochastic Gradient Descent (SGD)</a>
131
+ - <a href="https://en.wikipedia.org/wiki/Stochastic_gradient_descent#Adam">Adaptive Moment Estimation (Adam)</a>
132
+ - <a href="https://en.wikipedia.org/wiki/Stochastic_gradient_descent#RMSProp">Root Mean Square Propagation (RMSProp)</a>
133
+
134
+ ```python
135
+ from froog.tensor import Tensor
136
+ import froog.optim as optim
137
+ from froog.nn import Linear
138
+
139
+ class mnistMLP:
140
+ def __init__(self):
141
+ self.l1 = Tensor(Linear(784, 128))
142
+ self.l2 = Tensor(Linear(128, 10))
143
+
144
+ def forward(self, x):
145
+ return x.dot(self.l1).relu().dot(self.l2).logsoftmax()
146
+
147
+ model = mnistMLP()
148
+ optim = optim.SGD([model.l1, model.l2], lr=0.001)
149
+ ```
150
+
151
+ You can also create a convolutional neural net by
152
+
153
+ ```python
154
+ class SimpleConvNet:
155
+ def __init__(self):
156
+ conv_size = 5
157
+ channels = 17
158
+ self.c1 = Tensor(Linear(channels,1,conv_size,conv_size)) # (num_filters, color_channels, kernel_h, kernel_w)
159
+ self.l1 = Tensor(Linear((28-conv_size+1)**2*channels, 128)) # (28-conv+1)(28-conv+1) since kernel isn't padded
160
+ self.l2 = Tensor(Linear(128, 10)) # MNIST output is 10 classes
161
+
162
+ def forward(self, x):
163
+ x.data = x.data.reshape((-1, 1, 28, 28)) # get however many number of imgs in batch
164
+ x = x.conv2d(self.c1).relu() # pass through conv first
165
+ x = x.reshape(shape=(x.shape[0], -1))
166
+ return x.dot(self.l1).relu().dot(self.l2).logsoftmax()
167
+ ```
168
+
169
+ So there are two quick examples to get you up and running. You might have noticed some operations like ```reshape``` and were wondering what else you can do with ```froog```. We have many more operations that you can apply on tensors:
170
+ - ```.add()```
171
+ - ```.sub()```
172
+ - ```.mul()```
173
+ - ```.sum()```
174
+ - ```.pow()```
175
+ - ```.dot()```
176
+ - ```.relu()```
177
+ - ```.sigmoid()```
178
+ - ```.reshape()```
179
+ - ```.pad2d()```
180
+ - ```.logsoftmax()```
181
+ - ```.conv2d()```
182
+ - ```.im2col2dconv()```
183
+ - ```.max_pool2d()```
184
+ - ```.avg_pool2d()```
185
+
186
+ ## GPU Support
187
+
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.
189
+
190
+ Here's how you can send data to the GPU during a forward pass and bring it back to the CPU.
191
+
192
+ ```python
193
+ # ...
194
+ GPU = os.getenv("GPU", None) is not None
195
+ if GPU:
196
+ out = model.forward(Tensor(img).to_gpu()).cpu()
197
+ ```
198
+
199
+ ## EfficientNet in froog!
200
+
201
+ We have a really cool finished implementation of EfficientNet built entirely in ```froog```!
202
+
203
+ In order to run EfficientNet inference:
204
+
205
+ ```bash
206
+ VIZ=1 python models/efficientnet.py <https://put_your_image_url_here>
207
+ ```
208
+
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
+ ```
268
+
269
+ # Contributing
270
+ <!-- THERES LOT OF STUFF TO WORK ON! VISIT THE <a href="https://github.com/kevbuh/froog/blob/main/docs/bounties.md">BOUNTY SHOP</a> -->
271
+
272
+ Pull requests will be merged if they:
273
+ * increase simplicity
274
+ * increase functionality
275
+ * increase efficiency
276
+
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?
284
+
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
@@ -52,7 +52,7 @@ class Mul(Function): # x.mul(y)
52
52
  return y * grad_output, x * grad_output
53
53
  register("mul", Mul)
54
54
 
55
- class Sum(Function):
55
+ class Sum(Function): # x.sum()
56
56
  """
57
57
  reduce op
58
58
  reduces its input tensor to a single value by summing all the elements
@@ -10,10 +10,9 @@
10
10
  # inspired by tinygrad
11
11
  # inspired by https://github.com/karpathy/micrograd/blob/master/micrograd/engine.py
12
12
 
13
- from functools import partialmethod
14
- from inspect import signature
15
- import numpy as np
16
13
  import os
14
+ import numpy as np
15
+ from inspect import signature
17
16
 
18
17
  try:
19
18
  import pyopencl as cl
@@ -8,29 +8,31 @@
8
8
 
9
9
  import numpy as np
10
10
  from functools import lru_cache
11
+ import pathlib, hashlib, os, tempfile, urllib
11
12
 
12
13
  def fetch(url):
13
- import requests, os, hashlib, tempfile
14
- fp = os.path.join(tempfile.gettempdir(), hashlib.md5(url.encode('utf-8')).hexdigest())
15
- if os.path.isfile(fp) and os.stat(fp).st_size > 0:
16
- print(f"opening cache from {url}...")
17
- with open(fp, "rb") as f:
18
- dat = f.read()
19
- else:
20
- print(f"fetching {url}")
21
- dat = requests.get(url).content
22
- with open(fp+".tmp", "wb") as f:
23
- f.write(dat)
24
- os.rename(fp+".tmp", fp)
25
- return dat
14
+ if url.startswith(("/", ".")): return pathlib.Path(url)
15
+ else: fp = pathlib.Path("_cache_dir") / "froog" / "downloads" / (hashlib.md5(url.encode('utf-8')).hexdigest())
16
+ if not fp.is_file():
17
+ with urllib.request.urlopen(url, timeout=10) as r:
18
+ assert r.status == 200
19
+ total_length = int(r.headers.get('content-length', 0))
20
+ (path := fp.parent).mkdir(parents=True, exist_ok=True)
21
+ with tempfile.NamedTemporaryFile(dir=path, delete=False) as f:
22
+ while chunk := r.read(16384): f.write(chunk)
23
+ f.close()
24
+ if (file_size:=os.stat(f.name).st_size) < total_length: raise RuntimeError(f"fetch size incomplete, {file_size} < {total_length}")
25
+ pathlib.Path(f.name).rename(fp)
26
+ return fp
26
27
 
27
28
  def fetch_mnist():
28
29
  import gzip
29
- parse = lambda dat: np.frombuffer(gzip.decompress(dat), dtype=np.uint8).copy()
30
- X_train = parse(fetch("http://yann.lecun.com/exdb/mnist/train-images-idx3-ubyte.gz"))[0x10:].reshape((-1, 28, 28))
31
- Y_train = parse(fetch("http://yann.lecun.com/exdb/mnist/train-labels-idx1-ubyte.gz"))[8:]
32
- X_test = parse(fetch("http://yann.lecun.com/exdb/mnist/t10k-images-idx3-ubyte.gz"))[0x10:].reshape((-1, 28, 28))
33
- Y_test = parse(fetch("http://yann.lecun.com/exdb/mnist/t10k-labels-idx1-ubyte.gz"))[8:]
30
+ parse = lambda file: np.frombuffer(gzip.open(file).read(), dtype=np.uint8).copy()
31
+ BASE_URL = "https://storage.googleapis.com/cvdf-datasets/mnist/"
32
+ X_train = parse(fetch(f"{BASE_URL}train-images-idx3-ubyte.gz"))[0x10:].reshape((-1, 28*28)).astype(np.float32)
33
+ Y_train = parse(fetch(f"{BASE_URL}train-labels-idx1-ubyte.gz"))[8:].astype(np.int8)
34
+ X_test = parse(fetch(f"{BASE_URL}t10k-images-idx3-ubyte.gz"))[0x10:].reshape((-1, 28*28)).astype(np.float32)
35
+ Y_test = parse(fetch(f"{BASE_URL}t10k-labels-idx1-ubyte.gz"))[8:].astype(np.int8)
34
36
  return X_train, Y_train, X_test, Y_test
35
37
 
36
38
  def mask_like(like, mask_inx, mask_value=1.0):