├── .gitignore ├── Building a simple NN.ipynb ├── Derivatives with PyTorch.ipynb ├── LICENSE ├── NN class building.ipynb ├── README.md ├── Tensor basics - Matrix (2-D) operations.ipynb ├── Tensor basics - creation and conversion.ipynb ├── Tensor basics - indexing and slicing.ipynb ├── Tensor basics - vector (1-D) operations.ipynb └── images ├── NN-1.PNG ├── NN-2.PNG ├── Readme.md └── five-step-process.png /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | MANIFEST 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | .pytest_cache/ 49 | 50 | # Translations 51 | *.mo 52 | *.pot 53 | 54 | # Django stuff: 55 | *.log 56 | local_settings.py 57 | db.sqlite3 58 | 59 | # Flask stuff: 60 | instance/ 61 | .webassets-cache 62 | 63 | # Scrapy stuff: 64 | .scrapy 65 | 66 | # Sphinx documentation 67 | docs/_build/ 68 | 69 | # PyBuilder 70 | target/ 71 | 72 | # Jupyter Notebook 73 | .ipynb_checkpoints 74 | 75 | # pyenv 76 | .python-version 77 | 78 | # celery beat schedule file 79 | celerybeat-schedule 80 | 81 | # SageMath parsed files 82 | *.sage.py 83 | 84 | # Environments 85 | .env 86 | .venv 87 | env/ 88 | venv/ 89 | ENV/ 90 | env.bak/ 91 | venv.bak/ 92 | 93 | # Spyder project settings 94 | .spyderproject 95 | .spyproject 96 | 97 | # Rope project settings 98 | .ropeproject 99 | 100 | # mkdocs documentation 101 | /site 102 | 103 | # mypy 104 | .mypy_cache/ 105 | -------------------------------------------------------------------------------- /Building a simple NN.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Buidling simple layers of a neural net\n", 8 | "\n", 9 | "### Dr. Tirthajyoti Sarkar

Fremont, CA 94536

Nov 2019" 10 | ] 11 | }, 12 | { 13 | "cell_type": "code", 14 | "execution_count": 1, 15 | "metadata": {}, 16 | "outputs": [], 17 | "source": [ 18 | "import torch\n", 19 | "import numpy as np" 20 | ] 21 | }, 22 | { 23 | "cell_type": "code", 24 | "execution_count": 2, 25 | "metadata": {}, 26 | "outputs": [ 27 | { 28 | "data": { 29 | "text/plain": [ 30 | "" 31 | ] 32 | }, 33 | "execution_count": 2, 34 | "metadata": {}, 35 | "output_type": "execute_result" 36 | } 37 | ], 38 | "source": [ 39 | "torch.manual_seed(7)" 40 | ] 41 | }, 42 | { 43 | "cell_type": "markdown", 44 | "metadata": {}, 45 | "source": [ 46 | "### Simple feature vector of dimension 3" 47 | ] 48 | }, 49 | { 50 | "cell_type": "code", 51 | "execution_count": 3, 52 | "metadata": {}, 53 | "outputs": [], 54 | "source": [ 55 | "features = torch.randn((1,3))" 56 | ] 57 | }, 58 | { 59 | "cell_type": "code", 60 | "execution_count": 4, 61 | "metadata": {}, 62 | "outputs": [ 63 | { 64 | "name": "stdout", 65 | "output_type": "stream", 66 | "text": [ 67 | "tensor([[-0.1468, 0.7861, 0.9468]])\n" 68 | ] 69 | } 70 | ], 71 | "source": [ 72 | "print(features)" 73 | ] 74 | }, 75 | { 76 | "cell_type": "markdown", 77 | "metadata": {}, 78 | "source": [ 79 | "### Define the size of each layer of the neural network" 80 | ] 81 | }, 82 | { 83 | "cell_type": "code", 84 | "execution_count": 5, 85 | "metadata": {}, 86 | "outputs": [], 87 | "source": [ 88 | "n_input = features.shape[1] # Must match the shape of the features\n", 89 | "n_hidden = 5 # Number of hidden units\n", 90 | "n_output = 1 # Number of output units (for example 1 for binary classification)" 91 | ] 92 | }, 93 | { 94 | "cell_type": "markdown", 95 | "metadata": {}, 96 | "source": [ 97 | "### Weights for the input layer to the hidden layer" 98 | ] 99 | }, 100 | { 101 | "cell_type": "code", 102 | "execution_count": 6, 103 | "metadata": {}, 104 | "outputs": [], 105 | "source": [ 106 | "W1 = torch.randn(n_input,n_hidden)" 107 | ] 108 | }, 109 | { 110 | "cell_type": "markdown", 111 | "metadata": {}, 112 | "source": [ 113 | "### Weights for the hidden layer to the output layer" 114 | ] 115 | }, 116 | { 117 | "cell_type": "code", 118 | "execution_count": 7, 119 | "metadata": {}, 120 | "outputs": [], 121 | "source": [ 122 | "W2 = torch.randn(n_hidden,n_output)" 123 | ] 124 | }, 125 | { 126 | "cell_type": "markdown", 127 | "metadata": {}, 128 | "source": [ 129 | "### Bias terms for the hidden and the output layer" 130 | ] 131 | }, 132 | { 133 | "cell_type": "code", 134 | "execution_count": 8, 135 | "metadata": {}, 136 | "outputs": [], 137 | "source": [ 138 | "B1 = torch.randn((1,n_hidden))\n", 139 | "B2 = torch.randn((1,n_output))" 140 | ] 141 | }, 142 | { 143 | "cell_type": "markdown", 144 | "metadata": {}, 145 | "source": [ 146 | "### Define the activation function - sigmoid\n", 147 | "$$\\sigma(x)=\\frac{1}{1+exp(-x)}$$" 148 | ] 149 | }, 150 | { 151 | "cell_type": "code", 152 | "execution_count": 9, 153 | "metadata": {}, 154 | "outputs": [], 155 | "source": [ 156 | "def activation(x):\n", 157 | " \"\"\"\n", 158 | " Sigmoid activation function\n", 159 | " \"\"\"\n", 160 | " return 1/(1+torch.exp(-x))" 161 | ] 162 | }, 163 | { 164 | "cell_type": "markdown", 165 | "metadata": {}, 166 | "source": [ 167 | "### Check the shape of all the tensors" 168 | ] 169 | }, 170 | { 171 | "cell_type": "code", 172 | "execution_count": 10, 173 | "metadata": {}, 174 | "outputs": [ 175 | { 176 | "name": "stdout", 177 | "output_type": "stream", 178 | "text": [ 179 | "Shape of the input features: torch.Size([1, 3])\n", 180 | "Shape of the first tensor of weights (between input and hidden layers): torch.Size([3, 5])\n", 181 | "Shape of the second tensor of weights (between hidden and output layers): torch.Size([5, 1])\n", 182 | "Shape of the bias tensor added to the hidden layer: torch.Size([1, 5])\n", 183 | "Shape of the bias tensor added to the output layer: torch.Size([1, 1])\n" 184 | ] 185 | } 186 | ], 187 | "source": [ 188 | "print(\"Shape of the input features: \",features.shape)\n", 189 | "print(\"Shape of the first tensor of weights (between input and hidden layers): \",W1.shape)\n", 190 | "print(\"Shape of the second tensor of weights (between hidden and output layers): \",W2.shape)\n", 191 | "print(\"Shape of the bias tensor added to the hidden layer: \",B1.shape)\n", 192 | "print(\"Shape of the bias tensor added to the output layer: \",B2.shape)" 193 | ] 194 | }, 195 | { 196 | "cell_type": "markdown", 197 | "metadata": {}, 198 | "source": [ 199 | "![NN1](https://raw.githubusercontent.com/tirthajyoti/PyTorch_Machine_Learning/master/images/NN-1.PNG)" 200 | ] 201 | }, 202 | { 203 | "cell_type": "markdown", 204 | "metadata": {}, 205 | "source": [ 206 | "### First layer output\n", 207 | "$$\\mathbf{h_1} = sigmoid(\\mathbf{W_1}\\times\\mathbf{feature}+\\mathbf{B_1})$$" 208 | ] 209 | }, 210 | { 211 | "cell_type": "code", 212 | "execution_count": 11, 213 | "metadata": {}, 214 | "outputs": [], 215 | "source": [ 216 | "h1 = activation(torch.mm(features,W1)+B1)" 217 | ] 218 | }, 219 | { 220 | "cell_type": "code", 221 | "execution_count": 12, 222 | "metadata": {}, 223 | "outputs": [ 224 | { 225 | "name": "stdout", 226 | "output_type": "stream", 227 | "text": [ 228 | "Shape of the output of the hidden layer torch.Size([1, 5])\n" 229 | ] 230 | } 231 | ], 232 | "source": [ 233 | "print(\"Shape of the output of the hidden layer\",h1.shape)" 234 | ] 235 | }, 236 | { 237 | "cell_type": "markdown", 238 | "metadata": {}, 239 | "source": [ 240 | "### Second layer output\n", 241 | "$$\\mathbf{h_2} = sigmoid(\\mathbf{W_2}\\times\\mathbf{h1}+\\mathbf{B_1})$$" 242 | ] 243 | }, 244 | { 245 | "cell_type": "code", 246 | "execution_count": 13, 247 | "metadata": {}, 248 | "outputs": [], 249 | "source": [ 250 | "h2 = activation(torch.mm(h1,W2)+B2)" 251 | ] 252 | }, 253 | { 254 | "cell_type": "code", 255 | "execution_count": 14, 256 | "metadata": {}, 257 | "outputs": [ 258 | { 259 | "name": "stdout", 260 | "output_type": "stream", 261 | "text": [ 262 | "Shape of the output layer torch.Size([1, 1])\n" 263 | ] 264 | } 265 | ], 266 | "source": [ 267 | "print(\"Shape of the output layer\",h2.shape)" 268 | ] 269 | }, 270 | { 271 | "cell_type": "code", 272 | "execution_count": 15, 273 | "metadata": {}, 274 | "outputs": [ 275 | { 276 | "name": "stdout", 277 | "output_type": "stream", 278 | "text": [ 279 | "tensor([[0.9865]])\n" 280 | ] 281 | } 282 | ], 283 | "source": [ 284 | "print(h2)" 285 | ] 286 | } 287 | ], 288 | "metadata": { 289 | "kernelspec": { 290 | "display_name": "Python 3", 291 | "language": "python", 292 | "name": "python3" 293 | }, 294 | "language_info": { 295 | "codemirror_mode": { 296 | "name": "ipython", 297 | "version": 3 298 | }, 299 | "file_extension": ".py", 300 | "mimetype": "text/x-python", 301 | "name": "python", 302 | "nbconvert_exporter": "python", 303 | "pygments_lexer": "ipython3", 304 | "version": "3.7.0" 305 | } 306 | }, 307 | "nbformat": 4, 308 | "nbformat_minor": 4 309 | } 310 | -------------------------------------------------------------------------------- /Derivatives with PyTorch.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Derivatives with PyTorch\n", 8 | "\n", 9 | "### Dr. Tirthajyoti Sarkar

Fremont, CA 94536

