├── .gitignore ├── .vscode └── settings.json ├── 00-PyTorch Fundamentals.ipynb ├── 01-1-Pytorch +Numpy Single Layer Nueral Network.ipynb ├── 01-PyTorch Workflow Fundamentals.ipynb ├── 02-PyTorch Neural Network Classification.ipynb ├── 03-PyTorch Computer Vision.ipynb ├── 04-Pyotrch RNN+LSTM for Time Series.ipynb ├── 05-Pyotrch Multi-Head Attention.ipynb └── Figures ├── Transformers_zoom_in.jpg ├── dotproduct_1.png ├── encoder_decoder_layer_class.jpg ├── encoder_layer_class.jpg ├── multihead_attn-1.jpg ├── multihead_attn.jpg ├── scaled_dot_product_attn-1.jpg ├── scaled_dot_product_attn.jpg └── scaled_dot_product_attn.svg /.gitignore: -------------------------------------------------------------------------------- 1 | models 2 | data -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "cSpell.words": [ 3 | "Perceptron" 4 | ] 5 | } -------------------------------------------------------------------------------- /00-PyTorch Fundamentals.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 101, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "from IPython.display import Image\n", 10 | "import numpy as np" 11 | ] 12 | }, 13 | { 14 | "cell_type": "code", 15 | "execution_count": 1, 16 | "metadata": {}, 17 | "outputs": [ 18 | { 19 | "data": { 20 | "text/plain": [ 21 | "'1.12.1+cu102'" 22 | ] 23 | }, 24 | "execution_count": 1, 25 | "metadata": {}, 26 | "output_type": "execute_result" 27 | } 28 | ], 29 | "source": [ 30 | "import torch\n", 31 | "torch.__version__" 32 | ] 33 | }, 34 | { 35 | "attachments": {}, 36 | "cell_type": "markdown", 37 | "metadata": {}, 38 | "source": [ 39 | "#### Creating Tensors" 40 | ] 41 | }, 42 | { 43 | "cell_type": "code", 44 | "execution_count": 7, 45 | "metadata": {}, 46 | "outputs": [ 47 | { 48 | "name": "stdout", 49 | "output_type": "stream", 50 | "text": [ 51 | "tensor(7)\n", 52 | "\n", 53 | "0\n", 54 | "torch.Size([])\n" 55 | ] 56 | } 57 | ], 58 | "source": [ 59 | "# scalar tensor\n", 60 | "scalar_tensor =torch.tensor(7)\n", 61 | "print(scalar_tensor)\n", 62 | "\n", 63 | "print(scalar_tensor.__class__)\n", 64 | "\n", 65 | "# shape of a tensor\n", 66 | "print(scalar_tensor.ndim)\n", 67 | "\n", 68 | "# shape of a tensor\n", 69 | "print(scalar_tensor.shape)\n", 70 | "\n", 71 | "# turn the pytorch tenmsor to python number\n", 72 | "print(scalar_tensor.item())" 73 | ] 74 | }, 75 | { 76 | "cell_type": "code", 77 | "execution_count": 11, 78 | "metadata": {}, 79 | "outputs": [ 80 | { 81 | "name": "stdout", 82 | "output_type": "stream", 83 | "text": [ 84 | "tensor([1, 2, 3, 4, 5])\n", 85 | "1\n", 86 | "torch.Size([5])\n", 87 | "[1, 2, 3, 4, 5]\n" 88 | ] 89 | } 90 | ], 91 | "source": [ 92 | "# vector\n", 93 | "vector_tensor = torch.tensor([1,2,3,4,5])\n", 94 | "print(vector_tensor)\n", 95 | "\n", 96 | "# shape of a tensor vector\n", 97 | "print(vector_tensor.ndim)\n", 98 | "\n", 99 | "# shape of a tensor vector\n", 100 | "print(vector_tensor.shape)\n", 101 | "\n", 102 | "# turn the pytorch tenmsor to python list\n", 103 | "print(vector_tensor.tolist())" 104 | ] 105 | }, 106 | { 107 | "cell_type": "code", 108 | "execution_count": 12, 109 | "metadata": {}, 110 | "outputs": [ 111 | { 112 | "name": "stdout", 113 | "output_type": "stream", 114 | "text": [ 115 | "tensor([[ 1, 2, 3, 4, 5],\n", 116 | " [ 6, 7, 8, 9, 10]])\n", 117 | "2\n", 118 | "torch.Size([2, 5])\n", 119 | "[[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]]\n" 120 | ] 121 | } 122 | ], 123 | "source": [ 124 | "# matrix\n", 125 | "matrix_tensor = torch.tensor([[1,2,3,4,5],[6,7,8,9,10]])\n", 126 | "print(matrix_tensor)\n", 127 | "\n", 128 | "# shape of a tensor matrix\n", 129 | "print(matrix_tensor.ndim)\n", 130 | "\n", 131 | "# shape of a tensor matrix\n", 132 | "print(matrix_tensor.shape)\n", 133 | "\n", 134 | "# turn the pytorch tenmsor to python list\n", 135 | "print(matrix_tensor.tolist())" 136 | ] 137 | }, 138 | { 139 | "cell_type": "code", 140 | "execution_count": 13, 141 | "metadata": {}, 142 | "outputs": [ 143 | { 144 | "name": "stdout", 145 | "output_type": "stream", 146 | "text": [ 147 | "tensor([[[ 1, 2, 3],\n", 148 | " [ 4, 5, 6]],\n", 149 | "\n", 150 | " [[ 7, 8, 9],\n", 151 | " [10, 11, 12]]])\n", 152 | "3\n", 153 | "torch.Size([2, 2, 3])\n", 154 | "[[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]]\n" 155 | ] 156 | } 157 | ], 158 | "source": [ 159 | "# create 3d tensor in pytorch\n", 160 | "tensor_3d = torch.tensor([[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]])\n", 161 | "print(tensor_3d)\n", 162 | "\n", 163 | "# shape of a tensor 3d\n", 164 | "print(tensor_3d.ndim)\n", 165 | "\n", 166 | "# shape of a tensor 3d\n", 167 | "print(tensor_3d.shape)\n", 168 | "\n", 169 | "# turn the pytorch tenmsor to python list\n", 170 | "print(tensor_3d.tolist())" 171 | ] 172 | }, 173 | { 174 | "cell_type": "code", 175 | "execution_count": 16, 176 | "metadata": {}, 177 | "outputs": [ 178 | { 179 | "data": { 180 | "text/html": [ 181 | "" 182 | ], 183 | "text/plain": [ 184 | "" 185 | ] 186 | }, 187 | "execution_count": 16, 188 | "metadata": {}, 189 | "output_type": "execute_result" 190 | } 191 | ], 192 | "source": [ 193 | "# show the image from the web\n", 194 | "\n", 195 | "image_url = \"https://raw.githubusercontent.com/mrdbourke/pytorch-deep-learning/main/images/00-pytorch-different-tensor-dimensions.png\"\n", 196 | "Image(url= image_url, width=800, height=400)" 197 | ] 198 | }, 199 | { 200 | "attachments": {}, 201 | "cell_type": "markdown", 202 | "metadata": {}, 203 | "source": [ 204 | "#### Creating Random Tensors" 205 | ] 206 | }, 207 | { 208 | "cell_type": "code", 209 | "execution_count": 27, 210 | "metadata": {}, 211 | "outputs": [ 212 | { 213 | "name": "stdout", 214 | "output_type": "stream", 215 | "text": [ 216 | "random_tensor vlaue is \n", 217 | " tensor([[0.9402, 0.1363, 0.7646, 0.8853],\n", 218 | " [0.7855, 0.8835, 0.4324, 0.3900],\n", 219 | " [0.6175, 0.6068, 0.6155, 0.5684]]), \n", 220 | " its data type is \n", 221 | " torch.float32\n" 222 | ] 223 | } 224 | ], 225 | "source": [ 226 | "# create a random tensor of size (3,4)\n", 227 | "random_tensor = torch.rand(3,4)\n", 228 | "print(f\"random_tensor vlaue is \\n {random_tensor}, \\n its data type is \\n {random_tensor.dtype}\")" 229 | ] 230 | }, 231 | { 232 | "cell_type": "code", 233 | "execution_count": 28, 234 | "metadata": {}, 235 | "outputs": [ 236 | { 237 | "name": "stdout", 238 | "output_type": "stream", 239 | "text": [ 240 | "random_tensor vlaue dimesnion is is \n", 241 | " 3, \n", 242 | " its shape is \n", 243 | " torch.Size([224, 224, 3])\n" 244 | ] 245 | } 246 | ], 247 | "source": [ 248 | "# Create a random tensor of size (224, 224, 3)\n", 249 | "random_tensor = torch.rand(224, 224, 3)\n", 250 | "print(f\"random_tensor vlaue dimesnion is is \\n {random_tensor.ndim}, \\n its shape is \\n {random_tensor.shape}\")" 251 | ] 252 | }, 253 | { 254 | "cell_type": "markdown", 255 | "metadata": {}, 256 | "source": [ 257 | "#### Creating Zeros and Ones Tenors " 258 | ] 259 | }, 260 | { 261 | "cell_type": "code", 262 | "execution_count": 30, 263 | "metadata": {}, 264 | "outputs": [ 265 | { 266 | "name": "stdout", 267 | "output_type": "stream", 268 | "text": [ 269 | "tensor([[0., 0., 0., 0.],\n", 270 | " [0., 0., 0., 0.],\n", 271 | " [0., 0., 0., 0.]]) torch.float32\n" 272 | ] 273 | } 274 | ], 275 | "source": [ 276 | "# Create a tensor of all zeros\n", 277 | "tensor_of_zeros = torch.zeros(3,4)\n", 278 | "print(tensor_of_zeros, tensor_of_zeros.dtype)" 279 | ] 280 | }, 281 | { 282 | "cell_type": "code", 283 | "execution_count": 31, 284 | "metadata": {}, 285 | "outputs": [ 286 | { 287 | "name": "stdout", 288 | "output_type": "stream", 289 | "text": [ 290 | "tensor([[1., 1., 1., 1.],\n", 291 | " [1., 1., 1., 1.],\n", 292 | " [1., 1., 1., 1.]]) torch.float32\n" 293 | ] 294 | } 295 | ], 296 | "source": [ 297 | "# Create a tensor of all ones\n", 298 | "tensor_of_ones = torch.ones(3,4)\n", 299 | "print(tensor_of_ones, tensor_of_ones.dtype)" 300 | ] 301 | }, 302 | { 303 | "attachments": {}, 304 | "cell_type": "markdown", 305 | "metadata": {}, 306 | "source": [ 307 | "#### Creating a Range and Tensors Like" 308 | ] 309 | }, 310 | { 311 | "cell_type": "code", 312 | "execution_count": 33, 313 | "metadata": {}, 314 | "outputs": [ 315 | { 316 | "name": "stdout", 317 | "output_type": "stream", 318 | "text": [ 319 | "tensor([0, 2, 4, 6, 8])\n" 320 | ] 321 | } 322 | ], 323 | "source": [ 324 | "# create tesnors in a specific range\n", 325 | "tensor_in_range = torch.arange(start=0, end=10, step=2)\n", 326 | "print(tensor_in_range)" 327 | ] 328 | }, 329 | { 330 | "cell_type": "code", 331 | "execution_count": 34, 332 | "metadata": {}, 333 | "outputs": [ 334 | { 335 | "name": "stdout", 336 | "output_type": "stream", 337 | "text": [ 338 | "tensor([0, 0, 0, 0, 0])\n" 339 | ] 340 | } 341 | ], 342 | "source": [ 343 | "# zero tensors with the same shape as tensor_in_range\n", 344 | "zero_tensor = torch.zeros_like(tensor_in_range)\n", 345 | "print(zero_tensor)" 346 | ] 347 | }, 348 | { 349 | "attachments": {}, 350 | "cell_type": "markdown", 351 | "metadata": {}, 352 | "source": [ 353 | "#### Tensor datatypes " 354 | ] 355 | }, 356 | { 357 | "cell_type": "code", 358 | "execution_count": 37, 359 | "metadata": {}, 360 | "outputs": [ 361 | { 362 | "name": "stdout", 363 | "output_type": "stream", 364 | "text": [ 365 | "torch.Size([2, 3]) torch.float32 cpu False\n" 366 | ] 367 | } 368 | ], 369 | "source": [ 370 | "# Create a tensor with the dfeault datatype in pytroch\n", 371 | "tensor_default = torch.tensor([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]],\n", 372 | " dtype=None,\n", 373 | " device=None,\n", 374 | " requires_grad=False)\n", 375 | "print(tensor_default.shape, tensor_default.dtype, tensor_default.device, tensor_default.requires_grad)\n" 376 | ] 377 | }, 378 | { 379 | "cell_type": "code", 380 | "execution_count": 38, 381 | "metadata": {}, 382 | "outputs": [ 383 | { 384 | "name": "stdout", 385 | "output_type": "stream", 386 | "text": [ 387 | "torch.Size([2, 3]) torch.float16 cpu False\n" 388 | ] 389 | } 390 | ], 391 | "source": [ 392 | "# Create a tensor with the float16 datatype in pytroch\n", 393 | "tensor_float16 = torch.tensor([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]],\n", 394 | " dtype=torch.float16,\n", 395 | " device=None,\n", 396 | " requires_grad=False)\n", 397 | "\n", 398 | "print(tensor_float16.shape, tensor_float16.dtype, tensor_float16.device, tensor_float16.requires_grad)" 399 | ] 400 | }, 401 | { 402 | "attachments": {}, 403 | "cell_type": "markdown", 404 | "metadata": {}, 405 | "source": [ 406 | "#### Getting Information from Tensors" 407 | ] 408 | }, 409 | { 410 | "cell_type": "code", 411 | "execution_count": 41, 412 | "metadata": {}, 413 | "outputs": [ 414 | { 415 | "name": "stdout", 416 | "output_type": "stream", 417 | "text": [ 418 | "tesnor shape is torch.Size([2, 3])\n", 419 | "tesnor data type is torch.float32\n", 420 | "tesnor is stored on cpu\n" 421 | ] 422 | } 423 | ], 424 | "source": [ 425 | "# Create a tensor in pytorch\n", 426 | "temp_tensor = torch.tensor([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])\n", 427 | "\n", 428 | "# Get the ifnormation of the tensor\n", 429 | "print(f\"tesnor shape is {temp_tensor.shape}\")\n", 430 | "print(f\"tesnor data type is {temp_tensor.dtype}\")\n", 431 | "print(f\"tesnor is stored on {temp_tensor.device}\")" 432 | ] 433 | }, 434 | { 435 | "attachments": {}, 436 | "cell_type": "markdown", 437 | "metadata": {}, 438 | "source": [ 439 | "#### Manipulating Tensors (Tensor Pperations)" 440 | ] 441 | }, 442 | { 443 | "attachments": {}, 444 | "cell_type": "markdown", 445 | "metadata": {}, 446 | "source": [ 447 | "##### Basic Operations" 448 | ] 449 | }, 450 | { 451 | "cell_type": "code", 452 | "execution_count": 55, 453 | "metadata": {}, 454 | "outputs": [ 455 | { 456 | "name": "stdout", 457 | "output_type": "stream", 458 | "text": [ 459 | "tensor([[11., 12., 13.],\n", 460 | " [14., 15., 16.]])\n", 461 | "tensor([[10.2500, 20.5000, 30.7500],\n", 462 | " [41.0000, 51.2500, 61.5000]])\n", 463 | "tensor([[1., 2., 3.],\n", 464 | " [4., 5., 6.]])\n", 465 | "tensor([[-9., -8., -7.],\n", 466 | " [-6., -5., -4.]])\n", 467 | "tensor([[1., 2., 3.],\n", 468 | " [4., 5., 6.]])\n", 469 | "tensor([[ 1., 4., 9.],\n", 470 | " [16., 25., 36.]])\n", 471 | "tensor([[14., 32.],\n", 472 | " [32., 77.]])\n" 473 | ] 474 | } 475 | ], 476 | "source": [ 477 | "# Create a tensor of values\n", 478 | "temp_tensor = torch.tensor([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])\n", 479 | "\n", 480 | "# Add a number to it\n", 481 | "print(temp_tensor+10.0)\n", 482 | "\n", 483 | "# # Multiply it by 10.25\n", 484 | "print(temp_tensor * 10.25)\n", 485 | "\n", 486 | "# Tensors don't change unless reassigned\n", 487 | "print(temp_tensor)\n", 488 | "\n", 489 | "# Subtract and reassign\n", 490 | "temp_tensor = temp_tensor - 10.0\n", 491 | "print(temp_tensor)\n", 492 | "\n", 493 | "# Add and reassign\n", 494 | "temp_tensor = temp_tensor + 10.0\n", 495 | "print(temp_tensor)\n", 496 | "\n", 497 | "# Element-wise multiplication\n", 498 | "print(temp_tensor * temp_tensor)\n", 499 | "\n", 500 | "# Matrix multiplication with @ operator\n", 501 | "print(temp_tensor @ temp_tensor.T)" 502 | ] 503 | }, 504 | { 505 | "cell_type": "code", 506 | "execution_count": 54, 507 | "metadata": {}, 508 | "outputs": [ 509 | { 510 | "name": "stdout", 511 | "output_type": "stream", 512 | "text": [ 513 | "tensor([[11., 12., 13.],\n", 514 | " [14., 15., 16.]])\n", 515 | "tensor([[10.2500, 20.5000, 30.7500],\n", 516 | " [41.0000, 51.2500, 61.5000]])\n", 517 | "tensor([[-9., -8., -7.],\n", 518 | " [-6., -5., -4.]])\n", 519 | "tensor([[14., 32.],\n", 520 | " [32., 77.]])\n", 521 | "tensor([[14., 32.],\n", 522 | " [32., 77.]])\n" 523 | ] 524 | } 525 | ], 526 | "source": [ 527 | "temp_tensor = torch.tensor([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])\n", 528 | "\n", 529 | "# Add a number to it with torch function\n", 530 | "print(torch.add(temp_tensor, 10.0))\n", 531 | "\n", 532 | "# Multiply it by 10.25 with torch function\n", 533 | "print(torch.mul(temp_tensor, 10.25))\n", 534 | "\n", 535 | "# Subtract and reassign with torch function\n", 536 | "print(torch.sub(temp_tensor, 10.0))\n", 537 | "\n", 538 | "# Matrix multiplication\n", 539 | "print(torch.matmul(temp_tensor, temp_tensor.T))\n" 540 | ] 541 | }, 542 | { 543 | "cell_type": "code", 544 | "execution_count": 56, 545 | "metadata": {}, 546 | "outputs": [ 547 | { 548 | "data": { 549 | "text/html": [ 550 | "" 551 | ], 552 | "text/plain": [ 553 | "" 554 | ] 555 | }, 556 | "execution_count": 56, 557 | "metadata": {}, 558 | "output_type": "execute_result" 559 | } 560 | ], 561 | "source": [ 562 | "# show the image from the web\n", 563 | "\n", 564 | "image_url = \"https://github.com/mrdbourke/pytorch-deep-learning/raw/main/images/00-matrix-multiply-crop.gif\"\n", 565 | "Image(url= image_url, width=800, height=400)" 566 | ] 567 | }, 568 | { 569 | "attachments": {}, 570 | "cell_type": "markdown", 571 | "metadata": {}, 572 | "source": [ 573 | "#### Aggregation in Tensors" 574 | ] 575 | }, 576 | { 577 | "cell_type": "code", 578 | "execution_count": 68, 579 | "metadata": {}, 580 | "outputs": [ 581 | { 582 | "name": "stdout", 583 | "output_type": "stream", 584 | "text": [ 585 | "torch.Size([3, 4, 2])\n", 586 | "tensor([[ 9., 10.],\n", 587 | " [11., 12.],\n", 588 | " [13., 14.],\n", 589 | " [15., 16.]])\n", 590 | "tensor([[ 4., 5.],\n", 591 | " [12., 13.],\n", 592 | " [20., 21.]])\n", 593 | "tensor([[ 1.5000, 3.5000, 5.5000, 7.5000],\n", 594 | " [ 9.5000, 11.5000, 13.5000, 15.5000],\n", 595 | " [17.5000, 19.5000, 21.5000, 23.5000]])\n", 596 | "tensor([[ 9., 10.],\n", 597 | " [11., 12.],\n", 598 | " [13., 14.],\n", 599 | " [15., 16.]])\n", 600 | "tensor([[ 4., 5.],\n", 601 | " [12., 13.],\n", 602 | " [20., 21.]])\n", 603 | "tensor([[ 1.5000, 3.5000, 5.5000, 7.5000],\n", 604 | " [ 9.5000, 11.5000, 13.5000, 15.5000],\n", 605 | " [17.5000, 19.5000, 21.5000, 23.5000]])\n", 606 | "tensor([[27., 30.],\n", 607 | " [33., 36.],\n", 608 | " [39., 42.],\n", 609 | " [45., 48.]])\n", 610 | "tensor([[16., 20.],\n", 611 | " [48., 52.],\n", 612 | " [80., 84.]])\n", 613 | "tensor([[ 3., 7., 11., 15.],\n", 614 | " [19., 23., 27., 31.],\n", 615 | " [35., 39., 43., 47.]])\n", 616 | "tensor([[27., 30.],\n", 617 | " [33., 36.],\n", 618 | " [39., 42.],\n", 619 | " [45., 48.]])\n", 620 | "tensor([[16., 20.],\n", 621 | " [48., 52.],\n", 622 | " [80., 84.]])\n", 623 | "tensor([[ 3., 7., 11., 15.],\n", 624 | " [19., 23., 27., 31.],\n", 625 | " [35., 39., 43., 47.]])\n", 626 | "torch.return_types.max(\n", 627 | "values=tensor([[17., 18.],\n", 628 | " [19., 20.],\n", 629 | " [21., 22.],\n", 630 | " [23., 24.]]),\n", 631 | "indices=tensor([[2, 2],\n", 632 | " [2, 2],\n", 633 | " [2, 2],\n", 634 | " [2, 2]]))\n", 635 | "torch.return_types.min(\n", 636 | "values=tensor([[1., 2.],\n", 637 | " [3., 4.],\n", 638 | " [5., 6.],\n", 639 | " [7., 8.]]),\n", 640 | "indices=tensor([[0, 0],\n", 641 | " [0, 0],\n", 642 | " [0, 0],\n", 643 | " [0, 0]]))\n", 644 | "torch.return_types.max(\n", 645 | "values=tensor([[17., 18.],\n", 646 | " [19., 20.],\n", 647 | " [21., 22.],\n", 648 | " [23., 24.]]),\n", 649 | "indices=tensor([[2, 2],\n", 650 | " [2, 2],\n", 651 | " [2, 2],\n", 652 | " [2, 2]]))\n", 653 | "torch.return_types.min(\n", 654 | "values=tensor([[1., 2.],\n", 655 | " [3., 4.],\n", 656 | " [5., 6.],\n", 657 | " [7., 8.]]),\n", 658 | "indices=tensor([[0, 0],\n", 659 | " [0, 0],\n", 660 | " [0, 0],\n", 661 | " [0, 0]]))\n", 662 | "torch.return_types.max(\n", 663 | "values=tensor([[ 7., 8.],\n", 664 | " [15., 16.],\n", 665 | " [23., 24.]]),\n", 666 | "indices=tensor([[3, 3],\n", 667 | " [3, 3],\n", 668 | " [3, 3]]))\n", 669 | "torch.return_types.min(\n", 670 | "values=tensor([[ 1., 2.],\n", 671 | " [ 9., 10.],\n", 672 | " [17., 18.]]),\n", 673 | "indices=tensor([[0, 0],\n", 674 | " [0, 0],\n", 675 | " [0, 0]]))\n", 676 | "torch.return_types.max(\n", 677 | "values=tensor([[ 7., 8.],\n", 678 | " [15., 16.],\n", 679 | " [23., 24.]]),\n", 680 | "indices=tensor([[3, 3],\n", 681 | " [3, 3],\n", 682 | " [3, 3]]))\n", 683 | "torch.return_types.min(\n", 684 | "values=tensor([[ 1., 2.],\n", 685 | " [ 9., 10.],\n", 686 | " [17., 18.]]),\n", 687 | "indices=tensor([[0, 0],\n", 688 | " [0, 0],\n", 689 | " [0, 0]]))\n", 690 | "torch.return_types.max(\n", 691 | "values=tensor([[ 2., 4., 6., 8.],\n", 692 | " [10., 12., 14., 16.],\n", 693 | " [18., 20., 22., 24.]]),\n", 694 | "indices=tensor([[1, 1, 1, 1],\n", 695 | " [1, 1, 1, 1],\n", 696 | " [1, 1, 1, 1]]))\n", 697 | "torch.return_types.min(\n", 698 | "values=tensor([[ 1., 3., 5., 7.],\n", 699 | " [ 9., 11., 13., 15.],\n", 700 | " [17., 19., 21., 23.]]),\n", 701 | "indices=tensor([[0, 0, 0, 0],\n", 702 | " [0, 0, 0, 0],\n", 703 | " [0, 0, 0, 0]]))\n", 704 | "torch.return_types.max(\n", 705 | "values=tensor([[ 2., 4., 6., 8.],\n", 706 | " [10., 12., 14., 16.],\n", 707 | " [18., 20., 22., 24.]]),\n", 708 | "indices=tensor([[1, 1, 1, 1],\n", 709 | " [1, 1, 1, 1],\n", 710 | " [1, 1, 1, 1]]))\n", 711 | "torch.return_types.min(\n", 712 | "values=tensor([[ 1., 3., 5., 7.],\n", 713 | " [ 9., 11., 13., 15.],\n", 714 | " [17., 19., 21., 23.]]),\n", 715 | "indices=tensor([[0, 0, 0, 0],\n", 716 | " [0, 0, 0, 0],\n", 717 | " [0, 0, 0, 0]]))\n" 718 | ] 719 | } 720 | ], 721 | "source": [ 722 | "# Create a tensor of size (3,4,2)\n", 723 | "temp_tensor = torch.tensor([[[1.0, 2.0], [3.0, 4.0], [5.0, 6.0], [7.0, 8.0]],\n", 724 | " [[9.0, 10.0], [11.0, 12.0], [\n", 725 | " 13.0, 14.0], [15.0, 16.0]],\n", 726 | " [[17.0, 18.0], [19.0, 20.0], [21.0, 22.0], [23.0, 24.0]]])\n", 727 | "print(temp_tensor.shape)\n", 728 | "\n", 729 | "# Get the mean of the tensor\n", 730 | "print(torch.mean(temp_tensor, dim=0)) # will not work for int dtype\n", 731 | "print(torch.mean(temp_tensor, dim=1)) # will not work for int dtype\n", 732 | "print(torch.mean(temp_tensor, dim=2)) # will not work for int dtype\n", 733 | "\n", 734 | "print(temp_tensor.mean(dim=0)) # will not work for int dtype\n", 735 | "print(temp_tensor.mean(dim=1)) # will not work for int dtype\n", 736 | "print(temp_tensor.mean(dim=2)) # will not work for int dtype\n", 737 | "\n", 738 | "# Get the sum of the tensor\n", 739 | "print(torch.sum(temp_tensor, dim=0))\n", 740 | "print(torch.sum(temp_tensor, dim=1))\n", 741 | "print(torch.sum(temp_tensor, dim=2))\n", 742 | "\n", 743 | "print(temp_tensor.sum(dim=0))\n", 744 | "print(temp_tensor.sum(dim=1))\n", 745 | "print(temp_tensor.sum(dim=2))\n", 746 | "\n", 747 | "# Get the max and min of the tensor\n", 748 | "print(torch.max(temp_tensor, dim=0))\n", 749 | "print(torch.min(temp_tensor, dim=0))\n", 750 | "\n", 751 | "print(temp_tensor.max(dim=0))\n", 752 | "print(temp_tensor.min(dim=0))\n", 753 | "\n", 754 | "print(torch.max(temp_tensor, dim=1))\n", 755 | "print(torch.min(temp_tensor, dim=1))\n", 756 | "\n", 757 | "print(temp_tensor.max(dim=1))\n", 758 | "print(temp_tensor.min(dim=1))\n", 759 | "\n", 760 | "print(torch.max(temp_tensor, dim=2))\n", 761 | "print(torch.min(temp_tensor, dim=2))\n", 762 | "\n", 763 | "print(temp_tensor.max(dim=2))\n", 764 | "print(temp_tensor.min(dim=2))" 765 | ] 766 | }, 767 | { 768 | "cell_type": "code", 769 | "execution_count": 69, 770 | "metadata": {}, 771 | "outputs": [ 772 | { 773 | "name": "stdout", 774 | "output_type": "stream", 775 | "text": [ 776 | "tensor([[2, 2],\n", 777 | " [2, 2],\n", 778 | " [2, 2],\n", 779 | " [2, 2]])\n", 780 | "tensor([[0, 0],\n", 781 | " [0, 0],\n", 782 | " [0, 0],\n", 783 | " [0, 0]])\n", 784 | "tensor([[2, 2],\n", 785 | " [2, 2],\n", 786 | " [2, 2],\n", 787 | " [2, 2]])\n", 788 | "tensor([[0, 0],\n", 789 | " [0, 0],\n", 790 | " [0, 0],\n", 791 | " [0, 0]])\n", 792 | "tensor([[3, 3],\n", 793 | " [3, 3],\n", 794 | " [3, 3]])\n", 795 | "tensor([[0, 0],\n", 796 | " [0, 0],\n", 797 | " [0, 0]])\n", 798 | "tensor([[3, 3],\n", 799 | " [3, 3],\n", 800 | " [3, 3]])\n", 801 | "tensor([[0, 0],\n", 802 | " [0, 0],\n", 803 | " [0, 0]])\n", 804 | "tensor([[1, 1, 1, 1],\n", 805 | " [1, 1, 1, 1],\n", 806 | " [1, 1, 1, 1]])\n", 807 | "tensor([[0, 0, 0, 0],\n", 808 | " [0, 0, 0, 0],\n", 809 | " [0, 0, 0, 0]])\n", 810 | "tensor([[1, 1, 1, 1],\n", 811 | " [1, 1, 1, 1],\n", 812 | " [1, 1, 1, 1]])\n", 813 | "tensor([[0, 0, 0, 0],\n", 814 | " [0, 0, 0, 0],\n", 815 | " [0, 0, 0, 0]])\n" 816 | ] 817 | } 818 | ], 819 | "source": [ 820 | "# Create a tensor of size (3,4,2)\n", 821 | "temp_tensor = torch.tensor([[[1.0, 2.0], [3.0, 4.0], [5.0, 6.0], [7.0, 8.0]], \n", 822 | " [[9.0, 10.0], [11.0, 12.0], [13.0, 14.0], [15.0, 16.0]],\n", 823 | " [[17.0, 18.0], [19.0, 20.0], [21.0, 22.0], [23.0, 24.0]]])\n", 824 | "\n", 825 | "# Get the argmax and argmin of the tensor\n", 826 | "print(torch.argmax(temp_tensor, dim=0))\n", 827 | "print(torch.argmin(temp_tensor, dim=0))\n", 828 | "\n", 829 | "print(temp_tensor.argmax(dim=0))\n", 830 | "print(temp_tensor.argmin(dim=0))\n", 831 | "\n", 832 | "print(torch.argmax(temp_tensor, dim=1))\n", 833 | "print(torch.argmin(temp_tensor, dim=1))\n", 834 | "\n", 835 | "print(temp_tensor.argmax(dim=1))\n", 836 | "print(temp_tensor.argmin(dim=1))\n", 837 | "\n", 838 | "print(torch.argmax(temp_tensor, dim=2))\n", 839 | "print(torch.argmin(temp_tensor, dim=2))\n", 840 | "\n", 841 | "print(temp_tensor.argmax(dim=2))\n", 842 | "print(temp_tensor.argmin(dim=2))" 843 | ] 844 | }, 845 | { 846 | "attachments": {}, 847 | "cell_type": "markdown", 848 | "metadata": {}, 849 | "source": [ 850 | "#### Change Tensor datatype" 851 | ] 852 | }, 853 | { 854 | "cell_type": "code", 855 | "execution_count": 73, 856 | "metadata": {}, 857 | "outputs": [ 858 | { 859 | "name": "stdout", 860 | "output_type": "stream", 861 | "text": [ 862 | "torch.float32\n", 863 | "tensor([[1., 2., 3.],\n", 864 | " [4., 5., 6.]], dtype=torch.float16)\n", 865 | "tensor([[1, 2, 3],\n", 866 | " [4, 5, 6]], dtype=torch.int8)\n", 867 | "torch.float16\n", 868 | "tensor([[1., 2., 3.],\n", 869 | " [4., 5., 6.]])\n", 870 | "tensor([[1, 2, 3],\n", 871 | " [4, 5, 6]], dtype=torch.int8)\n", 872 | "torch.int8\n", 873 | "tensor([[1., 2., 3.],\n", 874 | " [4., 5., 6.]])\n", 875 | "tensor([[1., 2., 3.],\n", 876 | " [4., 5., 6.]], dtype=torch.float16)\n" 877 | ] 878 | } 879 | ], 880 | "source": [ 881 | "# Create a tensor and check its datatype\n", 882 | "temp_tensor_fp32 = torch.tensor([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])\n", 883 | "print(temp_tensor.dtype)\n", 884 | "print(temp_tensor_fp32.type(dtype= torch.float16))\n", 885 | "print(temp_tensor_fp32.type(dtype= torch.int8))\n", 886 | "\n", 887 | "# Create a float16 tensor and check its datatype\n", 888 | "temp_tensor_fp16 = torch.tensor([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]], dtype=torch.float16)\n", 889 | "print(temp_tensor_fp16.dtype)\n", 890 | "print(temp_tensor_fp16.type(dtype= torch.float32))\n", 891 | "print(temp_tensor_fp16.type(dtype= torch.int8))\n", 892 | "\n", 893 | "# Create a int8 tensor and check its datatype\n", 894 | "temp_tensor_int8 = torch.tensor([[1, 2, 3], [4, 5, 6]], dtype=torch.int8)\n", 895 | "print(temp_tensor_int8.dtype)\n", 896 | "print(temp_tensor_int8.type(dtype= torch.float32))\n", 897 | "print(temp_tensor_int8.type(dtype= torch.float16))\n", 898 | "\n" 899 | ] 900 | }, 901 | { 902 | "attachments": {}, 903 | "cell_type": "markdown", 904 | "metadata": {}, 905 | "source": [ 906 | "#### Reshaping, Stacking, Squeezing and Unsqueezing" 907 | ] 908 | }, 909 | { 910 | "cell_type": "code", 911 | "execution_count": 78, 912 | "metadata": {}, 913 | "outputs": [ 914 | { 915 | "name": "stdout", 916 | "output_type": "stream", 917 | "text": [ 918 | "torch.Size([3, 4, 2])\n", 919 | "[[[1.0, 2.0], [3.0, 4.0], [5.0, 6.0], [7.0, 8.0]], [[9.0, 10.0], [11.0, 12.0], [13.0, 14.0], [15.0, 16.0]], [[17.0, 18.0], [19.0, 20.0], [21.0, 22.0], [23.0, 24.0]]]\n", 920 | "[[[1.0, 2.0], [3.0, 4.0], [5.0, 6.0], [7.0, 8.0], [9.0, 10.0], [11.0, 12.0]], [[13.0, 14.0], [15.0, 16.0], [17.0, 18.0], [19.0, 20.0], [21.0, 22.0], [23.0, 24.0]]]\n", 921 | "torch.Size([2, 6, 2])\n" 922 | ] 923 | } 924 | ], 925 | "source": [ 926 | "# Create a tensor of size (3,4,2)\n", 927 | "temp_tensor = torch.tensor([[[1.0, 2.0], [3.0, 4.0], [5.0, 6.0], [7.0, 8.0]],\n", 928 | " [[9.0, 10.0], [11.0, 12.0], [13.0, 14.0], [15.0, 16.0]],\n", 929 | " [[17.0, 18.0], [19.0, 20.0], [21.0, 22.0], [23.0, 24.0]]])\n", 930 | "\n", 931 | "print(temp_tensor.shape)\n", 932 | "print(temp_tensor.tolist())\n", 933 | "\n", 934 | "# reshape the tensor\n", 935 | "reshaped_tensor = temp_tensor.reshape(2, 6, 2)\n", 936 | "print(reshaped_tensor.tolist())\n", 937 | "print(reshaped_tensor.shape)" 938 | ] 939 | }, 940 | { 941 | "cell_type": "code", 942 | "execution_count": 82, 943 | "metadata": {}, 944 | "outputs": [ 945 | { 946 | "name": "stdout", 947 | "output_type": "stream", 948 | "text": [ 949 | "torch.Size([2, 6, 2])\n", 950 | "[[[1.0, 2.0], [3.0, 4.0], [5.0, 6.0], [7.0, 8.0], [9.0, 10.0], [11.0, 12.0]], [[13.0, 14.0], [15.0, 16.0], [17.0, 18.0], [19.0, 20.0], [21.0, 22.0], [23.0, 24.0]]]\n", 951 | "tensor([[[ 0., 2.],\n", 952 | " [ 0., 4.],\n", 953 | " [ 0., 6.],\n", 954 | " [ 0., 8.],\n", 955 | " [ 0., 10.],\n", 956 | " [ 0., 12.]],\n", 957 | "\n", 958 | " [[ 0., 14.],\n", 959 | " [ 0., 16.],\n", 960 | " [ 0., 18.],\n", 961 | " [ 0., 20.],\n", 962 | " [ 0., 22.],\n", 963 | " [ 0., 24.]]]) tensor([[[ 0., 2.],\n", 964 | " [ 0., 4.],\n", 965 | " [ 0., 6.],\n", 966 | " [ 0., 8.]],\n", 967 | "\n", 968 | " [[ 0., 10.],\n", 969 | " [ 0., 12.],\n", 970 | " [ 0., 14.],\n", 971 | " [ 0., 16.]],\n", 972 | "\n", 973 | " [[ 0., 18.],\n", 974 | " [ 0., 20.],\n", 975 | " [ 0., 22.],\n", 976 | " [ 0., 24.]]])\n" 977 | ] 978 | } 979 | ], 980 | "source": [ 981 | "\"\"\" https://tinyurl.com/2jllf5b6\n", 982 | " As the name suggests, torch.view merely creates a view of the original tensor. \n", 983 | " The new tensor will always share its data with the original tensor. \n", 984 | " This means that if you change the original tensor, the reshaped tensor will change and vice versa.\n", 985 | "\"\"\"\n", 986 | "temp_tensor = torch.tensor([[[1.0, 2.0], [3.0, 4.0], [5.0, 6.0], [7.0, 8.0]],\n", 987 | " [[9.0, 10.0], [11.0, 12.0], [13.0, 14.0], [15.0, 16.0]],\n", 988 | " [[17.0, 18.0], [19.0, 20.0], [21.0, 22.0], [23.0, 24.0]]])\n", 989 | "\n", 990 | "viwed_tensor = temp_tensor.view(2, 6, 2)\n", 991 | "print(viwed_tensor.shape)\n", 992 | "print(viwed_tensor.tolist())\n", 993 | "\n", 994 | "# Changing the view tensor will change the original tensor\n", 995 | "viwed_tensor[:,:, 0] = 0\n", 996 | "print(viwed_tensor, temp_tensor)" 997 | ] 998 | }, 999 | { 1000 | "cell_type": "code", 1001 | "execution_count": 87, 1002 | "metadata": {}, 1003 | "outputs": [ 1004 | { 1005 | "name": "stdout", 1006 | "output_type": "stream", 1007 | "text": [ 1008 | "tensor([[[1., 2., 3., 4.],\n", 1009 | " [5., 6., 7., 8.]],\n", 1010 | "\n", 1011 | " [[1., 2., 3., 4.],\n", 1012 | " [5., 6., 7., 8.]],\n", 1013 | "\n", 1014 | " [[1., 2., 3., 4.],\n", 1015 | " [5., 6., 7., 8.]]])\n", 1016 | "torch.Size([3, 2, 4])\n", 1017 | "tensor([[[1., 2., 3., 4.],\n", 1018 | " [1., 2., 3., 4.],\n", 1019 | " [1., 2., 3., 4.]],\n", 1020 | "\n", 1021 | " [[5., 6., 7., 8.],\n", 1022 | " [5., 6., 7., 8.],\n", 1023 | " [5., 6., 7., 8.]]])\n", 1024 | "torch.Size([2, 3, 4])\n", 1025 | "tensor([[[1., 1., 1.],\n", 1026 | " [2., 2., 2.],\n", 1027 | " [3., 3., 3.],\n", 1028 | " [4., 4., 4.]],\n", 1029 | "\n", 1030 | " [[5., 5., 5.],\n", 1031 | " [6., 6., 6.],\n", 1032 | " [7., 7., 7.],\n", 1033 | " [8., 8., 8.]]])\n", 1034 | "torch.Size([2, 4, 3])\n" 1035 | ] 1036 | } 1037 | ], 1038 | "source": [ 1039 | "# Create a tensor of size (2,4)\n", 1040 | "\n", 1041 | "temp_tensor = torch.tensor([[1.0, 2.0, 3.0, 4.0], [5.0, 6.0, 7.0, 8.0]])\n", 1042 | "\n", 1043 | "# stack the tensor along the 0th dimension\n", 1044 | "stacked_tensor = torch.stack([temp_tensor, temp_tensor, temp_tensor], dim=0)\n", 1045 | "print(stacked_tensor)\n", 1046 | "print(stacked_tensor.shape)\n", 1047 | "\n", 1048 | "# stack the tensor along the 1st dimension\n", 1049 | "stacked_tensor = torch.stack([temp_tensor, temp_tensor, temp_tensor], dim=1)\n", 1050 | "print(stacked_tensor)\n", 1051 | "print(stacked_tensor.shape)\n", 1052 | "\n", 1053 | "# stack the tensor along the 2nd dimension\n", 1054 | "stacked_tensor = torch.stack([temp_tensor, temp_tensor, temp_tensor], dim=2)\n", 1055 | "print(stacked_tensor)\n", 1056 | "print(stacked_tensor.shape)\n" 1057 | ] 1058 | }, 1059 | { 1060 | "cell_type": "code", 1061 | "execution_count": 98, 1062 | "metadata": {}, 1063 | "outputs": [ 1064 | { 1065 | "name": "stdout", 1066 | "output_type": "stream", 1067 | "text": [ 1068 | "tensor([[1., 2., 3., 4.],\n", 1069 | " [5., 6., 7., 8.]])\n", 1070 | "torch.Size([2, 4])\n", 1071 | "tensor([[[1.],\n", 1072 | " [2.],\n", 1073 | " [3.],\n", 1074 | " [4.]],\n", 1075 | "\n", 1076 | " [[5.],\n", 1077 | " [6.],\n", 1078 | " [7.],\n", 1079 | " [8.]]])\n", 1080 | "torch.Size([2, 4, 1])\n" 1081 | ] 1082 | } 1083 | ], 1084 | "source": [ 1085 | "# Create a tensor of size (2,4,1)\n", 1086 | "temp_tensor = torch.tensor([[1.0, 2.0, 3.0, 4.0], [5.0, 6.0, 7.0, 8.0]])\n", 1087 | "\n", 1088 | "# Squueze the tensor along the last dimension\n", 1089 | "squeuezed_tensor = temp_tensor.squeeze(dim=-1)\n", 1090 | "print(squeuezed_tensor)\n", 1091 | "print(squeuezed_tensor.shape)\n", 1092 | "\n", 1093 | "# Unsqueezed the tensor along the last dimension\n", 1094 | "unsqueezed_tensor = squeuezed_tensor.unsqueeze(dim=-1)\n", 1095 | "print(unsqueezed_tensor)\n", 1096 | "print(unsqueezed_tensor.shape)" 1097 | ] 1098 | }, 1099 | { 1100 | "attachments": {}, 1101 | "cell_type": "markdown", 1102 | "metadata": {}, 1103 | "source": [ 1104 | "#### Indexing (Selecting Data from Tensors)" 1105 | ] 1106 | }, 1107 | { 1108 | "cell_type": "code", 1109 | "execution_count": 100, 1110 | "metadata": {}, 1111 | "outputs": [ 1112 | { 1113 | "name": "stdout", 1114 | "output_type": "stream", 1115 | "text": [ 1116 | "First square bracket:\n", 1117 | "tensor([[ 1., 2., 3.],\n", 1118 | " [ 4., 5., 6.],\n", 1119 | " [ 7., 8., 9.],\n", 1120 | " [10., 11., 12.]])\n", 1121 | "Second square bracket: tensor([1., 2., 3.])\n", 1122 | "Third square bracket: 1.0\n", 1123 | "0th dimension and the 0 index of 1st dimension:\n", 1124 | "tensor([[ 1., 2., 3.],\n", 1125 | " [13., 14., 15.]])\n", 1126 | "0th & 1st dimensions but only index 1 of 2nd dimension:\n", 1127 | "tensor([[ 2., 5., 8., 11.],\n", 1128 | " [14., 17., 20., 23.]])\n", 1129 | "0th dimension but only the 1 index value of the 1st and 2nd dimension:\n", 1130 | "tensor([ 5., 17.])\n", 1131 | "0th and 1st dimension and all values of 2nd dimension:\n", 1132 | "tensor([1., 2., 3.])\n" 1133 | ] 1134 | } 1135 | ], 1136 | "source": [ 1137 | "# Create a tensor of size (2, 4, 3)\n", 1138 | "temp_tensor = torch.tensor([[[1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [7.0, 8.0, 9.0], [10.0, 11.0, 12.0]],\n", 1139 | " [[13.0, 14.0, 15.0], [16.0, 17.0, 18.0], [19.0, 20.0, 21.0], [22.0, 23.0, 24.0]]])\n", 1140 | "\n", 1141 | "# Index bracket by bracket\n", 1142 | "print(f\"First square bracket:\\n{temp_tensor[0]}\") \n", 1143 | "print(f\"Second square bracket: {temp_tensor[0][0]}\") \n", 1144 | "print(f\"Third square bracket: {temp_tensor[0][0][0]}\")\n", 1145 | "\n", 1146 | "# Get all values of 0th dimension and the 0 index of 1st dimension\n", 1147 | "print(f\"0th dimension and the 0 index of 1st dimension:\\n{temp_tensor[:, 0]}\")\n", 1148 | "\n", 1149 | "# Get all values of 0th & 1st dimensions but only index 1 of 2nd dimension\n", 1150 | "print(f\"0th & 1st dimensions but only index 1 of 2nd dimension:\\n{temp_tensor[:, :, 1]}\")\n", 1151 | "\n", 1152 | "# Get all values of the 0 dimension but only the 1 index value of the 1st and 2nd dimension\n", 1153 | "print(f\"0th dimension but only the 1 index value of the 1st and 2nd dimension:\\n{temp_tensor[:, 1, 1]}\")\n", 1154 | "\n", 1155 | "# Get index 0 of 0th and 1st dimension and all values of 2nd dimension \n", 1156 | "print(f\"0th and 1st dimension and all values of 2nd dimension:\\n{temp_tensor[0, 0, :]}\")\n" 1157 | ] 1158 | }, 1159 | { 1160 | "attachments": {}, 1161 | "cell_type": "markdown", 1162 | "metadata": {}, 1163 | "source": [ 1164 | "#### PyTorch Tensors & NumPy" 1165 | ] 1166 | }, 1167 | { 1168 | "cell_type": "code", 1169 | "execution_count": 103, 1170 | "metadata": {}, 1171 | "outputs": [ 1172 | { 1173 | "name": "stdout", 1174 | "output_type": "stream", 1175 | "text": [ 1176 | "[[1 2 3]\n", 1177 | " [4 5 6]]\n", 1178 | "tensor([[1, 2, 3],\n", 1179 | " [4, 5, 6]])\n", 1180 | "[[1 2 3]\n", 1181 | " [4 5 6]]\n" 1182 | ] 1183 | } 1184 | ], 1185 | "source": [ 1186 | "\"\"\"\n", 1187 | " torch.from_numpy(ndarray) - NumPy array -> PyTorch tensor.\n", 1188 | " torch.Tensor.numpy() - PyTorch tensor -> NumPy array.\n", 1189 | "\"\"\"\n", 1190 | "\n", 1191 | "# Create a numpy array of size (2, 3)\n", 1192 | "temp_numpy_array = np.array([[1, 2, 3], [4, 5, 6]])\n", 1193 | "print(temp_numpy_array)\n", 1194 | "\n", 1195 | "# Convert the numpy array to a tensor\n", 1196 | "temp_tensor = torch.from_numpy(temp_numpy_array)\n", 1197 | "print(temp_tensor)\n", 1198 | "\n", 1199 | "# Convert the tensor to a numpy array\n", 1200 | "temp_numpy_array = temp_tensor.numpy()\n", 1201 | "print(temp_numpy_array)" 1202 | ] 1203 | }, 1204 | { 1205 | "attachments": {}, 1206 | "cell_type": "markdown", 1207 | "metadata": {}, 1208 | "source": [ 1209 | "#### Running Tensors on GPUs" 1210 | ] 1211 | }, 1212 | { 1213 | "cell_type": "code", 1214 | "execution_count": 104, 1215 | "metadata": {}, 1216 | "outputs": [ 1217 | { 1218 | "name": "stdout", 1219 | "output_type": "stream", 1220 | "text": [ 1221 | "False\n" 1222 | ] 1223 | } 1224 | ], 1225 | "source": [ 1226 | "# check for GPU\n", 1227 | "print(torch.cuda.is_available())" 1228 | ] 1229 | }, 1230 | { 1231 | "cell_type": "code", 1232 | "execution_count": 105, 1233 | "metadata": {}, 1234 | "outputs": [], 1235 | "source": [ 1236 | "# Set device type\n", 1237 | "device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")" 1238 | ] 1239 | }, 1240 | { 1241 | "cell_type": "code", 1242 | "execution_count": 107, 1243 | "metadata": {}, 1244 | "outputs": [ 1245 | { 1246 | "name": "stdout", 1247 | "output_type": "stream", 1248 | "text": [ 1249 | "0\n" 1250 | ] 1251 | } 1252 | ], 1253 | "source": [ 1254 | "# Count the number of GPUs available\n", 1255 | "print(torch.cuda.device_count())" 1256 | ] 1257 | }, 1258 | { 1259 | "cell_type": "code", 1260 | "execution_count": 111, 1261 | "metadata": {}, 1262 | "outputs": [ 1263 | { 1264 | "name": "stdout", 1265 | "output_type": "stream", 1266 | "text": [ 1267 | "tensor([[1., 2., 3.],\n", 1268 | " [4., 5., 6.]]) tensor([[1., 2., 3.],\n", 1269 | " [4., 5., 6.]])\n", 1270 | "tensor([[1., 2., 3.],\n", 1271 | " [4., 5., 6.]])\n" 1272 | ] 1273 | } 1274 | ], 1275 | "source": [ 1276 | "# Create a tensor\n", 1277 | "temp_tensor = torch.tensor([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])\n", 1278 | "\n", 1279 | "# Put the tensor on the device\n", 1280 | "temp_tensor_device = temp_tensor.to(device)\n", 1281 | "print(temp_tensor, temp_tensor_device)\n", 1282 | "\n", 1283 | "# Moving tensors back to the CPU\n", 1284 | "temp_tensor_cpu = temp_tensor_device.to(\"cpu\")\n", 1285 | "print(temp_tensor_cpu)" 1286 | ] 1287 | } 1288 | ], 1289 | "metadata": { 1290 | "kernelspec": { 1291 | "display_name": "Python 3", 1292 | "language": "python", 1293 | "name": "python3" 1294 | }, 1295 | "language_info": { 1296 | "codemirror_mode": { 1297 | "name": "ipython", 1298 | "version": 3 1299 | }, 1300 | "file_extension": ".py", 1301 | "mimetype": "text/x-python", 1302 | "name": "python", 1303 | "nbconvert_exporter": "python", 1304 | "pygments_lexer": "ipython3", 1305 | "version": "3.10.6" 1306 | }, 1307 | "orig_nbformat": 4, 1308 | "vscode": { 1309 | "interpreter": { 1310 | "hash": "916dbcbb3f70747c44a77c7bcd40155683ae19c65e1c03b4aa3499c5328201f1" 1311 | } 1312 | } 1313 | }, 1314 | "nbformat": 4, 1315 | "nbformat_minor": 2 1316 | } 1317 | -------------------------------------------------------------------------------- /01-1-Pytorch +Numpy Single Layer Nueral Network.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "attachments": {}, 5 | "cell_type": "markdown", 6 | "metadata": {}, 7 | "source": [ 8 | "#### Import Required Packages" 9 | ] 10 | }, 11 | { 12 | "cell_type": "code", 13 | "execution_count": 251, 14 | "metadata": {}, 15 | "outputs": [], 16 | "source": [ 17 | "import numpy as np\n", 18 | "import pandas as pd\n", 19 | "import matplotlib.pyplot as plt" 20 | ] 21 | }, 22 | { 23 | "attachments": {}, 24 | "cell_type": "markdown", 25 | "metadata": {}, 26 | "source": [ 27 | "##### Creating Linearly Separable Dataset" 28 | ] 29 | }, 30 | { 31 | "cell_type": "code", 32 | "execution_count": 255, 33 | "metadata": {}, 34 | "outputs": [], 35 | "source": [ 36 | "df = pd.read_csv('https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data', header=None)\n", 37 | "\n", 38 | "# setosa and versicolor\n", 39 | "y = df.iloc[:, 4].values\n", 40 | "y_sample = np.where(y == 'Iris-setosa', -1, 1)\n", 41 | "\n", 42 | "# sepal length and petal length\n", 43 | "x_sample = df.iloc[:, [0,2]].values" 44 | ] 45 | }, 46 | { 47 | "cell_type": "code", 48 | "execution_count": 256, 49 | "metadata": {}, 50 | "outputs": [ 51 | { 52 | "data": { 53 | "text/plain": [ 54 | "" 55 | ] 56 | }, 57 | "execution_count": 256, 58 | "metadata": {}, 59 | "output_type": "execute_result" 60 | }, 61 | { 62 | "data": { 63 | "image/png": "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A8D777+PESNGICQkBA4ODmjdujWmTJmCUaNGFXuOLO918y6w2K+4uDjh6+srTp48aXzO1G2RB+Xl5Yn69euL//znPxbI0HpSU1OFh4eHWLp06UO/7+DgIH788ccizy1YsED4+vpaIz2LMtX3B9nqa+7g4CA6depU5LlJkyaJjh07FntOcHCwmDlzZpHntmzZIgCI7Oxsi+RpCWXp+8N0795dPP/883KmZlX9+vUTQ4YMKbGNPb7XS9PvB9nq+1wIIdauXStq1aol1q5dK06dOiVWrVolvLy8RFhYWLHnyPFe55WLu06cOIHExES0adMGGo0GGo0G+/fvx9dffw2NRlNkMFBx7lWFly5dskLGllO1alU0bNiw2H7UqFEDt2/fLvLc7du3UaNGDWukZ1Gm+v4gW33N/f390aRJkyLPNW7cuMRbQsW97h4eHnBxcbFInpZQlr4/zCOPPGJzr/s9165dw65du/DKK6+U2M7e3uul7feDbPV9DgDvvvuu8epF8+bNMXr0aLz11lslXqGX473O4uKu3r17Izo6GlFRUcZHu3btMGrUKERFRUGtVpv8GXq9HtHR0fD397dCxpaTmZmJ2NjYYvvRqVMn7N69u8hzO3fuRKdOnayRnkWZ6vuDbPU179KlS5GR8ABw8eJF1K5du9hz7OV1L0vfHyYqKsrmXvd7VqxYAV9fXwwePLjEdvbymt9T2n4/yFbf5wCQnZ0NlaroR71arYbBYCj2HFle93Jdb7FzD94WGT16tHj//feNx5988onYsWOHiI2NFSdOnBAjRowQzs7O4syZMwpkW3Zvv/222Ldvn7hy5Yo4dOiQ6NOnj6hevbpITEwUQvy734cOHRIajUZ88cUX4ty5c2L69OnCwcFBREdHK9WFMjO37/bymh8/flxoNBoxY8YMERMTI9asWSNcXV3F6tWrjW3ef/99MXr0aOPx5cuXhaurq3j33XfFuXPnxIIFC4RarRbbt29XogtlVpa+z5s3T2zcuFHExMSI6OhoMXnyZKFSqcSuXbuU6EK56PV6ERQUJKZNm/av79nze92cftvL+1wIIcaMGSNq1qwp/vjjD3HlyhXx22+/ierVq4v33nvP2MYS73UWFyV4sLjo0aOHGDNmjPF4ypQpIigoSDg6Ogo/Pz8xaNAgERkZaf1Ey+nZZ58V/v7+wtHRUdSsWVM8++yz4tKlS8bvP9hvIYT4+eefRcOGDYWjo6No2rSp2LJli5Wzloe5fbeX11wIIX7//XfRrFkz4eTkJEJCQsTixYuLfH/MmDGiR48eRZ7bu3evaNWqlXB0dBT16tUTK1assF7CMjK377Nnzxb169cXzs7OwsvLSzz66KNiz549Vs5aHjt27BAAxIULF/71PXt+r5vTb3t6n2u1WjF58mQRFBQknJ2dRb169cSHH34odDqdsY0l3uvccp2IiIhkxTEXREREJCsWF0RERCQrFhdEREQkKxYXREREJCsWF0RERCQrFhdEREQkKxYXREREJCsWF0RERCQrFhdEREQkKxYXREREJCsWF0RERCQrFhdEREQkq/8HG/N29JHK+RkAAAAASUVORK5CYII=", 64 | "text/plain": [ 65 | "
" 66 | ] 67 | }, 68 | "metadata": {}, 69 | "output_type": "display_data" 70 | } 71 | ], 72 | "source": [ 73 | "# plot the data\n", 74 | "plt.scatter(x_sample[:, 0], x_sample[:, 1], c=y_sample, cmap='jet', s=4)" 75 | ] 76 | }, 77 | { 78 | "attachments": {}, 79 | "cell_type": "markdown", 80 | "metadata": {}, 81 | "source": [ 82 | "#### Develop Single Layer Perceptron " 83 | ] 84 | }, 85 | { 86 | "cell_type": "code", 87 | "execution_count": 257, 88 | "metadata": {}, 89 | "outputs": [], 90 | "source": [ 91 | "import numpy as np\n", 92 | "\n", 93 | "class Perceptron(object):\n", 94 | "\n", 95 | " def __init__(self, eta=0.01, epochs=50):\n", 96 | " self.eta = eta\n", 97 | " self.epochs = epochs\n", 98 | "\n", 99 | " def fit(self, X, y):\n", 100 | "\n", 101 | " self.w_ = np.zeros(1 + X.shape[1])\n", 102 | " self.errors_ = []\n", 103 | "\n", 104 | " for _ in range(self.epochs):\n", 105 | " errors = 0\n", 106 | " for xi, target in zip(X, y):\n", 107 | " update = self.eta * (target - self.predict(xi))\n", 108 | " self.w_[1:] += update * xi\n", 109 | " self.w_[0] += update\n", 110 | " errors += int(update != 0.0)\n", 111 | " self.errors_.append(errors)\n", 112 | " return self\n", 113 | "\n", 114 | " def net_input(self, X):\n", 115 | " return np.dot(X, self.w_[1:]) + self.w_[0]\n", 116 | "\n", 117 | " def predict(self, X):\n", 118 | " return np.where(self.net_input(X) >= 0.0, 1, -1)" 119 | ] 120 | }, 121 | { 122 | "cell_type": "code", 123 | "execution_count": 258, 124 | "metadata": {}, 125 | "outputs": [ 126 | { 127 | "name": "stdout", 128 | "output_type": "stream", 129 | "text": [ 130 | "[-0.4 -0.68 1.82]\n" 131 | ] 132 | } 133 | ], 134 | "source": [ 135 | "ppn = Perceptron(epochs=100, eta=0.1)\n", 136 | "ppn.fit(x_sample, y_sample)\n", 137 | "print(ppn.w_)" 138 | ] 139 | }, 140 | { 141 | "attachments": {}, 142 | "cell_type": "markdown", 143 | "metadata": {}, 144 | "source": [ 145 | "#### Develop Mini-Batch Gradient Descent" 146 | ] 147 | }, 148 | { 149 | "cell_type": "code", 150 | "execution_count": 373, 151 | "metadata": {}, 152 | "outputs": [], 153 | "source": [ 154 | "import numpy as np\n", 155 | "\n", 156 | "class Perceptron(object):\n", 157 | "\n", 158 | " def __init__(self, eta=0.01, epochs=50, batch_size=10):\n", 159 | " self.eta = eta\n", 160 | " self.epochs = epochs\n", 161 | " self.batch_size = batch_size\n", 162 | "\n", 163 | " def fit(self, X, y):\n", 164 | "\n", 165 | " self.w_ = np.zeros(1 + X.shape[1])\n", 166 | " self.errors_ = []\n", 167 | " self.losses_ = []\n", 168 | "\n", 169 | " for _ in range(self.epochs):\n", 170 | " for i in range(0, len(X), self.batch_size):\n", 171 | " x_batch = X[i:i + self.batch_size]\n", 172 | " y_batch = y[i:i + self.batch_size]\n", 173 | "\n", 174 | " # Calculate the predictions\n", 175 | " predictions = self.predict(x_batch)\n", 176 | "\n", 177 | " # Calculate the loss\n", 178 | " loss = np.mean(np.square(predictions - y_batch))\n", 179 | "\n", 180 | " # Backpropagate the error\n", 181 | " d_weights = np.dot(x_batch.T, (predictions - y_batch))\n", 182 | " d_biases = np.mean(predictions - y_batch)\n", 183 | "\n", 184 | " # Update the weights and biases\n", 185 | " self.w_[1:] -= self.eta * d_weights\n", 186 | " self.w_[0] -= self.eta * d_biases\n", 187 | "\n", 188 | " losses = round(np.mean(np.square(self.predict(X) - y)), 3)\n", 189 | " self.losses_.append(losses)\n", 190 | " \n", 191 | " errors = round(np.mean((self.predict(X)-y!=0)), 3)\n", 192 | " self.errors_.append(errors)\n", 193 | "\n", 194 | " def net_input(self, X):\n", 195 | " return np.dot(X, self.w_[1:]) + self.w_[0]\n", 196 | "\n", 197 | " def predict(self, X):\n", 198 | " return np.where(self.net_input(X) >= 0.0, 1, -1)" 199 | ] 200 | }, 201 | { 202 | "cell_type": "code", 203 | "execution_count": 376, 204 | "metadata": {}, 205 | "outputs": [ 206 | { 207 | "name": "stdout", 208 | "output_type": "stream", 209 | "text": [ 210 | "[-0.4 -0.68 1.82]\n", 211 | "[0.333, 0.333, 0.333, 0.333, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]\n", 212 | "[1.333, 1.333, 1.333, 1.333, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]\n" 213 | ] 214 | } 215 | ], 216 | "source": [ 217 | "ppn_batch = Perceptron(epochs=100, eta=0.1, batch_size=1)\n", 218 | "ppn_batch.fit(x_sample, y_sample)\n", 219 | "print(ppn_batch.w_)\n", 220 | "print(ppn_batch.errors_)\n", 221 | "print(ppn_batch.losses_)" 222 | ] 223 | } 224 | ], 225 | "metadata": { 226 | "kernelspec": { 227 | "display_name": "Python 3", 228 | "language": "python", 229 | "name": "python3" 230 | }, 231 | "language_info": { 232 | "codemirror_mode": { 233 | "name": "ipython", 234 | "version": 3 235 | }, 236 | "file_extension": ".py", 237 | "mimetype": "text/x-python", 238 | "name": "python", 239 | "nbconvert_exporter": "python", 240 | "pygments_lexer": "ipython3", 241 | "version": "3.10.6" 242 | }, 243 | "orig_nbformat": 4 244 | }, 245 | "nbformat": 4, 246 | "nbformat_minor": 2 247 | } 248 | -------------------------------------------------------------------------------- /Figures/Transformers_zoom_in.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/behroozazarkhalili/Pytorch-Tutorials/438f4ed0515af986fbd6bb49ea722d638804732f/Figures/Transformers_zoom_in.jpg -------------------------------------------------------------------------------- /Figures/dotproduct_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/behroozazarkhalili/Pytorch-Tutorials/438f4ed0515af986fbd6bb49ea722d638804732f/Figures/dotproduct_1.png -------------------------------------------------------------------------------- /Figures/encoder_decoder_layer_class.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/behroozazarkhalili/Pytorch-Tutorials/438f4ed0515af986fbd6bb49ea722d638804732f/Figures/encoder_decoder_layer_class.jpg -------------------------------------------------------------------------------- /Figures/encoder_layer_class.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/behroozazarkhalili/Pytorch-Tutorials/438f4ed0515af986fbd6bb49ea722d638804732f/Figures/encoder_layer_class.jpg -------------------------------------------------------------------------------- /Figures/multihead_attn-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/behroozazarkhalili/Pytorch-Tutorials/438f4ed0515af986fbd6bb49ea722d638804732f/Figures/multihead_attn-1.jpg -------------------------------------------------------------------------------- /Figures/multihead_attn.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/behroozazarkhalili/Pytorch-Tutorials/438f4ed0515af986fbd6bb49ea722d638804732f/Figures/multihead_attn.jpg -------------------------------------------------------------------------------- /Figures/scaled_dot_product_attn-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/behroozazarkhalili/Pytorch-Tutorials/438f4ed0515af986fbd6bb49ea722d638804732f/Figures/scaled_dot_product_attn-1.jpg -------------------------------------------------------------------------------- /Figures/scaled_dot_product_attn.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/behroozazarkhalili/Pytorch-Tutorials/438f4ed0515af986fbd6bb49ea722d638804732f/Figures/scaled_dot_product_attn.jpg -------------------------------------------------------------------------------- /Figures/scaled_dot_product_attn.svg: -------------------------------------------------------------------------------- 1 | 2 | 14 | 16 | 17 | 19 | image/svg+xml 20 | 22 | 23 | 24 | 25 | 26 | 28 | 30 | 33 | 37 | 38 | 41 | 45 | 46 | 49 | 53 | 54 | 57 | 61 | 62 | 65 | 69 | 70 | 73 | 77 | 78 | 81 | 85 | 86 | 89 | 93 | 94 | 97 | 101 | 102 | 105 | 109 | 110 | 113 | 117 | 118 | 121 | 125 | 126 | 129 | 133 | 134 | 137 | 141 | 142 | 145 | 149 | 150 | 153 | 157 | 158 | 161 | 165 | 166 | 167 | 169 | 172 | 173 | 178 | 180 | 184 | 185 | 190 | 191 | 193 | 196 | 201 | 206 | 211 | 216 | 221 | 226 | 227 | 230 | 235 | 240 | 245 | 250 | 255 | 260 | 265 | 270 | 275 | 280 | 285 | 286 | 289 | 294 | 299 | 304 | 309 | 314 | 319 | 324 | 329 | 334 | 335 | 339 | 344 | 345 | 346 | 347 | --------------------------------------------------------------------------------