{
 "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 --> Low-level implementation, using numpy, of a direct resolution for a 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",
       "div.todo:before { content:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI1My44OTEyIiBoZWlnaHQ9IjE0My4zOTAyIiB2aWV3Qm94PSIwIDAgNTMuODkxMiAxNDMuMzkwMiI+PHRpdGxlPjAwLUJvYi10b2RvPC90aXRsZT48cGF0aCBkPSJNMjMuNDU2OCwxMTQuMzAxNmExLjgwNjMsMS44MDYzLDAsMSwxLDEuODE1NywxLjgyNEExLjgyMDksMS44MjA5LDAsMCwxLDIzLjQ1NjgsMTE0LjMwMTZabS0xMC42NjEyLDEuODIyQTEuODI3MiwxLjgyNzIsMCwxLDAsMTAuOTgsMTE0LjMsMS44MiwxLjgyLDAsMCwwLDEyLjc5NTYsMTE2LjEyMzZabS03LjcwNyw0LjU4NzR2LTVzLjQ4NjMtOS4xMjIzLDguMDIxNS0xMS45Njc1YTE5LjIwODIsMTkuMjA4MiwwLDAsMSw2LjA0ODYtMS4yNDU0LDE5LjE3NzgsMTkuMTc3OCwwLDAsMSw2LjA0ODcsMS4yNDc1YzcuNTM1MSwyLjgzNDcsOC4wMTc0LDExLjk2NzQsOC4wMTc0LDExLjk2NzR2NS4wMjM0bC4wMDQyLDcuNjgydjIuNGMuMDE2Ny4xOTkyLjAzMzYuMzkyMS4wMzM2LjU4NzEsMCwuMjEzOC0uMDE2OC40MTA5LS4wMzM2LjYzMzJ2LjA1ODdoLS4wMDg0YTguMzcxOSw4LjM3MTksMCwwLDEtNy4zNzM4LDcuNjU0N3MtLjk5NTMsMy42MzgtNi42OTMzLDMuNjM4LTYuNjkzNC0zLjYzOC02LjY5MzQtMy42MzhhOC4zNyw4LjM3LDAsMCwxLTcuMzcxNi03LjY1NDdINS4wODQzdi0uMDU4N2MtLjAxODktLjIyLS4wMjk0LS40MTk0LS4wMjk0LS42MzMyLDAtLjE5MjkuMDE2Ny0uMzgzNy4wMjk0LS41ODcxdi0yLjRtMTguMDkzNy00LjA0YTEuMTU2NSwxLjE1NjUsMCwxLDAtMi4zMTI2LDAsMS4xNTY0LDEuMTU2NCwwLDEsMCwyLjMxMjYsMFptNC4wODM0LDBhMS4xNTk1LDEuMTU5NSwwLDEsMC0xLjE2MzYsMS4xN0ExLjE3NSwxLjE3NSwwLDAsMCwyNy4yNjE0LDEyNC4zNzc5Wk05LjM3MzksMTE0LjYzNWMwLDMuMTA5MywyLjQxMzIsMy4zMSwyLjQxMzIsMy4zMWExMzMuOTI0MywxMzMuOTI0MywwLDAsMCwxNC43MzQ4LDBzMi40MTExLS4xOTI5LDIuNDExMS0zLjMxYTguMDc3Myw4LjA3NzMsMCwwLDAtMi40MTExLTUuNTUxOWMtNC41LTMuNTAzMy05LjkxMjYtMy41MDMzLTE0Ljc0MTEsMEE4LjA4NTEsOC4wODUxLDAsMCwwLDkuMzczOSwxMTQuNjM1WiIgc3R5bGU9ImZpbGw6IzAxMDEwMSIvPjxjaXJjbGUgY3g9IjMzLjE0MzYiIGN5PSIxMjQuNTM0IiByPSIzLjgzNjMiIHN0eWxlPSJmaWxsOiMwMTAxMDEiLz48cmVjdCB4PSIzNS42NjU5IiB5PSIxMTIuOTYyNSIgd2lkdGg9IjIuMDc3IiBoZWlnaHQ9IjEwLjU0NTgiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDIxLjYgMjQxLjExMjEpIHJvdGF0ZSgtMTU1Ljc0NikiIHN0eWxlPSJmaWxsOiMwMTAxMDEiLz48Y2lyY2xlIGN4PSIzOC44NzA0IiBjeT0iMTEzLjQyNzkiIHI9IjIuNDA4NSIgc3R5bGU9ImZpbGw6IzAxMDEwMSIvPjxjaXJjbGUgY3g9IjUuMjI0OCIgY3k9IjEyNC41MzQiIHI9IjMuODM2MyIgc3R5bGU9ImZpbGw6IzAxMDEwMSIvPjxyZWN0IHg9IjEuNDE2NCIgeT0iMTI0LjYzMDEiIHdpZHRoPSIyLjA3NyIgaGVpZ2h0PSIxMC41NDU4IiB0cmFuc2Zvcm09InRyYW5zbGF0ZSg0LjkwOTcgMjU5LjgwNikgcm90YXRlKC0xODApIiBzdHlsZT0iZmlsbDojMDEwMTAxIi8+PGNpcmNsZSBjeD0iMi40MDkxIiBjeT0iMTM3LjA5OTYiIHI9IjIuNDA4NSIgc3R5bGU9ImZpbGw6IzAxMDEwMSIvPjxwYXRoIGQ9Ik0xOC4wNTExLDEwMC4xMDY2aC0uMDE0NlYxMDIuNjFoMi4zdi0yLjQyNzlhMi40MjI5LDIuNDIyOSwwLDEsMC0yLjI4NTQtLjA3NTVaIiBzdHlsZT0iZmlsbDojMDEwMTAxIi8+PHBhdGggZD0iTTM5LjQyMTQsMjcuMjU4djEuMDVBMTEuOTQ1MiwxMS45NDUyLDAsMCwwLDQ0LjU5NTQsNS43OWEuMjQ0OS4yNDQ5LDAsMCwxLS4wMjM1LS40MjI3TDQ2Ljc1LDMuOTUxNWEuMzg5Mi4zODkyLDAsMCwxLC40MjYyLDAsMTQuODQ0MiwxNC44NDQyLDAsMCwxLTcuNzU0MywyNy4yNTkxdjEuMDY3YS40NS40NSwwLDAsMS0uNzA0Ny4zNzU4bC0zLjg0MTktMi41MWEuNDUuNDUsMCwwLDEsMC0uNzUxNmwzLjg0MTktMi41MWEuNDUuNDUsMCwwLDEsLjY5NDYuMzc1OFpNNDMuMjMsMi41ODkyLDM5LjM4NzguMDc5NGEuNDUuNDUsMCwwLDAtLjcwNDYuMzc1OHYxLjA2N2ExNC44NDQyLDE0Ljg0NDIsMCwwLDAtNy43NTQzLDI3LjI1OTEuMzg5LjM4OSwwLDAsMCwuNDI2MSwwbDIuMTc3Ny0xLjQxOTNhLjI0NS4yNDUsMCwwLDAtLjAyMzUtLjQyMjgsMTEuOTQ1MSwxMS45NDUxLDAsMCwxLDUuMTc0LTIyLjUxNDZ2MS4wNWEuNDUuNDUsMCwwLDAsLjcwNDYuMzc1OGwzLjg1NTMtMi41MWEuNDUuNDUsMCwwLDAsMC0uNzUxNlpNMzkuMDUyMywxNC4yNDU4YTIuMTIwNiwyLjEyMDYsMCwxLDAsMi4xMjA2LDIuMTIwNmgwQTIuMTI0LDIuMTI0LDAsMCwwLDM5LjA1MjMsMTQuMjQ1OFptNi4wNzMyLTQuNzc4MS44MjU0LjgyNTVhMS4wNTY4LDEuMDU2OCwwLDAsMSwuMTE3NSwxLjM0MjFsLS44MDIsMS4xNDQyYTcuMTAxOCw3LjEwMTgsMCwwLDEsLjcxMTQsMS43MTEybDEuMzc1Ny4yNDE2YTEuMDU2OSwxLjA1NjksMCwwLDEsLjg3NTcsMS4wNHYxLjE2NDNhMS4wNTY5LDEuMDU2OSwwLDAsMS0uODc1NywxLjA0bC0xLjM3MjQuMjQxNkE3LjExLDcuMTEsMCwwLDEsNDUuMjcsMTkuOTNsLjgwMTksMS4xNDQyYTEuMDU3LDEuMDU3LDAsMCwxLS4xMTc0LDEuMzQyMmwtLjgyODguODQ4OWExLjA1NywxLjA1NywwLDAsMS0xLjM0MjEuMTE3NGwtMS4xNDQyLS44MDE5YTcuMTMzOCw3LjEzMzgsMCwwLDEtMS43MTEzLjcxMTNsLS4yNDE2LDEuMzcyNGExLjA1NjgsMS4wNTY4LDAsMCwxLTEuMDQuODc1N0gzOC40Njg0YTEuMDU2OCwxLjA1NjgsMCwwLDEtMS4wNC0uODc1N2wtLjI0MTYtMS4zNzI0YTcuMTM1NSw3LjEzNTUsMCwwLDEtMS43MTEzLS43MTEzbC0xLjE0NDEuODAxOWExLjA1NzEsMS4wNTcxLDAsMCwxLTEuMzQyMi0uMTE3NGwtLjgzNTUtLjgyNTVhMS4wNTcsMS4wNTcsMCwwLDEtLjExNzQtMS4zNDIxbC44MDE5LTEuMTQ0MmE3LjEyMSw3LjEyMSwwLDAsMS0uNzExMy0xLjcxMTJsLTEuMzcyNC0uMjQxNmExLjA1NjksMS4wNTY5LDAsMCwxLS44NzU3LTEuMDRWMTUuNzgyNmExLjA1NjksMS4wNTY5LDAsMCwxLC44NzU3LTEuMDRsMS4zNzU3LS4yNDE2YTcuMTEsNy4xMSwwLDAsMSwuNzExNC0xLjcxMTJsLS44MDItMS4xNDQyYTEuMDU3LDEuMDU3LDAsMCwxLC4xMTc1LTEuMzQyMmwuODI1NC0uODI1NEExLjA1NjgsMS4wNTY4LDAsMCwxLDM0LjMyNDUsOS4zNmwxLjE0NDIuODAxOUE3LjEzNTUsNy4xMzU1LDAsMCwxLDM3LjE4LDkuNDUxbC4yNDE2LTEuMzcyNGExLjA1NjgsMS4wNTY4LDAsMCwxLDEuMDQtLjg3NTdoMS4xNjc3YTEuMDU2OSwxLjA1NjksMCwwLDEsMS4wNC44NzU3bC4yNDE2LDEuMzcyNGE3LjEyNSw3LjEyNSwwLDAsMSwxLjcxMTIuNzExM0w0My43NjY2LDkuMzZBMS4wNTY5LDEuMDU2OSwwLDAsMSw0NS4xMjU1LDkuNDY3N1ptLTIuMDMsNi44OTg3QTQuMDQzMyw0LjA0MzMsMCwxLDAsMzkuMDUyMywyMC40MWgwQTQuMDQ2NSw0LjA0NjUsMCwwLDAsNDMuMDk1NSwxNi4zNjY0WiIgc3R5bGU9ImZpbGw6I2UxMjIyOSIvPjxwb2x5Z29uIHBvaW50cz0iMzkuNDEzIDM0Ljc1NyAzOS41MzcgMzQuNzU3IDM5LjY3NSAzNC43NTcgMzkuNjc1IDEwOS41MSAzOS41MzcgMTA5LjUxIDM5LjQxMyAxMDkuNTEgMzkuNDEzIDM0Ljc1NyAzOS40MTMgMzQuNzU3IiBzdHlsZT0iZmlsbDpub25lO3N0cm9rZTojOTk5O3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1taXRlcmxpbWl0OjEwO3N0cm9rZS13aWR0aDowLjMwODg1NDQ1MDU2MDE2MThweDtmaWxsLXJ1bGU6ZXZlbm9kZCIvPjwvc3ZnPg==);\n",
       "    float:left;\n",
       "    margin-right:20px;\n",
       "    margin-top:-20px;\n",
       "    margin-bottom:20px;\n",
       "}\n",
       "div.todo{\n",
       "    font-weight: bold;\n",
       "    font-size: 1.1em;\n",
       "    margin-top:40px;\n",
       "}\n",
       "div.todo ul{\n",
       "    margin: 0.2em;\n",
       "}\n",
       "div.todo li{\n",
       "    margin-left:60px;\n",
       "    margin-top:0;\n",
       "    margin-bottom:0;\n",
       "}\n",
       "\n",
       "div .comment{\n",
       "    font-size:0.8em;\n",
       "    color:#696969;\n",
       "}\n",
       "\n",
       "\n",
       "\n",
       "</style>\n",
       "\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/markdown": [
       "<br>**FIDLE 2020 - Practical Work Module**"
      ],
      "text/plain": [
       "<IPython.core.display.Markdown object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Version              : 1.2b1 DEV\n",
      "Notebook id          : LINR1\n",
      "Run time             : Sunday 10 January 2021, 21:51:29\n",
      "TensorFlow version   : 2.2.0\n",
      "Keras version        : 2.3.0-tf\n",
      "Datasets dir         : /home/pjluc/datasets/fidle\n",
      "Run dir              : ./run\n",
      "Update keras cache   : False\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 pwk\n",
    "\n",
    "datasets_dir = pwk.init('LINR1')"
   ]
  },
  {
   "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",
    "pwk.save_fig('01-set_of_points')\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",
      " [[3.60312881]\n",
      " [1.99988269]]\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": "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\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",
    "pwk.save_fig('02-regression-line')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "End time is : Sunday 10 January 2021, 21:51:29\n",
      "Duration is : 00:00:00 308ms\n",
      "This notebook ends here\n"
     ]
    }
   ],
   "source": [
    "pwk.end()"
   ]
  },
  {
   "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.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}