April 2019" 10 | ] 11 | }, 12 | { 13 | "cell_type": "code", 14 | "execution_count": 1, 15 | "metadata": {}, 16 | "outputs": [], 17 | "source": [ 18 | "import torch\n", 19 | "import numpy as np" 20 | ] 21 | }, 22 | { 23 | "cell_type": "markdown", 24 | "metadata": {}, 25 | "source": [ 26 | "### Define a simple algebraic function\n", 27 | "Let's say,\n", 28 | "### $$ y = f(x) = x^3-7x^2+11x $$\n", 29 | "Therefore,\n", 30 | "### $$ y' = f'(x) = \\frac{d}{dx}(x^3-7x^2+11x) = 3x^2-14x+11 $$" 31 | ] 32 | }, 33 | { 34 | "cell_type": "code", 35 | "execution_count": 2, 36 | "metadata": {}, 37 | "outputs": [], 38 | "source": [ 39 | "def func(x):\n", 40 | " return (x**3 - 7*x**2 + 11*x)" 41 | ] 42 | }, 43 | { 44 | "cell_type": "markdown", 45 | "metadata": {}, 46 | "source": [ 47 | "### Now, let's define a tensor variable with the argument `requires_grad` = `True`" 48 | ] 49 | }, 50 | { 51 | "cell_type": "code", 52 | "execution_count": 3, 53 | "metadata": {}, 54 | "outputs": [], 55 | "source": [ 56 | "x = torch.tensor(2.0, requires_grad=True)" 57 | ] 58 | }, 59 | { 60 | "cell_type": "markdown", 61 | "metadata": {}, 62 | "source": [ 63 | "### Differentiation at $x=2$ yields,\n", 64 | "### $$ f'(x)\\mid _{x=2} = (3x^2-14x+11)\\mid_{x=2} = -5 $$" 65 | ] 66 | }, 67 | { 68 | "cell_type": "markdown", 69 | "metadata": {}, 70 | "source": [ 71 | "### Let's define `y` as the function of `x` i.e. `func(x)`" 72 | ] 73 | }, 74 | { 75 | "cell_type": "code", 76 | "execution_count": 4, 77 | "metadata": {}, 78 | "outputs": [], 79 | "source": [ 80 | "y = func(x)" 81 | ] 82 | }, 83 | { 84 | "cell_type": "markdown", 85 | "metadata": {}, 86 | "source": [ 87 | "### Use the `backward()` method on `y`" 88 | ] 89 | }, 90 | { 91 | "cell_type": "code", 92 | "execution_count": 5, 93 | "metadata": {}, 94 | "outputs": [], 95 | "source": [ 96 | "y.backward()" 97 | ] 98 | }, 99 | { 100 | "cell_type": "markdown", 101 | "metadata": {}, 102 | "source": [ 103 | "### Show the value of the derivative with the `grad()` method on `x` (Note that we use `grad` on `x` and not on `y`)" 104 | ] 105 | }, 106 | { 107 | "cell_type": "code", 108 | "execution_count": 6, 109 | "metadata": {}, 110 | "outputs": [ 111 | { 112 | "data": { 113 | "text/plain": [ 114 | "tensor(-5.)" 115 | ] 116 | }, 117 | "execution_count": 6, 118 | "metadata": {}, 119 | "output_type": "execute_result" 120 | } 121 | ], 122 | "source": [ 123 | "x.grad" 124 | ] 125 | }, 126 | { 127 | "cell_type": "markdown", 128 | "metadata": {}, 129 | "source": [ 130 | "### So, if we want to change the computation at a different value of `x`, we can do that easily by re-defining `x`" 131 | ] 132 | }, 133 | { 134 | "cell_type": "code", 135 | "execution_count": 7, 136 | "metadata": {}, 137 | "outputs": [], 138 | "source": [ 139 | "x = torch.tensor(3.0, requires_grad=True)" 140 | ] 141 | }, 142 | { 143 | "cell_type": "code", 144 | "execution_count": 8, 145 | "metadata": {}, 146 | "outputs": [ 147 | { 148 | "ename": "RuntimeError", 149 | "evalue": "Trying to backward through the graph a second time, but the buffers have already been freed. Specify retain_graph=True when calling backward the first time.", 150 | "output_type": "error", 151 | "traceback": [ 152 | "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", 153 | "\u001b[1;31mRuntimeError\u001b[0m Traceback (most recent call last)", 154 | "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0my\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mbackward\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", 155 | "\u001b[1;32mc:\\users\\tirtha\\python\\anaconda3\\lib\\site-packages\\torch\\tensor.py\u001b[0m in \u001b[0;36mbackward\u001b[1;34m(self, gradient, retain_graph, create_graph)\u001b[0m\n\u001b[0;32m 100\u001b[0m \u001b[0mproducts\u001b[0m\u001b[1;33m.\u001b[0m \u001b[0mDefaults\u001b[0m \u001b[0mto\u001b[0m\u001b[0;31m \u001b[0m\u001b[0;31m`\u001b[0m\u001b[0;31m`\u001b[0m\u001b[1;32mFalse\u001b[0m\u001b[0;31m`\u001b[0m\u001b[0;31m`\u001b[0m\u001b[1;33m.\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 101\u001b[0m \"\"\"\n\u001b[1;32m--> 102\u001b[1;33m \u001b[0mtorch\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mautograd\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mbackward\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mgradient\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mretain_graph\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mcreate_graph\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 103\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 104\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0mregister_hook\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mhook\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", 156 | "\u001b[1;32mc:\\users\\tirtha\\python\\anaconda3\\lib\\site-packages\\torch\\autograd\\__init__.py\u001b[0m in \u001b[0;36mbackward\u001b[1;34m(tensors, grad_tensors, retain_graph, create_graph, grad_variables)\u001b[0m\n\u001b[0;32m 88\u001b[0m Variable._execution_engine.run_backward(\n\u001b[0;32m 89\u001b[0m \u001b[0mtensors\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mgrad_tensors\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mretain_graph\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mcreate_graph\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 90\u001b[1;33m allow_unreachable=True) # allow_unreachable flag\n\u001b[0m\u001b[0;32m 91\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 92\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n", 157 | "\u001b[1;31mRuntimeError\u001b[0m: Trying to backward through the graph a second time, but the buffers have already been freed. Specify retain_graph=True when calling backward the first time." 158 | ] 159 | } 160 | ], 161 | "source": [ 162 | "y.backward()" 163 | ] 164 | }, 165 | { 166 | "cell_type": "markdown", 167 | "metadata": {}, 168 | "source": [ 169 | "### So, we learned that we need to switch on the `retain_graph` to `True` the first time the `backward()` method is called to retain the computation graph structure and taking derivatives afterwards" 170 | ] 171 | }, 172 | { 173 | "cell_type": "code", 174 | "execution_count": 9, 175 | "metadata": {}, 176 | "outputs": [], 177 | "source": [ 178 | "x = torch.tensor(2.0, requires_grad=True)" 179 | ] 180 | }, 181 | { 182 | "cell_type": "code", 183 | "execution_count": 10, 184 | "metadata": {}, 185 | "outputs": [], 186 | "source": [ 187 | "y= func(x)" 188 | ] 189 | }, 190 | { 191 | "cell_type": "code", 192 | "execution_count": 11, 193 | "metadata": {}, 194 | "outputs": [], 195 | "source": [ 196 | "y.backward(retain_graph=True)" 197 | ] 198 | }, 199 | { 200 | "cell_type": "code", 201 | "execution_count": 12, 202 | "metadata": {}, 203 | "outputs": [ 204 | { 205 | "data": { 206 | "text/plain": [ 207 | "tensor(-5.)" 208 | ] 209 | }, 210 | "execution_count": 12, 211 | "metadata": {}, 212 | "output_type": "execute_result" 213 | } 214 | ], 215 | "source": [ 216 | "x.grad" 217 | ] 218 | }, 219 | { 220 | "cell_type": "code", 221 | "execution_count": 13, 222 | "metadata": {}, 223 | "outputs": [], 224 | "source": [ 225 | "x = torch.tensor(3.0, requires_grad=True)" 226 | ] 227 | }, 228 | { 229 | "cell_type": "code", 230 | "execution_count": 14, 231 | "metadata": {}, 232 | "outputs": [], 233 | "source": [ 234 | "y= func(x)" 235 | ] 236 | }, 237 | { 238 | "cell_type": "code", 239 | "execution_count": 15, 240 | "metadata": {}, 241 | "outputs": [], 242 | "source": [ 243 | "y.backward()" 244 | ] 245 | }, 246 | { 247 | "cell_type": "code", 248 | "execution_count": 16, 249 | "metadata": {}, 250 | "outputs": [ 251 | { 252 | "data": { 253 | "text/plain": [ 254 | "tensor(-4.)" 255 | ] 256 | }, 257 | "execution_count": 16, 258 | "metadata": {}, 259 | "output_type": "execute_result" 260 | } 261 | ], 262 | "source": [ 263 | "x.grad" 264 | ] 265 | }, 266 | { 267 | "cell_type": "markdown", 268 | "metadata": {}, 269 | "source": [ 270 | "## Partial derivative" 271 | ] 272 | }, 273 | { 274 | "cell_type": "markdown", 275 | "metadata": {}, 276 | "source": [ 277 | "Let's suppose,\n", 278 | "### $$f(u,v) = 3u^2v - 4v^3$$\n", 279 | "Therefore,\n", 280 | "### $$ \\frac{\\partial}{\\partial u}{f(u,v)}=6uv; \\ \\frac{\\partial}{\\partial v}{f(u,v)}=3u^2-12v^2$$" 281 | ] 282 | }, 283 | { 284 | "cell_type": "markdown", 285 | "metadata": {}, 286 | "source": [ 287 | "### Let's define `u`, `v`, and the function" 288 | ] 289 | }, 290 | { 291 | "cell_type": "code", 292 | "execution_count": 23, 293 | "metadata": {}, 294 | "outputs": [], 295 | "source": [ 296 | "u = torch.tensor(2.0, requires_grad=True)\n", 297 | "v = torch.tensor(1.0, requires_grad=True)" 298 | ] 299 | }, 300 | { 301 | "cell_type": "code", 302 | "execution_count": 24, 303 | "metadata": {}, 304 | "outputs": [], 305 | "source": [ 306 | "f = 3*u**2*v - 4*v**3" 307 | ] 308 | }, 309 | { 310 | "cell_type": "markdown", 311 | "metadata": {}, 312 | "source": [ 313 | "### $$\\frac{\\partial f(2,1)}{\\partial u}=6uv\\mid_{(u=2,v=1)}=12$$\n", 314 | "### $$\\frac{\\partial f(2,1)}{\\partial u}=3u^2-12v^2\\mid_{(u=2,v=1)}=0$$" 315 | ] 316 | }, 317 | { 318 | "cell_type": "code", 319 | "execution_count": 26, 320 | "metadata": {}, 321 | "outputs": [], 322 | "source": [ 323 | "f.backward(retain_graph=True)" 324 | ] 325 | }, 326 | { 327 | "cell_type": "code", 328 | "execution_count": 27, 329 | "metadata": {}, 330 | "outputs": [ 331 | { 332 | "data": { 333 | "text/plain": [ 334 | "tensor(12.)" 335 | ] 336 | }, 337 | "execution_count": 27, 338 | "metadata": {}, 339 | "output_type": "execute_result" 340 | } 341 | ], 342 | "source": [ 343 | "u.grad" 344 | ] 345 | }, 346 | { 347 | "cell_type": "code", 348 | "execution_count": 28, 349 | "metadata": {}, 350 | "outputs": [ 351 | { 352 | "data": { 353 | "text/plain": [ 354 | "tensor(0.)" 355 | ] 356 | }, 357 | "execution_count": 28, 358 | "metadata": {}, 359 | "output_type": "execute_result" 360 | } 361 | ], 362 | "source": [ 363 | "v.grad" 364 | ] 365 | }, 366 | { 367 | "cell_type": "markdown", 368 | "metadata": {}, 369 | "source": [ 370 | "## Derivatives w.r.t. to a vector\n", 371 | "PyTorch computes derivatives of scalar functions only but if we pass a vector then essentially it computes derivatives element wise and stores them in an array of same dimension.\n", 372 | "\n", 373 | "Let's say,\n", 374 | "### $$y = x_1^2+x_2^2+x_3^2$$\n", 375 | "After differentiation, the $y$ looks like following,\n", 376 | "### $$\\frac{dy}{dx} = [2x_1 \\ \\ 2x_2 \\ \\ 2x_3] $$" 377 | ] 378 | }, 379 | { 380 | "cell_type": "markdown", 381 | "metadata": {}, 382 | "source": [ 383 | "### Let's illustrate through a graphical example" 384 | ] 385 | }, 386 | { 387 | "cell_type": "code", 388 | "execution_count": 41, 389 | "metadata": {}, 390 | "outputs": [], 391 | "source": [ 392 | "# Create a vector of x values\n", 393 | "x = torch.linspace(-10.0,10.0,requires_grad=True)" 394 | ] 395 | }, 396 | { 397 | "cell_type": "code", 398 | "execution_count": 44, 399 | "metadata": {}, 400 | "outputs": [], 401 | "source": [ 402 | "# Store x-squared values in another vector\n", 403 | "x_squared = x**2" 404 | ] 405 | }, 406 | { 407 | "cell_type": "code", 408 | "execution_count": 45, 409 | "metadata": {}, 410 | "outputs": [], 411 | "source": [ 412 | "# Sum of x squared as a tensor\n", 413 | "y = torch.sum(x**2)" 414 | ] 415 | }, 416 | { 417 | "cell_type": "code", 418 | "execution_count": 46, 419 | "metadata": {}, 420 | "outputs": [], 421 | "source": [ 422 | "# Differentiating the sum vector\n", 423 | "y.backward()" 424 | ] 425 | }, 426 | { 427 | "cell_type": "code", 428 | "execution_count": 47, 429 | "metadata": {}, 430 | "outputs": [], 431 | "source": [ 432 | "import matplotlib.pyplot as plt" 433 | ] 434 | }, 435 | { 436 | "cell_type": "markdown", 437 | "metadata": {}, 438 | "source": [ 439 | "### Plot the original function values and the derivative on the same graph. Note the use of `detach` method before applying `numpy()` method for tensors with `requires_grad=True`" 440 | ] 441 | }, 442 | { 443 | "cell_type": "code", 444 | "execution_count": 50, 445 | "metadata": {}, 446 | "outputs": [ 447 | { 448 | "data": { 449 | "image/png": "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\n", 450 | "text/plain": [ 451 | "
" 452 | ] 453 | }, 454 | "metadata": {}, 455 | "output_type": "display_data" 456 | } 457 | ], 458 | "source": [ 459 | "plt.figure(figsize=(8,5))\n", 460 | "plt.plot(x.detach().numpy(),x_squared.detach().numpy(),label='Function',color='blue',lw=3)\n", 461 | "plt.plot(x.detach().numpy(),x.grad.detach().numpy(),label='Derivative',color='red',lw=3,linestyle='--')\n", 462 | "plt.legend(fontsize=15)\n", 463 | "plt.xticks(fontsize=14)\n", 464 | "plt.yticks(fontsize=14)\n", 465 | "plt.show()" 466 | ] 467 | }, 468 | { 469 | "cell_type": "markdown", 470 | "metadata": {}, 471 | "source": [ 472 | "### Another example with the ReLU function" 473 | ] 474 | }, 475 | { 476 | "cell_type": "code", 477 | "execution_count": 51, 478 | "metadata": {}, 479 | "outputs": [], 480 | "source": [ 481 | "import torch.nn.functional as Fun" 482 | ] 483 | }, 484 | { 485 | "cell_type": "code", 486 | "execution_count": 52, 487 | "metadata": {}, 488 | "outputs": [], 489 | "source": [ 490 | "x = torch.linspace(-2.0,2.0,100,requires_grad=True)" 491 | ] 492 | }, 493 | { 494 | "cell_type": "code", 495 | "execution_count": 53, 496 | "metadata": {}, 497 | "outputs": [], 498 | "source": [ 499 | "x_relu = Fun.relu(x)" 500 | ] 501 | }, 502 | { 503 | "cell_type": "code", 504 | "execution_count": 54, 505 | "metadata": {}, 506 | "outputs": [], 507 | "source": [ 508 | "y = torch.sum(Fun.relu(x))" 509 | ] 510 | }, 511 | { 512 | "cell_type": "code", 513 | "execution_count": 55, 514 | "metadata": {}, 515 | "outputs": [], 516 | "source": [ 517 | "y.backward()" 518 | ] 519 | }, 520 | { 521 | "cell_type": "code", 522 | "execution_count": 56, 523 | "metadata": {}, 524 | "outputs": [ 525 | { 526 | "data": { 527 | "image/png": "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\n", 528 | "text/plain": [ 529 | "
" 530 | ] 531 | }, 532 | "metadata": {}, 533 | "output_type": "display_data" 534 | } 535 | ], 536 | "source": [ 537 | "plt.figure(figsize=(8,5))\n", 538 | "plt.plot(x.detach().numpy(),x_relu.detach().numpy(),label='Function',color='blue',lw=3)\n", 539 | "plt.plot(x.detach().numpy(),x.grad.detach().numpy(),label='Derivative',color='red',lw=3,linestyle='--')\n", 540 | "plt.legend(fontsize=15)\n", 541 | "plt.xticks(fontsize=14)\n", 542 | "plt.yticks(fontsize=14)\n", 543 | "plt.show()" 544 | ] 545 | }, 546 | { 547 | "cell_type": "code", 548 | "execution_count": null, 549 | "metadata": {}, 550 | "outputs": [], 551 | "source": [] 552 | } 553 | ], 554 | "metadata": { 555 | "kernelspec": { 556 | "display_name": "Python 3", 557 | "language": "python", 558 | "name": "python3" 559 | }, 560 | "language_info": { 561 | "codemirror_mode": { 562 | "name": "ipython", 563 | "version": 3 564 | }, 565 | "file_extension": ".py", 566 | "mimetype": "text/x-python", 567 | "name": "python", 568 | "nbconvert_exporter": "python", 569 | "pygments_lexer": "ipython3", 570 | "version": "3.6.2" 571 | }, 572 | "latex_envs": { 573 | "LaTeX_envs_menu_present": true, 574 | "autoclose": false, 575 | "autocomplete": true, 576 | "bibliofile": "biblio.bib", 577 | "cite_by": "apalike", 578 | "current_citInitial": 1, 579 | "eqLabelWithNumbers": true, 580 | "eqNumInitial": 1, 581 | "hotkeys": { 582 | "equation": "Ctrl-E", 583 | "itemize": "Ctrl-I" 584 | }, 585 | "labels_anchors": false, 586 | "latex_user_defs": false, 587 | "report_style_numbering": false, 588 | "user_envs_cfg": false 589 | } 590 | }, 591 | "nbformat": 4, 592 | "nbformat_minor": 2 593 | } 594 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Tirthajyoti Sarkar 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Machine Learning with PyTorch Notebooks 2 | Machine learning, Deep Learning, Convolutional Neural Network (CNN) using PyTorch. 3 | 4 | ### Please feel free to [connect with me here on LinkedIn](https://www.linkedin.com/in/tirthajyoti-sarkar-2127aa7/) if you are interested in data science and would like to connect. 5 | 6 | --- 7 | 8 | ## Notebooks 9 | 10 | ### [Tensor basics - creation and conversion](https://github.com/tirthajyoti/PyTorch_Machine_Learning/blob/master/Tensor%20basics%20-%20creation%20and%20conversion.ipynb) 11 | ### [Tensor basics - indexing and slicing](https://github.com/tirthajyoti/PyTorch_Machine_Learning/blob/master/Tensor%20basics%20-%20indexing%20and%20slicing.ipynb) 12 | ### [Tensor basics - vector (1-D) operations](https://github.com/tirthajyoti/PyTorch_Machine_Learning/blob/master/Tensor%20basics%20-%20vector%20(1-D)%20operations.ipynb) 13 | ### [Tensor basics - matrix (2-D) operations](https://github.com/tirthajyoti/PyTorch_Machine_Learning/blob/master/Tensor%20basics%20-%20Matrix%20(2-D)%20operations.ipynb) 14 | ### [Derivatives with PyTorch](https://github.com/tirthajyoti/PyTorch_Machine_Learning/blob/master/Derivatives%20with%20PyTorch.ipynb) 15 | ### [Example of building layers of a simple neural net from scratch](https://github.com/tirthajyoti/PyTorch_Machine_Learning/blob/master/Building%20a%20simple%20NN.ipynb) 16 | ### [Building the class definition of a neural net and associated methods](https://github.com/tirthajyoti/PyTorch_Machine_Learning/blob/master/NN%20class%20building.ipynb) 17 | 18 | ## Article 19 | 20 | Here is my Medium article on building a neural network using PyTorch step-by-step, 21 | 22 | ***[How PyTorch lets you build and experiment with a neural net](https://towardsdatascience.com/how-pytorch-lets-you-build-and-experiment-with-a-neural-net-de079b25a3e0)*** 23 | 24 | ![five-step](https://raw.githubusercontent.com/tirthajyoti/PyTorch_Machine_Learning/master/images/five-step-process.png) 25 | 26 | -------------------------------------------------------------------------------- /Tensor basics - Matrix (2-D) operations.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Tensor basics - Matrix (2-D) operations\n", 8 | "\n", 9 | "### Dr. Tirthajyoti Sarkar

