From e5819a4121288ed45d65a340ff667de3578d6ccb Mon Sep 17 00:00:00 2001 From: lucasdelimanogueira Date: Mon, 6 May 2024 19:47:27 -0300 Subject: [PATCH] nn module v1 --- build/libtensor.so | Bin 125568 -> 121424 bytes build/tensor.o | Bin 37944 -> 36608 bytes norch/__init__.py | 3 +- norch/__pycache__/__init__.cpython-38.pyc | Bin 193 -> 220 bytes norch/__pycache__/tensor.cpython-38.pyc | Bin 13289 -> 12248 bytes norch/csrc/tensor.cpp | 36 ------------------ norch/nn/__init__.py | 3 +- norch/nn/__pycache__/__init__.cpython-38.pyc | Bin 199 -> 215 bytes norch/nn/__pycache__/loss.cpython-38.pyc | Bin 0 -> 1403 bytes norch/nn/__pycache__/module.cpython-38.pyc | Bin 3442 -> 4026 bytes norch/nn/__pycache__/parameter.cpython-38.pyc | Bin 728 -> 728 bytes norch/nn/loss.py | 25 ++++++++++++ norch/nn/module.py | 14 +++++++ .../modules/__pycache__/linear.cpython-38.pyc | Bin 1086 -> 1036 bytes norch/nn/modules/linear.py | 1 - norch/nn/parameter.py | 1 - norch/optim/__init__.py | 1 + .../optim/__pycache__/__init__.cpython-38.pyc | Bin 0 -> 183 bytes .../__pycache__/optimizer.cpython-38.pyc | Bin 0 -> 1049 bytes norch/optim/optimizer.py | 22 +++++++++++ norch/optim/optimizers/__init__.py | 1 + .../__pycache__/__init__.cpython-38.pyc | Bin 0 -> 187 bytes .../optimizers/__pycache__/sgd.cpython-38.pyc | Bin 0 -> 1098 bytes norch/optim/optimizers/sgd.py | 19 +++++++++ test.py | 33 +++++++++++++--- 25 files changed, 113 insertions(+), 46 deletions(-) create mode 100644 norch/nn/__pycache__/loss.cpython-38.pyc create mode 100644 norch/nn/loss.py create mode 100644 norch/optim/__init__.py create mode 100644 norch/optim/__pycache__/__init__.cpython-38.pyc create mode 100644 norch/optim/__pycache__/optimizer.cpython-38.pyc create mode 100644 norch/optim/optimizer.py create mode 100644 norch/optim/optimizers/__init__.py create mode 100644 norch/optim/optimizers/__pycache__/__init__.cpython-38.pyc create mode 100644 norch/optim/optimizers/__pycache__/sgd.cpython-38.pyc create mode 100644 norch/optim/optimizers/sgd.py diff --git a/build/libtensor.so b/build/libtensor.so index dacb48e0bb022859616833926ef2ebc1b0eab7bf..856e9851d8365d3814006ac71d5dd33a113ef558 100755 GIT binary patch delta 25605 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 F{|5mWVo(48 delta 26482 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 literal 37944 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 diff --git a/norch/__init__.py b/norch/__init__.py index 98156f7..e013fa7 100644 --- a/norch/__init__.py +++ b/norch/__init__.py @@ -1 +1,2 @@ -from norch.tensor import Tensor \ No newline at end of file +from norch.tensor import Tensor +from .optim import * \ No newline at end of file diff --git a/norch/__pycache__/__init__.cpython-38.pyc b/norch/__pycache__/__init__.cpython-38.pyc index bf1db319d29c7a6e6b07713e7f40c25a58ed3d4a..60e1eea56ed04b091e3eea4e2a40899c12ea57d4 100644 GIT binary patch delta 126 zcmX@ec!!ZUl$V!_0SF33EYnOT^2)|a068fPDU3M`xr|Yaj0`DEDa<)cAq*)j!3>(L zFF|TG8E>(Lq~;ap7rkVJa2d7yG?}A#^74z4GxSQpQbkNasavf11tpoeD;bK|fV?8M NiFtnP#UKeDMgXeZ99jSX delta 99 zcmcb^c#x4dl$V!_0SH>-4ASH$^2)jh068fPDU3M`xr|Yaj0`DE!3>(rFF|TF8E>(L qq~;ap7x`&2Me*e27bR!tm4F3`n1J#t8H$*JR1x#Uc0bn7ARPc6krqY( diff --git a/norch/__pycache__/tensor.cpython-38.pyc b/norch/__pycache__/tensor.cpython-38.pyc index d22bb3487b42de49907843d4667ea7b54f648206..ce87ffb2f013b1ac88340e55f5f6e187e4937681 100644 GIT binary patch delta 861 zcmZXS%TE(g6o-3SS_(r4aMDs#ItVRv!18D%i1HAPVnk~M%A-6cg(+{CdYMWzF_OsI zM9$u4Sg;~wV&ck;JM|9`7RG=s+-XeQ7!vOp2+=s1e7TeRJKsI`WWG&(RK>;W^-CB$$^`=a_mJ>Hy5(&1c?yGsHC}W(efO21|-~+qHEw zZ+KZ1kL);R7L6U}ZH)AX%|xybIU2FF_{N8a#)b6 zow_ldW~_l~8u?*9S4z`V^*u)X3N{?i$1UG>0qdphKEePslD)`S!l)GvOXBZ=0FH) zaWt^v8Rx}{-MR)FwC1!Q$b(+YmAiya5>F6lfv zKvnkW0tYt3GD)})E`ZlB?}h1{%}@=lD=}g5Uzu3I$6>H+TAR6}s-Mi9nyUam%^S5% z08aDa>30An7_WN^X?&a~V`F_cG~)gGV6ozeGaq+dQ6Nrl7%xQ=56+OiiO@_qPv{_6 zKUoj0h6qW*C}E616J{D=k}yS>CCn2R2s$A{xJ_V$C5|0;hUu9!Gww3Oh9_g?(2i}K VejJOHi_FU-ii?R9&*G!l@E>>m-Io9W delta 2026 zcmZ`)O>7%Q6y7&$JN7zpejLZ9a#Dw+X|_L38)%d&O`EnrtBR(mX=zBBZnoJ?VkhxB zvzs&xYq`R`QT4za;6?%$pb`RE2%!p4#SJ)sR3v1nLZt}7ja~q8f%n#FTK-m^Z{Ezj z`R2{@zHh(Pex8Y(t*cWcd|v;vfBM?F_apZKcD%y+;gHzR+M`28oe{YTWA#S8(Qs87 zYcLLr1@=MRpm7jK-3A+x)Fb8X^06RP%2xOn2L0v9NZbd{iIt`|8lFXBev%+ca7yfm z8iCVf4v59pxVRBbNBlUXb`+caqqv)BEjm5}40cs={H~M@xR4E$*i%voN>E^~v{vJ? zbtp(KY*_HXYfk1DoS-3>;3aTEYl;(I-|T0YQ=6^JMzs3PmFl>G=GP*~(TFECuCqc> zc4|vf!RN}ZPirLdwWf6m?EuW8aK@EdM2Li{S`cHpahqT3igR#Be6=`Y=Df z;VHnoJ$Pg^eAsMiNd#A#Xg<#hcsB<(x~x=W&r2XJGD8}Xcmh3CsK^WYiYixFdQXMf zd$ILaQ|jfl8GS0D12bmMT*>o;UlB7M;gbT=YWo>8XInh2X}V!(TKd4eHKotn2h*GW zf9$Th*r|mj+eyue+wu4zbj~;#E2k!S7tza^oKx{n&s(~~dvSuFAlOe(L+iB{xuqLZ zy6tF=#RtXx<|I@^B$nP;2_H6$Bl^_bC7m05D>|!w-bs7>mNRSeu@K%(vuE|ZDc;+) zC0Vl(=@;l?)7cV4pjJ+T0*biRk`!;n?rl@qFnD^)gt!T)=aBr+l;XH3(Gi^axp#D0NLB;oYvS@bR0losR13+#z;#KM`Jjgb1%7 z3f*;Zul#cNae&{;x7B?BN?FskwQU7w8%@r9vjL*V0iV! z8J*9VPRe`dH;PVQHdE%}l0KiZcxpB?gN2bYG7DI{ScG=UnbmU$Caz{?GC6c}%v=%c z`fu98Fdx)BZE5n7Goci~kTwJb@O;L}W7v}q9Gt~L1+;&t2_MDjljyjiBTQQD+R%|l z>bz+EhnjfwtMQ|HE@wHZP4DVuZ8hx41>b`FJV-D|u$|yI0Vzr)$jxPw+or)|G}l2u zUn#YwS`1X)W3~AXZsyILp<$lvu^^&moAc9S3R#YqV*aF9564gQ^SI$@x=tG!5-N$0 zMIb1rP*oa0krg=rK?vY{kgZ1leNju5hj|O`d`5*~`l(`n`fPC@&hS2heu4u8Lj>L@ zZiK8!f{O$u!88GtHJ>NQ5m*GAz#&*7xJ0l*aG7A0;6;Q=Fwd>L$(_sGrLPD-FKT<* dVMwHVQqU?+^`sh diff --git a/norch/csrc/tensor.cpp b/norch/csrc/tensor.cpp index 741662e..1c46245 100644 --- a/norch/csrc/tensor.cpp +++ b/norch/csrc/tensor.cpp @@ -11,7 +11,6 @@ extern "C" { Tensor* create_tensor(float* data, int* shape, int ndim, char* device) { - printf("Creating tensor\n"); Tensor* tensor = (Tensor*)malloc(sizeof(Tensor)); if (tensor == NULL) { fprintf(stderr, "Memory allocation failed\n"); @@ -44,39 +43,6 @@ extern "C" { tensor->strides[i] = stride; stride *= shape[i]; } - - printf("Tensor created successfully\n"); - printf("Tensor information:\n"); - printf("Number of dimensions: %d\n", tensor->ndim); - printf("Number size: %d\n", tensor->size); - printf("Device: %s\n", tensor->device); - - printf("Shape: ["); - for (int i = 0; i < ndim; i++) { - printf("%d", tensor->shape[i]); - if (i < ndim - 1) { - printf(", "); - } - } - printf("]\n"); - - printf("Strides: ["); - for (int i = 0; i < ndim; i++) { - printf("%d", tensor->strides[i]); - if (i < ndim - 1) { - printf(", "); - } - } - printf("]\n"); - - /*printf("Data:\n["); - for (int i = 0; i < stride; i++) { - printf("%.2f", tensor->data[i]); - if (i < stride - 1) { - printf(", "); - } - } - printf("]\n\n\n");*/ return tensor; } @@ -98,8 +64,6 @@ extern "C" { } void to_device(Tensor* tensor, char* target_device) { - printf("Sending tensor to device: %s\n", target_device); - if ((strcmp(target_device, "cuda") == 0) && (strcmp(tensor->device, "cpu") == 0)) { cpu_to_cuda(tensor); } diff --git a/norch/nn/__init__.py b/norch/nn/__init__.py index 12c8a92..dadface 100644 --- a/norch/nn/__init__.py +++ b/norch/nn/__init__.py @@ -1,2 +1,3 @@ from .modules import * -from .activation import * \ No newline at end of file +from .activation import * +from .loss import * \ No newline at end of file diff --git a/norch/nn/__pycache__/__init__.cpython-38.pyc b/norch/nn/__pycache__/__init__.cpython-38.pyc index 8726808e98edf3f98a7d2e931a956a88dc1044b5..1f19ab62795fbb5ec30fbec1f63af9cd477f3d17 100644 GIT binary patch delta 100 zcmX@kc%6|ql$V!_0SF?wEYn;j^2+MV068fPDU3M`ArP7oN;3gzreFq5=9i2>C7O)4 n7`6N~nI{H{^50^~$uBNm$xy@!lqh1Im>LLf9FkY);I&}4qe2$a%fyv3;H tr^$4SJvTq4G$*wB(p5BBr`v6B|{MlP)!lb#M&S>CLoK05dd-U7Z(5k diff --git a/norch/nn/__pycache__/loss.cpython-38.pyc b/norch/nn/__pycache__/loss.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9f14563815cf8eaeeed05164a9068af89a8e719f GIT binary patch literal 1403 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 R0Aql8fUG+%&OYR({{XQl@gV>J diff --git a/norch/nn/__pycache__/parameter.cpython-38.pyc b/norch/nn/__pycache__/parameter.cpython-38.pyc index 7c686b8177ea2771ab48033c592b38ecf60edaf8..a54bfe0836fb64a82650f5f7c971bc3f4c0fc807 100644 GIT binary patch delta 28 icmcb?dV`fWl$V!_0SKC7EYnms@;+x|WSsn!@i72pGza(q delta 28 icmcb?dV`fWl$V!_0SGF7TcoLNPHGVokRLVqEVDfTohc(v diff --git a/norch/nn/modules/linear.py b/norch/nn/modules/linear.py index 83ce02d..2d61023 100644 --- a/norch/nn/modules/linear.py +++ b/norch/nn/modules/linear.py @@ -10,7 +10,6 @@ class Linear(Module): self.bias = Parameter(shape=[self.output_dim, 1]) def forward(self, x): - print(self.weight.shape, x.shape, self.bias.shape, "@@@@@@\n\n\n\n") z = self.weight @ x + self.bias return z diff --git a/norch/nn/parameter.py b/norch/nn/parameter.py index 8203ba4..2324a1a 100644 --- a/norch/nn/parameter.py +++ b/norch/nn/parameter.py @@ -8,5 +8,4 @@ class Parameter(Tensor): """ def __init__(self, shape): data = utils.generate_random_list(shape=shape) - super().__init__(data, requires_grad=True) \ No newline at end of file diff --git a/norch/optim/__init__.py b/norch/optim/__init__.py new file mode 100644 index 0000000..c5baa22 --- /dev/null +++ b/norch/optim/__init__.py @@ -0,0 +1 @@ +from .optimizers import * \ No newline at end of file diff --git a/norch/optim/__pycache__/__init__.cpython-38.pyc b/norch/optim/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..34d28a85703fb81364eb566b4a50638ec941d041 GIT binary patch literal 183 zcmWIL<>g`kf-)h?G)W-+7{oyaOhAqU5Et_Ri4=wu#vFzah7_h?22JLdj6fkx##@Y9 zewvI?T=@khnYo!&sYS&r8H$*JQefhjqkcwyZmNDxPM*F?esXDUYFjlcRu;ANY7k5j@@jn^$mf!l@)R z9Z`yMAcHy_g_L|CJmk?8;gO)1;V9yr1Cqr*;R}*c7w+ut!4)5h#wcB)_8~#my9_Tt z5M)F-83mkS`wR?0G*0+8G;X#dh+_#-ky#kKD zfxF`oJfS%&+9x0xKR`NLy-$s%ztW-$qUqB<1z}FUl6~@Ja86-z^ag4=jj;@k5wpO9 z=6bM4iXH2Mg9dAGy(PZ?l%qGmjBN1dAOOZ}{l1=MoMF~Q{2EvY#$2DVTJfnwdBE7| zw2*%+UB3=a@^5(9vZJd>FX+Q_TZ#jkaa{vGU literal 0 HcmV?d00001 diff --git a/norch/optim/optimizer.py b/norch/optim/optimizer.py new file mode 100644 index 0000000..fabd468 --- /dev/null +++ b/norch/optim/optimizer.py @@ -0,0 +1,22 @@ +from abc import ABC +from norch.tensor import Tensor + +class Optimizer(ABC): + """ + Abstract class for optimizers + """ + + def __init__(self, parameters): + if isinstance(parameters, Tensor): + raise TypeError("parameters should be an iterable but got {}".format(type(parameters))) + elif isinstance(parameters, dict): + parameters = parameters.values() + + self.parameters = list(parameters) + + def step(self): + raise NotImplementedError + + def zero_grad(self): + for parameter in self.parameters: + parameter.zero_grad() \ No newline at end of file diff --git a/norch/optim/optimizers/__init__.py b/norch/optim/optimizers/__init__.py new file mode 100644 index 0000000..bd076ac --- /dev/null +++ b/norch/optim/optimizers/__init__.py @@ -0,0 +1 @@ +from .sgd import * \ No newline at end of file diff --git a/norch/optim/optimizers/__pycache__/__init__.cpython-38.pyc b/norch/optim/optimizers/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..463119074bbc9bbc48c3e4148eae8dcfa3d771fe GIT binary patch literal 187 zcmWIL<>g`kf&?MUG$A1U7{oyaOhAqU5Et_Ri4=wu#vFzah7_h?22JLdj6fkx##@Y9 zewvI?%*E*`D;bKIfns3dmydo%er~FMPEMY_OMY@`ZfaghezAU0YI0F(Vo7RzL1jsP zQF4ZUT7JHM9+;J1P?DLe4<<9KQj3c9LRVpw7tZ|I zYabW6YG>J~-7S(yu0~~H+FB)A^-CqjrzP@r+#VD~d*oIHk=k~as5NbKBwOQCTkmA4 zDU%`}@7Aa&sxAZ$(JVKb5&wG8;Yc#9IK{peWS90-X zw6R{=fBaJQr0-D82Q($Mhs{|R4&NT|8Jl4Phg`BpP@&GSkwdTYc3cxHJ`8r?A$hUI zF9Gk;`StA%oYY-&`M%!3$OyltM##KI!k2LFq1(Z6z^s3y`?Be4>a%5OT)Uye1^CxZ zO<0kaQjKrn%D7*QZL=-@fJb~95nMWKavf3%8cj@(w2zQpA#7cUypWTO)(s&}CjD%A z;t14_Dg5R&zlqAS6~}I#?o&v|HZe`?xgm(yR;bCd-wbT+W^go(ux+@ZYL)K4)bz$( WU4!I8J6us`S=%oC2rhJkHTYjTr}H)d literal 0 HcmV?d00001 diff --git a/norch/optim/optimizers/sgd.py b/norch/optim/optimizers/sgd.py new file mode 100644 index 0000000..eb194db --- /dev/null +++ b/norch/optim/optimizers/sgd.py @@ -0,0 +1,19 @@ +from ..optimizer import Optimizer +from norch.tensor import Tensor + +class SGD(Optimizer): + def __init__(self, parameters, lr=1e-1, momentum=0): + super().__init__(parameters) + self.lr = lr + self.momentum = momentum + self._cache = {'velocity': [p.zeros_like() for p in self.parameters]} + + def step(self): + for i, parameter in enumerate(self.parameters): + velocity = self._cache['velocity'][i] + + velocity = self.momentum * velocity - self.lr * parameter.grad + + parameter += velocity + + self._cache['velocity'][i] = velocity diff --git a/test.py b/test.py index 706ab10..68948c6 100644 --- a/test.py +++ b/test.py @@ -73,22 +73,43 @@ if __name__ == "__main__": def __init__(self): super(MeuModulo, self).__init__() - self.layer1 = nn.Linear(10, 100) - self.layer2 = nn.Linear(100, 2) + self.layer1 = nn.Linear(10, 2) + #self.layer2 = nn.Linear(5, 2) self.sigmoid = nn.Sigmoid() def forward(self, x): out = self.layer1(x) - out = self.layer2(out) out = self.sigmoid(out) + #out = self.layer2(out) + #out = self.sigmoid(out) return out modelo = MeuModulo() - input_list = [[0.01 for _ in range(10)]] + input_list = [[0.05 for _ in range(10)]] input = norch.Tensor(input_list).T - output = modelo(input) - print(output) + criterion = nn.MSELoss() + optimizer = norch.optim.SGD(modelo.parameters(), lr=0.5) + + target_list = [[0.1 for _ in range(2)]] + target = norch.Tensor(target_list).T + + for epoch in range(2): + output = modelo(input) + loss = criterion(output, target) + #print('FORA ANTES: ', modelo.layer1.bias, '\n') + optimizer.zero_grad() + #print(modelo.layer1.weight.grad) + loss.backward() + #print(modelo.layer1.weight.grad) + optimizer.step() + #print('FORA DEPOIS: ', modelo.layer1.bias.data, '\n') + + #print("\n\n") + #print(modelo.layer1.weight.grad) + + #print(modelo.layer1.weight[0,0]) + print(loss) exit()