From 68bee8b457cbf532367328f0a137945076e25395 Mon Sep 17 00:00:00 2001 From: lucasdelimanogueira Date: Fri, 10 May 2024 02:01:09 -0300 Subject: [PATCH] add example training --- examples/train.ipynb | 177 ++++++++++++++++++ install.sh | 2 + norch/__pycache__/tensor.cpython-38.pyc | Bin 13775 -> 13805 bytes .../__pycache__/functions.cpython-38.pyc | Bin 6118 -> 6122 bytes norch/autograd/functions.py | 4 +- norch/tensor.py | 2 + 6 files changed, 184 insertions(+), 1 deletion(-) create mode 100644 examples/train.ipynb create mode 100755 install.sh diff --git a/examples/train.ipynb b/examples/train.ipynb new file mode 100644 index 0000000..84d7fdc --- /dev/null +++ b/examples/train.ipynb @@ -0,0 +1,177 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Build and train a neural network" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "/home/lln/Documentos/recreate_pytorch/foo\n" + ] + } + ], + "source": [ + "%cd ../" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Epoch [1/10], Loss: 1.7035\n", + "Epoch [2/10], Loss: 0.7193\n", + "Epoch [3/10], Loss: 0.3068\n", + "Epoch [4/10], Loss: 0.1742\n", + "Epoch [5/10], Loss: 0.1342\n", + "Epoch [6/10], Loss: 0.1232\n", + "Epoch [7/10], Loss: 0.1220\n", + "Epoch [8/10], Loss: 0.1241\n", + "Epoch [9/10], Loss: 0.1270\n", + "Epoch [10/10], Loss: 0.1297\n" + ] + } + ], + "source": [ + "import norch\n", + "import norch.nn as nn\n", + "import norch.optim as optim\n", + "import random\n", + "import math\n", + "\n", + "random.seed(1)\n", + "\n", + "class MyModel(nn.Module):\n", + " def __init__(self):\n", + " super(MyModel, self).__init__()\n", + " self.fc1 = nn.Linear(1, 10)\n", + " self.sigmoid = nn.Sigmoid()\n", + " self.fc2 = nn.Linear(10, 1)\n", + "\n", + " def forward(self, x):\n", + " out = self.fc1(x)\n", + " out = self.sigmoid(out)\n", + " out = self.fc2(out)\n", + " \n", + " return out\n", + "\n", + "device = \"cpu\"\n", + "epochs = 10\n", + "\n", + "model = MyModel().to(device)\n", + "criterion = nn.MSELoss()\n", + "optimizer = optim.SGD(model.parameters(), lr=0.001)\n", + "loss_list = []\n", + "\n", + "x_values = [0. , 0.4, 0.8, 1.2, 1.6, 2. , 2.4, 2.8, 3.2, 3.6, 4. ,\n", + " 4.4, 4.8, 5.2, 5.6, 6. , 6.4, 6.8, 7.2, 7.6, 8. , 8.4,\n", + " 8.8, 9.2, 9.6, 10. , 10.4, 10.8, 11.2, 11.6, 12. , 12.4, 12.8,\n", + " 13.2, 13.6, 14. , 14.4, 14.8, 15.2, 15.6, 16. , 16.4, 16.8, 17.2,\n", + " 17.6, 18. , 18.4, 18.8, 19.2, 19.6, 20.]\n", + "\n", + "y_true = []\n", + "for x in x_values:\n", + " y_true.append(math.pow(math.sin(x), 2))\n", + "\n", + "\n", + "for epoch in range(epochs):\n", + " for x, target in zip(x_values, y_true):\n", + " x = norch.Tensor([[x]]).T\n", + " target = norch.Tensor([[target]]).T\n", + "\n", + " x = x.to(device)\n", + " target = target.to(device)\n", + "\n", + " outputs = model(x)\n", + " loss = criterion(outputs, target)\n", + " \n", + " optimizer.zero_grad()\n", + " loss.backward()\n", + " optimizer.step()\n", + "\n", + " print(f'Epoch [{epoch + 1}/{epochs}], Loss: {loss[0]:.4f}')\n", + " loss_list.append(loss[0])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Check loss" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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evVqdejQQTfccINzv0qVKun+++/XoUOH9OOPP0qSPvnkE9WoUUOPPPJItjx/HXJ5Jb9TAOCqKE4A4Cbq1q0rX1/fbNt/+OEH9e3bV4GBgQoICFDNmjWdb8CTkpLy/b5XXXVVls8z3/DmVi7yOjbz+Mxjjx8/rj///FONGzfOtl9O24ri119/lSQ1bdo029eaNWvm/Lqfn5+mTZumNWvWKCgoSDfeeKNeeeUVZ4GQpJtuukn9+/fX888/rxo1aqh379768MMPlZaWVqAsjRs3zlYimjRpIknO+6iqVKmiXr16acGCBc59oqKiVLduXd1yyy0F+jlXX321IiMjsy0BAQGFzvPrr7/meO4yZ3HMPH+//PKLmjZtWqBJQq7kdwoAXBXFCQDcxOVXljKdPn1aN910k3bu3KkpU6bo008/VUxMjKZNmyZJBZp+3NvbO8ftlmWV6LEmjB07Vj///LOmTp0qf39/TZw4Uc2bN9eOHTsk2VdOlixZok2bNunhhx/WkSNHNGrUKLVr105nzpwpthzDhw/XgQMH9N133yklJUUrV67UkCFD5OXlGf8su9vvBQAUhGf8FxoAyqgNGzbo999/19y5czVmzBj17NlTkZGRWYZJmVSrVi35+/tr//792b6W07aiqF+/viRp79692b62d+9e59czNWrUSP/4xz+0fv167d69W+fPn9drr72WZZ/rrrtOL774orZu3aqoqCj98MMPWrhwYb5Z9u/fn60c/Pzzz5KUZUbDO+64QzVr1lRUVJSWLVums2fP6p577inQ6y2MguSpX79+jucuc5hn5vlr1KiR9u7dW6QhjADgCShOAODGMv+yf/mb4/Pnz+vdd981FSkLb29vRUZGavny5Tp69Khz+/79+7VmzZpi+Rnt27dXrVq1NGvWrCxD6tasWaM9e/aoR48ekuyZ6M6dO5fl2EaNGqly5crO4/74449sRaNNmzaSVKDhekePHtWyZcucnycnJ+ujjz5SmzZtVLt2bed2Hx8fDRkyRIsXL9bcuXN1zTXXqHXr1oV74QVQkDzdu3fX5s2btWnTJud+qampmj17tkJDQ533TfXv318nT57U9OnTs/0criQBKAuYjhwA3Nj111+vqlWrasSIEXr00UflcDg0f/58l3oj+9xzz2n9+vXq1KmTHnzwQaWnp2v69Olq1aqV4uLiCvQ9Lly4oH/+85/ZtlerVk0PPfSQpk2bppEjR+qmm27SkCFDnNORh4aGOqf9/vnnn3Xrrbdq4MCBatGihXx8fLRs2TIlJiZq8ODBkqR58+bp3XffVd++fdWoUSOlpKRozpw5CggIUPfu3fPN2aRJE/3tb3/Tli1bFBQUpA8++ECJiYn68MMPs+07fPhwvf322/ryyy+dQysLavv27fr444+zbW/UqJEiIiIKlWf8+PGKjo5Wt27d9Oijj6patWqaN2+eDh48qE8++cQ5fHD48OH66KOPNG7cOG3evFmdO3dWamqqPv/8cz300EMFmkYdANwZxQkA3Fj16tX12Wef6R//+IeeffZZVa1aVXfffbduvfVWde3a1XQ8SVK7du20Zs0aPf7445o4caJCQkI0ZcoU7dmzp0Cz/kn2VbSJEydm296oUSM99NBDuvfee1WhQgW9/PLLeuqpp1SxYkX17dtX06ZNc86UFxISoiFDhig2Nlbz58+Xj4+PmjVrpsWLF6t///6S7MkhNm/erIULFyoxMVGBgYHq0KGDoqKi1KBBg3xzXn311XrnnXf0xBNPaO/evWrQoIEWLVqU4/8W7dq1U8uWLbVnzx4NGzasQOchU3R0dI4Pyh0xYkSW4lSQPEFBQfruu+/01FNP6Z133tG5c+fUunVrffrpp86rdZJ99XD16tV68cUXtWDBAn3yySeqXr26brjhBl1zzTWFyg8A7shhudKfJQEAZUafPn30ww8/aN++faajGBMeHq5q1aopNja22L93aGioWrVqpc8++6zYvzcAlEXc4wQAKHF//vlnls/37dun1atX6+abbzYTyAVs3bpVcXFxGj58uOkoAIACYKgeAKDENWzYUPfee68aNmyoX3/9VTNnzpSvr6+efPJJ09FK3e7du7Vt2za99tprCg4O1qBBg0xHAgAUAMUJAFDi7rjjDkVHRyshIUF+fn6KiIjQSy+9pKuvvtp0tFK3ZMkSTZkyRU2bNlV0dLT8/f1NRwIAFAD3OAEAAABAPrjHCQAAAADyQXECAAAAgHyUuXucMjIydPToUVWuXFkOh8N0HAAAAACGWJallJQU1alTx/nA79yUueJ09OhRhYSEmI4BAAAAwEXEx8erXr16ee5T5opT5cqVJdknJyAgwHAaAAAAAKYkJycrJCTE2RHyUuaKU+bwvICAAIoTAAAAgALdwsPk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iT/H6c8//1RaWpqzNP3666968803tXfvXpcuTTAvMlKqVUs6eVJav950GgAAAKBgilScevfurY8++kiSdPr0aXXs2FGvvfaa+vTpo5kzZxZrQHgWHx9pyBB7neF6AAAAcBdFKk7bt29X586dJUlLlixRUFCQfv31V3300Ud6++23izUgPE/m7HrLl0vJyUajAAAAAAVSpOJ09uxZVa5cWZK0fv169evXT15eXrruuuv066+/FmtAeJ527aSmTaVz56Rly0ynAQAAAPJXpOLUuHFjLV++XPHx8Vq3bp1uv/12SdLx48eZcAH5cjguXXViuB4AAADcQZGK06RJk/T4448rNDRUHTp0UEREhCT76lN4eHixBoRnGjrU/hgba8+uBwAAALiyIhWnAQMG6PDhw9q6davWrVvn3H7rrbfqjTfeKLZw8FwNG0qdOkmWJUVHm04DAAAA5K1IxUmSateurfDwcB09elS//fabJKlDhw5q1qxZsYWDZ2O4HgAAANxFkYpTRkaGpkyZosDAQNWvX1/169dXlSpV9MILLygjI6O4M8JD3XWX/QDcuDhp927TaQAAAIDcFak4PfPMM5o+fbpefvll7dixQzt27NBLL72kd955RxMnTizujPBQ1atL3bvb61FRZrMAAAAAeXFYlmUV9qA6depo1qxZuvPOO7NsX7FihR566CEdOXKk2AIWt+TkZAUGBiopKYkZAF3AkiX2laeQEOnQIcmryINHAQAAgMIpTDco0tvUU6dO5XgvU7NmzXTq1KmifEuUUT17SgEBUny89PXXptMAAAAAOStScQoLC9P06dOzbZ8+fbpat259xaFQdvj721ecJCaJAAAAgOsq0lC9jRs3qkePHrrqqqucz3DatGmT4uPjtXr1anXu3LnYgxYXhuq5ng0bpC5dpMBAKSHBLlMAAABASSvxoXo33XSTfv75Z/Xt21enT5/W6dOn1a9fP/3www+aP39+kUKj7LrxRqlePSkpSVq1ynQaAAAAILsiXXHKzc6dO9W2bVulp6cX17csdlxxck3jx0vTpkl9+kjLlplOAwAAgLKgxK84AcUt82G4q1ZJzC8CAAAAV0Nxgkto1UoKC5MuXJD+8x/TaQAAAICsKE5wGZlXnZhdDwAAAK7GpzA79+vXL8+vnz59+kqyoIwbMkR68knpm2+kgwelBg1MJwIAAABs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5F4+/PBD1apVSz169DAdxS2cPXtWXl5Z3wp6e3srIyPDUCL3U7FiRQUHB+uPP/7QunXr1Lt3b9OR3EaDBg1Uu3ZtxcbGOrclJyfr+++/d9l7sBmqZ8iZM2ey/PX14MGDiouLU7Vq1XTVVVcZTObaRo8erQULFmjFihWqXLmycwxsYGCgypcvbzid65owYYK6deumq666SikpKVqwYIE2bNigdevWmY7m0ipXrpzt/rmKFSuqevXq3FeXh8cff1y9evVS/fr1dfToUU2ePFne3t4aMmSI6Wgu77HHHtP111+vl156SQMHDtTmzZs1e/ZszZ4923Q0l5eRkaEPP/xQI0aMkI8Pb28KolevXnrxxRd11VVXqWXLltqxY4def/11jRo1ynQ0l7du3TpZlqWmTZtq//79euKJJ9SsWTONHDnSdDSXkt/73bFjx+qf//ynrr76ajVo0EATJ05UnTp11KdPH3Oh82J6Wr+y6ssvv7QkZVtGjBhhOppLy+mcSbI+/PBD09Fc2qhRo6z69etbvr6+Vs2aNa1bb73VWr9+velYbonpyPM3aNAgKzg42PL19bXq1q1rDRo0yNq/f7/pWG7j008/tVq1amX5+flZzZo1s2bPnm06kltYt26dJcnau3ev6ShuIzk52RozZox11VVXWf7+/lbDhg2tZ555xkpLSzMdzeUtWrTIatiwoeXr62vVrl3bGj16tHX69GnTsVxOfu93MzIyrIkTJ1pBQUGWn5+fdeutt7r0/4cdlsXjoQEAAAAgL9zjBAAAAAD5oDgBAAAAQD4oTgAAAACQD4oTAAAAAOSD4gQAAAAA+aA4AQAAAEA+KE4AAAAAkA+KEwAAAADkg+IEAEAhOBwOLV++3HQMAEApozgBANzGvffeK4fDkW254447TEcDAHg4H9MBAAAojDvuuEMffvhhlm1+fn6G0gAAygquOAEA3Iqfn59q166dZalataokexjdzJkz1a1bN5UvX14NGzbUkiVLshy/a9cu3XLLLSpfvryqV6+u+++/X2fOnMmyzwcffKCWLVvKz89PwcHBevjhh7N8/eTJk+rbt68qVKigq6++WitXrizZFw0AMI7iBADwKBMnTlT//v21c+dODRs2TIMHD9aePXskSampqeratauqVq2qLVu26D//+Y8+//zzLMVo5syZGj16tO6//37t2rVLK1euVOPGjbP8jOeff14DBw7U//73P3Xv3l3Dhg3TqVOnSvV1AgBKl8OyLMt0CAAACuLee+/Vxx9/LH9//yzbn376aT399NNyOBx64IEHNHPmTOfXrrvuOrVt21bvvvuu5syZo6eeekrx8fGqWLGiJGn16tXq1auXjh49qqCgINWtW1cjR47UP//5zxwzOBwOPfvss3rhhRck2WWsUqVKWrNmDfdaAYAH4x4nAIBb6dKlS5ZiJEnVqlVzrkdERGT5WkREhOLi4iRJe/bsUVhYmLM0SVKnTp2UkZGhvXv3yuFw6OjRo7r11lvzzNC6dWvnesWKFRUQEKDjx48X9SUBANwAxQkA4FYqVqyYbehccSlfvnyB9itXrlyWzx0OhzIyMkoiEgDARXCPEwDAo/z3v//N9nnz5s0lSc2bN9fOnTuVmprq/Pq3334rLy8vNW3aVJUrV1ZoaKhiY2NLNTMAwPVxxQkA4FbS0tKUkJCQZZuPj49q1KghSfrPf/6j9u3b64YbblBUVJQ2b96s999/X5I0bNgwTZ48WSNGjNBzzz2nEydO6JFHHtE999yjoKAgSdJzzz2nBx54QLVq1VK3bt2UkpKib7/9Vo888kjpvlAAgEuhOAEA3MratWsVHBycZVvTpk31008/SbJnvFu4cKEeeughBQcHKzo6Wi1atJAkVahQQevWrdOYMWN07bXXqkKFCurfv79ef/115/caMWKEzp07pzfeeEOPP/64atSooQEDBpTeCwQAuCRm1QMAeAyHw6Fly5apT58+pqMAADwM9zgBAAAAQD4oTgAAAACQD+5xAgB4DEafAwBKClecAAAAACAfFCcAAAAAyAfFCQAAAADyQXECAAAAgHxQnAAAAAAgHxQnAAAAAMgHxQkAAAAA8kFxAgAAAIB8/D9+bdOrEm6qZgAAAABJRU5ErkJggg==", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import matplotlib.pyplot as plt\n", + "\n", + "epochs_list = range(1, len(loss_list) + 1)\n", + "\n", + "plt.figure(figsize=(10, 5))\n", + "\n", + "plt.plot(epochs_list, loss_list, 'b', marker='o')\n", + "plt.title('Training Loss by Epoch')\n", + "plt.xlabel('Epoch')\n", + "plt.ylabel('Loss')\n", + "plt.xticks(epochs_list)\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.10" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/install.sh b/install.sh new file mode 100755 index 0000000..56577b5 --- /dev/null +++ b/install.sh @@ -0,0 +1,2 @@ +cd build +make \ No newline at end of file diff --git a/norch/__pycache__/tensor.cpython-38.pyc b/norch/__pycache__/tensor.cpython-38.pyc index 21215c7e87621d2a76cfe2e8eded9d80ed1496a3..74a53d0b87c6d5237c6be0f1f046e6827181235d 100644 GIT binary patch delta 3858 zcmbVPO>7%Q6!xsMwqwVR6FYHgr%Cf4H))!rNvVKVq7Af^G*qNTVrjKF_9k5?@w&6? zq%8?4Z9$xn$_Ug`)tpcyq^h!j0|zRVOF2*u2#G}?R0)YoL5LIL!h5r^W4pGaHis{> zGjHC{_ujl2KbU_s?>+7Hx^3|H$Mu7=pWgA#l7Q)wXH{h(q01XK8iXYp%)U<^*hw>c zU3|Hv9cP>XCeb&Sai%HzrPx8p4)&9ypG278JmcYen{aWMsm`eZ{EpVpUYyy3Fob}r zEIoU1#O1^6p)=dM1HPj^>ci=Jgc^iqgidzH)jZgR!)}Bg1nyK#TuWc1F8s#0XdA$W zo%XVST-}yOmRqc|_WSAh_Xig>^on0GK#}N0Mi~zB%)5P#&pfmSVC1&hAHX>1Y$auR9!Wcgq2L(FNr8qRAp?e z{(Kwfl~5GfAeK`F{;+%XQU{7`2wa4-Lyy2j5gCX4FRU3bY1meXL9Pnaze487Dlvo= za+R#ulJ1!xUss4B-f|eub?d*Fbgh#)!Kh8TlODOw5R=}`u@A;BOG6O!erN-I zAa%i3Cv{K>6 z81nTV1@~~LQ%xlxTe>MO#TGJ3VUW1&k!8?=N@V$Sn9v&mY{X3*#7A60E2$G2iC?(X zcuGm>8Xc0e_Zw~yVzQaQDCuDz2S)2Tx%^%K8GYAO;&O@Fy9vR>AFYef#J=xMt!ujxM9Jf>nPS4Cdad6X_nWEsz`i1!c-Et#= zy66NiY)}(*LLJmac2`&={pZj#6`@jCeE$IRg$LNl7EktSgb2}+$ap>Tw3W6_%p$wH zQ|w3EQiC3kEySq2m|3V0ZaaIlGvvT-M~^Xg+pB~8E>ZA%41uStgnNh)70MIry|&d6 z-WLefKswjY`1X=bSc-gCitTGZ+Bb#D(+K727A&NcIaxl>*4q#Ep#>}d6=c(zF3SeU zHf6)R{u3OV7h0sNFWiND^9S52b?X*mXSyPZW3ViF7h^^NL%fuIC-_`Z!lRv1rK#`?XUe5m9)k$3Zs0L^}m!N{9)?ghoIjt?rR>De8T-j8kS@hNPoYa_oi0aaX#wWEq8D()3#(G0 zb9cVYdi!pYMov#NZ`|}K?yN>sLS1?)qWlvo-iTVNh%G6{KdRmAcm*!=V&c6Q`o2Lk z3W~|UW|L8otmU$b9#a&I)xbY^jT zvv$zD7p&gjK7L(IRr8@zWlNrEwYY*R#1Hxp=i_hLdvkk_;?T&--?>#gfaE!%>DyBy z+Cl$m^e8(uJV z=MbXyDH>w_u>)&n&5?=8NwX%YsVR!LE$v4LBk-5UejGi6Z~)Atx)44y^3>N z_j3Naf*%;c@gCx1&yMdoj)xR}`S5Ob4aQPqEMsW+vtej9lZqSAK6SHp8k$Yq$WW!= MCuFH+c4xfpe~;VvTmS$7 delta 3723 zcmbVPOKclO81~rlBk?0iormj$#A%*x9&OSDQb7x86H!813TdmdeQX`?CfUUCy0hz~ zPtu2kI3dAE+^8CHiiA{ETf~hPxWI+>+U0Sm#El9ekPvX;|7VkUZS0gbhcB};|NQ^= zKjxqD zv1veoM)q4E@}d=0_!i1_Rg~mKB`MQl9f7hI6h0Hj0@0@S0T&&PtbN;n)0LC6mLk;M8-*K7X%FS}n7i5pC##|v9WiMC9 zrCfl0GqNs%qYGAitB}}65yzoaVZ!t(X$exGneN3zDl6NWrdJd-or>a@ z>`u+=+t&hq0+$N|iPAn%q;dwtzc=EwJ){vcZn_lA?Q}{_=yVWw@_HVFatkl#qEP`Q zA?k8kQ)xlH6+LLY{{178lvn$!R#!3Isy-`ITD1C+5_pB?MCVTq)*BsUyXzmtPa(C_ z2nhsRiQo?OjBoi9cWgJ(kv0qb`Z!9oF61&K|bk%Q0B#h^&X`Zb$vmr!h{mNF#<&s+hUeZ;bBF8)OT2x{lgv z8Qq_v+NdrZYDRc=$uE^KDghuSutd%R!; z|73RI$>v<3xtD#>`|Xqc)|B*S97>%WAfni6q_p3l{}txn@jsX(q4PXLaR~nXs`liN zxLu%s5;D+jT;Ews)(`EC{)V=aht?K*_G5qj-Wa&K*0=g*VxCqPCSoig6>Bsau?81SojDJlLrP4 z;vpVq+;xc7vA)6KWua{U=){CsHm53S+JY)N5w;@mhr~P6F)sQ13V%PWZ{ef1F)~v9KkP)m412_f2QhNgW!aCX`P?w@K<* PD%*a$6>4VphnoHcr#IM@ diff --git a/norch/autograd/__pycache__/functions.cpython-38.pyc b/norch/autograd/__pycache__/functions.cpython-38.pyc index 73c0c12bdc44075afd84c55fb170e07c3a81bc33..87e1cfd71b1d61176788abdebd02e435659c91fc 100644 GIT binary patch delta 746 zcmY*X&rcIk5Z>ACkL{M-mVMhcN(EE|%cYT`RBKbvf?h15QKAW^1p`VVm}xW`OM;0P z^(2#c_M!=1)Qcwm8y-xIXN?|=#v>k>d7)}InQtdE-#72g%=?o6o_8;}u4C{wzgAv6 z`^MdfP`@3jS{yma)*N7H8Oz31*k!Dl+B4a+T2>1Jqh$&%ndgm7tA@bbZvq%%*ra=Q z&fCLYGs0ki0}es-2kfVx(MKlkreA@gXLbk%>A5|wdYH3M*dn&Uwy=k0qT^JI-GBnU zh`pz4&hbb;Cvh*mbPmB0`s|!ieH<8J`zPzuvfJ@GOwz~rV>nFRlshOy# zJo7JhX!2SUPOe4@9LG_8<`vpV&c}OoK%hX=;VdjrwtGTJS95Ib&cZmNOT6x`>>Rs9 zH~lpA`ZKW1-qG-3W-n4BsL>z44y!b$Zb6nls1tyc4yM!?=U4u#XyKTy_$p}6;4Z~d z(nupU3N3n?Dyt&%?{sL2S~Hk#Ywpu}`jW5bW@4DBpRDHf6+HHLzYoaDlg&^$`!FhPy7tM%Vbr|OM1TNc(xby IVvOu<19caZC;$Ke delta 758 zcmY+COKTHR6vyXIGLKB=PNs7wjR~o3t+kC<(==(Z$Y5XAjrD;oDitx(8nssC79WJ- z3s)5vdccJ%KYS18$r*x(2^OrhjY*Tf9KBm-}zPkQRWMrI~qQZ z?nhT@E&kGkPd+afv9iwAwd>jv%WL6wu2bI7&uFE@iJuHLQiUX(G>YI`2CSIfuwnGU zqSa!(!0ipal!WghguiCU_Cm{^5P8IUaIGaV*vwAIJZu>gFq2wk6?m80w6Hn#g%u|< zccVyl!&|4qYVgfDCc3aN9K*X5-b`O&)9^L@jLkyBjYL0creeB&rTgPfvVHKv6^4s% z=ioH2+XI-DOt}X(`3yS+|M+1sh^6B(d{E)fy`ydT0{r&QvH_URRM|Pqi!{6#LT*0B z4k6t?g}S)I3h-G>vD;7xXT>P0Zp4(M>Y(>wyH)pq zXKB{uY>hSHbv6=X$lQ%_V~X3~+0H$Lr=8~mWw9;|lz&OAUArj{DGxHZe*#u6DvV?H zAl8g3rHt%@i@99~>93J=_mVDF()CF4S&~bVW|cICq;HbrkV)s@W3DJH&-Vh)@odlX IQW!D&57G3IjsO4v diff --git a/norch/autograd/functions.py b/norch/autograd/functions.py index dec3f54..d5a2684 100644 --- a/norch/autograd/functions.py +++ b/norch/autograd/functions.py @@ -27,7 +27,9 @@ class ElementwiseMulBackward: self.input = [x, y] def backward(self, gradient): - return [gradient * self.input[1], gradient * self.input[0]] + x = self.input[0] + y = self.input[1] + return [y * gradient, x * gradient] class MatmulBackward: def __init__(self, x, y): diff --git a/norch/tensor.py b/norch/tensor.py index 3d309f9..7f5f9c9 100644 --- a/norch/tensor.py +++ b/norch/tensor.py @@ -179,6 +179,8 @@ class Tensor: self.grad_fn = None def __getitem__(self, indices): + if isinstance(indices, int): + indices = [indices] if len(indices) != self.ndim: raise ValueError("Number of indices must match the number of dimensions")