Fremont, CA 94536

April 2019" 10 | ] 11 | }, 12 | { 13 | "cell_type": "code", 14 | "execution_count": 1, 15 | "metadata": {}, 16 | "outputs": [], 17 | "source": [ 18 | "import torch\n", 19 | "import numpy as np" 20 | ] 21 | }, 22 | { 23 | "cell_type": "markdown", 24 | "metadata": {}, 25 | "source": [ 26 | "### Creating 2-D Tensor (aka Matrix)" 27 | ] 28 | }, 29 | { 30 | "cell_type": "code", 31 | "execution_count": 13, 32 | "metadata": {}, 33 | "outputs": [], 34 | "source": [ 35 | "lst_of_lst = []\n", 36 | "\n", 37 | "for i in range(3):\n", 38 | " inner_lst=[]\n", 39 | " for j in range(3):\n", 40 | " inner_lst.append(10*(i+1)+j)\n", 41 | " lst_of_lst.append(inner_lst)" 42 | ] 43 | }, 44 | { 45 | "cell_type": "code", 46 | "execution_count": 14, 47 | "metadata": {}, 48 | "outputs": [ 49 | { 50 | "data": { 51 | "text/plain": [ 52 | "[[10, 11, 12], [20, 21, 22], [30, 31, 32]]" 53 | ] 54 | }, 55 | "execution_count": 14, 56 | "metadata": {}, 57 | "output_type": "execute_result" 58 | } 59 | ], 60 | "source": [ 61 | "lst_of_lst" 62 | ] 63 | }, 64 | { 65 | "cell_type": "code", 66 | "execution_count": 15, 67 | "metadata": {}, 68 | "outputs": [], 69 | "source": [ 70 | "A = torch.tensor(lst_of_lst)" 71 | ] 72 | }, 73 | { 74 | "cell_type": "code", 75 | "execution_count": 16, 76 | "metadata": {}, 77 | "outputs": [ 78 | { 79 | "data": { 80 | "text/plain": [ 81 | "tensor([[10, 11, 12],\n", 82 | " [20, 21, 22],\n", 83 | " [30, 31, 32]])" 84 | ] 85 | }, 86 | "execution_count": 16, 87 | "metadata": {}, 88 | "output_type": "execute_result" 89 | } 90 | ], 91 | "source": [ 92 | "A" 93 | ] 94 | }, 95 | { 96 | "cell_type": "markdown", 97 | "metadata": {}, 98 | "source": [ 99 | "### Dimension, shape and size of the 2-D Tensor" 100 | ] 101 | }, 102 | { 103 | "cell_type": "code", 104 | "execution_count": 18, 105 | "metadata": {}, 106 | "outputs": [ 107 | { 108 | "name": "stdout", 109 | "output_type": "stream", 110 | "text": [ 111 | "Dimension of the tensor: 2\n" 112 | ] 113 | } 114 | ], 115 | "source": [ 116 | "print(\"Dimension of the tensor:\",A.ndimension())" 117 | ] 118 | }, 119 | { 120 | "cell_type": "code", 121 | "execution_count": 21, 122 | "metadata": {}, 123 | "outputs": [ 124 | { 125 | "name": "stdout", 126 | "output_type": "stream", 127 | "text": [ 128 | "Shape of the tensor: torch.Size([3, 3])\n" 129 | ] 130 | } 131 | ], 132 | "source": [ 133 | "# shape is an attribute of the tensor\n", 134 | "print(\"Shape of the tensor:\",A.shape)" 135 | ] 136 | }, 137 | { 138 | "cell_type": "code", 139 | "execution_count": 26, 140 | "metadata": {}, 141 | "outputs": [ 142 | { 143 | "name": "stdout", 144 | "output_type": "stream", 145 | "text": [ 146 | "Total size of the tensor: torch.Size([3, 3])\n" 147 | ] 148 | } 149 | ], 150 | "source": [ 151 | "# size is a function/method which returns the size/shape of the tensor\n", 152 | "print(\"Total size of the tensor:\",A.size())" 153 | ] 154 | }, 155 | { 156 | "cell_type": "markdown", 157 | "metadata": {}, 158 | "source": [ 159 | "### Total number of elements can be found by casting the `size` attribute to an ndarray and then applying `prod`" 160 | ] 161 | }, 162 | { 163 | "cell_type": "code", 164 | "execution_count": 28, 165 | "metadata": {}, 166 | "outputs": [ 167 | { 168 | "name": "stdout", 169 | "output_type": "stream", 170 | "text": [ 171 | "Total size of the tensor: 9\n" 172 | ] 173 | } 174 | ], 175 | "source": [ 176 | "print(\"Total size of the tensor:\",np.array(A.size()).prod())" 177 | ] 178 | }, 179 | { 180 | "cell_type": "markdown", 181 | "metadata": {}, 182 | "source": [ 183 | "### Matrix (tensor) addition" 184 | ] 185 | }, 186 | { 187 | "cell_type": "code", 188 | "execution_count": 29, 189 | "metadata": {}, 190 | "outputs": [], 191 | "source": [ 192 | "lst_of_lst = []\n", 193 | "\n", 194 | "for i in range(3):\n", 195 | " inner_lst=[]\n", 196 | " for j in range(4):\n", 197 | " inner_lst.append(10*(i+1)+j)\n", 198 | " lst_of_lst.append(inner_lst)" 199 | ] 200 | }, 201 | { 202 | "cell_type": "code", 203 | "execution_count": 30, 204 | "metadata": {}, 205 | "outputs": [], 206 | "source": [ 207 | "A = torch.tensor(lst_of_lst)" 208 | ] 209 | }, 210 | { 211 | "cell_type": "code", 212 | "execution_count": 32, 213 | "metadata": {}, 214 | "outputs": [ 215 | { 216 | "data": { 217 | "text/plain": [ 218 | "tensor([[10, 11, 12, 13],\n", 219 | " [20, 21, 22, 23],\n", 220 | " [30, 31, 32, 33]])" 221 | ] 222 | }, 223 | "execution_count": 32, 224 | "metadata": {}, 225 | "output_type": "execute_result" 226 | } 227 | ], 228 | "source": [ 229 | "A" 230 | ] 231 | }, 232 | { 233 | "cell_type": "code", 234 | "execution_count": 33, 235 | "metadata": {}, 236 | "outputs": [], 237 | "source": [ 238 | "lst_of_lst = []\n", 239 | "\n", 240 | "for i in range(3):\n", 241 | " inner_lst=[]\n", 242 | " for j in range(4):\n", 243 | " inner_lst.append(10*(i+1)-j)\n", 244 | " lst_of_lst.append(inner_lst)" 245 | ] 246 | }, 247 | { 248 | "cell_type": "code", 249 | "execution_count": 34, 250 | "metadata": {}, 251 | "outputs": [], 252 | "source": [ 253 | "B = torch.tensor(lst_of_lst)" 254 | ] 255 | }, 256 | { 257 | "cell_type": "code", 258 | "execution_count": 35, 259 | "metadata": {}, 260 | "outputs": [ 261 | { 262 | "data": { 263 | "text/plain": [ 264 | "tensor([[10, 9, 8, 7],\n", 265 | " [20, 19, 18, 17],\n", 266 | " [30, 29, 28, 27]])" 267 | ] 268 | }, 269 | "execution_count": 35, 270 | "metadata": {}, 271 | "output_type": "execute_result" 272 | } 273 | ], 274 | "source": [ 275 | "B" 276 | ] 277 | }, 278 | { 279 | "cell_type": "markdown", 280 | "metadata": {}, 281 | "source": [ 282 | "$$ \\begin{bmatrix}\n", 283 | "10 & 11 & 12 & 13\\\\ 20 & 21 & 22 & 23 \\\\ 30 & 31 & 32 & 33 \\end{bmatrix} + \\begin{bmatrix}\n", 284 | "10 & 9 & 8 & 7\\\\ 20 & 19 & 18 & 17 \\\\ 30 & 29 & 28 & 27 \\end{bmatrix} = \\begin{bmatrix}\n", 285 | "20 & 20 & 20 & 20\\\\ 40 & 40 & 40 & 40 \\\\ 60 & 60 & 60 & 60 \\end{bmatrix}$$" 286 | ] 287 | }, 288 | { 289 | "cell_type": "code", 290 | "execution_count": 37, 291 | "metadata": {}, 292 | "outputs": [], 293 | "source": [ 294 | "C=A+B" 295 | ] 296 | }, 297 | { 298 | "cell_type": "code", 299 | "execution_count": 38, 300 | "metadata": {}, 301 | "outputs": [ 302 | { 303 | "data": { 304 | "text/plain": [ 305 | "tensor([[20, 20, 20, 20],\n", 306 | " [40, 40, 40, 40],\n", 307 | " [60, 60, 60, 60]])" 308 | ] 309 | }, 310 | "execution_count": 38, 311 | "metadata": {}, 312 | "output_type": "execute_result" 313 | } 314 | ], 315 | "source": [ 316 | "C" 317 | ] 318 | }, 319 | { 320 | "cell_type": "markdown", 321 | "metadata": {}, 322 | "source": [ 323 | "### Multiplying matrix by a scalar" 324 | ] 325 | }, 326 | { 327 | "cell_type": "code", 328 | "execution_count": 41, 329 | "metadata": {}, 330 | "outputs": [], 331 | "source": [ 332 | "D = 2.2*A" 333 | ] 334 | }, 335 | { 336 | "cell_type": "code", 337 | "execution_count": 42, 338 | "metadata": {}, 339 | "outputs": [ 340 | { 341 | "data": { 342 | "text/plain": [ 343 | "tensor([[20, 22, 24, 26],\n", 344 | " [40, 42, 44, 46],\n", 345 | " [60, 62, 64, 66]])" 346 | ] 347 | }, 348 | "execution_count": 42, 349 | "metadata": {}, 350 | "output_type": "execute_result" 351 | } 352 | ], 353 | "source": [ 354 | "D" 355 | ] 356 | }, 357 | { 358 | "cell_type": "markdown", 359 | "metadata": {}, 360 | "source": [ 361 | "#### The result is not exactly as we expected because A had the `IntTensor` type. We have to convert `A` to a `FloatTensor` type" 362 | ] 363 | }, 364 | { 365 | "cell_type": "code", 366 | "execution_count": 45, 367 | "metadata": {}, 368 | "outputs": [], 369 | "source": [ 370 | "A = A.type(torch.FloatTensor)" 371 | ] 372 | }, 373 | { 374 | "cell_type": "code", 375 | "execution_count": 46, 376 | "metadata": {}, 377 | "outputs": [], 378 | "source": [ 379 | "D = 2.2*A" 380 | ] 381 | }, 382 | { 383 | "cell_type": "code", 384 | "execution_count": 47, 385 | "metadata": {}, 386 | "outputs": [ 387 | { 388 | "data": { 389 | "text/plain": [ 390 | "tensor([[22.0000, 24.2000, 26.4000, 28.6000],\n", 391 | " [44.0000, 46.2000, 48.4000, 50.6000],\n", 392 | " [66.0000, 68.2000, 70.4000, 72.6000]])" 393 | ] 394 | }, 395 | "execution_count": 47, 396 | "metadata": {}, 397 | "output_type": "execute_result" 398 | } 399 | ], 400 | "source": [ 401 | "D" 402 | ] 403 | }, 404 | { 405 | "cell_type": "markdown", 406 | "metadata": {}, 407 | "source": [ 408 | "### Adding a scalar to a matrix" 409 | ] 410 | }, 411 | { 412 | "cell_type": "code", 413 | "execution_count": 61, 414 | "metadata": {}, 415 | "outputs": [], 416 | "source": [ 417 | "E = A+5.5" 418 | ] 419 | }, 420 | { 421 | "cell_type": "code", 422 | "execution_count": 62, 423 | "metadata": {}, 424 | "outputs": [ 425 | { 426 | "data": { 427 | "text/plain": [ 428 | "tensor([[15.5000, 16.5000, 17.5000, 18.5000],\n", 429 | " [25.5000, 26.5000, 27.5000, 28.5000],\n", 430 | " [35.5000, 36.5000, 37.5000, 38.5000]])" 431 | ] 432 | }, 433 | "execution_count": 62, 434 | "metadata": {}, 435 | "output_type": "execute_result" 436 | } 437 | ], 438 | "source": [ 439 | "E" 440 | ] 441 | }, 442 | { 443 | "cell_type": "markdown", 444 | "metadata": {}, 445 | "source": [ 446 | "### Slicing and indexing matrix elements" 447 | ] 448 | }, 449 | { 450 | "cell_type": "code", 451 | "execution_count": 48, 452 | "metadata": {}, 453 | "outputs": [ 454 | { 455 | "data": { 456 | "text/plain": [ 457 | "tensor([[10., 11., 12., 13.],\n", 458 | " [20., 21., 22., 23.],\n", 459 | " [30., 31., 32., 33.]])" 460 | ] 461 | }, 462 | "execution_count": 48, 463 | "metadata": {}, 464 | "output_type": "execute_result" 465 | } 466 | ], 467 | "source": [ 468 | "A" 469 | ] 470 | }, 471 | { 472 | "cell_type": "code", 473 | "execution_count": 51, 474 | "metadata": {}, 475 | "outputs": [ 476 | { 477 | "data": { 478 | "text/plain": [ 479 | "tensor(10.)" 480 | ] 481 | }, 482 | "execution_count": 51, 483 | "metadata": {}, 484 | "output_type": "execute_result" 485 | } 486 | ], 487 | "source": [ 488 | "A[0,0]" 489 | ] 490 | }, 491 | { 492 | "cell_type": "code", 493 | "execution_count": 52, 494 | "metadata": {}, 495 | "outputs": [ 496 | { 497 | "data": { 498 | "text/plain": [ 499 | "tensor([31., 32.])" 500 | ] 501 | }, 502 | "execution_count": 52, 503 | "metadata": {}, 504 | "output_type": "execute_result" 505 | } 506 | ], 507 | "source": [ 508 | "A[2,1:3]" 509 | ] 510 | }, 511 | { 512 | "cell_type": "code", 513 | "execution_count": 53, 514 | "metadata": {}, 515 | "outputs": [ 516 | { 517 | "data": { 518 | "text/plain": [ 519 | "tensor([[11., 12.],\n", 520 | " [21., 22.]])" 521 | ] 522 | }, 523 | "execution_count": 53, 524 | "metadata": {}, 525 | "output_type": "execute_result" 526 | } 527 | ], 528 | "source": [ 529 | "A[:2,1:3]" 530 | ] 531 | }, 532 | { 533 | "cell_type": "code", 534 | "execution_count": 58, 535 | "metadata": {}, 536 | "outputs": [ 537 | { 538 | "data": { 539 | "text/plain": [ 540 | "tensor([[10., 12.],\n", 541 | " [20., 22.],\n", 542 | " [30., 32.]])" 543 | ] 544 | }, 545 | "execution_count": 58, 546 | "metadata": {}, 547 | "output_type": "execute_result" 548 | } 549 | ], 550 | "source": [ 551 | "A[0:3,[0,2]]" 552 | ] 553 | }, 554 | { 555 | "cell_type": "markdown", 556 | "metadata": {}, 557 | "source": [ 558 | "### Element-wise product of matrices" 559 | ] 560 | }, 561 | { 562 | "cell_type": "code", 563 | "execution_count": 69, 564 | "metadata": {}, 565 | "outputs": [], 566 | "source": [ 567 | "X = torch.tensor([[1,2,-1],[3.5,0,1],[7,3,-2]])" 568 | ] 569 | }, 570 | { 571 | "cell_type": "code", 572 | "execution_count": 70, 573 | "metadata": {}, 574 | "outputs": [], 575 | "source": [ 576 | "Y = torch.tensor([[4,1,-3],[4,5,2.4],[7.5,-3,5]])" 577 | ] 578 | }, 579 | { 580 | "cell_type": "code", 581 | "execution_count": 71, 582 | "metadata": {}, 583 | "outputs": [ 584 | { 585 | "data": { 586 | "text/plain": [ 587 | "tensor([[ 1.0000, 2.0000, -1.0000],\n", 588 | " [ 3.5000, 0.0000, 1.0000],\n", 589 | " [ 7.0000, 3.0000, -2.0000]])" 590 | ] 591 | }, 592 | "execution_count": 71, 593 | "metadata": {}, 594 | "output_type": "execute_result" 595 | } 596 | ], 597 | "source": [ 598 | "X" 599 | ] 600 | }, 601 | { 602 | "cell_type": "code", 603 | "execution_count": 72, 604 | "metadata": {}, 605 | "outputs": [ 606 | { 607 | "data": { 608 | "text/plain": [ 609 | "tensor([[ 4.0000, 1.0000, -3.0000],\n", 610 | " [ 4.0000, 5.0000, 2.4000],\n", 611 | " [ 7.5000, -3.0000, 5.0000]])" 612 | ] 613 | }, 614 | "execution_count": 72, 615 | "metadata": {}, 616 | "output_type": "execute_result" 617 | } 618 | ], 619 | "source": [ 620 | "Y" 621 | ] 622 | }, 623 | { 624 | "cell_type": "code", 625 | "execution_count": 73, 626 | "metadata": {}, 627 | "outputs": [], 628 | "source": [ 629 | "Z = X*Y" 630 | ] 631 | }, 632 | { 633 | "cell_type": "code", 634 | "execution_count": 74, 635 | "metadata": {}, 636 | "outputs": [ 637 | { 638 | "data": { 639 | "text/plain": [ 640 | "tensor([[ 4.0000, 2.0000, 3.0000],\n", 641 | " [ 14.0000, 0.0000, 2.4000],\n", 642 | " [ 52.5000, -9.0000, -10.0000]])" 643 | ] 644 | }, 645 | "execution_count": 74, 646 | "metadata": {}, 647 | "output_type": "execute_result" 648 | } 649 | ], 650 | "source": [ 651 | "Z" 652 | ] 653 | }, 654 | { 655 | "cell_type": "markdown", 656 | "metadata": {}, 657 | "source": [ 658 | "### Matrix multiplication (shape of the individual tensors must line up accordingly)" 659 | ] 660 | }, 661 | { 662 | "cell_type": "code", 663 | "execution_count": 120, 664 | "metadata": {}, 665 | "outputs": [], 666 | "source": [ 667 | "X = torch.tensor([[1,2.5],[3.5,0],[11,2]])" 668 | ] 669 | }, 670 | { 671 | "cell_type": "code", 672 | "execution_count": 121, 673 | "metadata": {}, 674 | "outputs": [ 675 | { 676 | "data": { 677 | "text/plain": [ 678 | "tensor([[ 1.0000, 2.5000],\n", 679 | " [ 3.5000, 0.0000],\n", 680 | " [11.0000, 2.0000]])" 681 | ] 682 | }, 683 | "execution_count": 121, 684 | "metadata": {}, 685 | "output_type": "execute_result" 686 | } 687 | ], 688 | "source": [ 689 | "X" 690 | ] 691 | }, 692 | { 693 | "cell_type": "code", 694 | "execution_count": 122, 695 | "metadata": {}, 696 | "outputs": [], 697 | "source": [ 698 | "Y = torch.tensor([[4,1,-3],[1.7,5,2.4]])" 699 | ] 700 | }, 701 | { 702 | "cell_type": "code", 703 | "execution_count": 123, 704 | "metadata": {}, 705 | "outputs": [ 706 | { 707 | "data": { 708 | "text/plain": [ 709 | "tensor([[ 4.0000, 1.0000, -3.0000],\n", 710 | " [ 1.7000, 5.0000, 2.4000]])" 711 | ] 712 | }, 713 | "execution_count": 123, 714 | "metadata": {}, 715 | "output_type": "execute_result" 716 | } 717 | ], 718 | "source": [ 719 | "Y" 720 | ] 721 | }, 722 | { 723 | "cell_type": "code", 724 | "execution_count": 124, 725 | "metadata": {}, 726 | "outputs": [], 727 | "source": [ 728 | "W = X.mm(Y)" 729 | ] 730 | }, 731 | { 732 | "cell_type": "code", 733 | "execution_count": 125, 734 | "metadata": {}, 735 | "outputs": [ 736 | { 737 | "data": { 738 | "text/plain": [ 739 | "tensor([[ 8.2500, 13.5000, 3.0000],\n", 740 | " [ 14.0000, 3.5000, -10.5000],\n", 741 | " [ 47.4000, 21.0000, -28.2000]])" 742 | ] 743 | }, 744 | "execution_count": 125, 745 | "metadata": {}, 746 | "output_type": "execute_result" 747 | } 748 | ], 749 | "source": [ 750 | "W" 751 | ] 752 | }, 753 | { 754 | "cell_type": "markdown", 755 | "metadata": {}, 756 | "source": [ 757 | "### Matrix transpose\n", 758 | "Need to specify the dimensions as `dim0`, `dim1` argument to the method" 759 | ] 760 | }, 761 | { 762 | "cell_type": "code", 763 | "execution_count": 126, 764 | "metadata": {}, 765 | "outputs": [ 766 | { 767 | "data": { 768 | "text/plain": [ 769 | "tensor([[ 8.2500, 13.5000, 3.0000],\n", 770 | " [ 14.0000, 3.5000, -10.5000],\n", 771 | " [ 47.4000, 21.0000, -28.2000]])" 772 | ] 773 | }, 774 | "execution_count": 126, 775 | "metadata": {}, 776 | "output_type": "execute_result" 777 | } 778 | ], 779 | "source": [ 780 | "W" 781 | ] 782 | }, 783 | { 784 | "cell_type": "code", 785 | "execution_count": 127, 786 | "metadata": {}, 787 | "outputs": [ 788 | { 789 | "data": { 790 | "text/plain": [ 791 | "tensor([[ 8.2500, 14.0000, 47.4000],\n", 792 | " [ 13.5000, 3.5000, 21.0000],\n", 793 | " [ 3.0000, -10.5000, -28.2000]])" 794 | ] 795 | }, 796 | "execution_count": 127, 797 | "metadata": {}, 798 | "output_type": "execute_result" 799 | } 800 | ], 801 | "source": [ 802 | "W.transpose(0,1)" 803 | ] 804 | }, 805 | { 806 | "cell_type": "markdown", 807 | "metadata": {}, 808 | "source": [ 809 | "### Matrix inverse and determinant" 810 | ] 811 | }, 812 | { 813 | "cell_type": "code", 814 | "execution_count": 137, 815 | "metadata": {}, 816 | "outputs": [], 817 | "source": [ 818 | "X = torch.tensor([[2.5,1.2],[3,2]])\n", 819 | "Y = torch.tensor([[1.2,-1],[2,3]])" 820 | ] 821 | }, 822 | { 823 | "cell_type": "code", 824 | "execution_count": 138, 825 | "metadata": {}, 826 | "outputs": [], 827 | "source": [ 828 | "W = torch.mm(X,Y)" 829 | ] 830 | }, 831 | { 832 | "cell_type": "code", 833 | "execution_count": 139, 834 | "metadata": {}, 835 | "outputs": [ 836 | { 837 | "data": { 838 | "text/plain": [ 839 | "tensor([[5.4000, 1.1000],\n", 840 | " [7.6000, 3.0000]])" 841 | ] 842 | }, 843 | "execution_count": 139, 844 | "metadata": {}, 845 | "output_type": "execute_result" 846 | } 847 | ], 848 | "source": [ 849 | "W" 850 | ] 851 | }, 852 | { 853 | "cell_type": "code", 854 | "execution_count": 140, 855 | "metadata": {}, 856 | "outputs": [ 857 | { 858 | "data": { 859 | "text/plain": [ 860 | "tensor([[ 0.3827, -0.1403],\n", 861 | " [-0.9694, 0.6888]])" 862 | ] 863 | }, 864 | "execution_count": 140, 865 | "metadata": {}, 866 | "output_type": "execute_result" 867 | } 868 | ], 869 | "source": [ 870 | "torch.inverse(W)" 871 | ] 872 | }, 873 | { 874 | "cell_type": "code", 875 | "execution_count": 141, 876 | "metadata": {}, 877 | "outputs": [ 878 | { 879 | "data": { 880 | "text/plain": [ 881 | "tensor(7.8400)" 882 | ] 883 | }, 884 | "execution_count": 141, 885 | "metadata": {}, 886 | "output_type": "execute_result" 887 | } 888 | ], 889 | "source": [ 890 | "torch.det(W)" 891 | ] 892 | } 893 | ], 894 | "metadata": { 895 | "kernelspec": { 896 | "display_name": "Python 3", 897 | "language": "python", 898 | "name": "python3" 899 | }, 900 | "language_info": { 901 | "codemirror_mode": { 902 | "name": "ipython", 903 | "version": 3 904 | }, 905 | "file_extension": ".py", 906 | "mimetype": "text/x-python", 907 | "name": "python", 908 | "nbconvert_exporter": "python", 909 | "pygments_lexer": "ipython3", 910 | "version": "3.6.2" 911 | }, 912 | "latex_envs": { 913 | "LaTeX_envs_menu_present": true, 914 | "autoclose": false, 915 | "autocomplete": true, 916 | "bibliofile": "biblio.bib", 917 | "cite_by": "apalike", 918 | "current_citInitial": 1, 919 | "eqLabelWithNumbers": true, 920 | "eqNumInitial": 1, 921 | "hotkeys": { 922 | "equation": "Ctrl-E", 923 | "itemize": "Ctrl-I" 924 | }, 925 | "labels_anchors": false, 926 | "latex_user_defs": false, 927 | "report_style_numbering": false, 928 | "user_envs_cfg": false 929 | } 930 | }, 931 | "nbformat": 4, 932 | "nbformat_minor": 2 933 | } 934 | -------------------------------------------------------------------------------- /Tensor basics - creation and conversion.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Tensor basics - creation and conversion\n", 8 | "\n", 9 | "### Dr. Tirthajyoti Sarkar

