To ask for grad, just use A.grad(B) , which can give you partial A partial B
Philosophy:Efficiency is the last thing I will consider.
>>> mat1 = Mat([[1, 2], [2, 3], [2, math.e]])
>>> format(op.log(mat1), '.3f')
['0.000', '0.693']
['0.693', '1.099']
['0.693', '1.000']
- refactor project structure
- add unittest
- .T() -> .T
- add MatMulInternalError
- add NN for exclusive-or problem
- remove children of Mat and Node
- optimize zero_grad to simplify computation graph
- add node scalar operation, make Mat scalar operation depend on it
- overload > < of Node
- add softmax
- fix zero_grad error
Since Node and Mat both implement __roper__ method, we will face error when we do Mat + Node or Node + Mat
- singledispatch
- combine Node.zero_grad and Mat.zero_grad
- fix some awful feature
- add flag require_grad to simplify computation graph
- fix format
- random
- Node-based gradient -> Mat-based gradient
- use numpy avoid overloading
- use require_grad
- calculate gradient in forward step for require_grad = 1