From d3acac93215e28d9ad7c858b464737361cbbdcf0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?M=C3=A1t=C3=A9=20Zolt=C3=A1n=20Farkas?=
 <mate.farkas@rwth-aachen.de>
Date: Fri, 29 Jul 2022 14:53:23 +0200
Subject: [PATCH] python tutorial material ready

---
 lecture1/exercise_0_python.ipynb     | 379 ++++++++++++++++++++++++---
 lecture1/exercise_0_tensorflow.ipynb |  42 +++
 2 files changed, 378 insertions(+), 43 deletions(-)
 create mode 100644 lecture1/exercise_0_tensorflow.ipynb

diff --git a/lecture1/exercise_0_python.ipynb b/lecture1/exercise_0_python.ipynb
index 46ece82..c9af740 100644
--- a/lecture1/exercise_0_python.ipynb
+++ b/lecture1/exercise_0_python.ipynb
@@ -17,7 +17,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 17,
+   "execution_count": 1,
    "id": "c8562e26",
    "metadata": {
     "scrolled": false
@@ -45,7 +45,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 18,
+   "execution_count": 2,
    "id": "bea4da9f",
    "metadata": {},
    "outputs": [
@@ -72,7 +72,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 19,
+   "execution_count": 3,
    "id": "6b5d414b",
    "metadata": {},
    "outputs": [],
@@ -82,7 +82,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 20,
+   "execution_count": 4,
    "id": "d69d90e9",
    "metadata": {},
    "outputs": [
@@ -115,7 +115,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 21,
+   "execution_count": 5,
    "id": "f7179786",
    "metadata": {},
    "outputs": [],
@@ -130,7 +130,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 27,
+   "execution_count": 6,
    "id": "d0586d1b",
    "metadata": {},
    "outputs": [
@@ -139,7 +139,7 @@
      "evalue": "invalid syntax (998780084.py, line 3)",
      "output_type": "error",
      "traceback": [
-      "\u001b[0;36m  File \u001b[0;32m\"/tmp/ipykernel_51154/998780084.py\"\u001b[0;36m, line \u001b[0;32m3\u001b[0m\n\u001b[0;31m    print(\"The second element in a is:\", None,\"(should be 3)\")?\u001b[0m\n\u001b[0m                                                              ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m invalid syntax\n"
+      "\u001b[0;36m  Input \u001b[0;32mIn [6]\u001b[0;36m\u001b[0m\n\u001b[0;31m    print(\"The second element in a is:\", None,\"(should be 3)\")?\u001b[0m\n\u001b[0m                                                              ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m invalid syntax\n"
      ]
     }
    ],
@@ -160,7 +160,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 28,
+   "execution_count": 12,
    "id": "86b8e68c",
    "metadata": {},
    "outputs": [
@@ -169,7 +169,7 @@
      "evalue": "invalid syntax (2320046825.py, line 2)",
      "output_type": "error",
      "traceback": [
-      "\u001b[0;36m  File \u001b[0;32m\"/tmp/ipykernel_51154/2320046825.py\"\u001b[0;36m, line \u001b[0;32m2\u001b[0m\n\u001b[0;31m    print(\"13 x 14.5 =\", \"?\")?\u001b[0m\n\u001b[0m                             ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m invalid syntax\n"
+      "\u001b[0;36m  Input \u001b[0;32mIn [12]\u001b[0;36m\u001b[0m\n\u001b[0;31m    print(\"13 x 14.5 =\", \"?\")?\u001b[0m\n\u001b[0m                             ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m invalid syntax\n"
      ]
     }
    ],
@@ -178,9 +178,35 @@
     "print(\"13 x 14.5 =\", \"?\")?"
    ]
   },