Fremont, CA 94536

April 2019" 10 | ] 11 | }, 12 | { 13 | "cell_type": "code", 14 | "execution_count": 113, 15 | "metadata": {}, 16 | "outputs": [], 17 | "source": [ 18 | "import torch\n", 19 | "import numpy as np\n", 20 | "import pandas as pd" 21 | ] 22 | }, 23 | { 24 | "cell_type": "markdown", 25 | "metadata": {}, 26 | "source": [ 27 | "### 1-D Tensor from a list" 28 | ] 29 | }, 30 | { 31 | "cell_type": "code", 32 | "execution_count": 121, 33 | "metadata": {}, 34 | "outputs": [], 35 | "source": [ 36 | "a = torch.tensor([i for i in range(5)])" 37 | ] 38 | }, 39 | { 40 | "cell_type": "code", 41 | "execution_count": 122, 42 | "metadata": {}, 43 | "outputs": [ 44 | { 45 | "data": { 46 | "text/plain": [ 47 | "tensor([0, 1, 2, 3, 4])" 48 | ] 49 | }, 50 | "execution_count": 122, 51 | "metadata": {}, 52 | "output_type": "execute_result" 53 | } 54 | ], 55 | "source": [ 56 | "a" 57 | ] 58 | }, 59 | { 60 | "cell_type": "code", 61 | "execution_count": 123, 62 | "metadata": {}, 63 | "outputs": [ 64 | { 65 | "data": { 66 | "text/plain": [ 67 | "torch.Tensor" 68 | ] 69 | }, 70 | "execution_count": 123, 71 | "metadata": {}, 72 | "output_type": "execute_result" 73 | } 74 | ], 75 | "source": [ 76 | "type(a)" 77 | ] 78 | }, 79 | { 80 | "cell_type": "code", 81 | "execution_count": 124, 82 | "metadata": {}, 83 | "outputs": [ 84 | { 85 | "data": { 86 | "text/plain": [ 87 | "torch.int64" 88 | ] 89 | }, 90 | "execution_count": 124, 91 | "metadata": {}, 92 | "output_type": "execute_result" 93 | } 94 | ], 95 | "source": [ 96 | "a.dtype" 97 | ] 98 | }, 99 | { 100 | "cell_type": "code", 101 | "execution_count": 125, 102 | "metadata": {}, 103 | "outputs": [ 104 | { 105 | "data": { 106 | "text/plain": [ 107 | "'torch.LongTensor'" 108 | ] 109 | }, 110 | "execution_count": 125, 111 | "metadata": {}, 112 | "output_type": "execute_result" 113 | } 114 | ], 115 | "source": [ 116 | "a.type()" 117 | ] 118 | }, 119 | { 120 | "cell_type": "markdown", 121 | "metadata": {}, 122 | "source": [ 123 | "### Acessing element (indexing) and data type" 124 | ] 125 | }, 126 | { 127 | "cell_type": "code", 128 | "execution_count": 126, 129 | "metadata": {}, 130 | "outputs": [ 131 | { 132 | "data": { 133 | "text/plain": [ 134 | "tensor(0)" 135 | ] 136 | }, 137 | "execution_count": 126, 138 | "metadata": {}, 139 | "output_type": "execute_result" 140 | } 141 | ], 142 | "source": [ 143 | "a[0]" 144 | ] 145 | }, 146 | { 147 | "cell_type": "code", 148 | "execution_count": 127, 149 | "metadata": {}, 150 | "outputs": [ 151 | { 152 | "data": { 153 | "text/plain": [ 154 | "tensor(3)" 155 | ] 156 | }, 157 | "execution_count": 127, 158 | "metadata": {}, 159 | "output_type": "execute_result" 160 | } 161 | ], 162 | "source": [ 163 | "a[3]" 164 | ] 165 | }, 166 | { 167 | "cell_type": "markdown", 168 | "metadata": {}, 169 | "source": [ 170 | "### Accessing the actual number using `item()` method" 171 | ] 172 | }, 173 | { 174 | "cell_type": "code", 175 | "execution_count": 128, 176 | "metadata": {}, 177 | "outputs": [ 178 | { 179 | "data": { 180 | "text/plain": [ 181 | "2" 182 | ] 183 | }, 184 | "execution_count": 128, 185 | "metadata": {}, 186 | "output_type": "execute_result" 187 | } 188 | ], 189 | "source": [ 190 | "a[2].item()" 191 | ] 192 | }, 193 | { 194 | "cell_type": "code", 195 | "execution_count": 129, 196 | "metadata": {}, 197 | "outputs": [ 198 | { 199 | "data": { 200 | "text/plain": [ 201 | "int" 202 | ] 203 | }, 204 | "execution_count": 129, 205 | "metadata": {}, 206 | "output_type": "execute_result" 207 | } 208 | ], 209 | "source": [ 210 | "type(a[3].item())" 211 | ] 212 | }, 213 | { 214 | "cell_type": "markdown", 215 | "metadata": {}, 216 | "source": [ 217 | "### Creating a `torch.FloatTensor` using `FloatTensor()` method" 218 | ] 219 | }, 220 | { 221 | "cell_type": "code", 222 | "execution_count": 33, 223 | "metadata": {}, 224 | "outputs": [], 225 | "source": [ 226 | "a = torch.tensor([1.0,2.0,3.0,4.0,5.0])" 227 | ] 228 | }, 229 | { 230 | "cell_type": "code", 231 | "execution_count": 35, 232 | "metadata": {}, 233 | "outputs": [ 234 | { 235 | "data": { 236 | "text/plain": [ 237 | "'torch.FloatTensor'" 238 | ] 239 | }, 240 | "execution_count": 35, 241 | "metadata": {}, 242 | "output_type": "execute_result" 243 | } 244 | ], 245 | "source": [ 246 | "a.type()" 247 | ] 248 | }, 249 | { 250 | "cell_type": "code", 251 | "execution_count": 36, 252 | "metadata": {}, 253 | "outputs": [], 254 | "source": [ 255 | "a = torch.FloatTensor([1,2,3,4,5])" 256 | ] 257 | }, 258 | { 259 | "cell_type": "code", 260 | "execution_count": 37, 261 | "metadata": {}, 262 | "outputs": [ 263 | { 264 | "data": { 265 | "text/plain": [ 266 | "'torch.FloatTensor'" 267 | ] 268 | }, 269 | "execution_count": 37, 270 | "metadata": {}, 271 | "output_type": "execute_result" 272 | } 273 | ], 274 | "source": [ 275 | "a.type()" 276 | ] 277 | }, 278 | { 279 | "cell_type": "markdown", 280 | "metadata": {}, 281 | "source": [ 282 | "### Converting from a `LongTensor` using `type` method" 283 | ] 284 | }, 285 | { 286 | "cell_type": "code", 287 | "execution_count": 25, 288 | "metadata": {}, 289 | "outputs": [], 290 | "source": [ 291 | "b = torch.tensor([i for i in range(5)])" 292 | ] 293 | }, 294 | { 295 | "cell_type": "code", 296 | "execution_count": 26, 297 | "metadata": {}, 298 | "outputs": [ 299 | { 300 | "data": { 301 | "text/plain": [ 302 | "tensor([0, 1, 2, 3, 4])" 303 | ] 304 | }, 305 | "execution_count": 26, 306 | "metadata": {}, 307 | "output_type": "execute_result" 308 | } 309 | ], 310 | "source": [ 311 | "b" 312 | ] 313 | }, 314 | { 315 | "cell_type": "code", 316 | "execution_count": 27, 317 | "metadata": {}, 318 | "outputs": [ 319 | { 320 | "data": { 321 | "text/plain": [ 322 | "torch.int64" 323 | ] 324 | }, 325 | "execution_count": 27, 326 | "metadata": {}, 327 | "output_type": "execute_result" 328 | } 329 | ], 330 | "source": [ 331 | "b.dtype" 332 | ] 333 | }, 334 | { 335 | "cell_type": "code", 336 | "execution_count": 28, 337 | "metadata": {}, 338 | "outputs": [ 339 | { 340 | "data": { 341 | "text/plain": [ 342 | "'torch.LongTensor'" 343 | ] 344 | }, 345 | "execution_count": 28, 346 | "metadata": {}, 347 | "output_type": "execute_result" 348 | } 349 | ], 350 | "source": [ 351 | "b.type()" 352 | ] 353 | }, 354 | { 355 | "cell_type": "code", 356 | "execution_count": 29, 357 | "metadata": {}, 358 | "outputs": [], 359 | "source": [ 360 | "b = b.type(torch.FloatTensor)" 361 | ] 362 | }, 363 | { 364 | "cell_type": "code", 365 | "execution_count": 30, 366 | "metadata": {}, 367 | "outputs": [ 368 | { 369 | "data": { 370 | "text/plain": [ 371 | "tensor([0., 1., 2., 3., 4.])" 372 | ] 373 | }, 374 | "execution_count": 30, 375 | "metadata": {}, 376 | "output_type": "execute_result" 377 | } 378 | ], 379 | "source": [ 380 | "b" 381 | ] 382 | }, 383 | { 384 | "cell_type": "code", 385 | "execution_count": 31, 386 | "metadata": {}, 387 | "outputs": [ 388 | { 389 | "data": { 390 | "text/plain": [ 391 | "torch.float32" 392 | ] 393 | }, 394 | "execution_count": 31, 395 | "metadata": {}, 396 | "output_type": "execute_result" 397 | } 398 | ], 399 | "source": [ 400 | "b.dtype" 401 | ] 402 | }, 403 | { 404 | "cell_type": "code", 405 | "execution_count": 32, 406 | "metadata": {}, 407 | "outputs": [ 408 | { 409 | "data": { 410 | "text/plain": [ 411 | "'torch.FloatTensor'" 412 | ] 413 | }, 414 | "execution_count": 32, 415 | "metadata": {}, 416 | "output_type": "execute_result" 417 | } 418 | ], 419 | "source": [ 420 | "b.type()" 421 | ] 422 | }, 423 | { 424 | "cell_type": "markdown", 425 | "metadata": {}, 426 | "source": [ 427 | "### Size and dimension" 428 | ] 429 | }, 430 | { 431 | "cell_type": "code", 432 | "execution_count": 44, 433 | "metadata": {}, 434 | "outputs": [ 435 | { 436 | "data": { 437 | "text/plain": [ 438 | "tensor([0., 1., 2., 3., 4.])" 439 | ] 440 | }, 441 | "execution_count": 44, 442 | "metadata": {}, 443 | "output_type": "execute_result" 444 | } 445 | ], 446 | "source": [ 447 | "b" 448 | ] 449 | }, 450 | { 451 | "cell_type": "code", 452 | "execution_count": 45, 453 | "metadata": {}, 454 | "outputs": [ 455 | { 456 | "data": { 457 | "text/plain": [ 458 | "torch.Size([5])" 459 | ] 460 | }, 461 | "execution_count": 45, 462 | "metadata": {}, 463 | "output_type": "execute_result" 464 | } 465 | ], 466 | "source": [ 467 | "b.size()" 468 | ] 469 | }, 470 | { 471 | "cell_type": "code", 472 | "execution_count": 46, 473 | "metadata": {}, 474 | "outputs": [ 475 | { 476 | "data": { 477 | "text/plain": [ 478 | "1" 479 | ] 480 | }, 481 | "execution_count": 46, 482 | "metadata": {}, 483 | "output_type": "execute_result" 484 | } 485 | ], 486 | "source": [ 487 | "b.ndimension()" 488 | ] 489 | }, 490 | { 491 | "cell_type": "markdown", 492 | "metadata": {}, 493 | "source": [ 494 | "### Changing the view of a tensor" 495 | ] 496 | }, 497 | { 498 | "cell_type": "code", 499 | "execution_count": 54, 500 | "metadata": {}, 501 | "outputs": [], 502 | "source": [ 503 | "a = torch.tensor([i for i in range(1,6)])" 504 | ] 505 | }, 506 | { 507 | "cell_type": "code", 508 | "execution_count": 55, 509 | "metadata": {}, 510 | "outputs": [ 511 | { 512 | "data": { 513 | "text/plain": [ 514 | "tensor([1, 2, 3, 4, 5])" 515 | ] 516 | }, 517 | "execution_count": 55, 518 | "metadata": {}, 519 | "output_type": "execute_result" 520 | } 521 | ], 522 | "source": [ 523 | "a" 524 | ] 525 | }, 526 | { 527 | "cell_type": "code", 528 | "execution_count": 63, 529 | "metadata": {}, 530 | "outputs": [ 531 | { 532 | "data": { 533 | "text/plain": [ 534 | "torch.Size([5])" 535 | ] 536 | }, 537 | "execution_count": 63, 538 | "metadata": {}, 539 | "output_type": "execute_result" 540 | } 541 | ], 542 | "source": [ 543 | "a.size()" 544 | ] 545 | }, 546 | { 547 | "cell_type": "code", 548 | "execution_count": 56, 549 | "metadata": {}, 550 | "outputs": [ 551 | { 552 | "data": { 553 | "text/plain": [ 554 | "1" 555 | ] 556 | }, 557 | "execution_count": 56, 558 | "metadata": {}, 559 | "output_type": "execute_result" 560 | } 561 | ], 562 | "source": [ 563 | "a.ndimension()" 564 | ] 565 | }, 566 | { 567 | "cell_type": "code", 568 | "execution_count": 57, 569 | "metadata": {}, 570 | "outputs": [], 571 | "source": [ 572 | "a_col = a.view(5,1)" 573 | ] 574 | }, 575 | { 576 | "cell_type": "code", 577 | "execution_count": 58, 578 | "metadata": {}, 579 | "outputs": [ 580 | { 581 | "data": { 582 | "text/plain": [ 583 | "tensor([[1],\n", 584 | " [2],\n", 585 | " [3],\n", 586 | " [4],\n", 587 | " [5]])" 588 | ] 589 | }, 590 | "execution_count": 58, 591 | "metadata": {}, 592 | "output_type": "execute_result" 593 | } 594 | ], 595 | "source": [ 596 | "a_col" 597 | ] 598 | }, 599 | { 600 | "cell_type": "code", 601 | "execution_count": 59, 602 | "metadata": {}, 603 | "outputs": [ 604 | { 605 | "data": { 606 | "text/plain": [ 607 | "'torch.LongTensor'" 608 | ] 609 | }, 610 | "execution_count": 59, 611 | "metadata": {}, 612 | "output_type": "execute_result" 613 | } 614 | ], 615 | "source": [ 616 | "a_col.type()" 617 | ] 618 | }, 619 | { 620 | "cell_type": "code", 621 | "execution_count": 61, 622 | "metadata": {}, 623 | "outputs": [ 624 | { 625 | "data": { 626 | "text/plain": [ 627 | "2" 628 | ] 629 | }, 630 | "execution_count": 61, 631 | "metadata": {}, 632 | "output_type": "execute_result" 633 | } 634 | ], 635 | "source": [ 636 | "a_col.ndimension()" 637 | ] 638 | }, 639 | { 640 | "cell_type": "code", 641 | "execution_count": 62, 642 | "metadata": {}, 643 | "outputs": [ 644 | { 645 | "data": { 646 | "text/plain": [ 647 | "torch.Size([5, 1])" 648 | ] 649 | }, 650 | "execution_count": 62, 651 | "metadata": {}, 652 | "output_type": "execute_result" 653 | } 654 | ], 655 | "source": [ 656 | "a_col.size()" 657 | ] 658 | }, 659 | { 660 | "cell_type": "markdown", 661 | "metadata": {}, 662 | "source": [ 663 | "### If we don't know the original size, we can use -1 as placeholder" 664 | ] 665 | }, 666 | { 667 | "cell_type": "code", 668 | "execution_count": 86, 669 | "metadata": {}, 670 | "outputs": [ 671 | { 672 | "name": "stdout", 673 | "output_type": "stream", 674 | "text": [ 675 | "Original tensor: tensor([0, 1, 2, 3, 4, 5])\n", 676 | "Reshaped view of tensor with 3 columns:\n", 677 | " tensor([[0, 1, 2],\n", 678 | " [3, 4, 5]])\n", 679 | "========================================\n", 680 | "Original tensor: tensor([0, 1, 2, 3, 4, 5, 6, 7, 8])\n", 681 | "Reshaped view of tensor with 3 columns:\n", 682 | " tensor([[0, 1, 2],\n", 683 | " [3, 4, 5],\n", 684 | " [6, 7, 8]])\n", 685 | "========================================\n", 686 | "Original tensor: tensor([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])\n", 687 | "Reshaped view of tensor with 3 columns:\n", 688 | " tensor([[ 0, 1, 2],\n", 689 | " [ 3, 4, 5],\n", 690 | " [ 6, 7, 8],\n", 691 | " [ 9, 10, 11]])\n", 692 | "========================================\n" 693 | ] 694 | } 695 | ], 696 | "source": [ 697 | "n = [6, 9, 12]\n", 698 | "for k in n:\n", 699 | " a = torch.tensor([i for i in range(k)])\n", 700 | " a_col = a.view(-1,3)\n", 701 | " print(\"Original tensor:\", a)\n", 702 | " print(\"Reshaped view of tensor with 3 columns:\\n\",a_col)\n", 703 | " print(\"=\"*40)" 704 | ] 705 | }, 706 | { 707 | "cell_type": "markdown", 708 | "metadata": {}, 709 | "source": [ 710 | "### Changing back and forth between tensor and `NumPy` array" 711 | ] 712 | }, 713 | { 714 | "cell_type": "code", 715 | "execution_count": 105, 716 | "metadata": {}, 717 | "outputs": [], 718 | "source": [ 719 | "np_array = np.arange(1.0,3.5,0.5)" 720 | ] 721 | }, 722 | { 723 | "cell_type": "code", 724 | "execution_count": 106, 725 | "metadata": {}, 726 | "outputs": [ 727 | { 728 | "data": { 729 | "text/plain": [ 730 | "array([1. , 1.5, 2. , 2.5, 3. ])" 731 | ] 732 | }, 733 | "execution_count": 106, 734 | "metadata": {}, 735 | "output_type": "execute_result" 736 | } 737 | ], 738 | "source": [ 739 | "np_array" 740 | ] 741 | }, 742 | { 743 | "cell_type": "code", 744 | "execution_count": 107, 745 | "metadata": {}, 746 | "outputs": [], 747 | "source": [ 748 | "tensor_from_array = torch.from_numpy(np_array)" 749 | ] 750 | }, 751 | { 752 | "cell_type": "code", 753 | "execution_count": 108, 754 | "metadata": {}, 755 | "outputs": [ 756 | { 757 | "data": { 758 | "text/plain": [ 759 | "tensor([1.0000, 1.5000, 2.0000, 2.5000, 3.0000], dtype=torch.float64)" 760 | ] 761 | }, 762 | "execution_count": 108, 763 | "metadata": {}, 764 | "output_type": "execute_result" 765 | } 766 | ], 767 | "source": [ 768 | "tensor_from_array" 769 | ] 770 | }, 771 | { 772 | "cell_type": "code", 773 | "execution_count": 109, 774 | "metadata": {}, 775 | "outputs": [ 776 | { 777 | "data": { 778 | "text/plain": [ 779 | "'torch.DoubleTensor'" 780 | ] 781 | }, 782 | "execution_count": 109, 783 | "metadata": {}, 784 | "output_type": "execute_result" 785 | } 786 | ], 787 | "source": [ 788 | "tensor_from_array.type()" 789 | ] 790 | }, 791 | { 792 | "cell_type": "code", 793 | "execution_count": 110, 794 | "metadata": {}, 795 | "outputs": [], 796 | "source": [ 797 | "back_to_np = tensor_from_array.numpy()" 798 | ] 799 | }, 800 | { 801 | "cell_type": "code", 802 | "execution_count": 111, 803 | "metadata": {}, 804 | "outputs": [ 805 | { 806 | "data": { 807 | "text/plain": [ 808 | "array([1. , 1.5, 2. , 2.5, 3. ])" 809 | ] 810 | }, 811 | "execution_count": 111, 812 | "metadata": {}, 813 | "output_type": "execute_result" 814 | } 815 | ], 816 | "source": [ 817 | "back_to_np" 818 | ] 819 | }, 820 | { 821 | "cell_type": "markdown", 822 | "metadata": {}, 823 | "source": [ 824 | "### Pointer from re-converted numpy array points to the tensor object, which, in turn, points to the original numpy array. So, any change in the original numpy array reflects back." 825 | ] 826 | }, 827 | { 828 | "cell_type": "code", 829 | "execution_count": 112, 830 | "metadata": {}, 831 | "outputs": [ 832 | { 833 | "data": { 834 | "text/plain": [ 835 | "array([1. , 1.5, 2. , 2.5, 3. ])" 836 | ] 837 | }, 838 | "execution_count": 112, 839 | "metadata": {}, 840 | "output_type": "execute_result" 841 | } 842 | ], 843 | "source": [ 844 | "np_array" 845 | ] 846 | }, 847 | { 848 | "cell_type": "code", 849 | "execution_count": 101, 850 | "metadata": {}, 851 | "outputs": [ 852 | { 853 | "data": { 854 | "text/plain": [ 855 | "array([2., 3., 4., 5., 6.])" 856 | ] 857 | }, 858 | "execution_count": 101, 859 | "metadata": {}, 860 | "output_type": "execute_result" 861 | } 862 | ], 863 | "source": [ 864 | "np_array" 865 | ] 866 | }, 867 | { 868 | "cell_type": "code", 869 | "execution_count": 102, 870 | "metadata": {}, 871 | "outputs": [ 872 | { 873 | "data": { 874 | "text/plain": [ 875 | "array([1. , 1.5, 2. , 2.5, 3. ])" 876 | ] 877 | }, 878 | "execution_count": 102, 879 | "metadata": {}, 880 | "output_type": "execute_result" 881 | } 882 | ], 883 | "source": [ 884 | "back_to_np" 885 | ] 886 | }, 887 | { 888 | "cell_type": "code", 889 | "execution_count": 103, 890 | "metadata": {}, 891 | "outputs": [ 892 | { 893 | "data": { 894 | "text/plain": [ 895 | "tensor([1.0000, 1.5000, 2.0000, 2.5000, 3.0000], dtype=torch.float64)" 896 | ] 897 | }, 898 | "execution_count": 103, 899 | "metadata": {}, 900 | "output_type": "execute_result" 901 | } 902 | ], 903 | "source": [ 904 | "tensor_from_array" 905 | ] 906 | }, 907 | { 908 | "cell_type": "markdown", 909 | "metadata": {}, 910 | "source": [ 911 | "### Conversion from a Pandas series" 912 | ] 913 | }, 914 | { 915 | "cell_type": "code", 916 | "execution_count": 114, 917 | "metadata": {}, 918 | "outputs": [], 919 | "source": [ 920 | "pd_series = pd.Series([i for i in range(1,6)])" 921 | ] 922 | }, 923 | { 924 | "cell_type": "code", 925 | "execution_count": 115, 926 | "metadata": {}, 927 | "outputs": [ 928 | { 929 | "data": { 930 | "text/plain": [ 931 | "0 1\n", 932 | "1 2\n", 933 | "2 3\n", 934 | "3 4\n", 935 | "4 5\n", 936 | "dtype: int64" 937 | ] 938 | }, 939 | "execution_count": 115, 940 | "metadata": {}, 941 | "output_type": "execute_result" 942 | } 943 | ], 944 | "source": [ 945 | "pd_series" 946 | ] 947 | }, 948 | { 949 | "cell_type": "code", 950 | "execution_count": 117, 951 | "metadata": {}, 952 | "outputs": [], 953 | "source": [ 954 | "pd_to_torch = torch.from_numpy(pd_series.values)" 955 | ] 956 | }, 957 | { 958 | "cell_type": "code", 959 | "execution_count": 118, 960 | "metadata": {}, 961 | "outputs": [ 962 | { 963 | "data": { 964 | "text/plain": [ 965 | "tensor([1, 2, 3, 4, 5])" 966 | ] 967 | }, 968 | "execution_count": 118, 969 | "metadata": {}, 970 | "output_type": "execute_result" 971 | } 972 | ], 973 | "source": [ 974 | "pd_to_torch" 975 | ] 976 | }, 977 | { 978 | "cell_type": "markdown", 979 | "metadata": {}, 980 | "source": [ 981 | "### Converting back to a list using `tolist()`" 982 | ] 983 | }, 984 | { 985 | "cell_type": "code", 986 | "execution_count": 119, 987 | "metadata": {}, 988 | "outputs": [], 989 | "source": [ 990 | "to_list = pd_to_torch.tolist()" 991 | ] 992 | }, 993 | { 994 | "cell_type": "code", 995 | "execution_count": 120, 996 | "metadata": {}, 997 | "outputs": [ 998 | { 999 | "data": { 1000 | "text/plain": [ 1001 | "[1, 2, 3, 4, 5]" 1002 | ] 1003 | }, 1004 | "execution_count": 120, 1005 | "metadata": {}, 1006 | "output_type": "execute_result" 1007 | } 1008 | ], 1009 | "source": [ 1010 | "to_list" 1011 | ] 1012 | } 1013 | ], 1014 | "metadata": { 1015 | "kernelspec": { 1016 | "display_name": "Python 3", 1017 | "language": "python", 1018 | "name": "python3" 1019 | }, 1020 | "language_info": { 1021 | "codemirror_mode": { 1022 | "name": "ipython", 1023 | "version": 3 1024 | }, 1025 | "file_extension": ".py", 1026 | "mimetype": "text/x-python", 1027 | "name": "python", 1028 | "nbconvert_exporter": "python", 1029 | "pygments_lexer": "ipython3", 1030 | "version": "3.6.2" 1031 | }, 1032 | "latex_envs": { 1033 | "LaTeX_envs_menu_present": true, 1034 | "autoclose": false, 1035 | "autocomplete": true, 1036 | "bibliofile": "biblio.bib", 1037 | "cite_by": "apalike", 1038 | "current_citInitial": 1, 1039 | "eqLabelWithNumbers": true, 1040 | "eqNumInitial": 1, 1041 | "hotkeys": { 1042 | "equation": "Ctrl-E", 1043 | "itemize": "Ctrl-I" 1044 | }, 1045 | "labels_anchors": false, 1046 | "latex_user_defs": false, 1047 | "report_style_numbering": false, 1048 | "user_envs_cfg": false 1049 | } 1050 | }, 1051 | "nbformat": 4, 1052 | "nbformat_minor": 2 1053 | } 1054 | -------------------------------------------------------------------------------- /Tensor basics - indexing and slicing.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Tensor basics - indexing and slicing\n", 8 | "\n", 9 | "### Dr. Tirthajyoti Sarkar

