├── .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 | ""
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 | 
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
--------------------------------------------------------------------------------