which I suppose can best be described as Lisp and Python having a baby. It was immense fun to code neural networks from scratch in it. I hope Clojure can find a bigger place in the world of ML.
[1] http://torch.ch/
For high performing parts of your code, a subset of lush would generate C code and compile them. I imagined that this is what it was like to write the first version of C++, the one that generated C code.
Perhaps Cling can do something, or not, but I guess that's up to people who prefer Cling to find out and utilize.
* Always have the call to action repeated at the bottom of the page; you did a great job having it above the fold, but I got to the end and had to scroll back up to express intent. That's a flowbreaking design.
* This is purely stylistic, but I strongly prefer the first letter of each line to be capitalized. I find the stylistic inconsistency around capitalization offputting.
* You have pretty nicely made docs, consider making the link to view the sample chapters a clickable picture of the first diagram-page in your chapter.
Thanks for making this!
Love it! :D What better way to define a neural network in code than an S-expression?
Python:
model = Sequential()
model.add(Conv2D(32, kernel_size=(3, 3),
activation='relu',
input_shape=(28, 28, 1)))
Clojure: (defonce net-bp
(network (desc [128 1 28 28] :float :nchw)
Which one is more readable? looking on the Clojure code I see 128 1 28 28 thrown on me, without digging in the documentation I have no idea what's happening.Python:
model = Sequential()
model.add(Conv2D(32, (3, 3),'relu', (28, 28, 1)))
Clojure: (defonce net-bp
(network (desc :input-shape [128 1 28 28]
:type :float
:something :nchw)
It all depends on how desc is defined.Disclaimer: no idea what those functions mean, I only made syntactic changes.
Both are equally readable to me.
Now, granted 128 1 28 28 can be difficult to understand without documentation but that is not due to Lisp's fully parenthesized prefix notation. The Clojure code would also look equally readable if it had used keyword arguments.
Are you sure you are not confounding familiarity with readability? With Lisp, after a while, the parentheses become invisible to the programmer.
You’re throwing alway all the names of the arguments and using arbitrary words like “conv” to represent operations.
This is typical bad clojure in my experience; write once, forget wtf the magic was, throw away and rewrite it again later.
Clojure doesn’t have to be incomprehensible arcane magic that does everything in 10 lines.
The more complex the code, the more important it is that what you do is clear and clearly documented.
Don’t write a 1 line regex to solve a complicated problem; it’s the wrong tool for that job, no matter how smart your substring matches are.
You don’t win a prize for making unmaintainable code.
I similarly think the goal of being burning my concise in ML code is deeply misguided.
Regarding the magic, I believe you haven't read my writings related to this. Exactly the opposite - there is no magic other than usual Clojure-fu, which I explain in a layered way.
But it's difficult to exactly reply to your critique, because you haven't given any example of an approach that would be good Clojure. Ok, give me an example of how you would do it in a comprehensible way (if what I provide is incomprehensible). You don't have to actually implement it. Show a non-working alternative. How would it look like?
The code is on github [2, 3] see for yourself if you think it's more or less obvious than the python equivalent of a 'trivial' network.
I would say 'conv2d' is probably reasonably standard in meaning; I refer to 'convo' as arbitrary, because it is. Either (ideally) avoid abbreviations, or use standard ones.
[1] - https://pytorch.org/docs/stable/generated/torch.nn.Conv2d.ht...
[1] - https://github.com/uncomplicate/deep-diamond/blob/master/tes...
[2] - https://github.com/uncomplicate/deep-diamond/blob/master/tes...
Also, most options are provided as a map to convo as well it looks like, so you'd have similar named arguments for convo once you get to defining optional things like padding and strides.
This book explains and executes every single line of code interactively, from low level operations to high-level networks that do everything automatically. The code is built on the state of the art performance operations of oneDNN (Intel, CPU) and cuDNN (CUDA, GPU). Very concise readable and understandable by humans.
https://aiprobook.com/deep-learning-for-programmers/
Here's the open source library built throughout the book:
https://github.com/uncomplicate/deep-diamond
Some chapters from the beginning of the book are available on my blog, as a tutorial series:
https://dragan.rocks