Fremont, CA 94536

April 2019" 10 | ] 11 | }, 12 | { 13 | "cell_type": "code", 14 | "execution_count": 1, 15 | "metadata": {}, 16 | "outputs": [], 17 | "source": [ 18 | "import torch\n", 19 | "import numpy as np" 20 | ] 21 | }, 22 | { 23 | "cell_type": "code", 24 | "execution_count": 2, 25 | "metadata": {}, 26 | "outputs": [], 27 | "source": [ 28 | "c = torch.Tensor([i for i in range(5)])" 29 | ] 30 | }, 31 | { 32 | "cell_type": "code", 33 | "execution_count": 3, 34 | "metadata": {}, 35 | "outputs": [ 36 | { 37 | "data": { 38 | "text/plain": [ 39 | "tensor([0., 1., 2., 3., 4.])" 40 | ] 41 | }, 42 | "execution_count": 3, 43 | "metadata": {}, 44 | "output_type": "execute_result" 45 | } 46 | ], 47 | "source": [ 48 | "c" 49 | ] 50 | }, 51 | { 52 | "cell_type": "markdown", 53 | "metadata": {}, 54 | "source": [ 55 | "### Accessing element" 56 | ] 57 | }, 58 | { 59 | "cell_type": "code", 60 | "execution_count": 4, 61 | "metadata": {}, 62 | "outputs": [ 63 | { 64 | "data": { 65 | "text/plain": [ 66 | "tensor(0.)" 67 | ] 68 | }, 69 | "execution_count": 4, 70 | "metadata": {}, 71 | "output_type": "execute_result" 72 | } 73 | ], 74 | "source": [ 75 | "c[0]" 76 | ] 77 | }, 78 | { 79 | "cell_type": "code", 80 | "execution_count": 5, 81 | "metadata": {}, 82 | "outputs": [ 83 | { 84 | "data": { 85 | "text/plain": [ 86 | "tensor(2.)" 87 | ] 88 | }, 89 | "execution_count": 5, 90 | "metadata": {}, 91 | "output_type": "execute_result" 92 | } 93 | ], 94 | "source": [ 95 | "c[2]" 96 | ] 97 | }, 98 | { 99 | "cell_type": "markdown", 100 | "metadata": {}, 101 | "source": [ 102 | "### Changing element" 103 | ] 104 | }, 105 | { 106 | "cell_type": "code", 107 | "execution_count": 6, 108 | "metadata": {}, 109 | "outputs": [], 110 | "source": [ 111 | "c[0]=100" 112 | ] 113 | }, 114 | { 115 | "cell_type": "code", 116 | "execution_count": 7, 117 | "metadata": {}, 118 | "outputs": [ 119 | { 120 | "data": { 121 | "text/plain": [ 122 | "tensor([100., 1., 2., 3., 4.])" 123 | ] 124 | }, 125 | "execution_count": 7, 126 | "metadata": {}, 127 | "output_type": "execute_result" 128 | } 129 | ], 130 | "source": [ 131 | "c" 132 | ] 133 | }, 134 | { 135 | "cell_type": "code", 136 | "execution_count": 8, 137 | "metadata": {}, 138 | "outputs": [], 139 | "source": [ 140 | "c[4]=-100" 141 | ] 142 | }, 143 | { 144 | "cell_type": "code", 145 | "execution_count": 9, 146 | "metadata": {}, 147 | "outputs": [ 148 | { 149 | "data": { 150 | "text/plain": [ 151 | "tensor([ 100., 1., 2., 3., -100.])" 152 | ] 153 | }, 154 | "execution_count": 9, 155 | "metadata": {}, 156 | "output_type": "execute_result" 157 | } 158 | ], 159 | "source": [ 160 | "c" 161 | ] 162 | }, 163 | { 164 | "cell_type": "markdown", 165 | "metadata": {}, 166 | "source": [ 167 | "### Slicing a part of the tensor" 168 | ] 169 | }, 170 | { 171 | "cell_type": "code", 172 | "execution_count": 10, 173 | "metadata": {}, 174 | "outputs": [], 175 | "source": [ 176 | "d = c[1:4]" 177 | ] 178 | }, 179 | { 180 | "cell_type": "code", 181 | "execution_count": 11, 182 | "metadata": {}, 183 | "outputs": [ 184 | { 185 | "data": { 186 | "text/plain": [ 187 | "tensor([1., 2., 3.])" 188 | ] 189 | }, 190 | "execution_count": 11, 191 | "metadata": {}, 192 | "output_type": "execute_result" 193 | } 194 | ], 195 | "source": [ 196 | "d" 197 | ] 198 | }, 199 | { 200 | "cell_type": "markdown", 201 | "metadata": {}, 202 | "source": [ 203 | "### Changing a slice (portion) of the tensor" 204 | ] 205 | }, 206 | { 207 | "cell_type": "code", 208 | "execution_count": 12, 209 | "metadata": {}, 210 | "outputs": [ 211 | { 212 | "data": { 213 | "text/plain": [ 214 | "tensor([ 100., 1., 2., 3., -100.])" 215 | ] 216 | }, 217 | "execution_count": 12, 218 | "metadata": {}, 219 | "output_type": "execute_result" 220 | } 221 | ], 222 | "source": [ 223 | "c" 224 | ] 225 | }, 226 | { 227 | "cell_type": "code", 228 | "execution_count": 14, 229 | "metadata": {}, 230 | "outputs": [], 231 | "source": [ 232 | "c[1:4] = torch.Tensor([11,12,13])" 233 | ] 234 | }, 235 | { 236 | "cell_type": "code", 237 | "execution_count": 15, 238 | "metadata": {}, 239 | "outputs": [ 240 | { 241 | "data": { 242 | "text/plain": [ 243 | "tensor([ 100., 11., 12., 13., -100.])" 244 | ] 245 | }, 246 | "execution_count": 15, 247 | "metadata": {}, 248 | "output_type": "execute_result" 249 | } 250 | ], 251 | "source": [ 252 | "c" 253 | ] 254 | } 255 | ], 256 | "metadata": { 257 | "kernelspec": { 258 | "display_name": "Python 3", 259 | "language": "python", 260 | "name": "python3" 261 | }, 262 | "language_info": { 263 | "codemirror_mode": { 264 | "name": "ipython", 265 | "version": 3 266 | }, 267 | "file_extension": ".py", 268 | "mimetype": "text/x-python", 269 | "name": "python", 270 | "nbconvert_exporter": "python", 271 | "pygments_lexer": "ipython3", 272 | "version": "3.6.2" 273 | }, 274 | "latex_envs": { 275 | "LaTeX_envs_menu_present": true, 276 | "autoclose": false, 277 | "autocomplete": true, 278 | "bibliofile": "biblio.bib", 279 | "cite_by": "apalike", 280 | "current_citInitial": 1, 281 | "eqLabelWithNumbers": true, 282 | "eqNumInitial": 1, 283 | "hotkeys": { 284 | "equation": "Ctrl-E", 285 | "itemize": "Ctrl-I" 286 | }, 287 | "labels_anchors": false, 288 | "latex_user_defs": false, 289 | "report_style_numbering": false, 290 | "user_envs_cfg": false 291 | } 292 | }, 293 | "nbformat": 4, 294 | "nbformat_minor": 2 295 | } 296 | -------------------------------------------------------------------------------- /Tensor basics - vector (1-D) operations.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Tensor basics - Vector (1-D) operations\n", 8 | "\n", 9 | "### Dr. Tirthajyoti Sarkar

