{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<img width=\"800px\" src=\"../fidle/img/00-Fidle-header-01.svg\"></img>\n",
    "\n",
    "# <!-- TITLE --> [LINR1] - Linear regression with direct resolution\n",
    "<!-- DESC --> Direct determination of linear regression \n",
    "<!-- AUTHOR : Jean-Luc Parouty (CNRS/SIMaP) -->\n",
    "\n",
    "## Objectives :\n",
    " - Just one, the illustration of a direct resolution :-)\n",
    "\n",
    "## What we're going to do :\n",
    "\n",
    "Equation : $ Y = X.\\theta + N$  \n",
    "Where N is a noise vector\n",
    "and $\\theta = (a,b)$ a vector as y = a.x + b"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Step 1 - Import and init"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<style>\n",
       "\n",
       "div.warn {    \n",
       "    background-color: #fcf2f2;\n",
       "    border-color: #dFb5b4;\n",
       "    border-left: 5px solid #dfb5b4;\n",
       "    padding: 0.5em;\n",
       "    font-weight: bold;\n",
       "    font-size: 1.1em;;\n",
       "    }\n",
       "\n",
       "\n",
       "\n",
       "div.nota {    \n",
       "    background-color: #DAFFDE;\n",
       "    border-left: 5px solid #92CC99;\n",
       "    padding: 0.5em;\n",
       "    }\n",
       "\n",
       "\n",
       "\n",
       "</style>\n",
       "\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "FIDLE 2020 - Practical Work Module\n",
      "Version              : 0.4.0\n",
      "Run time             : Saturday 22 February 2020, 15:41:32\n",
      "TensorFlow version   : 2.0.0\n",
      "Keras version        : 2.2.4-tf\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "import math\n",
    "import matplotlib\n",
    "import matplotlib.pyplot as plt\n",
    "import sys\n",
    "\n",
    "sys.path.append('..')\n",
    "import fidle.pwk as ooo\n",
    "\n",
    "ooo.init()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Step 2 - Retrieve a set of points"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "# ---- Paramètres\n",
    "nb    = 100     # Nombre de points\n",
    "xmin  = 0       # Distribution / x\n",
    "xmax  = 10\n",
    "a     = 4       # Distribution / y\n",
    "b     = 2       # y= a.x + b (+ bruit)\n",
    "noise = 7       # bruit\n",
    "\n",
    "theta = np.array([[a],[b]])\n",
    "\n",
    "# ---- Vecteur X  (1,x) x nb\n",
    "#      la premiere colonne est a 1 afin que X.theta <=> 1.b + x.a\n",
    "\n",
    "Xc1 = np.ones((nb,1))\n",
    "Xc2 = np.random.uniform(xmin,xmax,(nb,1))\n",
    "X = np.c_[ Xc1, Xc2 ]\n",
    "\n",
    "# ---- Noise\n",
    "# N = np.random.uniform(-noise,noise,(nb,1))\n",
    "N = noise * np.random.normal(0,1,(nb,1))\n",
    "\n",
    "# ---- Vecteur Y\n",
    "Y = (X @ theta) + N\n",
    "\n",
    "# print(\"X:\\n\",X,\"\\nY:\\n \",Y)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Show it"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 864x432 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "width = 12\n",
    "height = 6\n",
    "\n",
    "fig, ax = plt.subplots()\n",
    "fig.set_size_inches(width,height)\n",
    "ax.plot(X[:,1], Y, \".\")\n",
    "ax.tick_params(axis='both', which='both', bottom=False, left=False, labelbottom=False, labelleft=False)\n",
    "ax.set_xlabel('x axis')\n",
    "ax.set_ylabel('y axis')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Step 3 - Direct calculation of the normal equation\n",
    "\n",
    "\n",
    "We'll try to find an optimal value of $\\theta$, minimizing a cost function.  \n",
    "The cost function, classically used in the case of linear regressions, is the **root mean square error** (racine carré de l'erreur quadratique moyenne):  \n",
    "\n",
    "$RMSE(X,h_\\theta)=\\sqrt{\\frac1n\\sum_{i=1}^n\\left[h_\\theta(X^{(i)})-Y^{(i)}\\right]^2}$  \n",
    "\n",
    "With the simplified variant : $MSE(X,h_\\theta)=\\frac1n\\sum_{i=1}^n\\left[h_\\theta(X^{(i)})-Y^{(i)}\\right]^2$\n",
    "\n",
    "The optimal value of regression is : $ \\hat{ \\theta } =( X^{-T} .X)^{-1}.X^{-T}.Y$\n",
    "\n",
    "Démontstration : https://eli.thegreenplace.net/2014/derivation-of-the-normal-equation-for-linear-regression"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Theta :\n",
      " [[4]\n",
      " [2]] \n",
      "\n",
      "theta hat :\n",
      " [[6.68975287]\n",
      " [1.6787656 ]]\n"
     ]
    }
   ],
   "source": [
    "theta_hat = np.linalg.inv(X.T @ X) @ X.T @ Y\n",
    "\n",
    "print(\"Theta :\\n\",theta,\"\\n\\ntheta hat :\\n\",theta_hat)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Show it"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAsMAAAFrCAYAAAA0K4RcAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4xLjMsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+AADFEAAAgAElEQVR4nO3de3SkeV3n8U9VdSXp+y2dpDuX6U56epqL4gw23TuCAuLqHpWLi+IwiuBR0N9hYRf3LDC6RxG2WVfZo4v8XBCFZRmBXQWUI6yuII4LzhiU+9DTk6S7c+lO0rd00pcklaraP56qTlWuz5NU1XP5vV/n9OlOJak8SbqqPs/3+f6+v1SxWBQAAADgonTYBwAAAACEhTAMAAAAZxGGAQAA4CzCMAAAAJxFGAYAAICzQgnDxpiiMYYxFgAAAAjVlpC/PoEYAAAA9ZZa7R20SQAAAMBZhGEAAAA4izAMAAAAZxGGAQAA4CzCMAAAAJxFGAYAAICzCMMAAABwFmEYAAAAziIMAwAAwFmEYQAAADgr7O2YAQAAUCP5QlH9A5MaHJ9WX8cunTjapkx61Z2IIcIwAABAIuQLRT3y6BM6MzaluVxezdmMjnfu0emHTxKI10CbBAAAQAL0D0zqzNiUZnN5FSXN5vI6Mzal/oHJsA8t0gjDAAAACTA4Pq25XL7qtrlcXkMT0yEdUTwQhgEAABKgr2OXmrOZqtuasxn1tu8K6YjigTAMAACQACeOtul45x61ZDNKSWop9QyfONoW9qFFGgvoAAAAEiCTTun0wyfVPzCpoYlp9bYzTcIPwjAAAEBCZNIpnTrWrlPH2sM+lNigTQIAAADOIgwDAADAWYRhAAAAOIswDAAAAGcRhgEAAOAswjAAAACcRRgGAACAswjDAAAAcBZhGAAAAM4iDAMAAMBZhGEAAAA4izAMAAAAZxGGAQAA4CzCMAAAAJxFGAYAAICzCMMAAABwFmEYAAAAziIMAwAAwFmEYQAAADiLMAwAAABnEYYBAADgLMIwAAAAnEUYBgAAgLMIwwAAAHAWYRgAAADOIgwDAADAWYRhAAAAOIswDAAAAGcRhgEAAOAswjAAAACcRRgGAACAswjDAAAAcNaWsA8AAABEQ75QVP/ApAbHp9XXsUsnjrYpk06FfVhAXRGGAQCA8oWiHnn0CZ0Zm9JcLq/mbEbHO/fo9MMnCcRINNokAACA+gcmdWZsSrO5vIqSZnN5nRmbUv/AZNiHVnP5QlGPn53Qo489rcfPTihfKIZ9SAgRlWEAAKDB8WnN5fJVt83l8hqamNapY+0hHVXtUQHHUlSGAQCA+jp2qTmbqbqtOZtRb/uukI6oPlyqgMMfwjAAANCJo2063rlHLdmMUpJaShXTE0fbwj60mlqrAg430SYBAACUSad0+uGT6h+Y1NDEtHrbkzlNolwBn60IxEmqgDMRJDjCMAAAkOQF4lPH2hPVI7xUuQK+tGc4CRVw+qE3hjAMAACckeQKeGU/tFTdD53kE5zNIgwDAJzDpWS3JbUC7spEkFojDAMAnMKlZCRV0vuh64VpEpvA0G4AiB9GayGpXJkIUmtUhjeIygIAxBOXkpFUSe6HrifC8AbRpA4A8cSlZCRZUvuh64k2iQ1iaDcAREPQljUuJQOoRGV4g6gsAEC48oWinnh6Qu//6yd1dWZOuXzhbrBdq2WNS8kAKhGGNyjJQ7sBIOrK6zaeHL2u+YXC3dv9tqxxKRlAGWF4g6gsAEB4yus2KoNwGYvhAARBGN4EKgsAEI6V1m2U0bIGIAgW0AEAYqe8bmOpbCZNyxqAQKgMAwBiZ+m6jeyWtPbtaNYbfuiZOnmsnZY1AL4RhgEAscO6DQC1QhgGAMQS6zYA1AI9wwAAAHAWlWEAAOC0fKGo/oFJDY5Pq6+DlhvXEIYBAEBNxSlcljdwWbqJ1lq7GCJZCMMAAKBm4hYuyxu4zJbmVvvdxRDJQc8wAAComcpwWVR1uIyilTZwKe9iCDcQhgEAQM1sNlzmC0U9fnZCjz72tB4/O6F8oViPw7xrpQ1c2MWw8b+HMNEmAQAAaqYcLmcrArHfcBlGi8XSDVzKX9PlXQzj1uqyWYRhAABQM5sJl2H077KBy3Ku9VEThgEAQM1sJlyu1WJRzxDGBi7Vwvo9hIUwDAAAamqj4XIzLRaoHdd+DyygAwAAkVBusWjJZpSS1EL/bihc+z1QGQYAAJFA/2401OX3MDcrjZ2XikWp7xk1O9ZaIAwDAIDIoH83Gjb8eygWpRvXpJEhaWRQGjnn/T0x5r3vGfdLv/Lu+hz0BhGGAQAAEFw+L42PLA++MzdW/5yRIS8Up6JT7ScMAwmVLxTVPzCpwfFp9XVwqRHAcjxPwLfbt6TRUtgtB9+x89JCzt/np9JSR5fUfUTKzUtNzXU93CAIw0ACuTYwHUBwPE9gRcWidHWiVO2t+HNl3P99NG/1Qm93r9TdJ3X1Sp33SM0t9TvuTSAMAwnk2sB0AMHxPAHl5qWLFxbbG8rB984t//ex70Ap9FYE3wMdUjo+A8sIw0ACuTYwHe7gsn7t8DzhmJmpUtitCL7jI17frx+ZLdKhHi/sdvdKPX1S1xFpR/xnDxOGgQRybWA63MBl/drieSKhCnlp8lJFi0Mp+E5d9X8f23Z4Ybe71wu/PX3SwW5pS7Z+xx0iwjCQQOWB6UtDQ1IHpsMNXNavLZ4nEmButrSorSL4jp6T5uf838eBg4tV3u4+7997WyM17aHeCMNAAjG4HknEZf3a4nkiRopFr7JbCr2FkSHNDZ5Vy/UJpVT0dx/ZJqnzcHXw7Tosbd1ezyOPBcIwkFAMrkfScFm/9nieiKCFhYrZvRV/bi7O7k1L2rrWfezeW+rt7StNdeiT2julTKbeRx9LhGEAQCxwWR9JULkI9NiejB5ouqnMaEXovXjB9+zevFIaze7V+eYDOvzc5+ie+7/b6/Pdva/O30WyEIYBwDFxncgQ18v6cf15o4aKRenKhPLDg/rCZx/Tzisj+sHZK+rIT/u/j5ZtUvcRPZXep89dzmqwqVXns/s1n96ilKTXHD6me559b92+hSQjDAOAQ+I+kSFul/Xj/vPGBuTmpbEL0uiQNFya5DB6TrpzSxlJP+TnPva1ST29i2PMunulVm927/WzE/rbT36VdqEaIgwDgEOYyNBYQX7eVJBjaGZKGh6qDr7jI1Kh4OvTc0rrQnaf0j296v3e+xdHme3Yuern0C5Ue4RhAHAIExkay+/PmwpyxBXy0uTFiuBbGmN245r/+9i+Uzf2d+uLN5p1dst+DTYd0Eh2r7Y0NentP3G/en0+/uLaLhRlhGEAcAgTGRrL78+bin2EzN6Rxs4tBt9ym0OQ2b1th6q3KO7ulfa2akdR+vIKJz1Bq7pxaxeKOsJwg3D5C0AUcIm1sfz+vKnYh+Du7N7B6uA7edF7nx9Nzd7s3srg23XYW+y2gkxKVHUjiDDcAFz+AhAVXGJtLL8/7yRU7CNd9FlYkC4NL7Y4lIPvzQDTHHbvqwi9peDbfkhKB5vdS1U3egjDDcDlLwBRwotxY/n5ece9Yh+pos+tmcXWhuFBL/heHPY9u1fptNTRXR18u3q9jSxCFukTjhgjDDcAl78AAGuJe8U+lKJPsShdGa/Ypa00zeHqpP/7aNm2pNrbKx26x2t/iJhInXAkDGG4AZJw+QsAUF9xrtjXvegzP+ftzFYZfEfPSXdu+7+P/W3VC9q6e6X97V4lOAa4ylw/hOEGiPvlLwAA1lLTos/01GKVtxx8x0d9z+7Vlqx0qMdrbegpBd+uI9L21Wf3xgFXmeuHMNwAcb/8BQDAWjZU9CnkpYmLy4Pvjev+v/COXYs9vT2lqm9Ht7QlefGGq8z1k7z/LREV58tfAACsZd2iz+xtafR8dfAdO+9/dm8qtTi7tzL47tnvvc8BXGWuH8IwAADYtEw6pVP3tulUa9oLu5/9/GLwnbzo/46amr22hsrg23lEatlav4OPAa4y1w9hGAAABLeQky6NVExyOOf9fWvG/33s2b8YeMt/twWf3esKrjLXB2EYAIAGWjor9oHeA/rnocvRnh1bnt1bGXwvXpDyC/4+P52WDvZ4Fd+ePi/4dvdKu/bU97gBHwjDAAA0yEqzYrdkUsotFDS/UAh/dmyhcHd2b2F4UFNnvqPm8QvafivAorat2xbDbjn4dt4jZZvqd9zAJhCGAQBokJVmxapiY7SGzo6dn/MWsVXN7j3vLXaTlJa0b737aG1fHnxb251Z1IZkIAwDAJwTZFvbWm6Bu9Ks2KXqMjv2xvXqvt6RIW92b9Hf7N55pTXc3Kpdx+5T27OeVQq+R6RtO2p3jEBICMMAAKcE2da21lvgrjQrdqlNzY4t5KXxseXBdzrI7N7durSzQ1+6tU2D2VYNNh3QaHaPCqmMXvPAMb36Bfdu7NiAiCIMAwlVy2oWkCRBtrWt9Ra4K82KXaln2Nfs2Nnbi4F39Jw0POgtags8u7die+KePmn3Pl14elL/85NfrQrtLWzwgIQiDAMJVOtqFpAkQba1rfUWuCvNii1Pk1h1dmyxKF27XNHXWwq+ly/5/8J3Z/dWBN+uI1Jzy4ofzgYPcAlhGEigWlezgCQJsq1tPbbAXWlW7N23F3LSWCnsjgxJo0Pev2/f9P8F9uwvBd6K4Nt2MNDsXjZ4gEsIw0AMBG15qHU1C0iSIFXPulZIb84sht1y8L04HHx2793gW9q1bWdtZveywQNcQRgGIm4jLQ/1qGYBSRGk6lmTCmmhIF0e98LuyKCKw4OaPzeg5plr/u9j6/bFKm85+B5idi9QC4RhIOI20vJAvx+wtiBVz0AV0rlZaezC3eCr4SGvx3fuzt0PSUlqXus+WjuWB9/9zO4F6oUwDETcRloe6PcDGuDGteoNK4aHpImxALN7MzrftF8Xmg/o6PPu15Hnfk9pdu/2Oh84Go3pPtFGGAYibqMtD/T7ATWSz0sTo8uD78yU//vYuVvq7tOT2qvPTGQ02NSqkexeFVJppSS9puuYjhxjfm8SMd0n+gjDQMTR8gA00J1bXltDZfAduyDl5v19fioltXdWLGgrTXTYvU9KpTR9dkJfXjK/l37+ZGO6T/QRhoGIo+UBqIO7s3sHK4LvULDZvc0tFbN7S393Hl51dq/Eya2LgrS60U4RDsIwQsEDPhhaHoBNyM1Ll0aWB98gs3v3tlYsaistbDtw0BtvFkDUTm55Lq4/v61utFOEhzCMhuMBD6Bubk4vtjeUQ++lYa/v149MRuro9rYlvrtTW6/X81sjfk5ug4bUjYRanosbw+/VANopwkMYRsPxgAewaYWC19KwNPhev+L/Prbt8NocKoPvwZ7QZ/cGDakbDbU8FzeG36sBbJYUHsIwGo4HPJAMDbvEPjcrjZ2vXtQ2es673a8DB5cH331tkZzdGzSkbjTU8lzcOH6uBrBZUngIw2g4HvBA/NXlEnuxuGR2byn4Tlz0PbtXW7JS12GvtaEcfLuOeDu4xUTQkLrRUMtzcbSwuDI8hGE0HA94IP42fYk9n5fGR5YE36Cze/dIPb3Vwbe9y+v7jbGgIXWjoZbn4miJ2uJKlxCG0XBJfcCzKhsuCVSNvF2e3VvR2zt2XlrI+ftiqbQ3u3dp8N29rzbfTMQEDakbDbVJfS6OMyYHhYMwHCKXw1PSHvCsyoZrVqxGbknreMu89NV/qA6+V8b933FzSynwloJvd5/Uec+as3uTJmhI3UyoTdpzMbARmw7DxphWSS+QdFvS31hrfc6vcRvhaVESTgpYlQ3XnLhnj168645So0PquTOpvtwV9S1c1bb3B1jUtrfVC7uVwfdAR+DZvUkUNKQSaoGN8x2GjTG/LOm1kv6VtfZa6bbnSvo/ksrXqr5ijHmxtfZWrQ80aQhPnqScFLAqG3G35knpzA1pdEgaXhxjlhkf0ZuDzO492LO4NXH5z454L9RKwok8gGCV4VdJKpaDcMlvS9or6UOS2iX9qKRfkvSemh1hQoUdnqLyJJ6UkwJWZSPOyielT41e1/47VzVauKbbTTN60e45pUY3MLu3vEPb3dm93aHP7q2FyufNI2079en+83oq5ifyAIKF4Xsl/WX5jVJ7xA9I+qC19g2l256Q9GoRhtcVZniKUjU27JOCWmFVNmJnbtZb1DY6pCvf/JZe953v6J75q9pa9LmoTfJm91ZuT9zdK+07EMnZvZu19HlzSyatfKGgQtF7f1xP5AEEC8P7JU1WvP19pb8/VXHb38trpcA6wgxPUarGJqWiyqpsRFZ5du/w4GKrw+iQNDHmvU/eZb01H/nZJqnzcHXw7Tocq9m9m7X0eTOXXz73OI4n8gCCheFrklor3v4BSQVJX664rSjJnSW/mxBmeIpSNTZJFVUWsCB0CwvSxOjy4Dtzw/ddXEtv01BTqy60HNB3P/+E7n3e/YmY3btZKz1vLhXHE3msLSothaivIGH4O5J+3Bjzq5Ly8nqI+6210xUfc1hSgBk6bgsrPEWpGktFtT7q8QTOi0LE3L5VCrwVwffihWCzezu6pO5eFbqO6ENP5/TYzFZNFFvunpS+/KUnJX7HklZ+3kylpGwmrdxCIdYn8lhZlFoKUV9BwvDvSfq0pFFJC5K2SXpr+Z3GmIyk56u6UowIilo1lopqbdXjCZwXhRAVi9LVCW9e7/Dg4uYVVyb830fzVqn7SPWitkOLs3vTkl5bKOpZnJSuaqXnzfsO7dbLTx7R+ckZfmYJFKWWQtSX7zBsrf0LY8wvSXp96aZHrbUfrfiQl8hrkfirGh4f6oBqbLLV4wmcF4UGyc171d2q4Dsk3QkwrXLfgeXTHFrXn93LSena1nrefPC+jrAPD3UQpZbCeuGKnyfQphvW2g9I+sAq7/sreWPWEAO88CVXPZ7AXXhRaLiZqcUd2srB99KwVFi+MGtFmS3SoZ6q4JvvPKL+S3ecf2GrF5433RKllsJ64IrfIrZjBmooCmfZ9XgCT/qLQl0V8tLkRWmk1N5QXtQ2ddX/fWzfuXyE2cFuaUv27ofwwgbUVtRaCmuNK36LVg3Dxpie0j/HrLX5irfXZa0d3vSRATETlTBSjyfwpL8o1MzsHWns3GLwHRnyKr7zc/7vo+3Q8uC7t3Xd2b28sAG1lfSWQq74LVqrMnxe3qi0Z0g6W/H2eorr3C8CikK1EeuLShipxxP4Svf5QO8Bd/9fFoteZXdksDr4Tl68O7t3XdkmqevI8tm9Lds2dEi8sAG1l+TWGK74LVortH5EXrC9seRtNFBUqo1YX5TCSD2ewCvv06n/lwsL0vjIkuB7Trrpf3bvna27NNdxj3bdd1zpnj4v+LYfktK1m93r54WNE2sAZVzxW7RqGLbWvnatt9EYUak2Yn0unWUn9v/l7ZuLi9pGhrzge3E42Ozeg11Sd58KnUf0x0/P67GZrZostqg5k9HxO3t0+nvrc8Kw3gubUycwANaV9DaQIGhniLgoVRuxNpfOsmP//7JY9Ob0ltsbysH36uT6n1vWsm1xdm/XEamnz5vd29QsSfrHsxP6zDe+qtli/U8YyhXfZ/fs0zO79yqTTulox+6qF7aknsBQ7QY2LsltIEH4DsPGmBdYa//ex8e92Vr7e5s7LJS5VG2MO5fOsmP1/zI3L41dqA6+o0PSndv+72Nfm9TTWx1897evObu3UScMq1V8H3r+vVX/92J/ArMCqt0AaiFIZfgLxph3WGvftdI7jTF7JX1Y0o/J260ONeBStTEJXDnLjuz/y+mpxSpvOfiOjwSc3XuPt6Ctp29xgdv2nYEPZa0ThlpWM/1WfGN1AuNTUqvdABorSBgekPQOY8wLJf2MtXa8/A5jzIOSPiapW9KnanqEjnOp2oj4CP3/ZSEvTVxcHnxvXPN/Hzt2SV2lSQ49vd6/l8zu3YzVThge6D1Q02qm34pvZE9gNiGJ1W4AjRckDD9X0h9I+llJXzXGvMZa+3+NMW+X9A5JeUlvtNbaOhyn01ypNiJeGvb/cvbO4rbEI6Wd2oLO7m3vLFV5+xaDr4/ZvZux2glDrauZfiu+oZ/A1EESq90AGs93GLbW3pb0c8aYz0t6n6TPGWOelPQseXOIX2Wt/UZ9DhNA4hWL0vUr1QvaRs8Fm93b1OyF3nLw7e7d1OzezVrphKHW1cwgFd+knVgnsdoNJEHcFrYGniZhrf2IMWanpPdKeraky5K+31p7udYHBwQRtwef0xYWpEvD1WPMRoekm9P+72P3vlLgraj4ttV2dm891LqamcSKr18uf+9AVMVxYWugMGyMSUt6p6S3Srop6RuSHpT0RWPMT1trv1n7QwTWF8cHnzNuzSyZ3TvkBWGfs3vzSmkku1fnm9t0q61bP/LSFyrT0yft2lPnA6+PelQzk1bxDcLl7x2IojgubA0yWq1b3iK5ByV9XV5bxNmKnuEnjDH/np5hhCGOD77EKRSkqxPS8OBipXd4SLoWYHbv1m13F7UNNrXqfd+6o7PpPcqlvKeqlnRG+5u6dCqmQViimgkg2eK4sDVIZfhrkvbKW0T3FmvtnCRZa99tjPk7eUH5vcaYl1hrf6L2hwqsLo4Pvlibn5MuXqgOviPnpNkAs3v3ty329XaXZvi2tt9d1Pb4Y0/ryczZqj3gk/I7pZoJIKniuLA1SBhOS3qltfaTS99hrf2yMeY5kj4k6WW1OjjArzg++GLjxvXFKu/IoPfvS6NS0efs3i1Z6VBPdfDtOrLu7F5+pwBWwxqR6IrjwtYgYfh+a+351d5prZ2S9ApjzBs3fVQxxgM0HJt98PF7kze7d3xsMfiOlsLvjev+72PHrsUqbzn4dnRLW4Lv/B7HJ1QA9ccakWiLYytYquh3ZFENGWOKkpS09mIeoOEqB9qgDz4nf2+zt722htGKRW1j5/3P7k2lvMkNS4Pvnv01nd270d8pgOR6/OyE3v3Jr1ZdNWrJZvT2n7if1iOsZdUXj+DlGqyKRVzh2mgfZpDfW+wqyKXZvfkLA7r49W+qODykA9OXtHVqwv99lGf33g2+R6TOI1LL1voddwm9tQCWYo0Iai3oaLWUpFdK+mFJnZKaV/iworX2B2twbLHDAzSe/P7eIl9BXshJl0a8RW2VFd9bM8rI2yt9XXv2Vy9o6z4Si9m9ANzBegLUWpDRas2SPivphfJKzUVVl5yLFbc7Ka4P0NhVO2vM7+8tUpX/mzMVgbc00eHisJRf8PXpeaU019qpbUePVYTfXmlnfEeWAXAD6wlQa0Eqw2+V9CJ5m278N3k7z/2GpA/IC8j/WdKXJf1sTY8wRuL4AI18tbMB/P7e1qsg1+WkolCQroxXb1E8MiRd87/h43y2RWfS+zTYdEBDTa0ayrZquGmfHnrRM/XqF9y7ueMDgAaL4wItRFuQMPyTkv7ZWvvrkmSMkSRZa8clfdwY84/yZhH/W0nvqfFxxkIcH6CRqnaGxO/vba0Kck1OKubnvEVslaF35Jw0d8f/N9ParmJXr0a3t2so26pd9x3XnR379Vt//vVli02ifsUCAFbDegLUUpAw3CfpDyveLkrKlt+w1g4ZY/5S0mvlaBiW4vcApc/Z4+f3tlYFOfBJxY1ry7coHg86u/ceqadimkPXEeVbtleH8tFR3dd5U/cd2q2nLt6IzRULAAAaJUgYzkmarXh7RtKBJR9zQdJLN3tQaJy49jmHYa0K8monFecuXdepHbPLg+90kNm9u72w29PrbVXc0ye1d604u7f/7MSyUP7U2JTe+orvUTqVis0VCwAAGiVIGB6VN0Gi7Kykf7HkY+6XdG2zB4XGiWOfc5hWqyD3dezSnsyCDt2aVG/uivrmL6svd1VHP3bNm/LgRyoltXeWAm9F8N29z/fs3tVC+fnJGb36Bfc6Ve1HPLi+gBdA+IKE4S9JeknF25+W9C5jzB9J+qS8RXQvkfQnNTs61F1Yfc6xfgEsFr0FbHf7eod0cmRIH798yf99NDWXWhsqgm/XEam5ZVOHRqUfccICXgBRECQM/4mkbmPM4dK2zL8r6WWSXievTzglaUDS22p8jNiAIGGz0X3OsXoBXMh5I8tGBr3FbOUAfPtm1YetedR7W5cH37aDdZndS6UfccICXgBR4DsMW2u/KOmLFW/fNsZ8n7xAfFTSeUmfsdberu0hIqioh83IvgDenK6Y5FAKvpdGfM/uVSYjdXR7rQ2VwXfn7voed+UhxHCiCdzFAl4AUbCp7ZittQuS/qxGx4IaiWzYLAn9BbBQkC6Pe2F3dEgaLgXg61f838fW7aVFbRXB92CPlG2q33H7FLeJJo0S69achKKtB0AUbCoMI5pCD5vraOgL4NysNHahOviOBpvdW2zt0PW9nRrZ1q6W3nt19Hn3K9Pa7ntRG8IX9aslrqKtB0AUEIYDiEtlKerVlrq8ABaL3uze0XPScEXwnRgLNru383BVxTd/6LAe+dS3vGOdyqv5mykdv3Zepx9uVyZ6v3qsIupXS1xFWw+AKCAM+xSnylLUqy2bfgHM56XxkeXBd2bK/0Hs3L24WUVPnzfJoaPb6/utsNLcXr8hKi4nTy6I+tUSl9HWAyBshGGf4lRZikO1xfcL4O1bXugdHVoMvmMXpNy8vy+USnkbVHT3Vv/xObt3oyEqTidPLoj61RIAQHgIwz7FrbIUu2pLsShdmyz19JaD7zkpyOze5hZvMVtl6O08vKnZvRsNUXE6eXJB1K+WAADCQxj2icpSDeXmpUvDi1sTl4Pvktm9a9rbWmpzOLLY7nDgoJRO1/RQNxqi4nbylHRxuFoCAAiH7zBsjGmz1k7W82CijMrSBs3c8Cq9lcF3fMTr+/Ujk/FGli0NvjsacxKy0RDFyVP0xO5qCQCgIYJUhkeMMZ+W9H5r7RfqdUBRRWVpHYWC19IwMrjY6jAyFGx277YdpfaGiuB7sDv02b0bCVGcPAEAEA9BwvBZST8p6ZXGmEFJ75f0YWvt1bocWQRRWSqZm5XGzlfv1DZ6zrvdrwMHlyxq65P2HUjM7F5OngAAiIdUsVj0/cHGmAclvV5eKN4qaU7SJ+VVix8LcD9FSbLWBjpYNFh5du/SLYonxrz3+ZFtkjrvWWxv6M+scQkAABEGSURBVO71xpht3V7fYwcAAFi0ajUqUBguM8bslvQaecH4WZKK8irH/13SR6y119f5fMLwKkKbTbuwIE2MLg++Mzf838fOPd62xJXBt71r2exeAACABqttGK5Uqhb/oqSfktQir1r8vyT9vrX2K6t8DmF4BQ2bTXv7VsWitlLwHTsvLeT8fX4qLXV0VS9oK8/uBQAAiJ5Vg1QtRqtdlXRd0qy81okmeVXjnzXGfEbSz1trr9Xg6yRezWfTFovS1YnFSQ7lP1fG/d9H89ZS6C1VfLt6vbaHTczuBQAAiIoNhWFjTFbSv5b0BknfLy9tn5X0TkkflvQ9kv6DpJdKep+kh2pwrJFVq9aGTc2mzc1LFy8stjeUg++dW/4PYN+B6gVtXb3SgY6az+4FEC1sHQ7AZYHCsDHmqLw+4ddK2i8pL+nTkqy19vMVH/pFSV80xvyppB+pyZFGVC1bG3zPpp2ZKoXdiuAbaHbvFulQz+JubT193qK2Bs3uBRAdbB0OwHVBNt34G0kvklcFviivCvwBa+3FNT7tnyS9YlNHGHG1bG1YOpt265aUHty7oOdNnZE++bnF4DsVYJrdth1e2O3u9cJvT2l275ZsoGMDkExsHQ7AdUEqwy+W9LeSrKRPW2v9lCE/Iy84J1bNtt2dm1Vm9Jze3XVFl298W5mxc9o7dVGZwXmp3+d9HDi4WOXt7vP+vbc1MbN7AdQeW4cDcF2QMPwMa+1TQe7cWvstSd8KdkjxEnjb3WLRq+xWLWoblCYvSsWi0pLWe/kpZpt0a3+nLu08qC339Knngeco083sXiQLfayNwdbhAFznOwwHDcKuWHPb3YUFr5d36TSHmwFm9+7eW+rt9bYoznf16tc+P6onL85obj6v5vMZHc/d1Omj28Q0XyQFfayNw9bhAFxXi9FqTitvu/vP3zqnqaee0r0Ll9Vz59tKv+uj3nSHILN7D3ZVB9/OI+q/vFBVGesfmNSTF2fo70Oi0cfaOGwdDsB1hOGgikXpyoS3acWwt6AtMzqkE1cm/N9HyzZvdm95mkN3r9R5WGpqvvshq1XGnt2zj/4+JB59rI2VSad06lg7P1sATiIMryU3L41dqAq+Gj0XcHZvm7dFcWXwbV1/du9qlbFndu+lvw+JRx8rAKBRCMNlM1PS8FB18B0fkQoFf5+f2SIduqd6i+KuXmnHzg0dzmqVsUw6RX9fBFQu7jrStlNKSecmZljoVSP0sQIAGsW9MFzIe5Mb7gbf0jSHGwF2jN6+825f793gW+PZvatVxo527NZDz7+X/r4QVbawzObySqW84dvFoljoVSP0sQIAGsWdMDw3K73nbV6bw/yc/89rO1S9RXF3b0Nm965VGaO/L1xLW1iKRalYeh8LvWqH/+cAgEZwJww3t0hXJ1cPwk3N3iK2yuDbddhb7BYCKmPRtVILSyUWegEAEB/uhGHJC7g3rkm791WE3lLwbT8kpaM1qZfKWDSt1MJSiYVeAADEh1th+KFfllre4m1kAWxQZQvLaj3DLPTCethhDwCiwa0w3H4o7CNYhhfE+FnawnL4gDdN4vzkDO0s8IUd9gAgOtwKwxHDC2J8rdTC8uB9HSEeEeKEHfYAIDrW3vkBdVX5glhU9QsigORaa4c9AEBjEYZDxAsi4KbyIsxKLLwEgHAQhkPECyLgpvIizJZsRilJLSy8BIDQ0DO8AbVa9MaWs4CbmCMOANFBGA6oloveeEFkmgbcxRxxAIgGwnBAtV4F7vILItM0AABA2OgZDohFb7XDNA0AABA2wnBASV30li8U9fjZCT362NN6/OyE8oVi3b8mJxYAACBstEkElMRFb2G1K5RPLGYrAnESTiwAAEB8EIYDSuKit7B2w0riiQUAAIgXwvAGJG3R21rtCvX8HpN4YgEAAOKFMIxQ2xWSdmIBAADihQV0YDcsAADgLCrDoF0BAAA4izAMSbQrAAAAN9EmAQAAAGdRGYZv+UJR/QOTGhyfVl8HrRRAVPDYBICNIwzDl7A25gCwNh6bALA5tEmEKIwtkDeqcmOOoqo35gAQHh6bALA5VIZDErdqTlgbcwBYG49NANgcKsMhiVs1p7wxR6VGbcwBYHU8NgFgcwjDIVmrmhNFbMwBRBOPTQDYHNokQhLmFsgbwcYcwbm8wn+l712Ssz+PeuKxCQCbQxgOSbmas7RnOMrVHDbm8C9uPeG1tNL3ft+h3VIqpacc/Hk0Ao9NANg4wnBIqOYkW2VPuFTdE570wLLS9/7k6JRSKWl+oXD3Nld+HgCAaKNnOETlas6rX3CvTh1rJwgnSNx6wmtppe89ly/cDcJlrvw8AADRRhgG6sDlFf4rfe/ZTFpNW6qfblz5eQAAoo0wDNSByyv8V/ren9m1R8/o2uvkzwMAEG30DAN14HJP+GrfuyQnfx4AgGhLFYuN3wLYGFOUJGttw782AAAAnLNq9YU2CQAAADiLMAwAAABnEYYBAADgLMIwAAAAnEUYBgAAgLMIwwAAAHAWYRgAAADOIgwDAADAWYRhAAAAOIswDAAAAGcRhgEAAOCsLWEfAIDNyReK6h+Y1OD4tPo6dunE0TZl0qtuwQ4AACoQhhuAsIJ6yReKeuTRJ3RmbEpzubyasxkd79yj0w+f5P8YAAA+EIbrjLCCeuofmNSZsSnN5vKSpNlcXmfGptQ/MKlTx9pDPjoAAKKPnuE6qwwrRVWHFWCzBsenNVcKwmVzubyGJqZDOiIAAOKFMFxnhBXUU1/HLjVnM1W3NWcz6m3fFdIRAQAQL4ThOiOsoJ5OHG3T8c49aslmlJLUUmrDOXG0LexDAwAgFugZrrNyWFnaM0xYQS1k0imdfvik+gcmNTQxrd52FmgCABAEYbjOCCuot0w6pVPH2lkwBwDABhCGG4CwAgAAEE30DAMAAMBZhGEAAAA4izAMAAAAZxGGAQAA4CzCMAAAAJxFGAYAAICzCMMAAABwFmEYAAAAzmLTDWxIvlBU/8CkBsen1dfBrnoAACCeCMMILF8o6pFHn9CZsSnN5fJqzmZ0vHOPTj98kkAMAABihTYJBNY/MKkzY1OazeVVlDSby+vM2JT6BybDPjQAAIBACMMIbHB8WnO5fNVtc7m8hiamQzoiAACAjSEMI7C+jl1qzmaqbmvOZtTbviukIwIAANgYwjACO3G0Tcc796glm1FKUkupZ/jE0bawDw0AACAQFtAhsEw6pdMPn1T/wKSGJqbV2840CQAAEE+EYWxIJp3SqWPtOnWsPexDAQAA2DDaJAAAAOAswjAAAACcRRgGAACAswjDAAAAcBZhGAAAAM4iDAMAAMBZhGEAAAA4izAMAAAAZxGGAQAA4CzCMAAAAJxFGAYAAICzCMMAAABwFmEYAAAAziIMAwAAwFmEYQAAADiLMAwAAABnEYYBAADgrC1hH0Ac5AtF9Q9ManB8Wn0du3TiaJsy6VTYhwUAAIBNIgyvI18o6pFHn9CZsSnN5fJqzmZ0vHOPTj98kkAMAAAQc7RJrKN/YFJnxqY0m8urKGk2l9eZsSn1D0yGfWgAAADYJMLwOgbHpzWXy1fdNpfLa2hiOqQjAgAAQK0QhtfR17FLzdlM1W3N2Yx623eFdEQAAACoFcLwOk4cbdPxzj1qyWaUktRS6hk+cbQt7EMDAADAJrGAbh2ZdEqnHz6p/oFJDU1Mq7edaRIAAABJQRj2IZNO6dSxdp061h72oQAAAKCGaJMAAACAswjDAAAAcBZhGAAAAM4iDAMAAMBZhGEAAAA4izAMAAAAZxGGAQAA4CzCMAAAAJxFGAYAAICzCMMAAABwFmEYAAAAziIMAwAAwFlbwj4ARE++UFT/wKQGx6fV17FLJ462KZNOhX1YAAAANUcYRpV8oahHHn1CZ8amNJfLqzmb0fHOPTr98EkCMQAASBzaJFClf2BSZ8amNJvLqyhpNpfXmbEp9Q9Mhn1oAAAANUcYRpXB8WnN5fJVt83l8hqamA7piAAAAOqHMIwqfR271JzNVN3WnM2ot31XSEcEAABQP4RhVDlxtE3HO/eoJZtRSlJLqWf4xNG2sA8NAACg5lhAhyqZdEqnHz6p/oFJDU1Mq7edaRIAACC5CMNYJpNO6dSxdp061h72oQAAANQVbRIAAABwFmEYAAAAziIMAwAAwFmEYQAAADiLMAwAAABnEYYBAADgLMIwAAAAnEUYBgAAgLMIwwAAAHBWqDvQGWPC/PIAAABwQ9Fam1rpHVSGAQAA4KxUsVgM+xgAAACAUFAZBgAAgLMIwwAAAHBWqAvoAACNY4z5sKSfk3TEWns+3KMBgGigMgwAAABnEYYBwB1vl/QMSWNhHwgARAXTJAAAAOAseoYBYBOMMZ+W9DJJb7LWvnfJ+94p6dck/ZG19hd83NeLJD0k6fmSuiRlJQ1K+t+SfstaO1vxsUckfVVSQdL91toLFe/bLukrko5JerG19u9Kt39YK/QMG2NeKunNkp4paZ+kq5KelvQJa60N8OMAgNihTQIANufnJQ1L+m1jzP3lG40xPyjpEUlPSnqTz/t6q6R/Kelrkt4v6YOS5iX9hqTPGWMy5Q+01p6T9AuS9kr6mDGmsrhhJR2X9JvlILwaY8zrJf25vCD8GUnvkfRZSVslvc7ncQNAbFEZBoBNsNZeM8Y8JOnvJH3CGPOApG2SPippTtJPWWtv+7w7I+mctbaqf62iwvxKSZ+o+Np/aoz5A0m/LOmdkt5ujHmNpNdI+mLptvW8QV7gfo61dnLJ1231edwAEFtUhgFgk6y1X5b0HyXdK6+i+1FJHfJaJ74d4H6Glgbhkt8t/f3DK7zvLZK+Lumtxpg3yqsKX5b0sLW24PNLL0jKrXA8V3x+PgDEFpVhAKiN35L0QkmvLr39MWvtB4PcQanX982SXiGv33enpFTFh3Qu/Rxr7awx5lXyeoTfK6ko6ZXW2os+v+yj8lojvm2M+YS8CveXrLWXgxw7AMQVlWEAqIFSRfdTFTf97mofuxJjTFbSFyT9J0kt8toh3i3pHaU/ktS8yqeflfSN0r+flPTXfr+utfa/yltUNyyvt/lTkiaMMX9rjPneIN8DAMQRYRgAasAYc6+k35F0Xd6Ehw8aY1oC3MXLJD1P0v+w1n6Xtfb11tpftdb+hrzWi7W8TdKDkq5Iepa8ecK+WWs/Yq09JWm/pB+V9EeSvl/SXxlj2oLcFwDEDWEYADbJGNMsr5K7XdJPy6vofpeCVYePlv7+sxXe9wNrfO0HJf2mpKckPbv09zuMMc8P8LUlSdbaKWvtZ621vyjpw/LGrL0g6P0AQJwQhgFg835H0v2S/ou19q8l/bqkL0l6gzHmp3zex/nS3y+svNEY0yuvH3kZY8xeSR+TlJf009baCUmvkrcg7mPGmP3rfVFjzI8sGctWVq4I+52EAQCxxAI6ANgEY8zLJb1R0hPyxp/JWpsvjVv7mqQ/NMZ8xVo7tM5dfUbSgKS3GGO+S96GGj2SfkzSX5b+vdQfl25/k7X2a6Wv/XVjzK9I+n1JH5L00nW+7sclzRpj/p+8QJ6SVw0+IemfJP3NOp8PALFGZRgANsgY0yMvkN6Q9JC1dqH8PmvtiLwNOXZJ+rgxpmmt+7LW3pL0Ykl/Iq/v902SvlverOCfWeFr/xtJL5f0F0t3vrPWvk/eQrgfN8b8u3W+jbdJ+gdJD8ibc/w6eTvfvVXSi6y1y0auAUCSpIrFlUZaAgAAAMlHZRgAAADOIgwDAADAWYRhAAAAOIswDAAAAGcRhgEAAOAswjAAAACcRRgGAACAswjDAAAAcBZhGAAAAM4iDAMAAMBZ/x8fKEfKQuro5wAAAABJRU5ErkJggg==\n",
      "text/plain": [
       "<Figure size 864x432 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "Xd = np.array([[1,xmin], [1,xmax]])\n",
    "Yd = Xd @ theta_hat\n",
    "\n",
    "fig, ax = plt.subplots()\n",
    "fig.set_size_inches(width,height)\n",
    "ax.plot(X[:,1], Y, \".\")\n",
    "ax.plot(Xd[:,1], Yd, \"-\")\n",
    "ax.tick_params(axis='both', which='both', bottom=False, left=False, labelbottom=False, labelleft=False)\n",
    "ax.set_xlabel('x axis')\n",
    "ax.set_ylabel('y axis')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "<img width=\"80px\" src=\"../fidle/img/00-Fidle-logo-01.svg\"></img>"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "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.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}