From f50ce6adf60cf7e7c63291e9965c97d59b112b41 Mon Sep 17 00:00:00 2001 From: lucasdelimanogueira Date: Tue, 30 Apr 2024 20:34:58 -0300 Subject: [PATCH] autograd other functions --- norch/__pycache__/tensor.cpython-38.pyc | Bin 8028 -> 8465 bytes .../__pycache__/functions.cpython-38.pyc | Bin 594 -> 2222 bytes norch/autograd/functions.py | 33 ++++++++++++++++++ norch/tensor.py | 21 ++++++++++- test.py | 4 +-- 5 files changed, 55 insertions(+), 3 deletions(-) diff --git a/norch/__pycache__/tensor.cpython-38.pyc b/norch/__pycache__/tensor.cpython-38.pyc index 335bdd63192cfadf55266284e06f8596395504b5..ab543df4ed58369f5771f86f7223da5d93eec4ca 100644 GIT binary patch delta 1260 zcmZuw&u<$=6y7)9I2+49VkdU&*iJT4OX~xvh^QK+Re`i7LO`m-ZV#pHvi7bmukE#& z9ji*UR;5}({1OV96B1MoLgEr6z!G;Z75o7lsH)x&e*h8^7vMb`Qi||uzL|ONeKYgk z_x$MMM_bXWkw{3v-zWX&YJZ;jI$8|h{T8>r;wWCoQc8*smeSPt8d|`DIy3|P8NnLeCuT6_~&l7sZ*1fJ>ZPXgJrPn%KcRTL0Ue#=wTo<^rhtS`>U_w zioZrMN3cUMkMMBXFg(Ex<4CS2_JX@)-<0nqa`0gEMIr`pLGC7(y(ufLeI3q%b zAOcRg-uO`2e~(lU@$eFTRHucHvhG!e?Udx!Y!}V10iTz(pIh$UAvRqG}y!b29JyKJF zD9SjIFa@(Lje_Eysc1thTSQxe1&?E9QS7jMH+?B`1IY!(PvFGM@~3nTvhug|_NkZ1 zaFbw@V668T{?XgD>xQu;t;{xT%A-scRz}}v$|Q9@ThvScLkby2+Z2?babk2YdkJ7e zKFGZcu8icbom8AK>V?Azb4Ns|j<}DKeg!u9Zxv#)o4-tb5-IiCPbw+D%I8*I!N%~? zc&!2n%r-jCma3qQYY}4dm;C+~6^oxIc!6Ntse81#N^p&UD#C9O7zA$;R0ygBmi%mK gIU(oW!6)kVh%jmazQBUyT$nL;wH) delta 834 zcmYk4O=uHA6vy|?Zj()#Y}#Zu>82k^t5PEs5!6}>MXGJZk7D|D>BrC-TTQ=oc3UWH z5RG^c6y+Thv^BX{Pof083tmO^Rw;V%X{gf49#V4~K&a zJv$pm=ZCu98UvwQ4{7QtdBq9llu^ZloU*8kq^FditQ3G8R#mz@iaA>`JVhhTgKmY< zoP3r1fVeNClIB4f3e2tZSP^ot$iy{|<(N%>ptT*YPiE!)Bul2pL_p(twrljM+^=kzOZBP{0Qo)A6ve0Z%L21_yXn@i!b~b;D%7 z!eh~`j`I|W3lcGjOA;pGtDken6`XJ5@92o{vebLgf6UQ6nS7SL=GF{74ir`u}*mMu#__1jodNFG^<6XNQM)9S6!1q(u*@d5NOVuEV z4VHz$WWPR1a)ych_^qW0my!Xp){{f^r%4u55bfS1WWrBv!QycyAW{6V~eG=6J&B|y@Vq8M*M@&o1NN|Z+i8+ZY f_&uG#m2`W=(p5dACyAEcsHbr&oq!y^OHcjbVi~U!5*!=Wb}1-Q5AZ|U zWB$@!dntdRr_Q%dOd=9tm5pXIGi%T5+Zlh|*jQtZzv=HlL)J>cs@ zJU|OPNGISBLkaM{(P0u=9pS`~72=fxrvnO4Yx50YD(7fg8k?l0u4fOlCpH3&yiwq~ zYRz>=vB*O3>#lp2d0~Dc>+p?o&bdOdB>YKE8z`}8bGTz_jZebDLIV3lr2y_^NB;wG zUM1WDiR9^B^3y z4#NO*<$RC?rNFp5$x2-GZ3I0{eRsLX)l~<;2QYwXoL61&ZL0i~H^8F{nr8b3&3{A0 zr0%>`SisbM0hIt`i_E-$sbbtf^B_R#oorOJgf1Cb!~ze}rI@z=^jo44XmVA_zb4ca zn96wK+0YzXL;H$1ik7TMJf&)J6eMmq zI0=;93u7-;jvq%9VVWpQc&VrCZ(f)MD<{_LB243QA4AZ7DOyrZ15CZbt8B!Qh7+Zk2nJJ1Pg(;XplX>z+X4{F| ztz|VCZ?Tu8<`w4`6>BozVku6|NxQ{Zaf`8XB|{PWWPZklitIoWG?|K6fYdFH^rFO+ z%+$P+B9JJA;Fx@oQJ+zBG9#0k6emcO8!m;c$dO4(-%pdVh!LACQ0x|mO>TZlX-=vg KNX2I$W&i-jI4iaQ diff --git a/norch/autograd/functions.py b/norch/autograd/functions.py index a2a3344..67bc301 100644 --- a/norch/autograd/functions.py +++ b/norch/autograd/functions.py @@ -4,3 +4,36 @@ class AddBackward: def backward(self, gradient): return [gradient, gradient] + +class SubBackward: + def __init__(self, x, y): + self.tensors = [x, y] + + def backward(self, gradient): + return [gradient, -gradient] + +class ScalarMulBackward: + def __init__(self, x, scalar): + self.tensors = [x] + self.scalar = scalar + + def backward(self, gradient): + return [gradient * self.scalar] + + +class ElementwiseMulBackward: + def __init__(self, x, y): + self.tensors = [x, y] + + def backward(self, gradient): + return [gradient * self.tensors[1], gradient * self.tensors[0]] + +class SumBackward: + def __init__(self, x): + self.tensor = x + + def backward(self, gradient): + # Since sum reduces a tensor to a scalar, gradient is broadcasted to match the original shape. + return self.tensor.ones_like() * float(gradient.tensor.contents.data.value) + + diff --git a/norch/tensor.py b/norch/tensor.py index 265cb6b..5103ec1 100644 --- a/norch/tensor.py +++ b/norch/tensor.py @@ -133,8 +133,13 @@ class Tensor: return if gradient is None: + if self.shape != [1]: + raise RuntimeError("Gradient argument must be specified for non-scalar tensors.") gradient = self.ones_like() + if self.shape != [1]: + raise RuntimeError("Only scalar tensors can be used to trigger backward propagation.") + if self.grad is None: self.grad = gradient else: @@ -229,6 +234,10 @@ class Tensor: result_data.ndim = self.ndim result_data.device = self.device + result_data.requires_grad = self.requires_grad or other.requires_grad + if result_data.requires_grad: + result_data.grad_fn = SubBackward(self, other) + return result_data def __mul__(self, other): @@ -243,6 +252,10 @@ class Tensor: result_data.tensor = Tensor._C.scalar_mul_tensor(self.tensor, ctypes.c_float(other)) + result_data.requires_grad = self.requires_grad + if result_data.requires_grad: + result_data.grad_fn = ScalarMulBackward(self, other) + return result_data elif isinstance(other, Tensor): if self.shape != other.shape: @@ -259,6 +272,10 @@ class Tensor: result_data.ndim = self.ndim result_data.device = self.device + result_data.requires_grad = self.requires_grad or other.requires_grad + if result_data.requires_grad: + result_data.grad_fn = ElementwiseMulBackward(self, other) + return result_data else: raise TypeError("Unsupported operand type(s) for *: '{}' and '{}'".format(type(self), type(other))) @@ -321,6 +338,8 @@ class Tensor: result_data.ndim = 1 result_data.device = self.device - + result_data.requires_grad = self.requires_grad + if result_data.requires_grad: + result_data.grad_fn = SumBackward(self) return result_data \ No newline at end of file diff --git a/test.py b/test.py index 0dc6a80..56e4173 100644 --- a/test.py +++ b/test.py @@ -17,7 +17,7 @@ def matrix_sum(matrix1, matrix2): if __name__ == "__main__": import norch a = norch.Tensor([[1, 2, 3], [1, 2, 3], [1, 2, 3]], requires_grad=True)#.to("cuda") - b = norch.Tensor([[1, 2, 3], [1, 2, 3], [1, 2, 3]], requires_grad=True) + b = norch.Tensor([[1, 400, 3], [1, 2, 3], [1, 2, 3]], requires_grad=True) import time import random import numpy as np @@ -29,7 +29,7 @@ if __name__ == "__main__": #d = b-c - c = (a + b) + c = a.sum() c.backward() print(a.grad) print(b.grad)