{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "name": "intro_pytorch.ipynb",
      "provenance": [],
      "collapsed_sections": []
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    },
    "language_info": {
      "name": "python"
    },
    "accelerator": "GPU",
    "widgets": {
      "application/vnd.jupyter.widget-state+json": {
        "d5f90b47f01e426d9acb2a999e6c9c3c": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "HBoxModel",
          "state": {
            "_view_name": "HBoxView",
            "_dom_classes": [],
            "_model_name": "HBoxModel",
            "_view_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_view_count": null,
            "_view_module_version": "1.5.0",
            "box_style": "",
            "layout": "IPY_MODEL_fb2882cc1c264fbc9935e058ab5153da",
            "_model_module": "@jupyter-widgets/controls",
            "children": [
              "IPY_MODEL_9505455b9e7846a3a7fe4ead3ab61dec",
              "IPY_MODEL_81c475f07c6848f0aa08962c6b0e896b"
            ]
          }
        },
        "fb2882cc1c264fbc9935e058ab5153da": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "state": {
            "_view_name": "LayoutView",
            "grid_template_rows": null,
            "right": null,
            "justify_content": null,
            "_view_module": "@jupyter-widgets/base",
            "overflow": null,
            "_model_module_version": "1.2.0",
            "_view_count": null,
            "flex_flow": null,
            "width": null,
            "min_width": null,
            "border": null,
            "align_items": null,
            "bottom": null,
            "_model_module": "@jupyter-widgets/base",
            "top": null,
            "grid_column": null,
            "overflow_y": null,
            "overflow_x": null,
            "grid_auto_flow": null,
            "grid_area": null,
            "grid_template_columns": null,
            "flex": null,
            "_model_name": "LayoutModel",
            "justify_items": null,
            "grid_row": null,
            "max_height": null,
            "align_content": null,
            "visibility": null,
            "align_self": null,
            "height": null,
            "min_height": null,
            "padding": null,
            "grid_auto_rows": null,
            "grid_gap": null,
            "max_width": null,
            "order": null,
            "_view_module_version": "1.2.0",
            "grid_template_areas": null,
            "object_position": null,
            "object_fit": null,
            "grid_auto_columns": null,
            "margin": null,
            "display": null,
            "left": null
          }
        },
        "9505455b9e7846a3a7fe4ead3ab61dec": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "FloatProgressModel",
          "state": {
            "_view_name": "ProgressView",
            "style": "IPY_MODEL_3ba109a914df4c85b19831417b652588",
            "_dom_classes": [],
            "description": "",
            "_model_name": "FloatProgressModel",
            "bar_style": "success",
            "max": 26421880,
            "_view_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "value": 26421880,
            "_view_count": null,
            "_view_module_version": "1.5.0",
            "orientation": "horizontal",
            "min": 0,
            "description_tooltip": null,
            "_model_module": "@jupyter-widgets/controls",
            "layout": "IPY_MODEL_d62d0a49b7c540758375ecb6f053db0f"
          }
        },
        "81c475f07c6848f0aa08962c6b0e896b": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "HTMLModel",
          "state": {
            "_view_name": "HTMLView",
            "style": "IPY_MODEL_799c60c15ffe4814906d8a676eaccf83",
            "_dom_classes": [],
            "description": "",
            "_model_name": "HTMLModel",
            "placeholder": "​",
            "_view_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "value": " 26422272/? [00:04&lt;00:00, 6148614.24it/s]",
            "_view_count": null,
            "_view_module_version": "1.5.0",
            "description_tooltip": null,
            "_model_module": "@jupyter-widgets/controls",
            "layout": "IPY_MODEL_d0925adafaa44c8280b685cb6ed7ab99"
          }
        },
        "3ba109a914df4c85b19831417b652588": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "ProgressStyleModel",
          "state": {
            "_view_name": "StyleView",
            "_model_name": "ProgressStyleModel",
            "description_width": "initial",
            "_view_module": "@jupyter-widgets/base",
            "_model_module_version": "1.5.0",
            "_view_count": null,
            "_view_module_version": "1.2.0",
            "bar_color": null,
            "_model_module": "@jupyter-widgets/controls"
          }
        },
        "d62d0a49b7c540758375ecb6f053db0f": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "state": {
            "_view_name": "LayoutView",
            "grid_template_rows": null,
            "right": null,
            "justify_content": null,
            "_view_module": "@jupyter-widgets/base",
            "overflow": null,
            "_model_module_version": "1.2.0",
            "_view_count": null,
            "flex_flow": null,
            "width": null,
            "min_width": null,
            "border": null,
            "align_items": null,
            "bottom": null,
            "_model_module": "@jupyter-widgets/base",
            "top": null,
            "grid_column": null,
            "overflow_y": null,
            "overflow_x": null,
            "grid_auto_flow": null,
            "grid_area": null,
            "grid_template_columns": null,
            "flex": null,
            "_model_name": "LayoutModel",
            "justify_items": null,
            "grid_row": null,
            "max_height": null,
            "align_content": null,
            "visibility": null,
            "align_self": null,
            "height": null,
            "min_height": null,
            "padding": null,
            "grid_auto_rows": null,
            "grid_gap": null,
            "max_width": null,
            "order": null,
            "_view_module_version": "1.2.0",
            "grid_template_areas": null,
            "object_position": null,
            "object_fit": null,
            "grid_auto_columns": null,
            "margin": null,
            "display": null,
            "left": null
          }
        },
        "799c60c15ffe4814906d8a676eaccf83": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "DescriptionStyleModel",
          "state": {
            "_view_name": "StyleView",
            "_model_name": "DescriptionStyleModel",
            "description_width": "",
            "_view_module": "@jupyter-widgets/base",
            "_model_module_version": "1.5.0",
            "_view_count": null,
            "_view_module_version": "1.2.0",
            "_model_module": "@jupyter-widgets/controls"
          }
        },
        "d0925adafaa44c8280b685cb6ed7ab99": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "state": {
            "_view_name": "LayoutView",
            "grid_template_rows": null,
            "right": null,
            "justify_content": null,
            "_view_module": "@jupyter-widgets/base",
            "overflow": null,
            "_model_module_version": "1.2.0",
            "_view_count": null,
            "flex_flow": null,
            "width": null,
            "min_width": null,
            "border": null,
            "align_items": null,
            "bottom": null,
            "_model_module": "@jupyter-widgets/base",
            "top": null,
            "grid_column": null,
            "overflow_y": null,
            "overflow_x": null,
            "grid_auto_flow": null,
            "grid_area": null,
            "grid_template_columns": null,
            "flex": null,
            "_model_name": "LayoutModel",
            "justify_items": null,
            "grid_row": null,
            "max_height": null,
            "align_content": null,
            "visibility": null,
            "align_self": null,
            "height": null,
            "min_height": null,
            "padding": null,
            "grid_auto_rows": null,
            "grid_gap": null,
            "max_width": null,
            "order": null,
            "_view_module_version": "1.2.0",
            "grid_template_areas": null,
            "object_position": null,
            "object_fit": null,
            "grid_auto_columns": null,
            "margin": null,
            "display": null,
            "left": null
          }
        },
        "99e37a57afd24180916e382c9b3fbcf2": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "HBoxModel",
          "state": {
            "_view_name": "HBoxView",
            "_dom_classes": [],
            "_model_name": "HBoxModel",
            "_view_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_view_count": null,
            "_view_module_version": "1.5.0",
            "box_style": "",
            "layout": "IPY_MODEL_987f239bb9054db1b28d6e3fb455bf4b",
            "_model_module": "@jupyter-widgets/controls",
            "children": [
              "IPY_MODEL_320b69719b734cb587ac4164559de6ec",
              "IPY_MODEL_9bb05c53e6a94ff5a6a947925c98c7b7"
            ]
          }
        },
        "987f239bb9054db1b28d6e3fb455bf4b": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "state": {
            "_view_name": "LayoutView",
            "grid_template_rows": null,
            "right": null,
            "justify_content": null,
            "_view_module": "@jupyter-widgets/base",
            "overflow": null,
            "_model_module_version": "1.2.0",
            "_view_count": null,
            "flex_flow": null,
            "width": null,
            "min_width": null,
            "border": null,
            "align_items": null,
            "bottom": null,
            "_model_module": "@jupyter-widgets/base",
            "top": null,
            "grid_column": null,
            "overflow_y": null,
            "overflow_x": null,
            "grid_auto_flow": null,
            "grid_area": null,
            "grid_template_columns": null,
            "flex": null,
            "_model_name": "LayoutModel",
            "justify_items": null,
            "grid_row": null,
            "max_height": null,
            "align_content": null,
            "visibility": null,
            "align_self": null,
            "height": null,
            "min_height": null,
            "padding": null,
            "grid_auto_rows": null,
            "grid_gap": null,
            "max_width": null,
            "order": null,
            "_view_module_version": "1.2.0",
            "grid_template_areas": null,
            "object_position": null,
            "object_fit": null,
            "grid_auto_columns": null,
            "margin": null,
            "display": null,
            "left": null
          }
        },
        "320b69719b734cb587ac4164559de6ec": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "FloatProgressModel",
          "state": {
            "_view_name": "ProgressView",
            "style": "IPY_MODEL_fc17223bd00a4eb1b4fe6840e0a2f3c7",
            "_dom_classes": [],
            "description": "",
            "_model_name": "FloatProgressModel",
            "bar_style": "success",
            "max": 29515,
            "_view_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "value": 29515,
            "_view_count": null,
            "_view_module_version": "1.5.0",
            "orientation": "horizontal",
            "min": 0,
            "description_tooltip": null,
            "_model_module": "@jupyter-widgets/controls",
            "layout": "IPY_MODEL_c199f9a362f548f4a92943697ada5172"
          }
        },
        "9bb05c53e6a94ff5a6a947925c98c7b7": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "HTMLModel",
          "state": {
            "_view_name": "HTMLView",
            "style": "IPY_MODEL_8beb3a5ce0c64b878b83a1fa6b1658a5",
            "_dom_classes": [],
            "description": "",
            "_model_name": "HTMLModel",
            "placeholder": "​",
            "_view_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "value": " 29696/? [00:02&lt;00:00, 14659.37it/s]",
            "_view_count": null,
            "_view_module_version": "1.5.0",
            "description_tooltip": null,
            "_model_module": "@jupyter-widgets/controls",
            "layout": "IPY_MODEL_6b592b65e5ff43808c5a482381e2f4d8"
          }
        },
        "fc17223bd00a4eb1b4fe6840e0a2f3c7": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "ProgressStyleModel",
          "state": {
            "_view_name": "StyleView",
            "_model_name": "ProgressStyleModel",
            "description_width": "initial",
            "_view_module": "@jupyter-widgets/base",
            "_model_module_version": "1.5.0",
            "_view_count": null,
            "_view_module_version": "1.2.0",
            "bar_color": null,
            "_model_module": "@jupyter-widgets/controls"
          }
        },
        "c199f9a362f548f4a92943697ada5172": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "state": {
            "_view_name": "LayoutView",
            "grid_template_rows": null,
            "right": null,
            "justify_content": null,
            "_view_module": "@jupyter-widgets/base",
            "overflow": null,
            "_model_module_version": "1.2.0",
            "_view_count": null,
            "flex_flow": null,
            "width": null,
            "min_width": null,
            "border": null,
            "align_items": null,
            "bottom": null,
            "_model_module": "@jupyter-widgets/base",
            "top": null,
            "grid_column": null,
            "overflow_y": null,
            "overflow_x": null,
            "grid_auto_flow": null,
            "grid_area": null,
            "grid_template_columns": null,
            "flex": null,
            "_model_name": "LayoutModel",
            "justify_items": null,
            "grid_row": null,
            "max_height": null,
            "align_content": null,
            "visibility": null,
            "align_self": null,
            "height": null,
            "min_height": null,
            "padding": null,
            "grid_auto_rows": null,
            "grid_gap": null,
            "max_width": null,
            "order": null,
            "_view_module_version": "1.2.0",
            "grid_template_areas": null,
            "object_position": null,
            "object_fit": null,
            "grid_auto_columns": null,
            "margin": null,
            "display": null,
            "left": null
          }
        },
        "8beb3a5ce0c64b878b83a1fa6b1658a5": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "DescriptionStyleModel",
          "state": {
            "_view_name": "StyleView",
            "_model_name": "DescriptionStyleModel",
            "description_width": "",
            "_view_module": "@jupyter-widgets/base",
            "_model_module_version": "1.5.0",
            "_view_count": null,
            "_view_module_version": "1.2.0",
            "_model_module": "@jupyter-widgets/controls"
          }
        },
        "6b592b65e5ff43808c5a482381e2f4d8": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "state": {
            "_view_name": "LayoutView",
            "grid_template_rows": null,
            "right": null,
            "justify_content": null,
            "_view_module": "@jupyter-widgets/base",
            "overflow": null,
            "_model_module_version": "1.2.0",
            "_view_count": null,
            "flex_flow": null,
            "width": null,
            "min_width": null,
            "border": null,
            "align_items": null,
            "bottom": null,
            "_model_module": "@jupyter-widgets/base",
            "top": null,
            "grid_column": null,
            "overflow_y": null,
            "overflow_x": null,
            "grid_auto_flow": null,
            "grid_area": null,
            "grid_template_columns": null,
            "flex": null,
            "_model_name": "LayoutModel",
            "justify_items": null,
            "grid_row": null,
            "max_height": null,
            "align_content": null,
            "visibility": null,
            "align_self": null,
            "height": null,
            "min_height": null,
            "padding": null,
            "grid_auto_rows": null,
            "grid_gap": null,
            "max_width": null,
            "order": null,
            "_view_module_version": "1.2.0",
            "grid_template_areas": null,
            "object_position": null,
            "object_fit": null,
            "grid_auto_columns": null,
            "margin": null,
            "display": null,
            "left": null
          }
        },
        "f4a27eab2a904fc680717fcee757d7fe": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "HBoxModel",
          "state": {
            "_view_name": "HBoxView",
            "_dom_classes": [],
            "_model_name": "HBoxModel",
            "_view_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_view_count": null,
            "_view_module_version": "1.5.0",
            "box_style": "",
            "layout": "IPY_MODEL_89d5cad45e3f4f87af96c0646c4265a2",
            "_model_module": "@jupyter-widgets/controls",
            "children": [
              "IPY_MODEL_95dc5c65e7474ac38112140fd55097b4",
              "IPY_MODEL_e1b84f84308047b19714c873ccade0c0"
            ]
          }
        },
        "89d5cad45e3f4f87af96c0646c4265a2": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "state": {
            "_view_name": "LayoutView",
            "grid_template_rows": null,
            "right": null,
            "justify_content": null,
            "_view_module": "@jupyter-widgets/base",
            "overflow": null,
            "_model_module_version": "1.2.0",
            "_view_count": null,
            "flex_flow": null,
            "width": null,
            "min_width": null,
            "border": null,
            "align_items": null,
            "bottom": null,
            "_model_module": "@jupyter-widgets/base",
            "top": null,
            "grid_column": null,
            "overflow_y": null,
            "overflow_x": null,
            "grid_auto_flow": null,
            "grid_area": null,
            "grid_template_columns": null,
            "flex": null,
            "_model_name": "LayoutModel",
            "justify_items": null,
            "grid_row": null,
            "max_height": null,
            "align_content": null,
            "visibility": null,
            "align_self": null,
            "height": null,
            "min_height": null,
            "padding": null,
            "grid_auto_rows": null,
            "grid_gap": null,
            "max_width": null,
            "order": null,
            "_view_module_version": "1.2.0",
            "grid_template_areas": null,
            "object_position": null,
            "object_fit": null,
            "grid_auto_columns": null,
            "margin": null,
            "display": null,
            "left": null
          }
        },
        "95dc5c65e7474ac38112140fd55097b4": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "FloatProgressModel",
          "state": {
            "_view_name": "ProgressView",
            "style": "IPY_MODEL_e193c98b30e44176b81c2053f103258d",
            "_dom_classes": [],
            "description": "",
            "_model_name": "FloatProgressModel",
            "bar_style": "success",
            "max": 4422102,
            "_view_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "value": 4422102,
            "_view_count": null,
            "_view_module_version": "1.5.0",
            "orientation": "horizontal",
            "min": 0,
            "description_tooltip": null,
            "_model_module": "@jupyter-widgets/controls",
            "layout": "IPY_MODEL_4370152b266a4c9e8d0a1c7a8f6662e8"
          }
        },
        "e1b84f84308047b19714c873ccade0c0": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "HTMLModel",
          "state": {
            "_view_name": "HTMLView",
            "style": "IPY_MODEL_c49fe269b6bd4184866a4777b123b863",
            "_dom_classes": [],
            "description": "",
            "_model_name": "HTMLModel",
            "placeholder": "​",
            "_view_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "value": " 4422656/? [00:01&lt;00:00, 3137500.55it/s]",
            "_view_count": null,
            "_view_module_version": "1.5.0",
            "description_tooltip": null,
            "_model_module": "@jupyter-widgets/controls",
            "layout": "IPY_MODEL_3a8343f311f34c73ac7a458b15568637"
          }
        },
        "e193c98b30e44176b81c2053f103258d": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "ProgressStyleModel",
          "state": {
            "_view_name": "StyleView",
            "_model_name": "ProgressStyleModel",
            "description_width": "initial",
            "_view_module": "@jupyter-widgets/base",
            "_model_module_version": "1.5.0",
            "_view_count": null,
            "_view_module_version": "1.2.0",
            "bar_color": null,
            "_model_module": "@jupyter-widgets/controls"
          }
        },
        "4370152b266a4c9e8d0a1c7a8f6662e8": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "state": {
            "_view_name": "LayoutView",
            "grid_template_rows": null,
            "right": null,
            "justify_content": null,
            "_view_module": "@jupyter-widgets/base",
            "overflow": null,
            "_model_module_version": "1.2.0",
            "_view_count": null,
            "flex_flow": null,
            "width": null,
            "min_width": null,
            "border": null,
            "align_items": null,
            "bottom": null,
            "_model_module": "@jupyter-widgets/base",
            "top": null,
            "grid_column": null,
            "overflow_y": null,
            "overflow_x": null,
            "grid_auto_flow": null,
            "grid_area": null,
            "grid_template_columns": null,
            "flex": null,
            "_model_name": "LayoutModel",
            "justify_items": null,
            "grid_row": null,
            "max_height": null,
            "align_content": null,
            "visibility": null,
            "align_self": null,
            "height": null,
            "min_height": null,
            "padding": null,
            "grid_auto_rows": null,
            "grid_gap": null,
            "max_width": null,
            "order": null,
            "_view_module_version": "1.2.0",
            "grid_template_areas": null,
            "object_position": null,
            "object_fit": null,
            "grid_auto_columns": null,
            "margin": null,
            "display": null,
            "left": null
          }
        },
        "c49fe269b6bd4184866a4777b123b863": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "DescriptionStyleModel",
          "state": {
            "_view_name": "StyleView",
            "_model_name": "DescriptionStyleModel",
            "description_width": "",
            "_view_module": "@jupyter-widgets/base",
            "_model_module_version": "1.5.0",
            "_view_count": null,
            "_view_module_version": "1.2.0",
            "_model_module": "@jupyter-widgets/controls"
          }
        },
        "3a8343f311f34c73ac7a458b15568637": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "state": {
            "_view_name": "LayoutView",
            "grid_template_rows": null,
            "right": null,
            "justify_content": null,
            "_view_module": "@jupyter-widgets/base",
            "overflow": null,
            "_model_module_version": "1.2.0",
            "_view_count": null,
            "flex_flow": null,
            "width": null,
            "min_width": null,
            "border": null,
            "align_items": null,
            "bottom": null,
            "_model_module": "@jupyter-widgets/base",
            "top": null,
            "grid_column": null,
            "overflow_y": null,
            "overflow_x": null,
            "grid_auto_flow": null,
            "grid_area": null,
            "grid_template_columns": null,
            "flex": null,
            "_model_name": "LayoutModel",
            "justify_items": null,
            "grid_row": null,
            "max_height": null,
            "align_content": null,
            "visibility": null,
            "align_self": null,
            "height": null,
            "min_height": null,
            "padding": null,
            "grid_auto_rows": null,
            "grid_gap": null,
            "max_width": null,
            "order": null,
            "_view_module_version": "1.2.0",
            "grid_template_areas": null,
            "object_position": null,
            "object_fit": null,
            "grid_auto_columns": null,
            "margin": null,
            "display": null,
            "left": null
          }
        },
        "bc6976b9b75943b1a90e0952e437f67e": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "HBoxModel",
          "state": {
            "_view_name": "HBoxView",
            "_dom_classes": [],
            "_model_name": "HBoxModel",
            "_view_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_view_count": null,
            "_view_module_version": "1.5.0",
            "box_style": "",
            "layout": "IPY_MODEL_f911f0f9d38d4feb87ed2249e6d8a19e",
            "_model_module": "@jupyter-widgets/controls",
            "children": [
              "IPY_MODEL_72b6c85c55c2401ea1aba3bcda29d900",
              "IPY_MODEL_756123bd53c14cef8fcff36c991532b0"
            ]
          }
        },
        "f911f0f9d38d4feb87ed2249e6d8a19e": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "state": {
            "_view_name": "LayoutView",
            "grid_template_rows": null,
            "right": null,
            "justify_content": null,
            "_view_module": "@jupyter-widgets/base",
            "overflow": null,
            "_model_module_version": "1.2.0",
            "_view_count": null,
            "flex_flow": null,
            "width": null,
            "min_width": null,
            "border": null,
            "align_items": null,
            "bottom": null,
            "_model_module": "@jupyter-widgets/base",
            "top": null,
            "grid_column": null,
            "overflow_y": null,
            "overflow_x": null,
            "grid_auto_flow": null,
            "grid_area": null,
            "grid_template_columns": null,
            "flex": null,
            "_model_name": "LayoutModel",
            "justify_items": null,
            "grid_row": null,
            "max_height": null,
            "align_content": null,
            "visibility": null,
            "align_self": null,
            "height": null,
            "min_height": null,
            "padding": null,
            "grid_auto_rows": null,
            "grid_gap": null,
            "max_width": null,
            "order": null,
            "_view_module_version": "1.2.0",
            "grid_template_areas": null,
            "object_position": null,
            "object_fit": null,
            "grid_auto_columns": null,
            "margin": null,
            "display": null,
            "left": null
          }
        },
        "72b6c85c55c2401ea1aba3bcda29d900": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "FloatProgressModel",
          "state": {
            "_view_name": "ProgressView",
            "style": "IPY_MODEL_e3e798349fc142b08a16ad13dd09abc9",
            "_dom_classes": [],
            "description": "",
            "_model_name": "FloatProgressModel",
            "bar_style": "success",
            "max": 5148,
            "_view_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "value": 5148,
            "_view_count": null,
            "_view_module_version": "1.5.0",
            "orientation": "horizontal",
            "min": 0,
            "description_tooltip": null,
            "_model_module": "@jupyter-widgets/controls",
            "layout": "IPY_MODEL_defbdfe9d19949ab8fd9d1e6b42b7507"
          }
        },
        "756123bd53c14cef8fcff36c991532b0": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "HTMLModel",
          "state": {
            "_view_name": "HTMLView",
            "style": "IPY_MODEL_b06b801abd154a67805863289e7133f7",
            "_dom_classes": [],
            "description": "",
            "_model_name": "HTMLModel",
            "placeholder": "​",
            "_view_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "value": " 6144/? [00:00&lt;00:00, 29015.12it/s]",
            "_view_count": null,
            "_view_module_version": "1.5.0",
            "description_tooltip": null,
            "_model_module": "@jupyter-widgets/controls",
            "layout": "IPY_MODEL_76114a00a67f4a9fa0e559d904da9aa9"
          }
        },
        "e3e798349fc142b08a16ad13dd09abc9": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "ProgressStyleModel",
          "state": {
            "_view_name": "StyleView",
            "_model_name": "ProgressStyleModel",
            "description_width": "initial",
            "_view_module": "@jupyter-widgets/base",
            "_model_module_version": "1.5.0",
            "_view_count": null,
            "_view_module_version": "1.2.0",
            "bar_color": null,
            "_model_module": "@jupyter-widgets/controls"
          }
        },
        "defbdfe9d19949ab8fd9d1e6b42b7507": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "state": {
            "_view_name": "LayoutView",
            "grid_template_rows": null,
            "right": null,
            "justify_content": null,
            "_view_module": "@jupyter-widgets/base",
            "overflow": null,
            "_model_module_version": "1.2.0",
            "_view_count": null,
            "flex_flow": null,
            "width": null,
            "min_width": null,
            "border": null,
            "align_items": null,
            "bottom": null,
            "_model_module": "@jupyter-widgets/base",
            "top": null,
            "grid_column": null,
            "overflow_y": null,
            "overflow_x": null,
            "grid_auto_flow": null,
            "grid_area": null,
            "grid_template_columns": null,
            "flex": null,
            "_model_name": "LayoutModel",
            "justify_items": null,
            "grid_row": null,
            "max_height": null,
            "align_content": null,
            "visibility": null,
            "align_self": null,
            "height": null,
            "min_height": null,
            "padding": null,
            "grid_auto_rows": null,
            "grid_gap": null,
            "max_width": null,
            "order": null,
            "_view_module_version": "1.2.0",
            "grid_template_areas": null,
            "object_position": null,
            "object_fit": null,
            "grid_auto_columns": null,
            "margin": null,
            "display": null,
            "left": null
          }
        },
        "b06b801abd154a67805863289e7133f7": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "DescriptionStyleModel",
          "state": {
            "_view_name": "StyleView",
            "_model_name": "DescriptionStyleModel",
            "description_width": "",
            "_view_module": "@jupyter-widgets/base",
            "_model_module_version": "1.5.0",
            "_view_count": null,
            "_view_module_version": "1.2.0",
            "_model_module": "@jupyter-widgets/controls"
          }
        },
        "76114a00a67f4a9fa0e559d904da9aa9": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "state": {
            "_view_name": "LayoutView",
            "grid_template_rows": null,
            "right": null,
            "justify_content": null,
            "_view_module": "@jupyter-widgets/base",
            "overflow": null,
            "_model_module_version": "1.2.0",
            "_view_count": null,
            "flex_flow": null,
            "width": null,
            "min_width": null,
            "border": null,
            "align_items": null,
            "bottom": null,
            "_model_module": "@jupyter-widgets/base",
            "top": null,
            "grid_column": null,
            "overflow_y": null,
            "overflow_x": null,
            "grid_auto_flow": null,
            "grid_area": null,
            "grid_template_columns": null,
            "flex": null,
            "_model_name": "LayoutModel",
            "justify_items": null,
            "grid_row": null,
            "max_height": null,
            "align_content": null,
            "visibility": null,
            "align_self": null,
            "height": null,
            "min_height": null,
            "padding": null,
            "grid_auto_rows": null,
            "grid_gap": null,
            "max_width": null,
            "order": null,
            "_view_module_version": "1.2.0",
            "grid_template_areas": null,
            "object_position": null,
            "object_fit": null,
            "grid_auto_columns": null,
            "margin": null,
            "display": null,
            "left": null
          }
        }
      }
    }
  },
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "DaGg9EoMGXYM"
      },
      "source": [
        "# Introduction to Pytorch\n",
        "This notebook contains the supplementary examples from the \"Introduction to Pytorch\" tutorial in *CV4DL* course at WIS.\n",
        "\n",
        "Most of the material is based on the [Official Basic Pytorch Tutorials](https://pytorch.org/tutorials/beginner/basics/intro.html). You are encouraged to read them to gain in depth understanding of the Pytorch framework.\n",
        "\n",
        "**NOTE:** This notebook requiers GPU resources. \n",
        "To get a GPU in Google Colab, please go to the top menu and to: **Runtime ➔ Change runtime type.** Then, select **GPU** as **Hardware accelerator**."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "LnxbuyxEGRDs"
      },
      "source": [
        "# import calls\n",
        "import torch\n",
        "import numpy as np\n",
        "from torch import nn\n",
        "from torch.utils.data import DataLoader\n",
        "from torchvision import datasets\n",
        "from torchvision.transforms import ToTensor\n",
        "from torchvision.utils import make_grid\n",
        "import matplotlib.pyplot as plt"
      ],
      "execution_count": 2,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "idooLt-plX0T"
      },
      "source": [
        "## Tensor's and their Attributes\n",
        "\n",
        "### Tensors\n",
        "\n",
        "Tensors are the most basic building blocks in PyTorch. They are used as inputs, outputs, model weights, and gradients. They are represented by the `torch.Tensor` class, defined and handled in a similar manner to `np.ndarray` in the [NumPy](https://numpy.org/) library."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "JQmw0ZTelXeN",
        "outputId": "b38c9dcc-6991-445e-fcd9-996fddeae08e"
      },
      "source": [
        "# creation from data\n",
        "data = [[1, 2],[3, 4]]\n",
        "x_data = torch.tensor(data)\n",
        "\n",
        "print(x_data)\n",
        "type(x_data)"
      ],
      "execution_count": 3,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "tensor([[1, 2],\n",
            "        [3, 4]])\n"
          ],
          "name": "stdout"
        },
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "torch.Tensor"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 3
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "RO6lXeNUGW9f",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "845184df-91a5-43d1-9b29-10f246940259"
      },
      "source": [
        "# creation from numpy array\n",
        "np_array = np.array(data)\n",
        "x_np = torch.from_numpy(np_array)\n",
        "\n",
        "print(x_np)"
      ],
      "execution_count": 4,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "tensor([[1, 2],\n",
            "        [3, 4]])\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "ZUk84CgoqrbX"
      },
      "source": [
        "### Attributes\n",
        "\n",
        "Tensors have several basic attributes:\n",
        "* `shape` - the dimensions of the tensor.\n",
        "* `dtype` - the type of cell in a tensor.\n",
        "* `device` - the device on which the tensor is saved."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "GVMgYCkaqp8Z",
        "outputId": "fe8df636-deb9-428b-9302-284db6330919"
      },
      "source": [
        "x_data.shape"
      ],
      "execution_count": 5,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "torch.Size([2, 2])"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 5
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "PB-pHqNurvjg",
        "outputId": "e8ca3098-d8b7-4eb0-e2a8-255b9e1013d4"
      },
      "source": [
        "x_data.dtype"
      ],
      "execution_count": 6,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "torch.int64"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 6
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "2LqL-Z-MrzB0",
        "outputId": "fd00d523-5c69-4c12-a384-a551eb72df96"
      },
      "source": [
        "x_data.device"
      ],
      "execution_count": 7,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "device(type='cpu')"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 7
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "1T3KQaWR7g-3"
      },
      "source": [
        "### Tesnor Constructor Methods\n",
        "There exists many more Tensor construction methods that the ones above.\n",
        "For instance, these methods receive the new tensor's `shape` attribute.\n"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "_89Y_O5cnK4l",
        "outputId": "552a9526-24b9-4596-fe97-30d5b8437ee6"
      },
      "source": [
        "shape = (2,3)\n",
        "x_randn = torch.randn(shape)\n",
        "x_ones = torch.ones(shape)\n",
        "x_zeros = torch.zeros(shape)\n",
        "\n",
        "print(f\"Random tensor of size {shape}: \\n {x_randn} \\n\")\n",
        "print(f\"Ones tensor of size {shape}: \\n {x_ones} \\n\")\n",
        "print(f\"Zeros tensor of size {shape}: \\n {x_zeros} \\n\")\n"
      ],
      "execution_count": 8,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Random tensor of size (2, 3): \n",
            " tensor([[ 0.1761, -0.3410, -1.4495],\n",
            "        [-1.8822, -0.6533,  1.1695]]) \n",
            "\n",
            "Ones tensor of size (2, 3): \n",
            " tensor([[1., 1., 1.],\n",
            "        [1., 1., 1.]]) \n",
            "\n",
            "Zeros tensor of size (2, 3): \n",
            " tensor([[0., 0., 0.],\n",
            "        [0., 0., 0.]]) \n",
            "\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "SIVWWlvcsBhv"
      },
      "source": [
        "### Managing Device\n",
        "\n",
        "In our Deep Learning programs, we apply many kinds of operations on different tensors. Unless specified otherwise, these operations are executed on the computer's *Central Processing Unit* (CPU). However, some of these operations (e.g. matrix multiplication) run much faster on *Graphical Proccessing Units* (GPU).\n",
        "\n",
        "It is often beneficial to utilize GPU resources. This is done by setting the device of our tensors to be a GPU.\n",
        "\n",
        "Pytorch interacts with GPUs through CUDA - a library for accessing GPUS created by Nvidia. All GPU related operations are kept under the module `torch.cuda`.\n",
        "\n",
        "**NOTE:** An operation can be done on tensors only if THEY ARE ALL on the same device. Distributed operations between devices & machines will be discussed in later tutorials."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "oCDHmo3AuAsj",
        "outputId": "829548bf-57ee-4275-eb9c-b82f4885d47e"
      },
      "source": [
        "torch.cuda.is_available() # indicates if a CUDA GPU device is available."
      ],
      "execution_count": 9,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "True"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 9
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "0iqvG3IFvOLp",
        "outputId": "b6b0c242-7602-4339-dd44-6c8343b0ad9a"
      },
      "source": [
        "torch.cuda.device_count() # count how many GPU devices are available."
      ],
      "execution_count": 10,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "1"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 10
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "woDAkrL5wYLI",
        "outputId": "b176c21e-8390-448c-ccce-b36d08faf842"
      },
      "source": [
        "print(x_data.device)\n",
        "x_gpu = x_data.to('cuda')\n",
        "print(x_gpu.device)"
      ],
      "execution_count": 11,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "cpu\n",
            "cuda:0\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "FC6jEuTPUHDt"
      },
      "source": [
        "### Tensor Operations\n",
        "Tensors in PyTorch are highly inspired by numpy ndarrays. Most methods that you apply on numpy ndarrays have an equivalent in PyTorch. Here are some examples for useful Pytorch operations and their numpy equivalents. More operations can be foun in [Pytorch's Tensor Documentation](https://pytorch.org/docs/stable/tensors.html)."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "j6tl2P19xkX-",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "65c6c4e7-855f-44f0-ef65-f0affe2bb2bf"
      },
      "source": [
        "# initialization\n",
        "a = torch.Tensor([[1, 2, 3],[4, 5, 6],[7, 8, 9]])\n",
        "b = torch.eye(3)  \n",
        "\n",
        "print(f\"a: {a}\")\n",
        "print(f\"b: {b}\")"
      ],
      "execution_count": 66,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "a: tensor([[1., 2., 3.],\n",
            "        [4., 5., 6.],\n",
            "        [7., 8., 9.]])\n",
            "b: tensor([[1., 0., 0.],\n",
            "        [0., 1., 0.],\n",
            "        [0., 0., 1.]])\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "MamUkQbm_nsg"
      },
      "source": [
        "#### Basic operations\n",
        "Used in the same manner as with numpy `ndarray` objects."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "ZluxZQiA_veM",
        "outputId": "dd2dd1b4-e143-4a1b-fdb2-31625534f550"
      },
      "source": [
        "#bitwise addition\n",
        "a + b"
      ],
      "execution_count": 67,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "tensor([[ 2.,  2.,  3.],\n",
              "        [ 4.,  6.,  6.],\n",
              "        [ 7.,  8., 10.]])"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 67
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "eWIgTo-__0GJ",
        "outputId": "9f04ec23-0c7c-4b85-c993-583bc1713b8e"
      },
      "source": [
        "# bitwise subtraction\n",
        "a - b"
      ],
      "execution_count": 68,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "tensor([[0., 2., 3.],\n",
              "        [4., 4., 6.],\n",
              "        [7., 8., 8.]])"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 68
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "jYEeCl-s_0Ma",
        "outputId": "601f1284-fdd6-4a33-9dd1-1a841d65869f"
      },
      "source": [
        "# bitwise multiplication\n",
        "a * b"
      ],
      "execution_count": 15,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "tensor([[1., 0., 0.],\n",
              "        [0., 5., 0.],\n",
              "        [0., 0., 9.]])"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 15
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "kU_bolo3_0PF",
        "outputId": "ed7d18eb-2bd8-4de6-a33a-725d333cec3f"
      },
      "source": [
        "# bitwise division (dividing by zero yields infinity)\n",
        "a / b"
      ],
      "execution_count": 16,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "tensor([[1., inf, inf],\n",
              "        [inf, 5., inf],\n",
              "        [inf, inf, 9.]])"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 16
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "BSQCrQ5j_0Rs",
        "outputId": "f8de2b67-7d37-4450-e453-ee890fa601c2"
      },
      "source": [
        "# bitwise power\n",
        "a ** b"
      ],
      "execution_count": 17,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "tensor([[1., 1., 1.],\n",
              "        [1., 5., 1.],\n",
              "        [1., 1., 9.]])"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 17
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "oTd8tuvR-cRF",
        "outputId": "72eb2d87-7164-4ae5-f07f-3ef923e2fc16"
      },
      "source": [
        "# matrix multiplication\n",
        "a @ b"
      ],
      "execution_count": 18,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "tensor([[1., 2., 3.],\n",
              "        [4., 5., 6.],\n",
              "        [7., 8., 9.]])"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 18
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "Dx_u369POvQa"
      },
      "source": [
        "#### Basic in-place operations\n",
        "Used in the same manner as with numpy `ndarray` objects. \n",
        "Note that the results of these operation change the input object rather than create a new one."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "X2X8abZ-P03g",
        "outputId": "80a23cae-ab6a-4dd6-b9ec-67f94a593f86"
      },
      "source": [
        "a + b\n",
        "a"
      ],
      "execution_count": 69,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "tensor([[1., 2., 3.],\n",
              "        [4., 5., 6.],\n",
              "        [7., 8., 9.]])"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 69
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "2GAaOKhQO_4E",
        "outputId": "71131988-f1dd-4aad-ea6d-04a82dc5a411"
      },
      "source": [
        "a += b\n",
        "a"
      ],
      "execution_count": 70,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "tensor([[ 2.,  2.,  3.],\n",
              "        [ 4.,  6.,  6.],\n",
              "        [ 7.,  8., 10.]])"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 70
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "IWY5peHCPHcc",
        "outputId": "62ab792f-0614-4864-f54c-a63baf54c15d"
      },
      "source": [
        "a -= b\n",
        "a"
      ],
      "execution_count": 71,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "tensor([[1., 2., 3.],\n",
              "        [4., 5., 6.],\n",
              "        [7., 8., 9.]])"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 71
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "FTIOX1opQ7F1",
        "outputId": "5c2acb94-6faf-4f0a-9cf6-6752bfa79151"
      },
      "source": [
        "a.clamp(2, 5)\n",
        "a"
      ],
      "execution_count": 72,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "tensor([[1., 2., 3.],\n",
              "        [4., 5., 6.],\n",
              "        [7., 8., 9.]])"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 72
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "EQTW0YhmRAeW",
        "outputId": "fe34d9f4-a303-4254-cf41-b3a2b4043ef9"
      },
      "source": [
        "a.clamp_(2, 5)\n",
        "a"
      ],
      "execution_count": 74,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "tensor([[2., 2., 3.],\n",
              "        [4., 5., 5.],\n",
              "        [5., 5., 5.]])"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 74
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "CPEE34ZzPp0A"
      },
      "source": [
        "Some more basic operations..."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "WriTqdkWX_Zg",
        "outputId": "a8476138-3d48-4567-af19-2ea608bab900"
      },
      "source": [
        "# indexing\n",
        "print(f\"a[0,0]: {a[0,0]}\")\n",
        "print(f\"a[1,2]: {a[1,2]}\") # first index - row, second index - column"
      ],
      "execution_count": 19,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "a[0,0]: 1.0\n",
            "a[1,2]: 6.0\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "2AUJeutYYTWH",
        "outputId": "52822cf7-105d-492b-bcdf-a18dbe5d483b"
      },
      "source": [
        "# slicing\n",
        "print(f\"a[0,:]: {a[0,:]} \") # print first row\n",
        "print(f\"a[:,0]: {a[:,0]}\") # print first column\n",
        "print(f\"a[0::2,0::2]: \\n {a[0::2,0::2]}\") # print sub-matrix excluding odd rows and odd columns."
      ],
      "execution_count": 20,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "a[0,:]: tensor([1., 2., 3.]) \n",
            "a[:,0]: tensor([1., 4., 7.])\n",
            "a[0::2,0::2]: \n",
            " tensor([[1., 3.],\n",
            "        [7., 9.]])\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "IWduJHLrYWXc",
        "outputId": "3ca9eaf3-1f7b-4db0-cb65-7356631ada51"
      },
      "source": [
        "# concatenation\n",
        "torch.cat((a, b))"
      ],
      "execution_count": 21,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "tensor([[1., 2., 3.],\n",
              "        [4., 5., 6.],\n",
              "        [7., 8., 9.],\n",
              "        [1., 0., 0.],\n",
              "        [0., 1., 0.],\n",
              "        [0., 0., 1.]])"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 21
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "UAnWMcPaw_kR",
        "outputId": "22c1c5b7-99ca-48ff-e48c-f17c8878b2a0"
      },
      "source": [
        "torch.cat((a, b)).shape"
      ],
      "execution_count": 22,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "torch.Size([6, 3])"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 22
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "X4qtY-vqxC7D",
        "outputId": "1aa47fc7-f878-46bd-cf24-eadc5a59f793"
      },
      "source": [
        "torch.cat((a, b), dim=1)"
      ],
      "execution_count": 23,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "tensor([[1., 2., 3., 1., 0., 0.],\n",
              "        [4., 5., 6., 0., 1., 0.],\n",
              "        [7., 8., 9., 0., 0., 1.]])"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 23
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "VjMIFbSbxFqU",
        "outputId": "a9ec85cf-65ae-40dd-e23b-771926c0d452"
      },
      "source": [
        "torch.cat((a, b), dim=1).shape"
      ],
      "execution_count": 24,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "torch.Size([3, 6])"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 24
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "pOflROgoYWb0",
        "outputId": "de694406-dc53-4fe7-9331-8f79615706bc"
      },
      "source": [
        "# stacking\n",
        "torch.stack((a, b))"
      ],
      "execution_count": 25,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "tensor([[[1., 2., 3.],\n",
              "         [4., 5., 6.],\n",
              "         [7., 8., 9.]],\n",
              "\n",
              "        [[1., 0., 0.],\n",
              "         [0., 1., 0.],\n",
              "         [0., 0., 1.]]])"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 25
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "BqL9IEfmYWe8",
        "outputId": "d8565c60-d03b-4e95-ae43-480de38ae967"
      },
      "source": [
        "# splitting\n",
        "torch.split(a, 1)"
      ],
      "execution_count": 26,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "(tensor([[1., 2., 3.]]), tensor([[4., 5., 6.]]), tensor([[7., 8., 9.]]))"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 26
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "OtZ-7jBkYaMk",
        "outputId": "291f788d-53d4-43c4-a0df-ae3e72f47e5b"
      },
      "source": [
        "# reshaping\n",
        "a.reshape((1,9))"
      ],
      "execution_count": 27,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "tensor([[1., 2., 3., 4., 5., 6., 7., 8., 9.]])"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 27
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "02c5M3317fnb",
        "outputId": "242f84b6-fd2f-40a6-eb8d-81be2cc38764"
      },
      "source": [
        "a.shape"
      ],
      "execution_count": 28,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "torch.Size([3, 3])"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 28
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "XW0dcP0l7knC",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "dd52711e-d194-4b1f-e5e6-9c3c29188e43"
      },
      "source": [
        "a.reshape((1,9)).shape"
      ],
      "execution_count": 29,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "torch.Size([1, 9])"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 29
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "8TSgw8WDLqZU"
      },
      "source": [
        "# unsqueeze & squeeze\n",
        "a_unsqueeze = a.unsqueeze(dim=0)"
      ],
      "execution_count": 53,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "Ll_mJaMvMqqI",
        "outputId": "cd060fc3-f58f-4304-c542-5ab9bd7174ac"
      },
      "source": [
        "a_unsqueeze.shape"
      ],
      "execution_count": 56,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "torch.Size([1, 3, 3])"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 56
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "tXdrczWtM13h",
        "outputId": "415c6a44-56f2-475a-bcdd-d12bd27f077e"
      },
      "source": [
        "a_unsqueeze.squeeze_() # in-place operation"
      ],
      "execution_count": 57,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "tensor([[1., 2., 3.],\n",
              "        [4., 5., 6.],\n",
              "        [7., 8., 9.]])"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 57
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "r3lypsNEM9AR",
        "outputId": "2f5f5938-2464-4eac-d89d-3487135b7735"
      },
      "source": [
        "a_unsqueeze.shape"
      ],
      "execution_count": 58,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "torch.Size([3, 3])"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 58
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "G6I_VuhU9_6Q",
        "outputId": "a09ca8bc-03ac-443f-ddc4-9f2947eaef3d"
      },
      "source": [
        "# an alternative way to define the Tensor a\n",
        "a_new = torch.arange(9).reshape(3,3)\n",
        "print(a_new)"
      ],
      "execution_count": 31,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "tensor([[0, 1, 2],\n",
            "        [3, 4, 5],\n",
            "        [6, 7, 8]])\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "bQ5TrZ_mVxc3"
      },
      "source": [
        "### **Case Study:** Matrix Multiplication\n",
        "\n",
        "In this example we will notice the importance of using PyTorch's built-in vectorized operations instead of \"re-implementing\" them ourselves in a less efficient way.\n",
        "Also, we will witness the speed differences when using different hardware resources."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "hFWkXZHCgtpr"
      },
      "source": [
        "size = 1000\n",
        "x = torch.randn((size, size))\n",
        "y = torch.randn((size, size))"
      ],
      "execution_count": 32,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "iVUWeh5RWW-I",
        "outputId": "e25b6f96-8a93-4ecd-d78c-08da7e7d96ad"
      },
      "source": [
        "# Case 1: nested for loops\n",
        "%%timeit\n",
        "res = torch.zeros((size, size))\n",
        "for i in range(size):\n",
        "  for j in range(size):\n",
        "    row = x[i, :]\n",
        "    col = y[:, j]\n",
        "    res[i, j] = torch.sum(row * col)"
      ],
      "execution_count": 33,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "1 loop, best of 5: 19.6 s per loop\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "AJalRg05gok2",
        "outputId": "995de7d2-21a9-495e-f2af-f7e543b4da76"
      },
      "source": [
        "# Case 2: single for loop\n",
        "%%timeit\n",
        "res = torch.zeros((size, size))\n",
        "for i in range(size):\n",
        "    row = x[i, :].unsqueeze_(dim=0)\n",
        "    res[i, :] = torch.mm(row, y)"
      ],
      "execution_count": 34,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "10 loops, best of 5: 129 ms per loop\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "l75KzPexg8mp",
        "outputId": "0b1a0146-6536-44fb-d877-f52df111cb7f"
      },
      "source": [
        "# Case 3: no loops\n",
        "%timeit torch.mm(x, y)"
      ],
      "execution_count": 35,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "10 loops, best of 5: 24.2 ms per loop\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "pFyqMN7Vg8tU",
        "outputId": "5a16bcf2-e893-4582-d432-acf7584c3a2b"
      },
      "source": [
        "# Case 4: np loops on GPU\n",
        "x_gpu = x.to('cuda')\n",
        "y_gpu = y.to('cuda')\n",
        "%timeit torch.mm(x_gpu, y_gpu)"
      ],
      "execution_count": 36,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "The slowest run took 19.97 times longer than the fastest. This could mean that an intermediate result is being cached.\n",
            "1000 loops, best of 5: 535 µs per loop\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "SJUKkVy2aBht"
      },
      "source": [
        "## Handling Data\n",
        "We want to properly handle the data we use for training, evaluation and testing. The module `utils.data` inside the `torchvision` library brings a solution to this need. They introduce relevant classes:\n",
        "* `Dataset` - manages loading structure and elements preprocessing in datasets.\n",
        "* `DataLoader` - manages batching and batch order when loading the datasets.\n"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "vQhKGKo7b0Nw",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 609,
          "referenced_widgets": [
            "d5f90b47f01e426d9acb2a999e6c9c3c",
            "fb2882cc1c264fbc9935e058ab5153da",
            "9505455b9e7846a3a7fe4ead3ab61dec",
            "81c475f07c6848f0aa08962c6b0e896b",
            "3ba109a914df4c85b19831417b652588",
            "d62d0a49b7c540758375ecb6f053db0f",
            "799c60c15ffe4814906d8a676eaccf83",
            "d0925adafaa44c8280b685cb6ed7ab99",
            "99e37a57afd24180916e382c9b3fbcf2",
            "987f239bb9054db1b28d6e3fb455bf4b",
            "320b69719b734cb587ac4164559de6ec",
            "9bb05c53e6a94ff5a6a947925c98c7b7",
            "fc17223bd00a4eb1b4fe6840e0a2f3c7",
            "c199f9a362f548f4a92943697ada5172",
            "8beb3a5ce0c64b878b83a1fa6b1658a5",
            "6b592b65e5ff43808c5a482381e2f4d8",
            "f4a27eab2a904fc680717fcee757d7fe",
            "89d5cad45e3f4f87af96c0646c4265a2",
            "95dc5c65e7474ac38112140fd55097b4",
            "e1b84f84308047b19714c873ccade0c0",
            "e193c98b30e44176b81c2053f103258d",
            "4370152b266a4c9e8d0a1c7a8f6662e8",
            "c49fe269b6bd4184866a4777b123b863",
            "3a8343f311f34c73ac7a458b15568637",
            "bc6976b9b75943b1a90e0952e437f67e",
            "f911f0f9d38d4feb87ed2249e6d8a19e",
            "72b6c85c55c2401ea1aba3bcda29d900",
            "756123bd53c14cef8fcff36c991532b0",
            "e3e798349fc142b08a16ad13dd09abc9",
            "defbdfe9d19949ab8fd9d1e6b42b7507",
            "b06b801abd154a67805863289e7133f7",
            "76114a00a67f4a9fa0e559d904da9aa9"
          ]
        },
        "outputId": "4cbdcc1e-e1f1-4c5b-9c58-c37f888a960f"
      },
      "source": [
        "training_data = datasets.FashionMNIST(\n",
        "    root=\"data\",\n",
        "    train=True,\n",
        "    download=True,\n",
        "    transform=ToTensor()\n",
        ")\n",
        "\n",
        "train_dataloader = DataLoader(training_data, batch_size=64)\n"
      ],
      "execution_count": 37,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Downloading http://fashion-mnist.s3-website.eu-central-1.amazonaws.com/train-images-idx3-ubyte.gz\n",
            "Downloading http://fashion-mnist.s3-website.eu-central-1.amazonaws.com/train-images-idx3-ubyte.gz to data/FashionMNIST/raw/train-images-idx3-ubyte.gz\n"
          ],
          "name": "stdout"
        },
        {
          "output_type": "display_data",
          "data": {
            "application/vnd.jupyter.widget-view+json": {
              "model_id": "d5f90b47f01e426d9acb2a999e6c9c3c",
              "version_minor": 0,
              "version_major": 2
            },
            "text/plain": [
              "HBox(children=(FloatProgress(value=0.0, max=26421880.0), HTML(value='')))"
            ]
          },
          "metadata": {
            "tags": []
          }
        },
        {
          "output_type": "stream",
          "text": [
            "\n",
            "Extracting data/FashionMNIST/raw/train-images-idx3-ubyte.gz to data/FashionMNIST/raw\n",
            "\n",
            "Downloading http://fashion-mnist.s3-website.eu-central-1.amazonaws.com/train-labels-idx1-ubyte.gz\n",
            "Downloading http://fashion-mnist.s3-website.eu-central-1.amazonaws.com/train-labels-idx1-ubyte.gz to data/FashionMNIST/raw/train-labels-idx1-ubyte.gz\n"
          ],
          "name": "stdout"
        },
        {
          "output_type": "display_data",
          "data": {
            "application/vnd.jupyter.widget-view+json": {
              "model_id": "99e37a57afd24180916e382c9b3fbcf2",
              "version_minor": 0,
              "version_major": 2
            },
            "text/plain": [
              "HBox(children=(FloatProgress(value=0.0, max=29515.0), HTML(value='')))"
            ]
          },
          "metadata": {
            "tags": []
          }
        },
        {
          "output_type": "stream",
          "text": [
            "\n",
            "Extracting data/FashionMNIST/raw/train-labels-idx1-ubyte.gz to data/FashionMNIST/raw\n",
            "\n",
            "Downloading http://fashion-mnist.s3-website.eu-central-1.amazonaws.com/t10k-images-idx3-ubyte.gz\n",
            "Downloading http://fashion-mnist.s3-website.eu-central-1.amazonaws.com/t10k-images-idx3-ubyte.gz to data/FashionMNIST/raw/t10k-images-idx3-ubyte.gz\n"
          ],
          "name": "stdout"
        },
        {
          "output_type": "display_data",
          "data": {
            "application/vnd.jupyter.widget-view+json": {
              "model_id": "f4a27eab2a904fc680717fcee757d7fe",
              "version_minor": 0,
              "version_major": 2
            },
            "text/plain": [
              "HBox(children=(FloatProgress(value=0.0, max=4422102.0), HTML(value='')))"
            ]
          },
          "metadata": {
            "tags": []
          }
        },
        {
          "output_type": "stream",
          "text": [
            "\n",
            "Extracting data/FashionMNIST/raw/t10k-images-idx3-ubyte.gz to data/FashionMNIST/raw\n",
            "\n",
            "Downloading http://fashion-mnist.s3-website.eu-central-1.amazonaws.com/t10k-labels-idx1-ubyte.gz\n",
            "Downloading http://fashion-mnist.s3-website.eu-central-1.amazonaws.com/t10k-labels-idx1-ubyte.gz to data/FashionMNIST/raw/t10k-labels-idx1-ubyte.gz\n"
          ],
          "name": "stdout"
        },
        {
          "output_type": "display_data",
          "data": {
            "application/vnd.jupyter.widget-view+json": {
              "model_id": "bc6976b9b75943b1a90e0952e437f67e",
              "version_minor": 0,
              "version_major": 2
            },
            "text/plain": [
              "HBox(children=(FloatProgress(value=0.0, max=5148.0), HTML(value='')))"
            ]
          },
          "metadata": {
            "tags": []
          }
        },
        {
          "output_type": "stream",
          "text": [
            "\n",
            "Extracting data/FashionMNIST/raw/t10k-labels-idx1-ubyte.gz to data/FashionMNIST/raw\n",
            "\n",
            "Processing...\n",
            "Done!\n"
          ],
          "name": "stdout"
        },
        {
          "output_type": "stream",
          "text": [
            "/usr/local/lib/python3.7/dist-packages/torchvision/datasets/mnist.py:502: UserWarning: The given NumPy array is not writeable, and PyTorch does not support non-writeable tensors. This means you can write to the underlying (supposedly non-writeable) NumPy array using the tensor. You may want to copy the array to protect its data or make it writeable before converting it to a tensor. This type of warning will be suppressed for the rest of this program. (Triggered internally at  /pytorch/torch/csrc/utils/tensor_numpy.cpp:143.)\n",
            "  return torch.from_numpy(parsed.astype(m[2], copy=False)).view(*s)\n"
          ],
          "name": "stderr"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "CrcoFc8qcZ47"
      },
      "source": [
        "It is always beneficial to see the data we work on, a common practice is to visualize a single batch."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 269
        },
        "id": "x5Ie5Bxmcmgf",
        "outputId": "7913aa06-0e91-4054-e6ca-4e3999d9b5c7"
      },
      "source": [
        "batch = next(iter(train_dataloader))\n",
        "images, labels = batch\n",
        "grid = make_grid(images).numpy()\n",
        "plt.imshow(np.transpose(grid, (1,2,0)))\n",
        "plt.show()"
      ],
      "execution_count": 38,
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "image/png": "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\n",
            "text/plain": [
              "<Figure size 432x288 with 1 Axes>"
            ]
          },
          "metadata": {
            "tags": [],
            "needs_background": "light"
          }
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "xG-I_ziuoe-s"
      },
      "source": [
        "## Building a Neural Network\n",
        "We want to build Neural Networks in a modular way, that supports automatic differentiation. The `torch.nn` module answers this need percisely. It enables modularity by introducing different building blocks that can be composed into neural networks.\n",
        "\n",
        "### `nn.Module`\n",
        "Each building block is a class, derived from the base class `nn.Module`. All of them must implement these two methods: \n",
        "\n",
        "* `__init__()`: defines all the components to be used inside this building block.\n",
        "* `forward()`: defines the forward pass of this building block - how the inputs will flow from one layer to another. This method usually recieves a `torch.Tensor` as input and yields `torch.Tensor` as output.\n",
        "\n",
        "Here you will see an implementation of a simple feed forward network using three building blocks:\n",
        "\n",
        "* `nn.Flatten` - Takes a tensor of shape BxCxHxW and reshapes it to BxCx(HxW). (Diminishing the number of dimensions is usually called *squeezing* or *flattening*).\n",
        "\n",
        "* `nn.Linear` - A fully-connected linear layer with bias.\n",
        "\n",
        "* `nn.ReLU` - A Rectified Linear Unit activation function.\n",
        "\n",
        "You can find a list of available building-blocks in [PyTorch `torch.nn` Documentation`](https://pytorch.org/docs/stable/nn.html)."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "O1qWL0_FoePM"
      },
      "source": [
        "INPUT_SIZE = 224\n",
        "C = 10 # num classes\n",
        "\n",
        "class MLP(nn.Module):\n",
        "  \n",
        "  def __init__(self):\n",
        "    super(MLP, self).__init__()\n",
        "    self.flatten = nn.Flatten()\n",
        "    self.fc1 = nn.Linear(INPUT_SIZE*INPUT_SIZE, 256)\n",
        "    self.relu1 = nn.ReLU()\n",
        "    self.fc2 = nn.Linear(256, 512)\n",
        "    self.relu2 = nn.ReLU()\n",
        "    self.fc3 = nn.Linear(512, C)\n",
        "\n",
        "  def forward(self, x):\n",
        "    x = self.flatten(x)\n",
        "    x = self.fc1(x)\n",
        "    x = self.relu1(x)\n",
        "    x = self.fc2(x)\n",
        "    x = self.relu2(x)\n",
        "    x = self.fc3(x)\n",
        "    return x"
      ],
      "execution_count": 39,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "yLa1QknHEQOe"
      },
      "source": [
        "B = 10 # batch size\n",
        "\n",
        "input = torch.randn(B, 1, INPUT_SIZE, INPUT_SIZE)\n",
        "model = MLP()"
      ],
      "execution_count": 40,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "v2nuqx0xFUnB",
        "outputId": "d7ddf15b-8def-4e54-e800-ccaad9b97716"
      },
      "source": [
        "# run with CPU\n",
        "%%timeit\n",
        "\n",
        "output = model(input)"
      ],
      "execution_count": 41,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "100 loops, best of 5: 8.46 ms per loop\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "mn8QOojGGvql",
        "outputId": "8014a123-9a24-4c47-d644-6fe568811026"
      },
      "source": [
        "# run with GPU\n",
        "\n",
        "gpu_model = model.to('cuda')\n",
        "gpu_input = input.to('cuda')\n",
        "\n",
        "%timeit gpu_output = gpu_model(gpu_input)"
      ],
      "execution_count": 42,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "The slowest run took 18.60 times longer than the fastest. This could mean that an intermediate result is being cached.\n",
            "1000 loops, best of 5: 588 µs per loop\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "4_c1-0UgMyNX"
      },
      "source": [
        "### `nn.Sequential()`\n",
        "In the above example we defined a model by stating its internal building blocks and explicitly implementing the forward function. In many cases, the forward function is pretty simple - pass the input through a series of layers, one after the other. For this purpose, a class named `nn.Sequential` was conceived. It is a building block similar to the ones above, as it is derived from `nn.Module`, but its `forward` function is already implemented.\n",
        "\n",
        "Here is an updated example of a simple feed forward network using `nn.Sequential`, that alleviates the need to create an entire class from scratch."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "wxAF1ek6SaQf",
        "outputId": "350c6fb8-2fb3-4ded-ba24-c4aaac3ea77e"
      },
      "source": [
        "seq_model = nn.Sequential(\n",
        "    nn.Flatten(),\n",
        "    nn.Linear(INPUT_SIZE*INPUT_SIZE, 256),\n",
        "    nn.ReLU(),\n",
        "    nn.Linear(256, 512),\n",
        "    nn.ReLU(),\n",
        "    nn.Linear(512, 10),\n",
        ") \n",
        "\n",
        "output = seq_model(input)\n",
        "seq_model.to('cuda')\n",
        "gpu_output = seq_model(input.to('cuda'))\n",
        "print(gpu_output.shape)"
      ],
      "execution_count": 43,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "torch.Size([10, 10])\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "4GdPIBNSUuTJ"
      },
      "source": [
        "## AutoGrad\n",
        "In the last section we learned how to build models in a modular way, while effortlessly do a forward pass for any model. Now, \n",
        "\n",
        "Nevertheless, we still need to support a backward pass through these models, that computes the gradients of all weights w.r.t. the loss. `torch.autograd` orchestrates this entire operation.\n",
        "\n",
        "The following section is heavily inspired by [PyTorch's Autograd Tutorial](https://pytorch.org/tutorials/beginner/former_torchies/autograd_tutorial.html). For further discussion see [A Gentle Introduction for Autograd](https://pytorch.org/tutorials/beginner/blitz/autograd_tutorial.html) and [Autograd Mechanics](https://pytorch.org/docs/stable/notes/autograd.html).\n",
        "\n",
        "A few attributes are available for tensors to support autograd:\n",
        "* `requires_grad` - do the tensor's gradients get tracked\n",
        "* `data` - the actual data of the tensor (type `torch.Tensor`)\n",
        "* `grad` - the gradient of the tensor (type `torch.Tensor`)\n",
        "* `grad_fn` - the function used to get the gradient of the tensor during backward pass.\n",
        "\n",
        "**NOTE:** `x.grad` is None until explicitly populated by a call to the `backward` function, further details ahead."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "L6dyE1TyLMBQ",
        "outputId": "694e76cb-6e4b-41f0-fbab-d2acf165f0f5"
      },
      "source": [
        "x = torch.ones(2, 2, requires_grad=True)\n",
        "print(x)\n",
        "print(x.data)\n",
        "print(x.grad)\n",
        "print(x.grad_fn)"
      ],
      "execution_count": 44,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "tensor([[1., 1.],\n",
            "        [1., 1.]], requires_grad=True)\n",
            "tensor([[1., 1.],\n",
            "        [1., 1.]])\n",
            "None\n",
            "None\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "soIJh5_l_CPh"
      },
      "source": [
        "Tensors that are created by an operation on other tensors that require gradients implicitly require gradients themselves (e.g. `y` and `z` in the following example). This is natural, since the new tensors' gradients are used to compute the original tensor's gradient according to the chain rule."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "5OoLIAkSLxS7",
        "outputId": "81685868-aaae-4bef-f3bb-c8249bd741d4"
      },
      "source": [
        "y = x + 2\n",
        "print(y)"
      ],
      "execution_count": 45,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "tensor([[3., 3.],\n",
            "        [3., 3.]], grad_fn=<AddBackward0>)\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "hVIisEZHMVmL",
        "outputId": "45836f93-9f3d-4766-9bbf-7b11d588f1f1"
      },
      "source": [
        "z = y * y * 3\n",
        "out = z.mean()\n",
        "print(z)\n",
        "print(out)"
      ],
      "execution_count": 46,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "tensor([[27., 27.],\n",
            "        [27., 27.]], grad_fn=<MulBackward0>)\n",
            "tensor(27., grad_fn=<MeanBackward0>)\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "sYUK37pp_jAx"
      },
      "source": [
        "The `backward` funtion is used to backward pass through all the tensors until the original one. In our case, `out.backward()` computes and propagates gradients in this order: `out -> z -> y -> x`."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "u_Zb0rRRMoj5",
        "outputId": "067bc52d-5903-4c6b-85a4-d2bedd9ceaf0"
      },
      "source": [
        "out.backward()\n",
        "print(x.grad)"
      ],
      "execution_count": 47,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "tensor([[4.5000, 4.5000],\n",
            "        [4.5000, 4.5000]])\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "RAO6K8mGMuqB"
      },
      "source": [
        "### Enabling and Disabling Gradients\n",
        "\n",
        "We can controll wether gradients are computed for tensors or not.\n",
        "The default behavior follows two rules:\n",
        "* `requiers_grad=False` is the default value for every Tensor construction method.\n",
        "* A tensor created by an operation on another tensor with `requiers_grad=True` will also have `requiers_grad=True`. Hence it will also have a `grad_fn` attribute, and `grad` attribute filled after the backward pass.\n",
        "\n",
        "Specific segments of code can entirely disregard gradients by nesting then within a `with torch.no_grad():` block. This is usually done for evaluation and inference purposes."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "IuAnIG1EEJhj",
        "outputId": "3134f7a9-63e7-4dee-bab9-d0643f994fe2"
      },
      "source": [
        "print(x.requires_grad)\n",
        "print((x ** 2).requires_grad)\n",
        "\n",
        "with torch.no_grad():\n",
        "    print((x ** 2).requires_grad)"
      ],
      "execution_count": 48,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "True\n",
            "True\n",
            "False\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "Lai44jt1ATry"
      },
      "source": [
        "### Back to NumPy\n",
        "Quite often we need to convert tensors with gradients to numpy (e.g. for visualizations during the training process). This is done by chaining the following methods:\n",
        "* `cpu` - Numpy does not support GPU hardware. This method moves the tensor to the CPU if necessary.\n",
        "* `detach` - If the tensor has gradients, it is attached to the computational graph. This method explicitly removes it from the computational graph. Alternatively, take its `data` attribute.\n",
        "* `numpy` - Converts a `torch.Tensor` to `np.ndarray`."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "vcSB1zp5ARN5",
        "outputId": "abffa385-526c-4b1d-985e-a4b41c9e72cc"
      },
      "source": [
        "np_out = out.detach().cpu().numpy()\n",
        "print(np_out)"
      ],
      "execution_count": 49,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "27.0\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "jlnNlliTxeW9"
      },
      "source": [
        "## Optimization Loop\n",
        "In this section, we will get familiar with PyTorch's optimization tools for training a model. These components are supported by `autograd` mechanism.\n",
        "\n",
        "### `torch.optim`\n",
        "This module includes implementations of a variety of optimization algorithms used to train deep neural networks. These optimizers are derived from `torch.Optimizer`, and implement the following methods:\n",
        "\n",
        "* `step` - This method executes an optimization step. That is, it updates all the gradients computed in the backward pass according to the optimization method.\n",
        "\n",
        "* `zero_grad` - This method sets all the gradients to zero. PyTorch's default behavior is to accumulate gradients, i.e. sum them from over all optimization steps. We want to process each batch independently from its predecessors, so we disregard the former batchs' gradients.\n",
        "\n",
        "Here you will find an example of creating an SGD optimizer. using the `step` and `zero_grad` methods will be found in the next and final example."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "80nLuONE01H5"
      },
      "source": [
        "model = nn.Sequential(\n",
        "    nn.Flatten(),\n",
        "    nn.Linear(224*224, 256),\n",
        "    nn.ReLU(),\n",
        "    nn.Linear(256, 512),\n",
        "    nn.ReLU(),\n",
        "    nn.Linear(512, 10),\n",
        "    nn.ReLU()\n",
        ") \n",
        "\n",
        "learning_rate = 0.1\n",
        "\n",
        "optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)\n",
        "\n",
        "optimizer.zero_grad()\n",
        "\n",
        "\n",
        "optimizer.step()\n",
        "\n"
      ],
      "execution_count": 50,
      "outputs": []
    }
  ]
}