+  {
+   "cell_type": "markdown",
+   "id": "32b1985e",
+   "metadata": {},
+   "source": [
+    "You can use the **double star** \\*\\*-operator to raise number to the **n-th power**:"
+   ]
+  },
   {
    "cell_type": "code",
-   "execution_count": 29,
+   "execution_count": 13,
+   "id": "8c45add3",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "1 4 9 16 1024\n"
+     ]
+    }
+   ],
+   "source": [
+    "print(1**2, 2**2, 3**2, 4**2, 32**2)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 14,
    "id": "29eac6ed",
    "metadata": {},
    "outputs": [
@@ -189,7 +215,7 @@
      "evalue": "invalid syntax (2665876267.py, line 2)",
      "output_type": "error",
      "traceback": [
-      "\u001b[0;36m  File \u001b[0;32m\"/tmp/ipykernel_51154/2665876267.py\"\u001b[0;36m, line \u001b[0;32m2\u001b[0m\n\u001b[0;31m    print(\"13 + True =\", \"?\")?\u001b[0m\n\u001b[0m                             ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m invalid syntax\n"
+      "\u001b[0;36m  Input \u001b[0;32mIn [14]\u001b[0;36m\u001b[0m\n\u001b[0;31m    print(\"13 + True =\", \"?\")?\u001b[0m\n\u001b[0m                             ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m invalid syntax\n"
      ]
     }
    ],
@@ -209,7 +235,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 30,
+   "execution_count": 15,
    "id": "b0a7cbe1",
    "metadata": {},
    "outputs": [
@@ -218,7 +244,7 @@
      "evalue": "invalid syntax (816995051.py, line 2)",
      "output_type": "error",
      "traceback": [
-      "\u001b[0;36m  File \u001b[0;32m\"/tmp/ipykernel_51154/816995051.py\"\u001b[0;36m, line \u001b[0;32m2\u001b[0m\n\u001b[0;31m    print((a==14) and not (c<d))?\u001b[0m\n\u001b[0m                                ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m invalid syntax\n"
+      "\u001b[0;36m  Input \u001b[0;32mIn [15]\u001b[0;36m\u001b[0m\n\u001b[0;31m    print((a==14) and not (c<d))?\u001b[0m\n\u001b[0m                                ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m invalid syntax\n"
      ]
     }
    ],