Fremont, CA 94536

April 2019" 10 | ] 11 | }, 12 | { 13 | "cell_type": "code", 14 | "execution_count": 1, 15 | "metadata": {}, 16 | "outputs": [], 17 | "source": [ 18 | "import torch\n", 19 | "import numpy as np" 20 | ] 21 | }, 22 | { 23 | "cell_type": "markdown", 24 | "metadata": {}, 25 | "source": [ 26 | "### Vector (tensor) addition" 27 | ] 28 | }, 29 | { 30 | "cell_type": "code", 31 | "execution_count": 2, 32 | "metadata": {}, 33 | "outputs": [], 34 | "source": [ 35 | "u = torch.Tensor([1,0])\n", 36 | "v = torch.Tensor([0,1])" 37 | ] 38 | }, 39 | { 40 | "cell_type": "code", 41 | "execution_count": 3, 42 | "metadata": {}, 43 | "outputs": [ 44 | { 45 | "data": { 46 | "text/plain": [ 47 | "tensor([1., 0.])" 48 | ] 49 | }, 50 | "execution_count": 3, 51 | "metadata": {}, 52 | "output_type": "execute_result" 53 | } 54 | ], 55 | "source": [ 56 | "u" 57 | ] 58 | }, 59 | { 60 | "cell_type": "code", 61 | "execution_count": 4, 62 | "metadata": {}, 63 | "outputs": [ 64 | { 65 | "data": { 66 | "text/plain": [ 67 | "tensor([0., 1.])" 68 | ] 69 | }, 70 | "execution_count": 4, 71 | "metadata": {}, 72 | "output_type": "execute_result" 73 | } 74 | ], 75 | "source": [ 76 | "v" 77 | ] 78 | }, 79 | { 80 | "cell_type": "code", 81 | "execution_count": 5, 82 | "metadata": {}, 83 | "outputs": [], 84 | "source": [ 85 | "w = u+v" 86 | ] 87 | }, 88 | { 89 | "cell_type": "code", 90 | "execution_count": 6, 91 | "metadata": {}, 92 | "outputs": [ 93 | { 94 | "data": { 95 | "text/plain": [ 96 | "tensor([1., 1.])" 97 | ] 98 | }, 99 | "execution_count": 6, 100 | "metadata": {}, 101 | "output_type": "execute_result" 102 | } 103 | ], 104 | "source": [ 105 | "w" 106 | ] 107 | }, 108 | { 109 | "cell_type": "markdown", 110 | "metadata": {}, 111 | "source": [ 112 | "### Vector multiplication with a scalar" 113 | ] 114 | }, 115 | { 116 | "cell_type": "code", 117 | "execution_count": 7, 118 | "metadata": {}, 119 | "outputs": [], 120 | "source": [ 121 | "y = torch.Tensor([[1],[2]])" 122 | ] 123 | }, 124 | { 125 | "cell_type": "code", 126 | "execution_count": 8, 127 | "metadata": {}, 128 | "outputs": [ 129 | { 130 | "data": { 131 | "text/plain": [ 132 | "tensor([[1.],\n", 133 | " [2.]])" 134 | ] 135 | }, 136 | "execution_count": 8, 137 | "metadata": {}, 138 | "output_type": "execute_result" 139 | } 140 | ], 141 | "source": [ 142 | "y" 143 | ] 144 | }, 145 | { 146 | "cell_type": "code", 147 | "execution_count": 9, 148 | "metadata": {}, 149 | "outputs": [], 150 | "source": [ 151 | "z= 1.5*y" 152 | ] 153 | }, 154 | { 155 | "cell_type": "code", 156 | "execution_count": 10, 157 | "metadata": {}, 158 | "outputs": [ 159 | { 160 | "data": { 161 | "text/plain": [ 162 | "tensor([[1.5000],\n", 163 | " [3.0000]])" 164 | ] 165 | }, 166 | "execution_count": 10, 167 | "metadata": {}, 168 | "output_type": "execute_result" 169 | } 170 | ], 171 | "source": [ 172 | "z" 173 | ] 174 | }, 175 | { 176 | "cell_type": "markdown", 177 | "metadata": {}, 178 | "source": [ 179 | "### Linear combination" 180 | ] 181 | }, 182 | { 183 | "cell_type": "code", 184 | "execution_count": 28, 185 | "metadata": {}, 186 | "outputs": [], 187 | "source": [ 188 | "u = torch.Tensor([1,2])\n", 189 | "v = torch.Tensor([3,-1])" 190 | ] 191 | }, 192 | { 193 | "cell_type": "markdown", 194 | "metadata": {}, 195 | "source": [ 196 | "$$2\\times\\begin{bmatrix}\n", 197 | "1 & 2\n", 198 | "\\end{bmatrix}+3\\times\\begin{bmatrix}\n", 199 | "3 & -1\n", 200 | "\\end{bmatrix}$$ = $$\\begin{bmatrix}\n", 201 | "11 & -1\n", 202 | "\\end{bmatrix}$$" 203 | ] 204 | }, 205 | { 206 | "cell_type": "code", 207 | "execution_count": 31, 208 | "metadata": {}, 209 | "outputs": [], 210 | "source": [ 211 | "w = 2*u+3*v" 212 | ] 213 | }, 214 | { 215 | "cell_type": "code", 216 | "execution_count": 32, 217 | "metadata": {}, 218 | "outputs": [ 219 | { 220 | "data": { 221 | "text/plain": [ 222 | "tensor([11., 1.])" 223 | ] 224 | }, 225 | "execution_count": 32, 226 | "metadata": {}, 227 | "output_type": "execute_result" 228 | } 229 | ], 230 | "source": [ 231 | "w" 232 | ] 233 | }, 234 | { 235 | "cell_type": "markdown", 236 | "metadata": {}, 237 | "source": [ 238 | "### Product (element-wise) of two tensors" 239 | ] 240 | }, 241 | { 242 | "cell_type": "code", 243 | "execution_count": 33, 244 | "metadata": {}, 245 | "outputs": [], 246 | "source": [ 247 | "u = torch.Tensor([[1],[3]])\n", 248 | "v = torch.Tensor([[2],[4]])" 249 | ] 250 | }, 251 | { 252 | "cell_type": "code", 253 | "execution_count": 34, 254 | "metadata": {}, 255 | "outputs": [ 256 | { 257 | "data": { 258 | "text/plain": [ 259 | "tensor([[1.],\n", 260 | " [3.]])" 261 | ] 262 | }, 263 | "execution_count": 34, 264 | "metadata": {}, 265 | "output_type": "execute_result" 266 | } 267 | ], 268 | "source": [ 269 | "u" 270 | ] 271 | }, 272 | { 273 | "cell_type": "code", 274 | "execution_count": 35, 275 | "metadata": {}, 276 | "outputs": [ 277 | { 278 | "data": { 279 | "text/plain": [ 280 | "tensor([[2.],\n", 281 | " [4.]])" 282 | ] 283 | }, 284 | "execution_count": 35, 285 | "metadata": {}, 286 | "output_type": "execute_result" 287 | } 288 | ], 289 | "source": [ 290 | "v" 291 | ] 292 | }, 293 | { 294 | "cell_type": "markdown", 295 | "metadata": {}, 296 | "source": [ 297 | "$$ u=\\begin{bmatrix}\n", 298 | "1 \\\\ 3 \\end{bmatrix}, \\ \\ v=\\begin{bmatrix}\n", 299 | "2 \\\\ 4 \\end{bmatrix} $$\n", 300 | "\n", 301 | "$$ u*v = \\begin{bmatrix}\n", 302 | "1\\times 2 \\\\ 3\\times 4 \\end{bmatrix}= \\begin{bmatrix}\n", 303 | "2 \\\\ 12 \\end{bmatrix}$$" 304 | ] 305 | }, 306 | { 307 | "cell_type": "code", 308 | "execution_count": 36, 309 | "metadata": {}, 310 | "outputs": [], 311 | "source": [ 312 | "z = u*v" 313 | ] 314 | }, 315 | { 316 | "cell_type": "code", 317 | "execution_count": 37, 318 | "metadata": {}, 319 | "outputs": [ 320 | { 321 | "data": { 322 | "text/plain": [ 323 | "tensor([[ 2.],\n", 324 | " [12.]])" 325 | ] 326 | }, 327 | "execution_count": 37, 328 | "metadata": {}, 329 | "output_type": "execute_result" 330 | } 331 | ], 332 | "source": [ 333 | "z" 334 | ] 335 | }, 336 | { 337 | "cell_type": "markdown", 338 | "metadata": {}, 339 | "source": [ 340 | "### DOT product using `dot` method" 341 | ] 342 | }, 343 | { 344 | "cell_type": "code", 345 | "execution_count": 38, 346 | "metadata": {}, 347 | "outputs": [], 348 | "source": [ 349 | "u = torch.Tensor([1,2])\n", 350 | "v = torch.Tensor([3,1])" 351 | ] 352 | }, 353 | { 354 | "cell_type": "code", 355 | "execution_count": 39, 356 | "metadata": {}, 357 | "outputs": [ 358 | { 359 | "data": { 360 | "text/plain": [ 361 | "tensor([1., 2.])" 362 | ] 363 | }, 364 | "execution_count": 39, 365 | "metadata": {}, 366 | "output_type": "execute_result" 367 | } 368 | ], 369 | "source": [ 370 | "u" 371 | ] 372 | }, 373 | { 374 | "cell_type": "code", 375 | "execution_count": 40, 376 | "metadata": {}, 377 | "outputs": [ 378 | { 379 | "data": { 380 | "text/plain": [ 381 | "tensor([3., 1.])" 382 | ] 383 | }, 384 | "execution_count": 40, 385 | "metadata": {}, 386 | "output_type": "execute_result" 387 | } 388 | ], 389 | "source": [ 390 | "v" 391 | ] 392 | }, 393 | { 394 | "cell_type": "code", 395 | "execution_count": 41, 396 | "metadata": {}, 397 | "outputs": [ 398 | { 399 | "data": { 400 | "text/plain": [ 401 | "tensor(5.)" 402 | ] 403 | }, 404 | "execution_count": 41, 405 | "metadata": {}, 406 | "output_type": "execute_result" 407 | } 408 | ], 409 | "source": [ 410 | "torch.dot(u,v)" 411 | ] 412 | }, 413 | { 414 | "cell_type": "markdown", 415 | "metadata": {}, 416 | "source": [ 417 | "### Matrix multiplication between tensors.\n", 418 | "Remember to use reshape the tensors using the `reshape()` method to ensure proper matrix multiplication" 419 | ] 420 | }, 421 | { 422 | "cell_type": "code", 423 | "execution_count": 45, 424 | "metadata": {}, 425 | "outputs": [], 426 | "source": [ 427 | "u = torch.Tensor([1,2])\n", 428 | "v = torch.Tensor([[3],[1]])" 429 | ] 430 | }, 431 | { 432 | "cell_type": "code", 433 | "execution_count": 46, 434 | "metadata": {}, 435 | "outputs": [ 436 | { 437 | "data": { 438 | "text/plain": [ 439 | "tensor([1., 2.])" 440 | ] 441 | }, 442 | "execution_count": 46, 443 | "metadata": {}, 444 | "output_type": "execute_result" 445 | } 446 | ], 447 | "source": [ 448 | "u" 449 | ] 450 | }, 451 | { 452 | "cell_type": "code", 453 | "execution_count": 47, 454 | "metadata": {}, 455 | "outputs": [], 456 | "source": [ 457 | "u = u.reshape(2,1)\n", 458 | "v = v.reshape(1,2)" 459 | ] 460 | }, 461 | { 462 | "cell_type": "code", 463 | "execution_count": 48, 464 | "metadata": {}, 465 | "outputs": [ 466 | { 467 | "data": { 468 | "text/plain": [ 469 | "tensor([[1.],\n", 470 | " [2.]])" 471 | ] 472 | }, 473 | "execution_count": 48, 474 | "metadata": {}, 475 | "output_type": "execute_result" 476 | } 477 | ], 478 | "source": [ 479 | "u" 480 | ] 481 | }, 482 | { 483 | "cell_type": "code", 484 | "execution_count": 49, 485 | "metadata": {}, 486 | "outputs": [ 487 | { 488 | "data": { 489 | "text/plain": [ 490 | "torch.Size([2, 1])" 491 | ] 492 | }, 493 | "execution_count": 49, 494 | "metadata": {}, 495 | "output_type": "execute_result" 496 | } 497 | ], 498 | "source": [ 499 | "u.shape" 500 | ] 501 | }, 502 | { 503 | "cell_type": "code", 504 | "execution_count": 50, 505 | "metadata": {}, 506 | "outputs": [ 507 | { 508 | "data": { 509 | "text/plain": [ 510 | "torch.Size([1, 2])" 511 | ] 512 | }, 513 | "execution_count": 50, 514 | "metadata": {}, 515 | "output_type": "execute_result" 516 | } 517 | ], 518 | "source": [ 519 | "v.shape" 520 | ] 521 | }, 522 | { 523 | "cell_type": "code", 524 | "execution_count": 51, 525 | "metadata": {}, 526 | "outputs": [], 527 | "source": [ 528 | "z = torch.mm(u,v)" 529 | ] 530 | }, 531 | { 532 | "cell_type": "code", 533 | "execution_count": 52, 534 | "metadata": {}, 535 | "outputs": [ 536 | { 537 | "data": { 538 | "text/plain": [ 539 | "tensor([[3., 1.],\n", 540 | " [6., 2.]])" 541 | ] 542 | }, 543 | "execution_count": 52, 544 | "metadata": {}, 545 | "output_type": "execute_result" 546 | } 547 | ], 548 | "source": [ 549 | "z" 550 | ] 551 | }, 552 | { 553 | "cell_type": "markdown", 554 | "metadata": {}, 555 | "source": [ 556 | "### Adding a scalar to a tensor (also known as broadcasting)" 557 | ] 558 | }, 559 | { 560 | "cell_type": "code", 561 | "execution_count": 53, 562 | "metadata": {}, 563 | "outputs": [], 564 | "source": [ 565 | "u = torch.Tensor([1,2,3,4])" 566 | ] 567 | }, 568 | { 569 | "cell_type": "code", 570 | "execution_count": 54, 571 | "metadata": {}, 572 | "outputs": [ 573 | { 574 | "data": { 575 | "text/plain": [ 576 | "tensor([1., 2., 3., 4.])" 577 | ] 578 | }, 579 | "execution_count": 54, 580 | "metadata": {}, 581 | "output_type": "execute_result" 582 | } 583 | ], 584 | "source": [ 585 | "u" 586 | ] 587 | }, 588 | { 589 | "cell_type": "code", 590 | "execution_count": 55, 591 | "metadata": {}, 592 | "outputs": [], 593 | "source": [ 594 | "z=u+10" 595 | ] 596 | }, 597 | { 598 | "cell_type": "code", 599 | "execution_count": 56, 600 | "metadata": {}, 601 | "outputs": [ 602 | { 603 | "data": { 604 | "text/plain": [ 605 | "tensor([11., 12., 13., 14.])" 606 | ] 607 | }, 608 | "execution_count": 56, 609 | "metadata": {}, 610 | "output_type": "execute_result" 611 | } 612 | ], 613 | "source": [ 614 | "z" 615 | ] 616 | } 617 | ], 618 | "metadata": { 619 | "kernelspec": { 620 | "display_name": "Python 3", 621 | "language": "python", 622 | "name": "python3" 623 | }, 624 | "language_info": { 625 | "codemirror_mode": { 626 | "name": "ipython", 627 | "version": 3 628 | }, 629 | "file_extension": ".py", 630 | "mimetype": "text/x-python", 631 | "name": "python", 632 | "nbconvert_exporter": "python", 633 | "pygments_lexer": "ipython3", 634 | "version": "3.6.2" 635 | }, 636 | "latex_envs": { 637 | "LaTeX_envs_menu_present": true, 638 | "autoclose": false, 639 | "autocomplete": true, 640 | "bibliofile": "biblio.bib", 641 | "cite_by": "apalike", 642 | "current_citInitial": 1, 643 | "eqLabelWithNumbers": true, 644 | "eqNumInitial": 1, 645 | "hotkeys": { 646 | "equation": "Ctrl-E", 647 | "itemize": "Ctrl-I" 648 | }, 649 | "labels_anchors": false, 650 | "latex_user_defs": false, 651 | "report_style_numbering": false, 652 | "user_envs_cfg": false 653 | } 654 | }, 655 | "nbformat": 4, 656 | "nbformat_minor": 2 657 | } 658 | -------------------------------------------------------------------------------- /images/NN-1.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tirthajyoti/PyTorch_Machine_Learning/f761848bb4f0b9744c0f118be656cb183c7f6aa5/images/NN-1.PNG -------------------------------------------------------------------------------- /images/NN-2.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tirthajyoti/PyTorch_Machine_Learning/f761848bb4f0b9744c0f118be656cb183c7f6aa5/images/NN-2.PNG -------------------------------------------------------------------------------- /images/Readme.md: -------------------------------------------------------------------------------- 1 | ### Images 2 | -------------------------------------------------------------------------------- /images/five-step-process.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tirthajyoti/PyTorch_Machine_Learning/f761848bb4f0b9744c0f118be656cb183c7f6aa5/images/five-step-process.png --------------------------------------------------------------------------------