{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# linear Regression\n",
    "    linear regresssion is a regression problem in which we try to predict through the bestfit line \n",
    "    \n",
    "![Linear Regression](linearRegression.png)\n",
    "\n",
    "[linear regression from scratch](https://towardsdatascience.com/linear-regression-using-python-b136c91bf0a2)\n",
    "\n",
    "[to know more click here](https://towardsdatascience.com/an-intuitive-perspective-to-linear-regression-32bb9885b312)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "# imports \n",
    "\n",
    "class LinearRegressionUsingGD:\n",
    "    \"\"\" Linear Resgression using Gradient descent.\n",
    "    \n",
    "    Parameters:\n",
    "    -----------\n",
    "    eta : float \n",
    "          Learning rate\n",
    "    n_iterations : int\n",
    "          Number of passes over training set\n",
    "          \n",
    "    Attributes:\n",
    "    -----------\n",
    "    w_ : weight/after fitting the model\n",
    "    cost_ : total error of model after each iteration\n",
    "    \n",
    "    \"\"\"\n",
    "    def __init__(self, eta = 0.05 , n_iterations = 1000):\n",
    "        self.eta = eta \n",
    "        self.n_iterations = n_iterations\n",
    "    \n",
    "    def fit(self , x , y):\n",
    "        \"\"\" fit the training data\n",
    "        \n",
    "        Parameters:\n",
    "        -----------\n",
    "        x : array-like , shape = [n_samples , n_features]\n",
    "            Training samples\n",
    "        y : array-like , shape = [n_samples , n_features]\n",
    "            Target values\n",
    "            \n",
    "        Returns:\n",
    "        --------\n",
    "        self : object\n",
    "        \n",
    "        \"\"\"\n",
    "        \n",
    "        self.cost_ = []\n",
    "        self.w_ = np.zeros((x.shape[1] , 1))\n",
    "        m = x.shape[0]\n",
    "        \n",
    "        for _ in range(self.n_iterations):\n",
    "            y_pred = np.dot(x , self.w_)\n",
    "            residuals = y_pred - y\n",
    "            gradient_vector = np.dot(x.T , residuals)\n",
    "            self.w_ -= (self.eta /m) * gradient_vector\n",
    "            cost = np.sum((residuals ** 2)) / (2*m)\n",
    "            self.cost_.append(cost)\n",
    "        return self\n",
    "    \n",
    "    def predict(self , x):\n",
    "        \"\"\" Predict the values after the model is trained \n",
    "        \n",
    "        Parameters:\n",
    "        -----------\n",
    "        x = array-like , shape = [n_samples , n_features]\n",
    "            Test samples\n",
    "            \n",
    "        Returns:\n",
    "        Predicted values\n",
    "        \n",
    "        \"\"\"\n",
    "        return np.dot(x , self.w_)\n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "# # Evaluate the performance of model we use RMSE\n",
    "# # mean square error\n",
    "# mse = np.sum((y_pred - y_actual)**2)\n",
    "\n",
    "# # root mean square error\n",
    "# rmse = np.sqrt(mse/m)\n",
    "\n",
    "import numpy as np\n",
    "class PerformanceMetrics:\n",
    "    \"\"\" Defines methods to evaluate the model\n",
    "    \n",
    "    Parameters:\n",
    "    -----------\n",
    "    y_actual : array-like , shape = (n_samples)\n",
    "            Observed values from the training samples\n",
    "    y_predicted : array-like , shape = (n_samples)\n",
    "            Predicted values from the model\n",
    "    \n",
    "    \"\"\"\n",
    "    \n",
    "    def __init__(self , y_actual , y_predicted):\n",
    "        self.y_actual = y_actual\n",
    "        self.y_predicted = y_predicted\n",
    "        \n",
    "    def compute_rmse(self):\n",
    "        \"\"\" Compute root mean squared error\n",
    "        \n",
    "        Returns :\n",
    "        ----------\n",
    "        rmse : root mean squared error\n",
    "        \n",
    "        \"\"\"\n",
    "        \n",
    "        return np.sqrt(self.sum_of_square_of_residuals())\n",
    "    \n",
    "    def compute_r2_score(self):\n",
    "        \"\"\"Compute r-squared score\n",
    "        \n",
    "        Returns :\n",
    "        ---------\n",
    "        r2_score : r-squared score\n",
    "        \n",
    "        \"\"\"\n",
    "        # sum of square of residuals\n",
    "        ssr = self.sum_of_square_of_residuals()\n",
    "        \n",
    "        # total sum of errors\n",
    "        sst = np.sum((self.y_actual - np.mean(y_actual))**2)\n",
    "        \n",
    "        return (1 - (ssr/sst))\n",
    "    \n",
    "    def sum_of_square_of_residuals(self):\n",
    "        return np.sum((self.y_actual - self.y_predicted)**2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "\n",
    "\n",
    "def scatter_plot(x, y, size=10, x_label='x', y_label='y', color='b'):\n",
    "    plt.scatter(x, y, s=size, color=color)\n",
    "    set_labels(x_label, y_label)\n",
    "\n",
    "\n",
    "def plot(x, y, x_label='x', y_label='y', color='r'):\n",
    "    plt.plot(x, y, color=color)\n",
    "    set_labels(x_label, y_label)\n",
    "\n",
    "\n",
    "def ploty(y, x_label='x', y_label='y'):\n",
    "    plt.plot(y)\n",
    "    set_labels(x_label, y_label)\n",
    "\n",
    "\n",
    "def set_labels(x_label, y_label):\n",
    "    plt.xlabel(x_label)\n",
    "    plt.ylabel(y_label)\n",
    "    plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[2.58109277]\n",
      " [2.89114079]]\n"
     ]
    },
    {
     "data": {
      "image/png": "[encoded data, 9064 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 7512 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 9496 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "ename": "NameError",
     "evalue": "name 'y_actual' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-8-47e7fdce332a>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m     48\u001b[0m     \u001b[0mmetrics\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mPerformanceMetrics\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0my\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mpredicted_values\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     49\u001b[0m     \u001b[0mrmse\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mmetrics\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcompute_rmse\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 50\u001b[0;31m     \u001b[0mr2_score\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mmetrics\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcompute_r2_score\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     51\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     52\u001b[0m     \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'The coefficient is {}'\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mformat\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mcoeffs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m<ipython-input-7-ce860d348502>\u001b[0m in \u001b[0;36mcompute_r2_score\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m     46\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     47\u001b[0m         \u001b[0;31m# total sum of errors\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 48\u001b[0;31m         \u001b[0msst\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msum\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0my_actual\u001b[0m \u001b[0;34m-\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmean\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0my_actual\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m**\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     49\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     50\u001b[0m         \u001b[0;32mreturn\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0;36m1\u001b[0m \u001b[0;34m-\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mssr\u001b[0m\u001b[0;34m/\u001b[0m\u001b[0msst\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mNameError\u001b[0m: name 'y_actual' is not defined"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "def generate_data_set():\n",
    "    \"\"\" Generates Random Data\n",
    "    Returns\n",
    "    -------\n",
    "    x : array-like, shape = [n_samples, n_features]\n",
    "            Training samples\n",
    "    y : array-like, shape = [n_samples, n_target_values]\n",
    "            Target values\n",
    "    \"\"\"\n",
    "    np.random.seed(0)\n",
    "    x = np.random.rand(100, 1)\n",
    "    y = 2 + 3 * x + np.random.rand(100, 1)\n",
    "    return x, y\n",
    "\n",
    "\n",
    "if __name__ == \"__main__\":\n",
    "    # initializing the model\n",
    "    linear_regression_model = LinearRegressionUsingGD()\n",
    "\n",
    "    # generate the data set\n",
    "    x, y = generate_data_set()\n",
    "\n",
    "    # transform the feature vectors to include the bias term\n",
    "    # adding 1 to all the instances of the training set.\n",
    "    m = x.shape[0]\n",
    "    x_train = np.c_[np.ones((m, 1)), x]\n",
    "\n",
    "    # fit/train the model\n",
    "    linear_regression_model.fit(x_train, y)\n",
    "\n",
    "    # predict values\n",
    "    predicted_values = linear_regression_model.predict(x_train)\n",
    "\n",
    "    # model parameters\n",
    "    print(linear_regression_model.w_)\n",
    "    intercept, coeffs = linear_regression_model.w_\n",
    "\n",
    "    # cost_function\n",
    "    cost_function = linear_regression_model.cost_\n",
    "\n",
    "    # plotting\n",
    "    scatter_plot(x, y)\n",
    "    plot(x, predicted_values)\n",
    "    ploty(cost_function, 'no of iterations', 'cost function')\n",
    "\n",
    "    # computing metrics\n",
    "    metrics = PerformanceMetrics(y, predicted_values)\n",
    "    rmse = metrics.compute_rmse()\n",
    "    r2_score = metrics.compute_r2_score()\n",
    "\n",
    "    print('The coefficient is {}'.format(coeffs))\n",
    "    print('The intercept is {}'.format(intercept))\n",
    "    print('Root mean squared error of the model is {}.'.format(rmse))\n",
    "    print('R-squared score is {}.'.format(r2_score))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "ename": "TypeError",
     "evalue": "data type not understood",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mTypeError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-1-dc59dca259e1>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m     75\u001b[0m     \u001b[0mx_train\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mc_\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mones\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mm\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     76\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 77\u001b[0;31m     \u001b[0mLModel\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfit\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx_train\u001b[0m \u001b[0;34m,\u001b[0m \u001b[0my\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     78\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     79\u001b[0m     \u001b[0mpredict\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mLModel\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mpredict\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx_train\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m<ipython-input-1-dc59dca259e1>\u001b[0m in \u001b[0;36mfit\u001b[0;34m(self, x, y)\u001b[0m\n\u001b[1;32m      9\u001b[0m     \u001b[0;32mdef\u001b[0m \u001b[0mfit\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mx\u001b[0m \u001b[0;34m,\u001b[0m \u001b[0my\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     10\u001b[0m         \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcost_\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 11\u001b[0;31m         \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mw_\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mzeros\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mshape\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m,\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     12\u001b[0m         \u001b[0mm\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mshape\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     13\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mTypeError\u001b[0m: data type not understood"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "class LinearRegressionUsingGD:\n",
    "    def __init__(self, n_iterations = 1000, eta = 0.05):\n",
    "        self.eta = eta\n",
    "        self.n_iterations = n_iterations\n",
    "        \n",
    "    def fit(self, x , y):\n",
    "        self.cost_ = []\n",
    "        self.w_ = np.zeros(x.shape[1] , 1)\n",
    "        m = x.shape[0]\n",
    "        \n",
    "        for _ in range(self.n_iterations):\n",
    "            y_pred = np.dot(x , self.w_)\n",
    "            residuals = y_pred - y\n",
    "            gradient_vector = np.dot(x.T , residuals)\n",
    "            self.w_ -= (self.eta /m) * gradient_vector\n",
    "            cost = np.sum((residual ** 2) / 2 *m)\n",
    "            self.cost_.append(cost)\n",
    "        return self\n",
    "    \n",
    "    def predict(self ,x):\n",
    "        return np.dot(x , self.w_)\n",
    "    \n",
    "class PerformanceMetrics:\n",
    "    def __init__(self , y_actual, y_predictions):\n",
    "        self.y_actual = y_actual\n",
    "        self.y_predictions = y_predictions\n",
    "    \n",
    "    def sum_of_square_of_residuals(self):\n",
    "        return np.sum((self.y_actual - self.y_predictions)**2)\n",
    "    \n",
    "    def compute_rmse(self):\n",
    "        return np.sqrt(self.sum_of_square_of_residuals())\n",
    "    \n",
    "    def compute_r2_score(self):\n",
    "        ssr = self.sum_of_square_of_residuals()\n",
    "        sst = np.sum((self.y_actual - np.mean(self.y_actual))**2)\n",
    "        \n",
    "        return (1 + (ssr/sst))\n",
    "    \n",
    "def scatter_plot(x, y, size=10, x_label='x', y_label='y', color='b'):\n",
    "    plt.scatter(x, y, s=size, color=color)\n",
    "    set_labels(x_label, y_label)\n",
    "\n",
    "\n",
    "def plot(x, y, x_label='x', y_label='y', color='r'):\n",
    "    plt.plot(x, y, color=color)\n",
    "    set_labels(x_label, y_label)\n",
    "\n",
    "\n",
    "def ploty(y, x_label='x', y_label='y'):\n",
    "    plt.plot(y)\n",
    "    set_labels(x_label, y_label)\n",
    "\n",
    "\n",
    "def set_labels(x_label, y_label):\n",
    "    plt.xlabel(x_label)\n",
    "    plt.ylabel(y_label)\n",
    "    plt.show()\n",
    "        \n",
    "def generateSampleData():\n",
    "    np.random.seed(0)\n",
    "    x = np.random.rand(100 , 1)\n",
    "    y = 2 + 3*x + np.random.rand(100 , 1)\n",
    "    \n",
    "    return x , y\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    LModel = LinearRegressionUsingGD()\n",
    "    \n",
    "    x , y = generateSampleData()\n",
    "    m = x.shape[0]\n",
    "    x_train = np.c_[np.ones((m, 1)), x]\n",
    "    \n",
    "    LModel.fit(x_train , y)\n",
    "    \n",
    "    predict = LModel.predict(x_train)\n",
    "    \n",
    "    print(LModel.w_)\n",
    "    intercept , coeff = LModel.w_\n",
    "    cost_function = LModel.cost_\n",
    "    \n",
    "    scatter_plot(x, y)\n",
    "    plot(x, predicted_values)\n",
    "    ploty(cost_function, 'no of iterations', 'cost function')\n",
    "    \n",
    "    metrics = PerformanceMetrics(y, predicted_values)\n",
    "    rmse = metrics.compute_rmse()\n",
    "    r2_score = metrics.compute_r2_score()\n",
    "\n",
    "    print('The coefficient is {}'.format(coeffs))\n",
    "    print('The intercept is {}'.format(intercept))\n",
    "    print('Root mean squared error of the model is {}.'.format(rmse))\n",
    "    print('R-squared score is {}.'.format(r2_score))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Slope: [[2.93655106]]\n",
      "Intercept: [2.55808002]\n",
      "Root mean squared error:  0.07623324582875007\n",
      "R2 score:  0.9038655568672764\n"
     ]
    },
    {
     "data": {
      "image/png": "[encoded data, 11504 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Linear Regression using scikit-learn\n",
    "\n",
    "import numpy as np \n",
    "import matplotlib.pyplot as plt\n",
    "from sklearn.linear_model import LinearRegression\n",
    "from sklearn.metrics import mean_squared_error ,r2_score\n",
    "\n",
    "\n",
    "# generate random data-set\n",
    "np.random.seed(0)\n",
    "x = np.random.rand(100, 1)\n",
    "y = 2 + 3 * x + np.random.rand(100, 1)\n",
    "\n",
    "# Model initialization\n",
    "regression_model = LinearRegression()\n",
    "# Fit the data (Train the model)\n",
    "regression_model.fit(x , y)\n",
    "# Predict\n",
    "y_predicted = regression_model.predict(x)\n",
    "\n",
    "# model evaluation\n",
    "rmse = mean_squared_error(y , y_predicted)\n",
    "r2 = r2_score(y , y_predicted)\n",
    "\n",
    "# printing values\n",
    "print('Slope:' ,regression_model.coef_)\n",
    "print('Intercept:', regression_model.intercept_)\n",
    "print('Root mean squared error: ', rmse)\n",
    "print('R2 score: ', r2)\n",
    "\n",
    "# data points\n",
    "plt.scatter(x, y, s=10)\n",
    "plt.xlabel('x')\n",
    "plt.ylabel('y')\n",
    "\n",
    "# predicted values\n",
    "plt.plot(x, y_predicted, color='r')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "mse 0.07623324582875007\n",
      "r2_score 0.9038655568672764\n",
      "slope [[2.93655106]]\n",
      "intercept [2.55808002]\n"
     ]
    },
    {
     "data": {
      "image/png": "[encoded data, 14316 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "from sklearn.linear_model import LinearRegression\n",
    "from sklearn.metrics import mean_squared_error , r2_score\n",
    "\n",
    "# generate sample data\n",
    "np.random.seed(0)\n",
    "X = np.random.rand(100, 1)\n",
    "y = 2 + 3*X + np.random.rand(100 , 1)\n",
    "\n",
    "linearModel = LinearRegression()\n",
    "linearModel.fit(X , y)\n",
    "predictions = linearModel.predict(X)\n",
    "\n",
    "# mse \n",
    "mse = mean_squared_error(y , predictions)\n",
    "\n",
    "# r squared score\n",
    "r2 = r2_score(y , predictions)\n",
    "\n",
    "print('mse' , mse)\n",
    "print('r2_score' , r2)\n",
    "print('slope' , linearModel.coef_)\n",
    "print('intercept' , linearModel.intercept_)\n",
    "\n",
    "plt.scatter(X , y , s = 10)\n",
    "plt.plot(X , predictions , 'r')\n",
    "plt.xlabel('X axis')\n",
    "plt.ylabel('y axis')\n",
    "plt.title('Linear Regression Practise')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "# # sum of square of residuals\n",
    "# ssr = np.sum((y_pred - y_actual)**2)\n",
    "\n",
    "# # total sum of squares\n",
    "# sst = np.sum((y_acutal - np.mean(y_acutal))**2)\n",
    "\n",
    "# # R2 score\n",
    "# r2_score = 1-(ssr/sst)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(11, 2)\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>area</th>\n",
       "      <th>price</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>2800</td>\n",
       "      <td>50000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>3000</td>\n",
       "      <td>54000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>3200</td>\n",
       "      <td>53000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>3700</td>\n",
       "      <td>60000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>4000</td>\n",
       "      <td>63000</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   area  price\n",
       "0  2800  50000\n",
       "1  3000  54000\n",
       "2  3200  53000\n",
       "3  3700  60000\n",
       "4  4000  63000"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#### Method 1:\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "plt.rcParams['figure.figsize'] = (20.0 ,10.0)\n",
    "\n",
    "#Read data\n",
    "data = pd.read_csv('areaprice.csv')\n",
    "print(data.shape)\n",
    "data.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "X = data['area'].values\n",
    "Y = data['price'].values"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "10.499130866650113 20957.784951576847\n"
     ]
    }
   ],
   "source": [
    "#Mean of X and Y\n",
    "mean_x = np.mean(X)\n",
    "mean_y = np.mean(Y)\n",
    "\n",
    "# total number of values in X\n",
    "n = len(X)\n",
    "\n",
    "numer = 0\n",
    "denom = 0\n",
    "for i in range(n):\n",
    "    numer = numer + ((X[i] - mean_x)* (Y[i] - mean_y))\n",
    "    denom =denom + ((X[i] - mean_x)** 2)\n",
    "\n",
    "b1 = numer/denom\n",
    "b0 = mean_y -(b1 * mean_x)\n",
    "\n",
    "# printing coefficients\n",
    "print(b1 ,b0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "5100 2100\n"
     ]
    },
    {
     "data": {
      "image/png": "[encoded data, 39488 characters]\n",
      "text/plain": [
       "<Figure size 1440x720 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Plotting values and Regression line\n",
    "max_x = np.max(X) +100\n",
    "min_x = np.min(X) -100\n",
    "\n",
    "print(max_x , min_x)\n",
    "#calculating line values x and y\n",
    "x = np.linspace(max_x , min_x , 1000)\n",
    "y = b0 +b1 * x\n",
    "\n",
    "#plotting line \n",
    "plt.plot(x , y ,color='red' , label = 'Regression Line')\n",
    "\n",
    "# Scatter plot\n",
    "plt.scatter(X , Y , color= 'black' , label = 'Actual points')\n",
    "plt.xlabel('Independent variable (area)')\n",
    "plt.ylabel('Dependent variable (price)')\n",
    "plt.legend()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Method 2 :\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "import pandas as pd\n",
    "from sklearn.linear_model import LinearRegression\n",
    "from sklearn.model_selection import train_test_split \n",
    "from sklearn.metrics import accuracy_score"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "collapsed": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'pandas.core.frame.DataFrame'>\n",
      "RangeIndex: 11 entries, 0 to 10\n",
      "Data columns (total 2 columns):\n",
      " #   Column  Non-Null Count  Dtype\n",
      "---  ------  --------------  -----\n",
      " 0   area    11 non-null     int64\n",
      " 1   price   11 non-null     int64\n",
      "dtypes: int64(2)\n",
      "memory usage: 304.0 bytes\n"
     ]
    }
   ],
   "source": [
    "data = pd.read_csv('areaprice.csv')\n",
    "data.info()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [],
   "source": [
    "lModel = LinearRegression()\n",
    "X = data.drop('price', axis = 1)\n",
    "y = data.price"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [],
   "source": [
    "X_train , X_test , y_train , y_test= train_test_split(X , y ,test_size = 0.3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "LinearRegression(copy_X=True, fit_intercept=True, n_jobs=None, normalize=False)"
      ]
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "lModel.fit(X_train , y_train)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Train data = 99.10842552208197  %\n",
      "Predicted data = 90.24220239676124  %\n"
     ]
    }
   ],
   "source": [
    "prediction=lModel.predict(X_test)\n",
    "print('Train data =',lModel.score(X_train , y_train)*100 , ' %')\n",
    "print('Predicted data =', lModel.score(X_test , y_test)*100,' %')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "98.53634055293017\n"
     ]
    }
   ],
   "source": [
    "print(lModel.score(X, y)*100)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "new values for constant and slope are 1.1942166666666667, 2.296241\n",
      "new values for constant and slope are 1.3004423682833335, 3.0007543440089446\n",
      "new values for constant and slope are 1.3588378687307063, 3.383616460023943\n",
      "new values for constant and slope are 1.3912337507054766, 3.591635456833548\n",
      "new values for constant and slope are 1.4094966794556214, 3.7046132666748948\n",
      "new values for constant and slope are 1.4200771353082968, 3.765928613252169\n",
      "new values for constant and slope are 1.4264814695121573, 3.799161297422246\n",
      "new values for constant and slope are 1.4306156640231555, 3.817128824195407\n",
      "done. Diff is less than 0.01\n",
      "constant : 1.4335157722700855 , slope: 3.826798531237839\n"
     ]
    }
   ],
   "source": [
    "## Method 3:\n",
    "# sales of vehicle as a function of GDP (for India)\n",
    "import collections\n",
    "stepSize = 0.01\n",
    "def read_data() :\n",
    "    data = open(\"vehicle_sale_data\" , \"r\")\n",
    "    gdp_sale = collections.OrderedDict()\n",
    "    for line in data.readlines()[1:] :\n",
    "        record = line.split(\",\")\n",
    "        gdp_sale[float(record[1])] = float(record[2].replace('\\n', \"\"))\n",
    "    return gdp_sale\n",
    "\n",
    "def sale_for_data(constant, slope, data):\n",
    "    return constant + slope * data   # y = c + ax format\n",
    "\n",
    "def step_cost_function_for(gdp_sale, constant, slope) :\n",
    "    global stepSize\n",
    "    diff_sum_constant = 0 # diff of sum for constant 'c' in \"c + ax\" equation\n",
    "    diff_sum_slope = 0  # diff of sum for 'a' in \"c + ax\" equation\n",
    "    gdp_for_years = list(gdp_sale.keys())\n",
    "    \n",
    "    for year_gdp in gdp_for_years: # for each year's gdp in the sample data\n",
    "        # get the sale for given 'c' and 'a'by giving the GDP for this sample record\n",
    "        trg_data_sale = sale_for_data(constant, slope, year_gdp) # calculated sale for current 'c' and 'a'\n",
    "        a_year_sale = gdp_sale.get(year_gdp) # real sale for this record\n",
    "        diff_sum_slope = diff_sum_slope + ((trg_data_sale - a_year_sale) * year_gdp) # slope's (h(y) - y) * x\n",
    "        diff_sum_constant = diff_sum_constant + (trg_data_sale - a_year_sale) # consant's (h(y) - y)\n",
    "        \n",
    "    step_for_constant = (stepSize / len(gdp_sale)) * diff_sum_constant # distance to be moved by c\n",
    "    step_for_slope = (stepSize / len(gdp_sale)) * diff_sum_slope # distance to be moved by a\n",
    "    new_constant = constant - step_for_constant # new c\n",
    "    new_slope = slope - step_for_slope # new a\n",
    "    return new_constant, new_slope\n",
    "\n",
    "def get_weights(gdp_sale) :\n",
    "    constant = 1\n",
    "    slope = 1\n",
    "    accepted_diff = 0.01\n",
    "    while 1 == 1:  # continue till we reach local minimum\n",
    "        new_constant, new_slope = step_cost_function_for(gdp_sale, constant, slope)\n",
    "        # if the diff is too less then lets break\n",
    "        if (abs(constant - new_constant) <= accepted_diff) and (abs(slope - new_slope) <= accepted_diff):\n",
    "            print (\"done. Diff is less than \" + str(accepted_diff))\n",
    "            return new_constant, new_slope\n",
    "        else:\n",
    "            constant = new_constant\n",
    "            slope = new_slope\n",
    "            print(\"new values for constant and slope are \" + str(new_constant) + \", \" + \\\n",
    "                  str(new_slope))\n",
    "                \n",
    "def main() :\n",
    "    contant, slope = get_weights(read_data())\n",
    "    print((\"constant : {} , slope: {}\").format(contant , slope) )\n",
    "    \n",
    "if __name__ == '__main__':\n",
    "    main()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "import numpy as np\n",
    "import seaborn as sns\n",
    "from sklearn.linear_model import LinearRegression\n",
    "from sklearn.preprocessing import LabelEncoder\n",
    "from sklearn.metrics import accuracy_score , confusion_matrix , classification_report \n",
    "from sklearn.model_selection import train_test_split"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "dataset = pd.read_csv('iris.csv')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "X = dataset.drop('variety' ,axis = 1) \n",
    "y = dataset.variety"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "encoder = LabelEncoder()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "dataset.variety = encoder.fit_transform(dataset.variety)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "X_train , X_test , y_train , y_test = train_test_split(X , y , test_size= 0.2 , random_state= 0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Model training 0.9340217779843487\n",
      "Model prediction 0.9055032992676105\n"
     ]
    }
   ],
   "source": [
    "linearModel = LinearRegression()\n",
    "linearModel.fit(X_train , y_train)\n",
    "predictions = linearModel.predict(X_test)\n",
    "\n",
    "print('Model training' , linearModel.score(X_train , y_train))\n",
    "print('Model prediction',linearModel.score(X_test, y_test))"
   ]
  }
 ],
 "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.6.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