@@ -233,13 +259,13 @@
    "metadata": {},
    "source": [
     "## Control Flow Tools\n",
-    "For pre-test loops you can use ```while```. Beware that in Python indented blocks of code belongs to the same parent line (similarly to ```{...}``` in C); mixing indentations yields an ```IndentationError```."
+    "For pre-test loops you can use ```while```. Beware that in Python indented blocks of code belong to the same parent line (similarly to ```{...}``` in C); mixing indentations raises an ```IndentationError```."
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 34,
-   "id": "bc0a1aa7",
+   "execution_count": 16,
+   "id": "5f42b63f",
    "metadata": {},
    "outputs": [
     {
@@ -247,7 +273,7 @@
      "evalue": "unexpected indent (3109148489.py, line 5)",
      "output_type": "error",
      "traceback": [
-      "\u001b[0;36m  File \u001b[0;32m\"/tmp/ipykernel_51154/3109148489.py\"\u001b[0;36m, line \u001b[0;32m5\u001b[0m\n\u001b[0;31m    i = i + 1\u001b[0m\n\u001b[0m    ^\u001b[0m\n\u001b[0;31mIndentationError\u001b[0m\u001b[0;31m:\u001b[0m unexpected indent\n"
+      "\u001b[0;36m  Input \u001b[0;32mIn [16]\u001b[0;36m\u001b[0m\n\u001b[0;31m    i = i + 1\u001b[0m\n\u001b[0m    ^\u001b[0m\n\u001b[0;31mIndentationError\u001b[0m\u001b[0;31m:\u001b[0m unexpected indent\n"
      ]
     }
    ],
@@ -261,7 +287,7 @@
   },
   {
    "cell_type": "markdown",
-   "id": "f5d33ba2",
+   "id": "118d8935",
    "metadata": {},
    "source": [
     "Using ```for``` and the iterable ```range(n)``` a for-like loop can be created:"
@@ -269,8 +295,8 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 45,
-   "id": "d26a4b8a",
+   "execution_count": 17,
+   "id": "7740d793",
    "metadata": {},
    "outputs": [
     {
@@ -278,7 +304,7 @@
      "evalue": "invalid syntax (756008327.py, line 5)",
      "output_type": "error",
      "traceback": [
-      "\u001b[0;36m  File \u001b[0;32m\"/tmp/ipykernel_51154/756008327.py\"\u001b[0;36m, line \u001b[0;32m5\u001b[0m\n\u001b[0;31m    print(sum)?\u001b[0m\n\u001b[0m              ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m invalid syntax\n"
+      "\u001b[0;36m  Input \u001b[0;32mIn [17]\u001b[0;36m\u001b[0m\n\u001b[0;31m    print(sum)?\u001b[0m\n\u001b[0m              ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m invalid syntax\n"
      ]
     }
    ],
@@ -292,7 +318,7 @@
   },
   {
    "cell_type": "markdown",
-   "id": "b3730030",
+   "id": "fd2059e5",
    "metadata": {},
    "source": [
     "For **conditional branching**, the usual keywords ```if``` and ```else``` are defined. Loops can be stopped with ```break``` and skipped with ```continue```."
@@ -300,8 +326,8 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 66,
-   "id": "9a89a44c",
+   "execution_count": 18,
+   "id": "0c47c5d6",
    "metadata": {},
    "outputs": [
     {
@@ -309,7 +335,7 @@
      "evalue": "invalid syntax (2853117672.py, line 9)",
      "output_type": "error",
      "traceback": [
-      "\u001b[0;36m  File \u001b[0;32m\"/tmp/ipykernel_51154/2853117672.py\"\u001b[0;36m, line \u001b[0;32m9\u001b[0m\n\u001b[0;31m    print(\"else block\")?\u001b[0m\n\u001b[0m                       ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m invalid syntax\n"
+      "\u001b[0;36m  Input \u001b[0;32mIn [18]\u001b[0;36m\u001b[0m\n\u001b[0;31m    print(\"else block\")?\u001b[0m\n\u001b[0m                       ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m invalid syntax\n"
      ]
     }
    ],
@@ -327,7 +353,7 @@
   },
   {
    "cell_type": "markdown",
-   "id": "2b795be3",
+   "id": "f51fc582",
    "metadata": {},
    "source": [
     "## Functions\n",
@@ -336,28 +362,32 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 69,
-   "id": "1768ca2b",
+   "execution_count": 32,
+   "id": "d5f33c84",
    "metadata": {},
    "outputs": [
     {
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "Hello John Cleese!\n"
+      "Hello John Cleese!\n",
+      "Hello Graham Chapman!\n",
+      "Hello Eric Idle!\n"
      ]
     }
    ],
    "source": [
     "def get_greeting(name):\n",
     "    return \"Hello \" + name +\"!\"\n",
-    "print(get_greeting(\"John Cleese\"))"
+    "print(get_greeting(\"John Cleese\"))\n",
+    "print(get_greeting(\"Graham Chapman\"))\n",
+    "print(get_greeting(\"Eric Idle\"))"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 82,
-   "id": "e123d01c",
+   "execution_count": 20,
+   "id": "04034c0e",
    "metadata": {},
    "outputs": [
     {
@@ -365,7 +395,7 @@
      "evalue": "invalid syntax (1882212969.py, line 5)",
      "output_type": "error",
      "traceback": [
-      "\u001b[0;36m  File \u001b[0;32m\"/tmp/ipykernel_51154/1882212969.py\"\u001b[0;36m, line \u001b[0;32m5\u001b[0m\n\u001b[0;31m    factorial(10)?\u001b[0m\n\u001b[0m                 ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m invalid syntax\n"
+      "\u001b[0;36m  Input \u001b[0;32mIn [20]\u001b[0;36m\u001b[0m\n\u001b[0;31m    factorial(10)?\u001b[0m\n\u001b[0m                 ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m invalid syntax\n"
      ]
     }
    ],
@@ -379,17 +409,17 @@
   },
   {
    "cell_type": "markdown",
-   "id": "179e54d9",
+   "id": "49898002",
    "metadata": {},
    "source": [
     "## Classes\n",
-    "Classes are high-level objects for storing and managing primitives. They are initialized with ```class class_name:``` after which the constructor ```__init__(self, args)``` is automatically called. Data in classes are stored using the ```self``` keyword, which are publicly accessible by default."
+    "Classes are high-level objects for storing and managing primitives. They are initialized with ```class class_name:``` after which the constructor ```__init__(self, args)``` is automatically called. Data in classes are stored using the ```self``` keyword and are publicly accessible by default."
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 79,
-   "id": "d399a53d",
+   "execution_count": 21,
+   "id": "dd4ae61f",
    "metadata": {},
    "outputs": [
     {
@@ -417,17 +447,17 @@
   },
   {
    "cell_type": "markdown",
-   "id": "cd09aaa1",
+   "id": "0d914e99",
    "metadata": {},
    "source": [
     "## Class Inheritance\n",
-    "A class can inherit the properties of the parent class. These properties can be freely overriden:"
+    "A class can inherit the properties of its parent class. These properties can be freely overriden:"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 81,
-   "id": "60a46ff6",
+   "execution_count": 22,
+   "id": "caf893b1",
    "metadata": {},
    "outputs": [
     {
@@ -442,12 +472,275 @@
     "class Student(Person):\n",
     "    def print_info(self):\n",
     "        \"\"\"\n",
-    "        Beware that name is inherited from 'Person'\n",
+    "        Beware that the attribute name has been inherited from 'Person'\n",
     "        \"\"\"\n",
     "        print(self.name, \"is a student!\")\n",
     "bob = Student(\"Bob\", 20)\n",
     "bob.print_info()"
    ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "39f231b0",
+   "metadata": {},
+   "source": [
+    "## Numpy Basics\n",
+    "Numpy is an performant, easy-to-use scientific library for numeric calculations. You will often encouter cases where numpy can perform calculations several orders of magnitues faster due its C-backend and ability to process data in a vectorized (not individuallistic) form."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 23,
+   "id": "dfaeae8a",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "import numpy as np  # numpy is usually imported this way"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "935518b0",
+   "metadata": {},
+   "source": [
+    "### Numpy One Dimensional Array Operations\n",
+    "Numpy operates on arrays element-wise meaning elementary operations are performed in an intuitive vectorized form."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 24,
+   "id": "2aff9b94",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "[3. 3. 3. 3. 3. 3. 3. 3. 3. 3.]\n",
+      "[11 22 33 44 55 66 77] <class 'numpy.ndarray'>\n"
+     ]
+    }
+   ],
+   "source": [
+    "zero_array = np.zeros(10)   # creates an an array of 10 zeros\n",
+    "one_array  = np.ones(10)    # creates an array of... guess what!\n",
+    "two_array  = np.ones(10)*2  # this one is a bit more tricky\n",
+    "\n",
+    "three_array = one_array + two_array    # arrays are added element-wise\n",
+    "print(three_array)\n",
+    "\n",
+    "# You can also create numpy arrays from python lists:\n",
+    "np_array_from_python_list = np.array([11, 22, 33, 44, 55, 66, 77])\n",
+    "print(np_array_from_python_list, type(np_array_from_python_list))"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "e6057042",
+   "metadata": {},
+   "source": [
+    "For this to work however the arrays must be of the same shape, otherwise a ```ValueError``` will be raised. In order to avoid this error, you can always access the shape of an array using the ```array.shape``` syntax:"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 25,
+   "id": "1141c56f",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Shape of array1 (10,)\n",
+      "Shape of array2 (5,)\n"
+     ]
+    },
+    {
+     "ename": "NameError",
+     "evalue": "name 'np_array1' is not defined",
+     "output_type": "error",
+     "traceback": [
+      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
+      "\u001b[0;31mNameError\u001b[0m                                 Traceback (most recent call last)",
+      "Input \u001b[0;32mIn [25]\u001b[0m, in \u001b[0;36m<cell line: 5>\u001b[0;34m()\u001b[0m\n\u001b[1;32m      3\u001b[0m array2 \u001b[38;5;241m=\u001b[39m np\u001b[38;5;241m.\u001b[39marray([\u001b[38;5;241m10\u001b[39m]\u001b[38;5;241m*\u001b[39m\u001b[38;5;241m5\u001b[39m)               \u001b[38;5;66;03m# [10, 10, 10, 10, 10 ]\u001b[39;00m\n\u001b[1;32m      4\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mShape of array2\u001b[39m\u001b[38;5;124m\"\u001b[39m, array2\u001b[38;5;241m.\u001b[39mshape)  \u001b[38;5;66;03m# shape (5,)\u001b[39;00m\n\u001b[0;32m----> 5\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[43mnp_array1\u001b[49m\u001b[38;5;241m/\u001b[39mnp_array2)\n",
+      "\u001b[0;31mNameError\u001b[0m: name 'np_array1' is not defined"
+     ]
+    }
+   ],
+   "source": [
+    "array1 = np.arange(10)                  # [0, 1, 2, ..., 9]\n",
+    "print(\"Shape of array1\", array1.shape)  # shape: (10,)\n",
+    "array2 = np.array([10]*5)               # [10, 10, 10, 10, 10 ]\n",
+    "print(\"Shape of array2\", array2.shape)  # shape (5,)\n",
+    "print(np_array1/np_array2)              # VoilĂ  ValueError due to conflicting shapes"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "d236a438",
+   "metadata": {},
+   "source": [
+    "### Numpy Arrays of Multiple Dimensions\n",
+    "Numpy supports the creation of n-dimensional arrays (arrays, matrices, tensors). Let's say you wish to generate 5 normally distributed samples of size 1000 with means 0, 10, 20, 30 and 40 and standard deviation 1. For this, you can first generate 5\\*1000 samples around 0, put them into a marix of shape (5, 1000) and shift each distribution to their respective means."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 26,
+   "id": "47d6ecce",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Shape of the original dataset: (5000,)\n",
+      "Shape of the reshaped dataset: (5, 1000)\n"
+     ]
+    }
+   ],
+   "source": [
+    "ndists = 5\n",
+    "sample_size = 1000\n",
+    "dataset = np.random.normal(0, 1, ndists*sample_size)             # Dataset generation\n",
+    "print(\"Shape of the original dataset:\", dataset.shape)           # Printing the dataset shape\n",
+    "dataset_reshaped = dataset.reshape(ndists, sample_size)          # Reshaping it to (5, 1000)\n",
+    "print(\"Shape of the reshaped dataset:\", dataset_reshaped.shape)  # Printing the new shape"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "8bffbc39",
+   "metadata": {},
+   "source": [
+    "Now we can define our shift vector, extend it with a new \"dimension\" (called axis, i.e. bring it into the shape (5, 1)), such that all elements at the second index \"see\" a scalar."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 27,
+   "id": "f2ea360c",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Shift vector shape: (5, 1)\n"
+     ]
+    }
+   ],
+   "source": [
+    "shift_vector = np.arange(5)*10                    # np.arange(n) creates an array of integers from 0 to n-1\n",
+    "shift_vector = shift_vector[:, np.newaxis]        # np.newaxis takes care of the new axis creation\n",
+    "print(\"Shift vector shape:\", shift_vector.shape)  # observe that reshape has not been called"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "64fdffa1",
+   "metadata": {},
+   "source": [
+    "Now our gaussians can be shifted to their right places!"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 28,
+   "id": "f0177d95",
+   "metadata": {
+    "scrolled": true
+   },
+   "outputs": [
+    {
+     "data": {
+      "image/png": "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\n",
+      "text/plain": [
+       "<Figure size 432x288 with 1 Axes>"
+      ]
+     },
+     "metadata": {
+      "needs_background": "light"
+     },
+     "output_type": "display_data"
+    }
+   ],
+   "source": [
+    "dataset_shifted = shift_vector + dataset_reshaped  # shape (5, 1) + shape (5, 1000) = shape (5, 1000)\n",
+    "\n",
+    "import matplotlib.pyplot as plt                    # import the plotting library to showcase the results\n",
+    "for hist in dataset_shifted:                       # Iterate over every distribution\n",
+    "    plt.hist(hist)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 29,
+   "id": "439f4bf4",
+   "metadata": {
+    "scrolled": true
+   },
+   "outputs": [
+    {
+     "data": {
+      "image/png": "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\n",
+      "text/plain": [
+       "<Figure size 432x288 with 1 Axes>"
+      ]
+     },
+     "metadata": {
+      "needs_background": "light"
+     },
+     "output_type": "display_data"
+    }
+   ],
+   "source": [
+    "# ... or you check the documentation and solve the problem directly by invoking:\n",
+    "dataset_shifted = np.random.normal(loc=np.arange(5)*10, scale=np.ones(5), size=(1000, 5)).T\n",
+    "for hist in dataset_shifted:\n",
+    "    plt.hist(hist)\n",
+    "\n",
+    "# Always check the docs before inventing something \"new\"!"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "7a826bff",
+   "metadata": {},
+   "source": [
+    "### Numpy Miscellaneous:\n",
+    "Below you can find a non-exhaustive list of built-in numpy functions for quick data analysis:"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 30,
+   "id": "973bd72b",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Basic array operations:\n",
+      "Sum 5050\n",
+      "Mean [ 0.08110435  9.98545632 20.02933072 30.02389687 39.97474169]\n",
+      "Std [0.99851965 0.97608616 1.0021044  0.98741231 1.00744611]\n",
+      "Flattened array: [-0.44605952 -0.22217352 -0.25286257 ... 41.29848664 39.92391046\n",
+      " 39.72392673]\n"
+     ]
+    }
+   ],
+   "source": [
+    "print(\"Basic array operations:\")\n",
+    "print(\"Sum\", np.sum(np.arange(101)))             # Sum of all numbers from 0 to 100\n",
+    "print(\"Mean\", np.mean(dataset_shifted, axis=1))  # Mean of the generated gaussians from above...\n",
+    "print(\"Std\", dataset_shifted.std(axis=1))        # ...and their respective standard deviations with a different syntax\n",
+    "\n",
+    "print(\"Flattened array:\", dataset_shifted.flatten())       # .flatten() makes an array 1D"
+   ]
   }
  ],
  "metadata": {
@@ -466,7 +759,7 @@
    "name": "python",
    "nbconvert_exporter": "python",
    "pygments_lexer": "ipython3",
-   "version": "3.7.7"
+   "version": "3.9.12"
   }
  },
  "nbformat": 4,
diff --git a/lecture1/exercise_0_tensorflow.ipynb b/lecture1/exercise_0_tensorflow.ipynb
new file mode 100644
index 0000000..51649a1
--- /dev/null
+++ b/lecture1/exercise_0_tensorflow.ipynb
@@ -0,0 +1,42 @@
+{
+ "cells": [
+  {
+   "cell_type": "markdown",
+   "id": "269d507c",
+   "metadata": {},
+   "source": [
+    "# Tensorflow Tutorial\n",
+    "---------------------------------"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "fb7e3964",
+   "metadata": {},
+   "outputs": [],
+   "source": []
+  }
+ ],
+ "metadata": {
+  "kernelspec": {
+   "display_name": "Python 3 (ipykernel)",
+   "language": "python",
+   "name": "python3"
+  },
+  "language_info": {
+   "codemirror_mode": {
+    "name": "ipython",
+    "version": 3
+   },
+   "file_extension": ".py",
+   "mimetype": "text/x-python",
+   "name": "python",
+   "nbconvert_exporter": "python",
+   "pygments_lexer": "ipython3",
+   "version": "3.9.12"
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
-- 
GitLab