{
"cells": [
{
"cell_type": "markdown",
"id": "c8e6a45e-ec06-46bf-b672-9cc0d8c0f16d",
"metadata": {},
"source": [
"### Toyota Car Prices"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "ab356672-aea9-4fc5-86a7-ea2e9088f3f8",
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"import pandas as pd\n",
"import matplotlib.pyplot as plt\n",
"from sklearn.model_selection import train_test_split\n",
"from sklearn.preprocessing import StandardScaler\n",
"from sklearn.linear_model import LinearRegression, Lasso, Ridge, LassoCV, BayesianRidge\n",
"from sklearn import metrics\n",
"from itertools import combinations\n",
"import statsmodels.formula.api as sm"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "67fe6d71-ba69-4a83-971e-98e1af9e351f",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"
\n",
"\n",
"
\n",
" \n",
" \n",
" \n",
" Id \n",
" Model \n",
" Price \n",
" Age_08_04 \n",
" Mfg_Month \n",
" Mfg_Year \n",
" KM \n",
" Fuel_Type \n",
" HP \n",
" Met_Color \n",
" ... \n",
" Powered_Windows \n",
" Power_Steering \n",
" Radio \n",
" Mistlamps \n",
" Sport_Model \n",
" Backseat_Divider \n",
" Metallic_Rim \n",
" Radio_cassette \n",
" Parking_Assistant \n",
" Tow_Bar \n",
" \n",
" \n",
" \n",
" \n",
" 0 \n",
" 1 \n",
" TOYOTA Corolla 2.0 D4D HATCHB TERRA 2/3-Doors \n",
" 13500 \n",
" 23 \n",
" 10 \n",
" 2002 \n",
" 46986 \n",
" Diesel \n",
" 90 \n",
" 1 \n",
" ... \n",
" 1 \n",
" 1 \n",
" 0 \n",
" 0 \n",
" 0 \n",
" 1 \n",
" 0 \n",
" 0 \n",
" 0 \n",
" 0 \n",
" \n",
" \n",
" 1 \n",
" 2 \n",
" TOYOTA Corolla 2.0 D4D HATCHB TERRA 2/3-Doors \n",
" 13750 \n",
" 23 \n",
" 10 \n",
" 2002 \n",
" 72937 \n",
" Diesel \n",
" 90 \n",
" 1 \n",
" ... \n",
" 0 \n",
" 1 \n",
" 0 \n",
" 0 \n",
" 0 \n",
" 1 \n",
" 0 \n",
" 0 \n",
" 0 \n",
" 0 \n",
" \n",
" \n",
" 2 \n",
" 3 \n",
" TOYOTA Corolla 2.0 D4D HATCHB TERRA 2/3-Doors \n",
" 13950 \n",
" 24 \n",
" 9 \n",
" 2002 \n",
" 41711 \n",
" Diesel \n",
" 90 \n",
" 1 \n",
" ... \n",
" 0 \n",
" 1 \n",
" 0 \n",
" 0 \n",
" 0 \n",
" 1 \n",
" 0 \n",
" 0 \n",
" 0 \n",
" 0 \n",
" \n",
" \n",
" 3 \n",
" 4 \n",
" TOYOTA Corolla 2.0 D4D HATCHB TERRA 2/3-Doors \n",
" 14950 \n",
" 26 \n",
" 7 \n",
" 2002 \n",
" 48000 \n",
" Diesel \n",
" 90 \n",
" 0 \n",
" ... \n",
" 0 \n",
" 1 \n",
" 0 \n",
" 0 \n",
" 0 \n",
" 1 \n",
" 0 \n",
" 0 \n",
" 0 \n",
" 0 \n",
" \n",
" \n",
" 4 \n",
" 5 \n",
" TOYOTA Corolla 2.0 D4D HATCHB SOL 2/3-Doors \n",
" 13750 \n",
" 30 \n",
" 3 \n",
" 2002 \n",
" 38500 \n",
" Diesel \n",
" 90 \n",
" 0 \n",
" ... \n",
" 1 \n",
" 1 \n",
" 0 \n",
" 1 \n",
" 0 \n",
" 1 \n",
" 0 \n",
" 0 \n",
" 0 \n",
" 0 \n",
" \n",
" \n",
"
\n",
"
5 rows × 39 columns
\n",
"
"
],
"text/plain": [
" Id Model Price Age_08_04 \\\n",
"0 1 TOYOTA Corolla 2.0 D4D HATCHB TERRA 2/3-Doors 13500 23 \n",
"1 2 TOYOTA Corolla 2.0 D4D HATCHB TERRA 2/3-Doors 13750 23 \n",
"2 3 TOYOTA Corolla 2.0 D4D HATCHB TERRA 2/3-Doors 13950 24 \n",
"3 4 TOYOTA Corolla 2.0 D4D HATCHB TERRA 2/3-Doors 14950 26 \n",
"4 5 TOYOTA Corolla 2.0 D4D HATCHB SOL 2/3-Doors 13750 30 \n",
"\n",
" Mfg_Month Mfg_Year KM Fuel_Type HP Met_Color ... Powered_Windows \\\n",
"0 10 2002 46986 Diesel 90 1 ... 1 \n",
"1 10 2002 72937 Diesel 90 1 ... 0 \n",
"2 9 2002 41711 Diesel 90 1 ... 0 \n",
"3 7 2002 48000 Diesel 90 0 ... 0 \n",
"4 3 2002 38500 Diesel 90 0 ... 1 \n",
"\n",
" Power_Steering Radio Mistlamps Sport_Model Backseat_Divider \\\n",
"0 1 0 0 0 1 \n",
"1 1 0 0 0 1 \n",
"2 1 0 0 0 1 \n",
"3 1 0 0 0 1 \n",
"4 1 0 1 0 1 \n",
"\n",
" Metallic_Rim Radio_cassette Parking_Assistant Tow_Bar \n",
"0 0 0 0 0 \n",
"1 0 0 0 0 \n",
"2 0 0 0 0 \n",
"3 0 0 0 0 \n",
"4 0 0 0 0 \n",
"\n",
"[5 rows x 39 columns]"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df = pd.read_csv(r'/Users/patriciaxufre/Documents/SBE - Disciplinas/2957 | ABA/2024-25/Datasets Examples/ToyotaCorolla.csv')\n",
"df.head()"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "0b2a104a-27d8-451f-bfe7-f8c48d2db922",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Index(['Id', 'Model', 'Price', 'Age_08_04', 'Mfg_Month', 'Mfg_Year', 'KM',\n",
" 'Fuel_Type', 'HP', 'Met_Color', 'Color', 'Automatic', 'CC', 'Doors',\n",
" 'Cylinders', 'Gears', 'Quarterly_Tax', 'Weight', 'Mfr_Guarantee',\n",
" 'BOVAG_Guarantee', 'Guarantee_Period', 'ABS', 'Airbag_1', 'Airbag_2',\n",
" 'Airco', 'Automatic_airco', 'Boardcomputer', 'CD_Player',\n",
" 'Central_Lock', 'Powered_Windows', 'Power_Steering', 'Radio',\n",
" 'Mistlamps', 'Sport_Model', 'Backseat_Divider', 'Metallic_Rim',\n",
" 'Radio_cassette', 'Parking_Assistant', 'Tow_Bar'],\n",
" dtype='object')"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df.columns"
]
},
{
"cell_type": "markdown",
"id": "72795da5-086a-4986-b5ef-c4e108648605",
"metadata": {},
"source": [
"#### 1st Linear Model"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "0aceb23c-2f41-44f4-b8cd-b140007879bd",
"metadata": {},
"outputs": [],
"source": [
"# create a list of predictor variables by removing the output variable and text columns\n",
"exclude = ('Price', 'Id', 'Model', 'Fuel_Type', 'Color')\n",
"predictors = [s for s in df.columns if s not in exclude]\n",
"outcome = 'Price'"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "31cb914e-6a01-42df-a80c-b8e1519763ad",
"metadata": {},
"outputs": [],
"source": [
"# partition data\n",
"X = df[predictors]\n",
"y = df[outcome]\n",
"train_X, test_X, train_y, test_y = train_test_split(X, y, test_size = 0.4, random_state = 1)"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "2b8a8dfa-655a-4872-ac98-d1c59a4acb52",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"LinearRegression() In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org. "
],
"text/plain": [
"LinearRegression()"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Linear Regression Model (only in the train set)\n",
"reg = LinearRegression()\n",
"reg.fit(train_X, train_y)"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "65bceac3-9142-404c-b2b8-335fe934e0b9",
"metadata": {},
"outputs": [],
"source": [
"pred_error_train = pd.DataFrame({\n",
" 'residual': train_y - reg.predict(train_X),\n",
" 'data set': 'training'\n",
"})\n",
"pred_error_test = pd.DataFrame({\n",
" 'residual': test_y - reg.predict(test_X),\n",
" 'data set': 'test'\n",
"})\n",
"boxdata_df = pd.concat([pred_error_train, pred_error_test], ignore_index = True)\n",
"order = ['training', 'test']\n",
"boxdata_df['data set']= pd.Categorical(boxdata_df['data set'], categories = order, ordered = True)"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "2c3b5589-9e9f-4c70-ad22-5900d46e93e3",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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Ea5duwYXFxeMGzcOO3bsgJ2dnTjPO++8gx49emDmzJmora3F+PHjsXXrVlhaWooxn376KRYtWiT2wjl16lS9d/NZWlpi3759mDdvHh577DFYW1sjMjISa9eu7exdQERGhkUeERERUTsEBQVBEIRmpx84cOCey+jZsyc2bNiADRs2NBvTt29ffPLJJ3ddzsCBA7F37957ro+ITBuLPCIiMkseS/cBAEremnTXGJmlgDWPdlVWRERE7ceOV4iIiIiIiEwIizwiIiIiIiITwts1qc10tzoREREREZHxYEseERERERGRCWGRR0REREREZEJY5BEREREREZkQFnlEREREREQmhEUeERGZNY+l+1rdkVRb5iEiIuoqLPKIiIiIiIhMCIs8IiIiIiIiE8Iij4iIiIiIyISwyCMiIiIiIjIhLPKIiIiIiIhMCIs8IiIiIiIiE8Iij4iIiIiIyISwyCMiIiIiIjIhLPKIiIiIiIhMCIs8IiIiIiIiE8Iij4jMRnJyMh555BHY2dnByckJYWFhOH36tF5MdHQ0JBKJ3mf06NEGypiIiIio9VjkEZHZyMrKwvz585GXlweVSoVbt25BoVCgurpaL27ChAkoLS0VP/v37zdQxkRERESt18PQCRARdZX09HS94S1btsDJyQkFBQUYO3asOF4mk0Eul3d1ekREREQdol1FXnJyMpYtW4ZXXnkF69evBwAIgoDExET84x//QEVFBfz8/PD3v/8dDzzwQEfkSybKY+k+8e+StyYZMBMyJ5WVlQCAvn376o3PzMyEk5MTevfujcDAQKxatQpOTk5NLkOtVkOtVovDVVVVAACNRgONRtNJmbeMbv2GzsNYySwFveE799Od02QWgt6/zc1DzTOmc9EYciAi6mxtLvLy8/Pxj3/8AyNHjtQbv2bNGqSkpGDr1q0YMmQIVq5cieDgYJw+fRp2dnbtTpiIqCMIgoDY2Fg8/vjj8PLyEseHhobiqaeegru7O4qLi/H666/jiSeeQEFBAWQyWaPlJCcnIzExsdH4jIwM2NjYdOo2tJRKpTJ0CkZpzaP6w3felttwGgC86VvfaBxv5W0dYzgXa2pqDJ0CEVGna1ORd+PGDTz33HP48MMPsXLlSnG8IAhYv349li9fjvDwcADAtm3b4OzsjO3bt2Pu3LkdkzURUTstWLAAP/74Iw4dOqQ3/umn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",
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"fig, axes = plt.subplots(nrows = 1, ncols = 3)\n",
"fig.set_size_inches(9,4)\n",
"common = {'bins': 100, 'range': [-6500,6500]}\n",
"pred_error_train.hist(ax = axes[0], **common)\n",
"pred_error_test.hist(ax = axes[1], **common)\n",
"boxdata_df.boxplot(ax=axes[2], by = 'data set')\n",
"axes[0].set_title(\"Training\")\n",
"axes[1].set_title(\"Test\")\n",
"axes[0].set_ylabel(\"\")\n",
"axes[1].set_ylabel(\"\")\n",
"axes[2].set_title(\"\")\n",
"fig.suptitle(\"\")\n",
"plt.tight_layout()\n",
"plt.show()"
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "d51a14fc-7991-4734-8a41-1c55b52bb52b",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Performance Measures - Training Set\n",
"Mean Absolute Error: 811.68\n",
"Mean Absolute Percentage Error: 8.01%\n",
"Root Mean Squared Error: 1121.06\n",
"\n",
"Performance Measures - Test Set\n",
"Mean Absolute Error: 880.14\n",
"Mean Absolute Percentage Error: 8.87%\n",
"Root Mean Squared Error: 1382.04\n"
]
}
],
"source": [
"# Evaluating Performance\n",
"# Training Set\n",
"mae = metrics.mean_absolute_error(train_y, reg.predict(train_X))\n",
"mape = metrics.mean_absolute_percentage_error(train_y, reg.predict(train_X))\n",
"mse = metrics.mean_squared_error(train_y, reg.predict(train_X))\n",
"rmse = np.sqrt(mse)\n",
"print('Performance Measures - Training Set')\n",
"print(f'Mean Absolute Error: {mae:.2f}')\n",
"print(f'Mean Absolute Percentage Error: {mape*100:.2f}%')\n",
"print(f'Root Mean Squared Error: {rmse:.2f}')\n",
"# Test Set\n",
"mae = metrics.mean_absolute_error(test_y,reg.predict(test_X))\n",
"mape = metrics.mean_absolute_percentage_error(test_y, reg.predict(test_X))\n",
"mse = metrics.mean_squared_error(test_y, reg.predict(test_X))\n",
"rmse = np.sqrt(mse)\n",
"print('\\nPerformance Measures - Test Set')\n",
"print(f'Mean Absolute Error: {mae:.2f}')\n",
"print(f'Mean Absolute Percentage Error: {mape*100:.2f}%')\n",
"print(f'Root Mean Squared Error: {rmse:.2f}')"
]
},
{
"cell_type": "markdown",
"id": "6b6aa2ce-7240-4484-bed9-2e6d60c014ad",
"metadata": {},
"source": [
"#### 2nd Linear Model"
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "183b91af-e593-440e-94b4-c049858a24d2",
"metadata": {},
"outputs": [],
"source": [
"predictors = ['Age_08_04', 'KM', 'Fuel_Type', 'HP', 'Met_Color', 'Automatic', 'CC', 'Doors', 'Quarterly_Tax', 'Weight']\n",
"outcome = 'Price'\n",
"# partition data\n",
"X = pd.get_dummies(df[predictors], drop_first = True)\n",
"y = df[outcome]\n",
"train_X, test_X, train_y, test_y = train_test_split(X, y, test_size = 0.4, random_state = 123)"
]
},
{
"cell_type": "code",
"execution_count": 14,
"id": "5c4108c8-a202-4227-9983-fc762b160b04",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" Predictor coefficient\n",
"0 Age_08_04 -113.244942\n",
"1 KM -0.015739\n",
"2 HP 2.325408\n",
"3 Met_Color -72.350023\n",
"4 Automatic -149.178152\n",
"5 CC -0.038289\n",
"6 Doors -251.428537\n",
"7 Quarterly_Tax 14.975890\n",
"8 Weight 32.255569\n",
"9 Fuel_Type_Diesel -1307.813608\n",
"10 Fuel_Type_Petrol 2785.721080\n"
]
}
],
"source": [
"lm = LinearRegression()\n",
"lm.fit(train_X, train_y)\n",
"\n",
"# coefficients:\n",
"print(pd.DataFrame({'Predictor': X.columns, 'coefficient': lm.coef_}))"
]
},
{
"cell_type": "code",
"execution_count": 15,
"id": "f2bbbfc3-e42c-40f0-af7a-55694bcedef3",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Performance Measures - Training Set\n",
"Mean Absolute Error: 922.12\n",
"Mean Absolute Percentage Error: 9.31%\n",
"Root Mean Squared Error: 1190.13\n",
"\n",
"Performance Measures - Test Set\n",
"Mean Absolute Error: 1018.69\n",
"Mean Absolute Percentage Error: 9.86%\n",
"Root Mean Squared Error: 1605.91\n"
]
}
],
"source": [
"# Evaluating Performance\n",
"# Training Set\n",
"mae = metrics.mean_absolute_error(train_y,lm.predict(train_X))\n",
"mape = metrics.mean_absolute_percentage_error(train_y, lm.predict(train_X))\n",
"mse = metrics.mean_squared_error(train_y, lm.predict(train_X))\n",
"rmse = np.sqrt(mse)\n",
"print('Performance Measures - Training Set')\n",
"print(f'Mean Absolute Error: {mae:.2f}')\n",
"print(f'Mean Absolute Percentage Error: {mape*100:.2f}%')\n",
"print(f'Root Mean Squared Error: {rmse:.2f}')\n",
"# Test Set\n",
"mae = metrics.mean_absolute_error(test_y,lm.predict(test_X))\n",
"mape = metrics.mean_absolute_percentage_error(test_y, lm.predict(test_X))\n",
"mse = metrics.mean_squared_error(test_y, lm.predict(test_X))\n",
"rmse = np.sqrt(mse)\n",
"print('\\nPerformance Measures - Test Set')\n",
"print(f'Mean Absolute Error: {mae:.2f}')\n",
"print(f'Mean Absolute Percentage Error: {mape*100:.2f}%')\n",
"print(f'Root Mean Squared Error: {rmse:.2f}')"
]
},
{
"cell_type": "code",
"execution_count": 16,
"id": "24fa6746-d6f2-4d9f-a56d-bd8f203349a1",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAA3kAAAF3CAYAAAAYZYKMAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAABAKUlEQVR4nO3df3RU9Z3/8deAYUgwCQImk0gIqFG0EUWiAVZNQBONSFWsR0U90GoXCljZ2IMidR2KJkj3UNxSabUW47YU16rVLRgyrk1oCyg/So1YXawBEQipCCQQmAzk8/2Db8ZMfg+ZyZ25eT7OmUPu537mft7vyU0+vHN/OYwxRgAAAAAAW+hjdQAAAAAAgNChyAMAAAAAG6HIAwAAAAAbocgDAAAAABuhyAMAAAAAG6HIAwAAAAAbocgDAAAAABuhyAMAAAAAG6HIAwAAAAAbocgDguRwOLr0Ki8v79Y4brdbDofjjN5bXl4ekhgAAAhWT82TklRfXy+32818B7RwltUBANFm48aNAcuLFi3SH//4R7377rsB7Zdeemm3xnnwwQd10003ndF7r7zySm3cuLHbMQAAEKyemiel00XewoULJUm5ubnd3h5gFxR5QJDGjh0bsHzuueeqT58+rdpbqq+vV1xcXJfHGTp0qIYOHXpGMSYkJHQaDwAA4XCm8ySA0OF0TSAMcnNzlZmZqfXr12v8+PGKi4vTd77zHUnSK6+8ovz8fKWkpCg2NlaXXHKJHnvsMR07dixgG22drjl8+HDdcsstKi0t1ZVXXqnY2FiNHDlSv/rVrwL6tXW65vTp03X22Wfr008/1c0336yzzz5baWlpeuSRR+T1egPe/8UXX+hb3/qW4uPjNXDgQN17773avHmzHA6HXnrppdB9UACAXqmhoUFPPfWURo4cKafTqXPPPVff/va39c9//jOg37vvvqvc3FwNHjxYsbGxGjZsmO644w7V19dr165dOvfccyVJCxcu9J8GOn36dAsyAiILR/KAMNm/f7/uu+8+zZs3T0VFRerT5/TfVHbu3Kmbb75Zc+fO1YABA/Txxx/rmWee0fvvv9/qVJa2/O1vf9Mjjzyixx57TMnJyfrlL3+pBx54QBdeeKGuu+66Dt/r8/n0zW9+Uw888IAeeeQRrV+/XosWLVJiYqL+/d//XZJ07NgxTZgwQV999ZWeeeYZXXjhhSotLdVdd93V/Q8FANDrNTY26tZbb9Wf/vQnzZs3T+PHj9fu3bv15JNPKjc3V1u2bFFsbKx27dqlSZMm6dprr9WvfvUrDRw4UHv37lVpaakaGhqUkpKi0tJS3XTTTXrggQf04IMPSpK/8AN6M4o8IEy++uorvfrqq5o4cWJA+w9/+EP/18YY/cu//IsuueQS5eTk6IMPPtCoUaM63O6XX36pv/zlLxo2bJgk6brrrtP//u//atWqVZ0WeQ0NDVq4cKHuvPNOSdL111+vLVu2aNWqVf4ir6SkRJ9++qnefvtt/zWB+fn5qq+v1y9+8YvgPgQAAFr47//+b5WWluq1117TlClT/O2XX365rrrqKr300kv63ve+p61bt+rEiRP68Y9/rMsvv9zfb+rUqf6vx4wZI+n0JQ6cDgp8jdM1gTA555xzWhV4kvTZZ59p6tSpcrlc6tu3r2JiYpSTkyNJ+vvf/97pdq+44gp/gSdJ/fv310UXXaTdu3d3+l6Hw6HJkycHtI0aNSrgvRUVFYqPj29105d77rmn0+0DANCZP/zhDxo4cKAmT56skydP+l9XXHGFXC6X/1KDK664Qv369dO//uu/qqSkRJ999pm1gQNRhCIPCJOUlJRWbUePHtW1116r9957T0899ZTKy8u1efNmvf7665Kk48ePd7rdwYMHt2pzOp1dem9cXJz69+/f6r0nTpzwLx88eFDJycmt3ttWGwAAwTpw4IAOHz6sfv36KSYmJuBVXV2tL7/8UpJ0wQUX6J133lFSUpJmz56tCy64QBdccIGeffZZizMAIh+nawJh0tYz7t59913t27dP5eXl/qN3knT48OEejKxjgwcP1vvvv9+qvbq62oJoAAB2M2TIEA0ePFilpaVtro+Pj/d/fe211+raa6/VqVOntGXLFv30pz/V3LlzlZycrLvvvrunQgaiDkfygB7UVPg5nc6A9ki61i0nJ0d1dXV6++23A9pXr15tUUQAADu55ZZbdPDgQZ06dUpZWVmtXhdffHGr9/Tt21fZ2dn62c9+Jknatm2bpK/n066czQL0JhzJA3rQ+PHjdc4552jmzJl68sknFRMTo9/85jf629/+ZnVoftOmTdNPfvIT3XfffXrqqad04YUX6u2339a6deskyX+XUAAAzsTdd9+t3/zmN7r55pv18MMP6+qrr1ZMTIy++OIL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6GXn3CTyi3Z2z6855rnIRn7RjfyiG/lFBocxYb7XNAAAAACgx4TlYegAAAAAAGtQ5AEAAACAjVDkAQAAAICNUOQBAAAAgI30uiJvzZo1ys7OVmxsrIYMGaIpU6YErP/88881efJkDRgwQEOGDNH3v/99NTQ0BPSprKxUTk6OYmNjdd555+lHP/qRWt6/pqKiQmPGjFH//v11/vnn6+c//3nYc2vi9Xp1xRVXyOFwaPv27QHrojG/Xbt26YEHHtCIESMUGxurCy64QE8++WSruKMxt2A999xzGjFihPr3768xY8boT3/6k9UhtVJcXKyrrrpK8fHxSkpK0m233aZPPvkkoI8xRm63W6mpqYqNjVVubq527NgR0Mfr9eqhhx7SkCFDNGDAAH3zm9/UF198EdDn0KFDuv/++5WYmKjExETdf//9Onz4cLhT9CsuLpbD4dDcuXP9bXbIbe/evbrvvvs0ePBgxcXF6YorrtDWrVv96+2Qo50xz0Vnfsx1pzHPRd7vSTvOdb1injO9yO9+9ztzzjnnmBUrVphPPvnEfPzxx+bVV1/1rz958qTJzMw0EyZMMNu2bTMej8ekpqaaOXPm+PscOXLEJCcnm7vvvttUVlaa1157zcTHx5v/+I//8Pf57LPPTFxcnHn44YfNRx99ZF544QUTExNjfve73/VInt///vdNQUGBkWT++te/Rn1+b7/9tpk+fbpZt26d+cc//mHefPNNk5SUZB555JGozy0Yq1evNjExMeaFF14wH330kXn44YfNgAEDzO7du60OLcCNN95oVq5caT788EOzfft2M2nSJDNs2DBz9OhRf5/Fixeb+Ph489prr5nKykpz1113mZSUFFNbW+vvM3PmTHPeeecZj8djtm3bZiZMmGAuv/xyc/LkSX+fm266yWRmZpoNGzaYDRs2mMzMTHPLLbf0SJ7vv/++GT58uBk1apR5+OGHbZPbV199ZdLT08306dPNe++9Z6qqqsw777xjPv30U9vkaGfMc9GbH3Md81wk/p6041zXW+a5XlPk+Xw+c95555lf/vKX7fZZu3at6dOnj9m7d6+/7be//a1xOp3myJEjxhhjnnvuOZOYmGhOnDjh71NcXGxSU1NNY2OjMcaYefPmmZEjRwZse8aMGWbs2LGhTKndHEaOHGl27NjRavKzQ35NlixZYkaMGOFftlNu7bn66qvNzJkzA9pGjhxpHnvsMYsi6pqamhojyVRUVBhjjGlsbDQul8ssXrzY3+fEiRMmMTHR/PznPzfGGHP48GETExNjVq9e7e+zd+9e06dPH1NaWmqMMeajjz4yksymTZv8fTZu3GgkmY8//jisOdXV1ZmMjAzj8XhMTk6Of+KzQ26PPvqoueaaa9pdb4cc7Yp5zh75Ndfb5jrmucj6PWnXua63zHO95nTNbdu2ae/everTp49Gjx6tlJQUFRQUBBx63bhxozIzM5Wamupvu/HGG+X1ev2HcDdu3KicnJyAByDeeOON2rdvn3bt2uXvk5+fHzD+jTfeqC1btsjn84UtxwMHDui73/2u/uu//ktxcXGt1kd7fs0dOXJEgwYN8i/bKbe2NDQ0aOvWra1iy8/P14YNGyyKqmuOHDkiSf7vV1VVlaqrqwNycTqdysnJ8eeydetW+Xy+gD6pqanKzMz099m4caMSExOVnZ3t7zN27FglJiaG/TOZPXu2Jk2apBtuuCGg3Q65vfXWW8rKytKdd96ppKQkjR49Wi+88IKtcrQr5rnoz6+l3jTXMc9F3u9Ju851vWWe6zVF3meffSZJcrvd+uEPf6g//OEPOuecc5STk6OvvvpKklRdXa3k5OSA951zzjnq16+fqqur2+3TtNxZn5MnT+rLL78MfXI6fe7w9OnTNXPmTGVlZbXZJ5rza+4f//iHfvrTn2rmzJn+Nrvk1p4vv/xSp06dajO2ptgjkTFGhYWFuuaaa5SZmSnp68+6o1yqq6vVr18/nXPOOR32SUpKajVmUlJSWD+T1atXa9u2bSouLm61Ltpzk07/rlyxYoUyMjK0bt06zZw5U9///vf18ssv+2Nrirej+CM5R7tinovu/FrqbXMd81zbfaz6PWnnua63zHNRX+S53W45HI4OX1u2bFFjY6MkacGCBbrjjjs0ZswYrVy5Ug6HQ6+++qp/ew6Ho9UYxpiA9pZ9zP+/mDnYPqHM76c//alqa2s1f/78DrcXSfl1Nbfm9u3bp5tuukl33nmnHnzwwYjNLVzaii0S4mrPnDlz9MEHH+i3v/1tq3Vnkktn38+ubudM7dmzRw8//LB+/etfq3///u32i8bcmjQ2NurKK69UUVGRRo8erRkzZui73/2uVqxYEdAvmnOMNsxz0TvPBZNfc715rmOes/73pN3nut4yz50V9hHCbM6cObr77rs77DN8+HDV1dVJki699FJ/u9Pp1Pnnn6/PP/9ckuRyufTee+8FvPfQoUPy+Xz+at7lcrWqvmtqaiSp0z5nnXWWBg8eHJb8nnrqKW3atCng9AxJysrK0r333quSkpKIy6+ruTXZt2+fJkyYoHHjxun5558P6BdpuYXakCFD1Ldv3zZja/mXpkjx0EMP6a233tL69es1dOhQf7vL5ZJ0+i9cKSkp/vbmubhcLjU0NOjQoUMBfyWrqanR+PHj/X0OHDjQatx//vOfYftMtm7dqpqaGo0ZM8bfdurUKa1fv17Lly/3310tGnNrkpKSEvB7UpIuueQSvfbaa/7YpOjOMdowz0XvPBdMfk1661zHPPd1H6t/T9p9rus181y4LvaLNEeOHDFOpzPggvSGhgaTlJRkfvGLXxhjvr6ged++ff4+q1evbnVB88CBA43X6/X3Wbx4casLmi+55JKA8WfOnBnWC5p3795tKisr/a9169YZSeZ3v/ud2bNnT9Tn98UXX5iMjAxz9913B9y1qEk059ZVV199tfne974X0HbJJZdE3AXpjY2NZvbs2SY1NdX83//9X5vrXS6XeeaZZ/xtXq+3zQuaX3nlFX+fffv2tXlB83vvvefvs2nTprBe0FxbWxvwc1ZZWWmysrLMfffdZyorK6M6tyb33HNPqwvS586da8aNG2eMie7vn90xz0V3fsYw1zHPRcbvSbvPdb1lnus1RZ4xxjz88MPmvPPOM+vWrTMff/yxeeCBB0xSUpL56quvjDFf35r4+uuvN9u2bTPvvPOOGTp0aMCtiQ8fPmySk5PNPffcYyorK83rr79uEhIS2rw18b/927+Zjz76yLz44os9fmviqqqqdm8tHW357d2711x44YVm4sSJ5osvvjD79+/3v6I9t2A03Vr6xRdfNB999JGZO3euGTBggNm1a5fVoQX43ve+ZxITE015eXnA96q+vt7fZ/HixSYxMdG8/vrrprKy0txzzz1t3pp46NCh5p133jHbtm0zEydObPPWxKNGjTIbN240GzduNJdddlmP34K/+R3HjIn+3N5//31z1llnmaefftrs3LnT/OY3vzFxcXHm17/+tW1ytDPmuejNj7mOeS6Sf0/aaa7rLfNcryryGhoazCOPPGKSkpJMfHy8ueGGG8yHH34Y0Gf37t1m0qRJJjY21gwaNMjMmTMn4DbExhjzwQcfmGuvvdY4nU7jcrmM2+32/3WsSXl5uRk9erTp16+fGT58uFmxYkXY82uurcnPmOjMb+XKlUZSm69ozy1YP/vZz0x6errp16+fufLKK/23a44k7X2vVq5c6e/T2NhonnzySeNyuYzT6TTXXXedqaysDNjO8ePHzZw5c8ygQYNMbGysueWWW8znn38e0OfgwYPm3nvvNfHx8SY+Pt7ce++95tChQz2Q5ddaTnx2yO1//ud/TGZmpnE6nWbkyJHm+eefD1hvhxztinkuevNjrjuNeS4yf0/aba7rDfOcw5j/f6UtAAAAACDqRf3dNQEAAAAAX6PIAwAAAAAbocgDAAAAABuhyAMAAAAAG6HIAwAAAAAbocgDAAAAABuhyAMAAAAAG6HIAwAAAAAbocgDAAAAABuhyAMAAAAAG6HIAwAAAAAbocgDAAAAABv5f82OExW8mcd4AAAAAElFTkSuQmCC",
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# Residuals\n",
"pred_error_train = pd.DataFrame({\n",
" 'residual': train_y - lm.predict(train_X),\n",
" 'data set': 'training'\n",
"})\n",
"pred_error_test = pd.DataFrame({\n",
" 'residual': test_y - lm.predict(test_X),\n",
" 'data set': 'test'\n",
"})\n",
"fig, axes = plt.subplots(nrows = 1, ncols = 2)\n",
"fig.set_size_inches(9,4)\n",
"common = {'bins': 100, 'range': [-6500,6500]}\n",
"pred_error_train.hist(ax = axes[0], **common)\n",
"pred_error_test.hist(ax = axes[1], **common)\n",
"axes[0].set_title(\"Training\")\n",
"axes[1].set_title(\"Test\")\n",
"axes[0].set_ylabel(\"\")\n",
"axes[1].set_ylabel(\"\")\n",
"fig.suptitle(\"\")\n",
"plt.tight_layout()\n",
"plt.show()"
]
},
{
"cell_type": "code",
"execution_count": 17,
"id": "fb27e5a6-9f98-414a-a11f-23a7d25a3268",
"metadata": {},
"outputs": [],
"source": [
"## Performance Measures\n",
"# Function to compute Adjusted R²\n",
"def adjusted_r2_score(y_true, y_pred, model):\n",
" r2 = metrics.r2_score(y_true, y_pred)\n",
" n = len(y_true) # number of observations\n",
" p = len(model.coef_) # number of predictors\n",
" return 1 - ((1 - r2) * (n-1) / (n-p-1)) # adj R2 formula\n",
" \n",
"# Function to compute AIC (Akaike Information Criterion)\n",
"def AIC_score(y_true, y_pred, model):\n",
" n = len(y_true)\n",
" rss = np.sum((y_true - y_pred)**2) # SSE - Residual sum of Squares\n",
" p = len(model.coef_)\n",
" return n*np.log(rss/n) + 2*(p+1) # AIC formula"
]
},
{
"cell_type": "markdown",
"id": "79418881-c7f0-4839-ac40-33a59f483906",
"metadata": {},
"source": [
"#### Exhaustive Feature Selection"
]
},
{
"cell_type": "code",
"execution_count": 19,
"id": "5469cf22-f89e-4319-ab7d-1e188508a088",
"metadata": {},
"outputs": [],
"source": [
"# Exhaustive Search Function\n",
"def exhaustive_search(variables, train_fn, score_fn):\n",
" best_results = []\n",
" for k in range(1,len(variables)+1):\n",
" for subset in combinations(variables, k):\n",
" model = train_fn(subset)\n",
" score = score_fn(model, subset)\n",
" best_results.append({'n': k, 'score': score, 'model': model, 'variables': subset})\n",
" return sorted(best_results, key = lambda x: x['score'], reverse = True)\n",
" \n",
"# Function to train a model with selected variables\n",
"def train_model(variables):\n",
" model = LinearRegression()\n",
" model.fit(train_X[list(variables)], train_y)\n",
" return model\n",
"\n",
"# Function to score the model using Adjusted R²\n",
"def score_model(model, variables):\n",
" pred_y = model.predict(train_X[list(variables)])\n",
" return -adjusted_r2_score(train_y, pred_y, model)"
]
},
{
"cell_type": "code",
"execution_count": 20,
"id": "de9b3396-57c4-445b-8583-ac32bcdadb04",
"metadata": {},
"outputs": [],
"source": [
"# Define predictors\n",
"allVariables = train_X.columns\n",
"\n",
"# Perform exhaustive feature search\n",
"results = exhaustive_search(allVariables, train_model, score_model)\n",
"\n",
"# Store results in a DataFrame\n",
"data = []\n",
"for result in results:\n",
" model = result['model']\n",
" variables = list(result['variables'])\n",
" AIC = AIC_score(train_y, model.predict(train_X[variables]), model)\n",
" d = {'n': result['n'], 'r2adj': -result['score'], 'AIC': AIC}\n",
" d.update({var: var in result['variables'] for var in allVariables})\n",
" data.append(d)"
]
},
{
"cell_type": "code",
"execution_count": 21,
"id": "7db67835-428d-49e7-9fa6-914d8f7b662a",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" \n",
" n \n",
" r2adj \n",
" AIC \n",
" Age_08_04 \n",
" Automatic \n",
" CC \n",
" Doors \n",
" Fuel_Type_Diesel \n",
" Fuel_Type_Petrol \n",
" HP \n",
" KM \n",
" Met_Color \n",
" Quarterly_Tax \n",
" Weight \n",
" \n",
" \n",
" \n",
" \n",
" 1024 \n",
" 1 \n",
" 0.765863 \n",
" 12807.545515 \n",
" True \n",
" False \n",
" False \n",
" False \n",
" False \n",
" False \n",
" False \n",
" False \n",
" False \n",
" False \n",
" False \n",
" \n",
" \n",
" 1208 \n",
" 2 \n",
" 0.800835 \n",
" 12669.255092 \n",
" True \n",
" False \n",
" False \n",
" False \n",
" False \n",
" False \n",
" True \n",
" False \n",
" False \n",
" False \n",
" False \n",
" \n",
" \n",
" 1671 \n",
" 3 \n",
" 0.855124 \n",
" 12396.234593 \n",
" True \n",
" False \n",
" False \n",
" False \n",
" False \n",
" True \n",
" False \n",
" False \n",
" False \n",
" False \n",
" True \n",
" \n",
" \n",
" 1878 \n",
" 4 \n",
" 0.871117 \n",
" 12296.514559 \n",
" True \n",
" False \n",
" False \n",
" False \n",
" False \n",
" True \n",
" False \n",
" True \n",
" False \n",
" False \n",
" True \n",
" \n",
" \n",
" 1990 \n",
" 5 \n",
" 0.878224 \n",
" 12248.669683 \n",
" True \n",
" False \n",
" False \n",
" False \n",
" False \n",
" True \n",
" False \n",
" True \n",
" False \n",
" True \n",
" True \n",
" \n",
" \n",
" 2022 \n",
" 6 \n",
" 0.881719 \n",
" 12224.591431 \n",
" True \n",
" False \n",
" False \n",
" True \n",
" False \n",
" True \n",
" False \n",
" True \n",
" False \n",
" True \n",
" True \n",
" \n",
" \n",
" 2046 \n",
" 7 \n",
" 0.883439 \n",
" 12212.969194 \n",
" True \n",
" False \n",
" False \n",
" True \n",
" True \n",
" True \n",
" False \n",
" True \n",
" False \n",
" True \n",
" True \n",
" \n",
" \n",
" 2045 \n",
" 8 \n",
" 0.883431 \n",
" 12214.014649 \n",
" True \n",
" True \n",
" False \n",
" True \n",
" True \n",
" True \n",
" False \n",
" True \n",
" False \n",
" True \n",
" True \n",
" \n",
" \n",
" 2044 \n",
" 9 \n",
" 0.883388 \n",
" 12215.322797 \n",
" True \n",
" True \n",
" False \n",
" True \n",
" True \n",
" True \n",
" False \n",
" True \n",
" True \n",
" True \n",
" True \n",
" \n",
" \n",
" 2037 \n",
" 10 \n",
" 0.883281 \n",
" 12217.098365 \n",
" True \n",
" True \n",
" False \n",
" True \n",
" True \n",
" True \n",
" True \n",
" True \n",
" True \n",
" True \n",
" True \n",
" \n",
" \n",
" 2031 \n",
" 11 \n",
" 0.883173 \n",
" 12218.884757 \n",
" True \n",
" True \n",
" True \n",
" True \n",
" True \n",
" True \n",
" True \n",
" True \n",
" True \n",
" True \n",
" True \n",
" \n",
" \n",
"
\n",
"
"
],
"text/plain": [
" n r2adj AIC Age_08_04 Automatic CC Doors \\\n",
"1024 1 0.765863 12807.545515 True False False False \n",
"1208 2 0.800835 12669.255092 True False False False \n",
"1671 3 0.855124 12396.234593 True False False False \n",
"1878 4 0.871117 12296.514559 True False False False \n",
"1990 5 0.878224 12248.669683 True False False False \n",
"2022 6 0.881719 12224.591431 True False False True \n",
"2046 7 0.883439 12212.969194 True False False True \n",
"2045 8 0.883431 12214.014649 True True False True \n",
"2044 9 0.883388 12215.322797 True True False True \n",
"2037 10 0.883281 12217.098365 True True False True \n",
"2031 11 0.883173 12218.884757 True True True True \n",
"\n",
" Fuel_Type_Diesel Fuel_Type_Petrol HP KM Met_Color \\\n",
"1024 False False False False False \n",
"1208 False False True False False \n",
"1671 False True False False False \n",
"1878 False True False True False \n",
"1990 False True False True False \n",
"2022 False True False True False \n",
"2046 True True False True False \n",
"2045 True True False True False \n",
"2044 True True False True True \n",
"2037 True True True True True \n",
"2031 True True True True True \n",
"\n",
" Quarterly_Tax Weight \n",
"1024 False False \n",
"1208 False False \n",
"1671 False True \n",
"1878 False True \n",
"1990 True True \n",
"2022 True True \n",
"2046 True True \n",
"2045 True True \n",
"2044 True True \n",
"2037 True True \n",
"2031 True True "
]
},
"execution_count": 21,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Create DataFrame with results\n",
"results_df = pd.DataFrame(data, columns=['n', 'r2adj', 'AIC'] + sorted(allVariables))\n",
"\n",
"best_models = results_df.loc[results_df.groupby('n')['r2adj'].idxmax()] # Get the best model for each subset size\n",
"\n",
"# Sort by number of features\n",
"best_models.sort_values(by='n')"
]
},
{
"cell_type": "markdown",
"id": "bb55159c-0fa1-48d5-887c-f717e75fc17f",
"metadata": {},
"source": [
"#### Iterative Features Selection"
]
},
{
"cell_type": "markdown",
"id": "fd11aa92-b061-4c6b-84de-2d19c11ea6db",
"metadata": {},
"source": [
"#### Forward Selection"
]
},
{
"cell_type": "code",
"execution_count": 24,
"id": "36a898ec-59fa-4ad2-b0d9-5bf1032d2f61",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Added Feature: Age_08_04, Adjusted R²: 0.7659\n",
"Added Feature: HP, Adjusted R²: 0.8008\n",
"Added Feature: Weight, Adjusted R²: 0.8327\n",
"Added Feature: KM, Adjusted R²: 0.8641\n",
"Added Feature: Fuel_Type_Petrol, Adjusted R²: 0.8724\n",
"Added Feature: Quarterly_Tax, Adjusted R²: 0.8794\n",
"Added Feature: Doors, Adjusted R²: 0.8823\n",
"Added Feature: Fuel_Type_Diesel, Adjusted R²: 0.8834\n",
"\n",
"Selected Features: ['Age_08_04', 'HP', 'Weight', 'KM', 'Fuel_Type_Petrol', 'Quarterly_Tax', 'Doors', 'Fuel_Type_Diesel']\n",
"\n",
"Final Model Performance:\n",
"Adjusted R² (Training Set): 0.8834\n",
"Adjusted R² (Test Set): 0.8217\n"
]
}
],
"source": [
"def forward_feature_selection(X, y):\n",
" selected_features = []\n",
" remaining_features = list(X.columns)\n",
" best_score = -np.inf # Start with a very low Adjusted R²\n",
" best_features = None\n",
" \n",
" while remaining_features:\n",
" scores = []\n",
" \n",
" for feature in remaining_features:\n",
" temp_features = selected_features + [feature]\n",
" model = LinearRegression()\n",
" model.fit(X[temp_features], y)\n",
" y_pred = model.predict(X[temp_features])\n",
" adj_r2 = adjusted_r2_score(y, y_pred, model) # Compute Adjusted R²\n",
" scores.append((feature, adj_r2))\n",
" \n",
" # Select the feature that maximizes Adjusted R²\n",
" scores.sort(key=lambda x: x[1], reverse=True)\n",
" best_new_feature, best_new_score = scores[0]\n",
" \n",
" # Stop if Adjusted R² does not improve significantly\n",
" if best_new_score <= best_score:\n",
" break\n",
" \n",
" selected_features.append(best_new_feature)\n",
" remaining_features.remove(best_new_feature)\n",
" best_score = best_new_score\n",
" best_features = selected_features.copy()\n",
" \n",
" print(f\"Added Feature: {best_new_feature}, Adjusted R²: {best_score:.4f}\")\n",
" \n",
" return best_features\n",
"\n",
"# Run forward feature selection\n",
"best_selected_features = forward_feature_selection(train_X, train_y)\n",
"\n",
"print(\"\\nSelected Features:\", best_selected_features)\n",
"\n",
"# Fit final model with selected features\n",
"final_model = LinearRegression()\n",
"final_model.fit(train_X[best_selected_features], train_y)\n",
"\n",
"# Predict on train and test sets\n",
"train_pred = final_model.predict(train_X[best_selected_features])\n",
"test_pred = final_model.predict(test_X[best_selected_features])\n",
"\n",
"# Compute performance metrics\n",
"train_adj_r2 = adjusted_r2_score(train_y, train_pred, final_model)\n",
"test_adj_r2 = adjusted_r2_score(test_y, test_pred, final_model)\n",
"\n",
"print(f\"\\nFinal Model Performance:\")\n",
"print(f\"Adjusted R² (Training Set): {train_adj_r2:.4f}\")\n",
"print(f\"Adjusted R² (Test Set): {test_adj_r2:.4f}\")"
]
},
{
"cell_type": "code",
"execution_count": 25,
"id": "b8eb5230-2a5e-49da-b066-4a0d186b9cb3",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"Performance Measures - Test Set\n",
"Mean Absolute Error: 1016.99\n",
"Mean Absolute Percentage Error: 9.83%\n",
"Root Mean Squared Error: 1592.14\n"
]
}
],
"source": [
"# Evaluating Performance\n",
"# Test Set\n",
"mae = metrics.mean_absolute_error(test_y,test_pred)\n",
"mape = metrics.mean_absolute_percentage_error(test_y, test_pred)\n",
"mse = metrics.mean_squared_error(test_y, test_pred)\n",
"rmse = np.sqrt(mse)\n",
"print('\\nPerformance Measures - Test Set')\n",
"print(f'Mean Absolute Error: {mae:.2f}')\n",
"print(f'Mean Absolute Percentage Error: {mape*100:.2f}%')\n",
"print(f'Root Mean Squared Error: {rmse:.2f}')"
]
},
{
"cell_type": "markdown",
"id": "71be37ef-5039-4c56-a163-c9ec792b56e8",
"metadata": {},
"source": [
"#### Backward Selection"
]
},
{
"cell_type": "code",
"execution_count": 27,
"id": "8c9ae645-cb54-4014-9a3a-48d4318ed91a",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Removed Feature: CC, Adjusted R²: 0.8833\n",
"Removed Feature: HP, Adjusted R²: 0.8834\n",
"Removed Feature: Met_Color, Adjusted R²: 0.8834\n",
"Removed Feature: Automatic, Adjusted R²: 0.8834\n",
"\n",
"Selected Features: ['Age_08_04', 'KM', 'Doors', 'Quarterly_Tax', 'Weight', 'Fuel_Type_Diesel', 'Fuel_Type_Petrol']\n",
"\n",
"Final Model Performance:\n",
"Adjusted R² (Training Set): 0.8834\n",
"Adjusted R² (Test Set): 0.8188\n"
]
}
],
"source": [
"def backward_feature_selection(X, y):\n",
" selected_features = list(X.columns) # Start with all features\n",
" best_score = adjusted_r2_score(y, LinearRegression().fit(X, y).predict(X), LinearRegression().fit(X, y)) # Initial Adjusted R²\n",
" best_features = selected_features.copy()\n",
"\n",
" while len(selected_features) > 1:\n",
" scores = []\n",
" \n",
" for feature in selected_features:\n",
" temp_features = [f for f in selected_features if f != feature] # Remove one feature at a time\n",
" model = LinearRegression()\n",
" model.fit(X[temp_features], y)\n",
" y_pred = model.predict(X[temp_features])\n",
" adj_r2 = adjusted_r2_score(y, y_pred, model) # Compute Adjusted R²\n",
" scores.append((feature, adj_r2))\n",
" \n",
" # Find the worst-performing feature (one whose removal improves Adjusted R²)\n",
" scores.sort(key=lambda x: x[1], reverse=True)\n",
" worst_feature, best_new_score = scores[0] # The last item has the lowest impact\n",
" \n",
" # Stop if Adjusted R² does not improve\n",
" \n",
" if best_new_score > best_score:\n",
" selected_features.remove(worst_feature)\n",
" best_score = best_new_score\n",
" best_features = selected_features.copy()\n",
" print(f\"Removed Feature: {worst_feature}, Adjusted R²: {best_score:.4f}\")\n",
" else:\n",
" break \n",
" \n",
" return best_features\n",
"\n",
"# Run backward feature selection\n",
"best_selected_features = backward_feature_selection(train_X, train_y)\n",
"\n",
"print(\"\\nSelected Features:\", best_selected_features)\n",
"\n",
"# Fit final model with selected features\n",
"final_model = LinearRegression()\n",
"final_model.fit(train_X[best_selected_features], train_y)\n",
"\n",
"# Predict on train and test sets\n",
"train_pred = final_model.predict(train_X[best_selected_features])\n",
"test_pred = final_model.predict(test_X[best_selected_features])\n",
"\n",
"# Compute performance metrics\n",
"train_adj_r2 = adjusted_r2_score(train_y, train_pred, final_model)\n",
"test_adj_r2 = adjusted_r2_score(test_y, test_pred, final_model)\n",
"\n",
"print(f\"\\nFinal Model Performance:\")\n",
"print(f\"Adjusted R² (Training Set): {train_adj_r2:.4f}\")\n",
"print(f\"Adjusted R² (Test Set): {test_adj_r2:.4f}\")"
]
},
{
"cell_type": "markdown",
"id": "fe089eca-55c5-42d7-9ade-f4eddac792eb",
"metadata": {},
"source": [
"#### Stepwise Regression Function (Forward + Backward Selection)"
]
},
{
"cell_type": "code",
"execution_count": 29,
"id": "e616bae3-0ff3-4a1c-9a2e-001c14724526",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Added Feature: Age_08_04, Adjusted R²: 0.7659\n",
"Added Feature: HP, Adjusted R²: 0.8008\n",
"Added Feature: Weight, Adjusted R²: 0.8327\n",
"Added Feature: KM, Adjusted R²: 0.8641\n",
"Added Feature: Fuel_Type_Petrol, Adjusted R²: 0.8724\n",
"Added Feature: Quarterly_Tax, Adjusted R²: 0.8794\n",
"Added Feature: Doors, Adjusted R²: 0.8823\n",
"Added Feature: Fuel_Type_Diesel, Adjusted R²: 0.8834\n",
"\n",
"Selected Features: ['Age_08_04', 'HP', 'Weight', 'KM', 'Fuel_Type_Petrol', 'Quarterly_Tax', 'Doors', 'Fuel_Type_Diesel']\n",
"\n",
"Final Model Performance:\n",
"Adjusted R² (Training Set): 0.8834\n",
"Adjusted R² (Test Set): 0.8217\n"
]
}
],
"source": [
"def stepwise_regression(X, y):\n",
" selected_features = [] # Start with an empty set of features\n",
" remaining_features = list(X.columns)\n",
" best_score = -np.inf\n",
" best_features = None\n",
" improved = True # Flag to track if improvement happens\n",
"\n",
" while improved:\n",
" improved = False # Reset improvement flag\n",
" \n",
" # FORWARD STEP: Try adding a new feature\n",
" forward_scores = []\n",
" for feature in remaining_features:\n",
" temp_features = selected_features + [feature]\n",
" model = LinearRegression()\n",
" model.fit(X[temp_features], y)\n",
" y_pred = model.predict(X[temp_features])\n",
" adj_r2 = adjusted_r2_score(y, y_pred, model)\n",
" forward_scores.append((feature, adj_r2))\n",
" \n",
" # Pick the feature that gives the best improvement\n",
" if forward_scores:\n",
" forward_scores.sort(key=lambda x: x[1], reverse=True)\n",
" best_new_feature, best_new_score = forward_scores[0]\n",
" \n",
" if best_new_score > best_score: # Add feature if Adjusted R² improves\n",
" selected_features.append(best_new_feature)\n",
" remaining_features.remove(best_new_feature)\n",
" best_score = best_new_score\n",
" improved = True\n",
" print(f\"Added Feature: {best_new_feature}, Adjusted R²: {best_score:.4f}\")\n",
"\n",
" # BACKWARD STEP: Try removing a feature\n",
" backward_scores = []\n",
" for feature in selected_features:\n",
" temp_features = [f for f in selected_features if f != feature]\n",
" if not temp_features: # Ensure at least one feature is selected\n",
" continue\n",
" model = LinearRegression()\n",
" model.fit(X[temp_features], y)\n",
" y_pred = model.predict(X[temp_features])\n",
" adj_r2 = adjusted_r2_score(y, y_pred, model)\n",
" backward_scores.append((feature, adj_r2))\n",
" \n",
" # Remove the worst-performing feature if it improves Adjusted R²\n",
" if backward_scores:\n",
" backward_scores.sort(key=lambda x: x[1], reverse=True)\n",
" worst_feature, best_new_score = backward_scores[-1] # The last item has the lowest impact\n",
" \n",
" if best_new_score > best_score: # Remove feature if Adjusted R² improves\n",
" selected_features.remove(worst_feature)\n",
" remaining_features.append(worst_feature)\n",
" best_score = best_new_score\n",
" improved = True\n",
" print(f\"Removed Feature: {worst_feature}, Adjusted R²: {best_score:.4f}\")\n",
"\n",
" return selected_features\n",
"\n",
"# Run stepwise regression\n",
"best_selected_features = stepwise_regression(train_X, train_y)\n",
"\n",
"print(\"\\nSelected Features:\", best_selected_features)\n",
"\n",
"# Fit final model with selected features\n",
"final_model = LinearRegression()\n",
"final_model.fit(train_X[best_selected_features], train_y)\n",
"\n",
"# Predict on train and test sets\n",
"train_pred = final_model.predict(train_X[best_selected_features])\n",
"test_pred = final_model.predict(test_X[best_selected_features])\n",
"\n",
"# Compute performance metrics\n",
"train_adj_r2 = adjusted_r2_score(train_y, train_pred, final_model)\n",
"test_adj_r2 = adjusted_r2_score(test_y, test_pred, final_model)\n",
"\n",
"print(f\"\\nFinal Model Performance:\")\n",
"print(f\"Adjusted R² (Training Set): {train_adj_r2:.4f}\")\n",
"print(f\"Adjusted R² (Test Set): {test_adj_r2:.4f}\")"
]
},
{
"cell_type": "markdown",
"id": "1b52b955-5636-4a68-a3d9-28dc6d582acd",
"metadata": {},
"source": [
"#### REGULARIZATION"
]
},
{
"cell_type": "code",
"execution_count": 31,
"id": "28cb0ca7-a200-45df-a90c-6a0bf5f442ef",
"metadata": {},
"outputs": [],
"source": [
"# Standardize features (since regularization methods are sensitive to feature scaling)\n"
]
},
{
"cell_type": "markdown",
"id": "01163fbc-5066-46ed-bf9e-cac402f896d3",
"metadata": {},
"source": [
"#### Lasso Method"
]
},
{
"cell_type": "code",
"execution_count": 56,
"id": "01f016c7-ca0c-4ccf-a33e-a89ae5d35c31",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"Performance Measures - Test Set\n",
"Mean Absolute Error: 1017.99\n",
"Mean Absolute Percentage Error: 9.85%\n",
"Root Mean Squared Error: 1602.96\n"
]
}
],
"source": [
"# Fit Lasso model: given alpha\n",
"\n",
"\n",
"# Test Set\n",
"mae = metrics.mean_absolute_error(test_y,lasso.predict(test_X_scaled))\n",
"mape = metrics.mean_absolute_percentage_error(test_y, lasso.predict(test_X_scaled))\n",
"mse = metrics.mean_squared_error(test_y, lasso.predict(test_X_scaled))\n",
"rmse = np.sqrt(mse)\n",
"print('\\nPerformance Measures - Test Set')\n",
"print(f'Mean Absolute Error: {mae:.2f}')\n",
"print(f'Mean Absolute Percentage Error: {mape*100:.2f}%')\n",
"print(f'Root Mean Squared Error: {rmse:.2f}')"
]
},
{
"cell_type": "code",
"execution_count": 58,
"id": "fc2937a5-5b72-4c0a-9a5e-f0195bc5c25b",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"Performance Measures - Test Set\n",
"Mean Absolute Error: 1004.52\n",
"Mean Absolute Percentage Error: 9.71%\n",
"Root Mean Squared Error: 1527.54\n",
"Lasso-CV chosen regularization: 32.8906\n"
]
},
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" \n",
" Feature \n",
" Lasso_Coefficient \n",
" \n",
" \n",
" \n",
" \n",
" 0 \n",
" Age_08_04 \n",
" -2064.078027 \n",
" \n",
" \n",
" 1 \n",
" KM \n",
" -605.185323 \n",
" \n",
" \n",
" 2 \n",
" HP \n",
" 122.425179 \n",
" \n",
" \n",
" 3 \n",
" Met_Color \n",
" -0.000000 \n",
" \n",
" \n",
" 4 \n",
" Automatic \n",
" -0.000000 \n",
" \n",
" \n",
" 5 \n",
" CC \n",
" -0.000000 \n",
" \n",
" \n",
" 6 \n",
" Doors \n",
" -151.531573 \n",
" \n",
" \n",
" 7 \n",
" Quarterly_Tax \n",
" 408.213102 \n",
" \n",
" \n",
" 8 \n",
" Weight \n",
" 1346.496654 \n",
" \n",
" \n",
" 9 \n",
" Fuel_Type_Diesel \n",
" -246.661435 \n",
" \n",
" \n",
" 10 \n",
" Fuel_Type_Petrol \n",
" 716.945506 \n",
" \n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Feature Lasso_Coefficient\n",
"0 Age_08_04 -2064.078027\n",
"1 KM -605.185323\n",
"2 HP 122.425179\n",
"3 Met_Color -0.000000\n",
"4 Automatic -0.000000\n",
"5 CC -0.000000\n",
"6 Doors -151.531573\n",
"7 Quarterly_Tax 408.213102\n",
"8 Weight 1346.496654\n",
"9 Fuel_Type_Diesel -246.661435\n",
"10 Fuel_Type_Petrol 716.945506"
]
},
"execution_count": 58,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Fit Lasso model: use cross-validation to determine alpha\n",
"\n",
"lassoCV.fit(train_X_scaled, train_y)\n",
"\n",
"# Test Set\n",
"mae = metrics.mean_absolute_error(test_y,lassoCV.predict(test_X_scaled))\n",
"mape = metrics.mean_absolute_percentage_error(test_y, lassoCV.predict(test_X_scaled))\n",
"mse = metrics.mean_squared_error(test_y, lassoCV.predict(test_X_scaled))\n",
"rmse = np.sqrt(mse)\n",
"print('\\nPerformance Measures - Test Set')\n",
"print(f'Mean Absolute Error: {mae:.2f}')\n",
"print(f'Mean Absolute Percentage Error: {mape*100:.2f}%')\n",
"print(f'Root Mean Squared Error: {rmse:.2f}')\n",
"print(f'Lasso-CV chosen regularization: {lassoCV.alpha_:.4f}')\n",
"\n",
"lasso_coef_df = pd.DataFrame({\n",
" \"Feature\": train_X.columns,\n",
" \"Lasso_Coefficient\": lassoCV.coef_\n",
"})\n",
"lasso_coef_df"
]
},
{
"cell_type": "markdown",
"id": "1760bbc0-5fb0-4575-8f69-06145d6432bb",
"metadata": {},
"source": [
"#### Ridge Method"
]
},
{
"cell_type": "code",
"execution_count": 60,
"id": "cccd8ecf-a9cf-41ad-8f9b-94d0b7632e34",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"Performance Measures - Test Set\n",
"Mean Absolute Error: 1018.24\n",
"Mean Absolute Percentage Error: 9.85%\n",
"Root Mean Squared Error: 1602.86\n"
]
}
],
"source": [
"# Fit Ridge model: given alpha\n",
"\n",
"\n",
"# Test Set\n",
"mae = metrics.mean_absolute_error(test_y,ridge.predict(test_X_scaled))\n",
"mape = metrics.mean_absolute_percentage_error(test_y, ridge.predict(test_X_scaled))\n",
"mse = metrics.mean_squared_error(test_y, ridge.predict(test_X_scaled))\n",
"rmse = np.sqrt(mse)\n",
"print('\\nPerformance Measures - Test Set')\n",
"print(f'Mean Absolute Error: {mae:.2f}')\n",
"print(f'Mean Absolute Percentage Error: {mape*100:.2f}%')\n",
"print(f'Root Mean Squared Error: {rmse:.2f}')"
]
},
{
"cell_type": "code",
"execution_count": 62,
"id": "39119203-7877-4998-a7b9-cfcda9a581c0",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"Performance Measures - Test Set\n",
"Mean Absolute Error: 1017.84\n",
"Mean Absolute Percentage Error: 9.85%\n",
"Root Mean Squared Error: 1600.13\n",
"Bayesian Ridge chosen regularization: 1.9180\n"
]
},
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" \n",
" Feature \n",
" Bayesian_Ridge_Coefficient \n",
" \n",
" \n",
" \n",
" \n",
" 0 \n",
" Age_08_04 \n",
" -2043.218002 \n",
" \n",
" \n",
" 1 \n",
" KM \n",
" -595.632852 \n",
" \n",
" \n",
" 2 \n",
" HP \n",
" 44.540875 \n",
" \n",
" \n",
" 3 \n",
" Met_Color \n",
" -33.249048 \n",
" \n",
" \n",
" 4 \n",
" Automatic \n",
" -33.543001 \n",
" \n",
" \n",
" 5 \n",
" CC \n",
" -19.911395 \n",
" \n",
" \n",
" 6 \n",
" Doors \n",
" -233.314366 \n",
" \n",
" \n",
" 7 \n",
" Quarterly_Tax \n",
" 592.973300 \n",
" \n",
" \n",
" 8 \n",
" Weight \n",
" 1504.044958 \n",
" \n",
" \n",
" 9 \n",
" Fuel_Type_Diesel \n",
" -400.972781 \n",
" \n",
" \n",
" 10 \n",
" Fuel_Type_Petrol \n",
" 892.664894 \n",
" \n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Feature Bayesian_Ridge_Coefficient\n",
"0 Age_08_04 -2043.218002\n",
"1 KM -595.632852\n",
"2 HP 44.540875\n",
"3 Met_Color -33.249048\n",
"4 Automatic -33.543001\n",
"5 CC -19.911395\n",
"6 Doors -233.314366\n",
"7 Quarterly_Tax 592.973300\n",
"8 Weight 1504.044958\n",
"9 Fuel_Type_Diesel -400.972781\n",
"10 Fuel_Type_Petrol 892.664894"
]
},
"execution_count": 62,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Fit Ridge model: use Bayesian method to determine alpha\n",
"\n",
"ridgeB.fit(train_X_scaled, train_y)\n",
"\n",
"# Test Set\n",
"mae = metrics.mean_absolute_error(test_y,ridgeB.predict(test_X_scaled))\n",
"mape = metrics.mean_absolute_percentage_error(test_y, ridgeB.predict(test_X_scaled))\n",
"mse = metrics.mean_squared_error(test_y, ridgeB.predict(test_X_scaled))\n",
"rmse = np.sqrt(mse)\n",
"print('\\nPerformance Measures - Test Set')\n",
"print(f'Mean Absolute Error: {mae:.2f}')\n",
"print(f'Mean Absolute Percentage Error: {mape*100:.2f}%')\n",
"print(f'Root Mean Squared Error: {rmse:.2f}')\n",
"regularization_strength = ridgeB.lambda_ / ridgeB.alpha_\n",
"print(f'Bayesian Ridge chosen regularization: {regularization_strength:.4f}')\n",
"\n",
"ridge_coef_df = pd.DataFrame({\n",
" \"Feature\": train_X.columns,\n",
" \"Bayesian_Ridge_Coefficient\": ridgeB.coef_\n",
"})\n",
"ridge_coef_df"
]
},
{
"cell_type": "markdown",
"id": "7d3a79f6-3b19-4114-b9c5-3f817136f3e3",
"metadata": {},
"source": [
"### OLS REGRESSION"
]
},
{
"cell_type": "code",
"execution_count": 65,
"id": "2bd73a22-a02d-4df0-b52b-94ce8866ce91",
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": 67,
"id": "8d1c84d2-a782-4569-9ef1-7de66a96c9c4",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"OLS Regression Results \n",
"\n",
" Dep. Variable: Price R-squared: 0.869 \n",
" \n",
"\n",
" Model: OLS Adj. R-squared: 0.868 \n",
" \n",
"\n",
" Method: Least Squares F-statistic: 859.6 \n",
" \n",
"\n",
" Date: Mon, 17 Mar 2025 Prob (F-statistic): 0.00 \n",
" \n",
"\n",
" Time: 18:50:19 Log-Likelihood: -12347. \n",
" \n",
"\n",
" No. Observations: 1436 AIC: 2.472e+04 \n",
" \n",
"\n",
" Df Residuals: 1424 BIC: 2.478e+04 \n",
" \n",
"\n",
" Df Model: 11 \n",
" \n",
"\n",
" Covariance Type: nonrobust \n",
" \n",
"
\n",
"\n",
"\n",
" coef std err t P>|t| [0.025 0.975] \n",
" \n",
"\n",
" Intercept -7325.9928 1231.633 -5.948 0.000 -9742.002 -4909.984 \n",
" \n",
"\n",
" Fuel_Type_Diesel[T.True] 627.9746 375.764 1.671 0.095 -109.136 1365.085 \n",
" \n",
"\n",
" Fuel_Type_Petrol[T.True] 2420.3110 368.314 6.571 0.000 1697.815 3142.807 \n",
" \n",
"\n",
" Age_08_04 -123.1200 2.596 -47.421 0.000 -128.213 -118.027 \n",
" \n",
"\n",
" KM -0.0169 0.001 -12.901 0.000 -0.019 -0.014 \n",
" \n",
"\n",
" HP 23.8514 3.466 6.881 0.000 17.052 30.651 \n",
" \n",
"\n",
" Met_Color 36.2887 74.966 0.484 0.628 -110.767 183.344 \n",
" \n",
"\n",
" Automatic 258.8277 157.775 1.640 0.101 -50.669 568.324 \n",
" \n",
"\n",
" CC -0.0627 0.091 -0.692 0.489 -0.241 0.115 \n",
" \n",
"\n",
" Doors -71.6120 39.658 -1.806 0.071 -149.407 6.183 \n",
" \n",
"\n",
" Quarterly_Tax 12.3125 1.650 7.463 0.000 9.076 15.549 \n",
" \n",
"\n",
" Weight 19.3566 1.218 15.894 0.000 16.968 21.746 \n",
" \n",
"
\n",
"\n",
"\n",
" Omnibus: 203.998 Durbin-Watson: 1.594 \n",
" \n",
"\n",
" Prob(Omnibus): 0.000 Jarque-Bera (JB): 2183.722 \n",
" \n",
"\n",
" Skew: -0.248 Prob(JB): 0.00 \n",
" \n",
"\n",
" Kurtosis: 9.021 Cond. No. 2.79e+06 \n",
" \n",
"
Notes: [1] Standard Errors assume that the covariance matrix of the errors is correctly specified. [2] The condition number is large, 2.79e+06. This might indicate that there are strong multicollinearity or other numerical problems."
],
"text/latex": [
"\\begin{center}\n",
"\\begin{tabular}{lclc}\n",
"\\toprule\n",
"\\textbf{Dep. Variable:} & Price & \\textbf{ R-squared: } & 0.869 \\\\\n",
"\\textbf{Model:} & OLS & \\textbf{ Adj. R-squared: } & 0.868 \\\\\n",
"\\textbf{Method:} & Least Squares & \\textbf{ F-statistic: } & 859.6 \\\\\n",
"\\textbf{Date:} & Mon, 17 Mar 2025 & \\textbf{ Prob (F-statistic):} & 0.00 \\\\\n",
"\\textbf{Time:} & 18:50:19 & \\textbf{ Log-Likelihood: } & -12347. \\\\\n",
"\\textbf{No. Observations:} & 1436 & \\textbf{ AIC: } & 2.472e+04 \\\\\n",
"\\textbf{Df Residuals:} & 1424 & \\textbf{ BIC: } & 2.478e+04 \\\\\n",
"\\textbf{Df Model:} & 11 & \\textbf{ } & \\\\\n",
"\\textbf{Covariance Type:} & nonrobust & \\textbf{ } & \\\\\n",
"\\bottomrule\n",
"\\end{tabular}\n",
"\\begin{tabular}{lcccccc}\n",
" & \\textbf{coef} & \\textbf{std err} & \\textbf{t} & \\textbf{P$> |$t$|$} & \\textbf{[0.025} & \\textbf{0.975]} \\\\\n",
"\\midrule\n",
"\\textbf{Intercept} & -7325.9928 & 1231.633 & -5.948 & 0.000 & -9742.002 & -4909.984 \\\\\n",
"\\textbf{Fuel\\_Type\\_Diesel[T.True]} & 627.9746 & 375.764 & 1.671 & 0.095 & -109.136 & 1365.085 \\\\\n",
"\\textbf{Fuel\\_Type\\_Petrol[T.True]} & 2420.3110 & 368.314 & 6.571 & 0.000 & 1697.815 & 3142.807 \\\\\n",
"\\textbf{Age\\_08\\_04} & -123.1200 & 2.596 & -47.421 & 0.000 & -128.213 & -118.027 \\\\\n",
"\\textbf{KM} & -0.0169 & 0.001 & -12.901 & 0.000 & -0.019 & -0.014 \\\\\n",
"\\textbf{HP} & 23.8514 & 3.466 & 6.881 & 0.000 & 17.052 & 30.651 \\\\\n",
"\\textbf{Met\\_Color} & 36.2887 & 74.966 & 0.484 & 0.628 & -110.767 & 183.344 \\\\\n",
"\\textbf{Automatic} & 258.8277 & 157.775 & 1.640 & 0.101 & -50.669 & 568.324 \\\\\n",
"\\textbf{CC} & -0.0627 & 0.091 & -0.692 & 0.489 & -0.241 & 0.115 \\\\\n",
"\\textbf{Doors} & -71.6120 & 39.658 & -1.806 & 0.071 & -149.407 & 6.183 \\\\\n",
"\\textbf{Quarterly\\_Tax} & 12.3125 & 1.650 & 7.463 & 0.000 & 9.076 & 15.549 \\\\\n",
"\\textbf{Weight} & 19.3566 & 1.218 & 15.894 & 0.000 & 16.968 & 21.746 \\\\\n",
"\\bottomrule\n",
"\\end{tabular}\n",
"\\begin{tabular}{lclc}\n",
"\\textbf{Omnibus:} & 203.998 & \\textbf{ Durbin-Watson: } & 1.594 \\\\\n",
"\\textbf{Prob(Omnibus):} & 0.000 & \\textbf{ Jarque-Bera (JB): } & 2183.722 \\\\\n",
"\\textbf{Skew:} & -0.248 & \\textbf{ Prob(JB): } & 0.00 \\\\\n",
"\\textbf{Kurtosis:} & 9.021 & \\textbf{ Cond. No. } & 2.79e+06 \\\\\n",
"\\bottomrule\n",
"\\end{tabular}\n",
"%\\caption{OLS Regression Results}\n",
"\\end{center}\n",
"\n",
"Notes: \\newline\n",
" [1] Standard Errors assume that the covariance matrix of the errors is correctly specified. \\newline\n",
" [2] The condition number is large, 2.79e+06. This might indicate that there are \\newline\n",
" strong multicollinearity or other numerical problems."
],
"text/plain": [
"\n",
"\"\"\"\n",
" OLS Regression Results \n",
"==============================================================================\n",
"Dep. Variable: Price R-squared: 0.869\n",
"Model: OLS Adj. R-squared: 0.868\n",
"Method: Least Squares F-statistic: 859.6\n",
"Date: Mon, 17 Mar 2025 Prob (F-statistic): 0.00\n",
"Time: 18:50:19 Log-Likelihood: -12347.\n",
"No. Observations: 1436 AIC: 2.472e+04\n",
"Df Residuals: 1424 BIC: 2.478e+04\n",
"Df Model: 11 \n",
"Covariance Type: nonrobust \n",
"============================================================================================\n",
" coef std err t P>|t| [0.025 0.975]\n",
"--------------------------------------------------------------------------------------------\n",
"Intercept -7325.9928 1231.633 -5.948 0.000 -9742.002 -4909.984\n",
"Fuel_Type_Diesel[T.True] 627.9746 375.764 1.671 0.095 -109.136 1365.085\n",
"Fuel_Type_Petrol[T.True] 2420.3110 368.314 6.571 0.000 1697.815 3142.807\n",
"Age_08_04 -123.1200 2.596 -47.421 0.000 -128.213 -118.027\n",
"KM -0.0169 0.001 -12.901 0.000 -0.019 -0.014\n",
"HP 23.8514 3.466 6.881 0.000 17.052 30.651\n",
"Met_Color 36.2887 74.966 0.484 0.628 -110.767 183.344\n",
"Automatic 258.8277 157.775 1.640 0.101 -50.669 568.324\n",
"CC -0.0627 0.091 -0.692 0.489 -0.241 0.115\n",
"Doors -71.6120 39.658 -1.806 0.071 -149.407 6.183\n",
"Quarterly_Tax 12.3125 1.650 7.463 0.000 9.076 15.549\n",
"Weight 19.3566 1.218 15.894 0.000 16.968 21.746\n",
"==============================================================================\n",
"Omnibus: 203.998 Durbin-Watson: 1.594\n",
"Prob(Omnibus): 0.000 Jarque-Bera (JB): 2183.722\n",
"Skew: -0.248 Prob(JB): 0.00\n",
"Kurtosis: 9.021 Cond. No. 2.79e+06\n",
"==============================================================================\n",
"\n",
"Notes:\n",
"[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.\n",
"[2] The condition number is large, 2.79e+06. This might indicate that there are\n",
"strong multicollinearity or other numerical problems.\n",
"\"\"\""
]
},
"execution_count": 67,
"metadata": {},
"output_type": "execute_result"
}
],
"source": []
},
{
"cell_type": "code",
"execution_count": 113,
"id": "0362501b-bfeb-4927-a873-81543963923e",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" \n",
" Age_08_04 \n",
" KM \n",
" HP \n",
" Quarterly_Tax \n",
" Weight \n",
" Fuel_Type_Petrol \n",
" Price \n",
" \n",
" \n",
" \n",
" \n",
" 0 \n",
" 23 \n",
" 46986 \n",
" 90 \n",
" 210 \n",
" 1165 \n",
" False \n",
" 13500 \n",
" \n",
" \n",
" 1 \n",
" 23 \n",
" 72937 \n",
" 90 \n",
" 210 \n",
" 1165 \n",
" False \n",
" 13750 \n",
" \n",
" \n",
" 2 \n",
" 24 \n",
" 41711 \n",
" 90 \n",
" 210 \n",
" 1165 \n",
" False \n",
" 13950 \n",
" \n",
" \n",
" 3 \n",
" 26 \n",
" 48000 \n",
" 90 \n",
" 210 \n",
" 1165 \n",
" False \n",
" 14950 \n",
" \n",
" \n",
" 4 \n",
" 30 \n",
" 38500 \n",
" 90 \n",
" 210 \n",
" 1170 \n",
" False \n",
" 13750 \n",
" \n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Age_08_04 KM HP Quarterly_Tax Weight Fuel_Type_Petrol Price\n",
"0 23 46986 90 210 1165 False 13500\n",
"1 23 72937 90 210 1165 False 13750\n",
"2 24 41711 90 210 1165 False 13950\n",
"3 26 48000 90 210 1165 False 14950\n",
"4 30 38500 90 210 1170 False 13750"
]
},
"execution_count": 113,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"\n",
"formula = 'Price ~' + '+'.join(predictors)"
]
},
{
"cell_type": "code",
"execution_count": 115,
"id": "c832c55b-e417-4063-9a58-d13eb774bd7f",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"OLS Regression Results \n",
"\n",
" Dep. Variable: Price R-squared: 0.868 \n",
" \n",
"\n",
" Model: OLS Adj. R-squared: 0.868 \n",
" \n",
"\n",
" Method: Least Squares F-statistic: 1569. \n",
" \n",
"\n",
" Date: Mon, 17 Mar 2025 Prob (F-statistic): 0.00 \n",
" \n",
"\n",
" Time: 19:01:35 Log-Likelihood: -12352. \n",
" \n",
"\n",
" No. Observations: 1436 AIC: 2.472e+04 \n",
" \n",
"\n",
" Df Residuals: 1429 BIC: 2.475e+04 \n",
" \n",
"\n",
" Df Model: 6 \n",
" \n",
"\n",
" Covariance Type: nonrobust \n",
" \n",
"
\n",
"\n",
"\n",
" coef std err t P>|t| [0.025 0.975] \n",
" \n",
"\n",
" Intercept -7162.2958 1186.423 -6.037 0.000 -9489.613 -4834.979 \n",
" \n",
"\n",
" Fuel_Type_Petrol[T.True] 1940.6025 250.039 7.761 0.000 1450.119 2431.086 \n",
" \n",
"\n",
" Age_08_04 -122.4599 2.571 -47.626 0.000 -127.504 -117.416 \n",
" \n",
"\n",
" KM -0.0172 0.001 -13.208 0.000 -0.020 -0.015 \n",
" \n",
"\n",
" HP 21.2704 3.095 6.872 0.000 15.199 27.342 \n",
" \n",
"\n",
" Quarterly_Tax 12.1300 1.650 7.351 0.000 8.893 15.367 \n",
" \n",
"\n",
" Weight 19.5809 1.074 18.240 0.000 17.475 21.687 \n",
" \n",
"
\n",
"\n",
"\n",
" Omnibus: 209.991 Durbin-Watson: 1.588 \n",
" \n",
"\n",
" Prob(Omnibus): 0.000 Jarque-Bera (JB): 2292.692 \n",
" \n",
"\n",
" Skew: -0.271 Prob(JB): 0.00 \n",
" \n",
"\n",
" Kurtosis: 9.166 Cond. No. 2.68e+06 \n",
" \n",
"
Notes: [1] Standard Errors assume that the covariance matrix of the errors is correctly specified. [2] The condition number is large, 2.68e+06. This might indicate that there are strong multicollinearity or other numerical problems."
],
"text/latex": [
"\\begin{center}\n",
"\\begin{tabular}{lclc}\n",
"\\toprule\n",
"\\textbf{Dep. Variable:} & Price & \\textbf{ R-squared: } & 0.868 \\\\\n",
"\\textbf{Model:} & OLS & \\textbf{ Adj. R-squared: } & 0.868 \\\\\n",
"\\textbf{Method:} & Least Squares & \\textbf{ F-statistic: } & 1569. \\\\\n",
"\\textbf{Date:} & Mon, 17 Mar 2025 & \\textbf{ Prob (F-statistic):} & 0.00 \\\\\n",
"\\textbf{Time:} & 19:01:35 & \\textbf{ Log-Likelihood: } & -12352. \\\\\n",
"\\textbf{No. Observations:} & 1436 & \\textbf{ AIC: } & 2.472e+04 \\\\\n",
"\\textbf{Df Residuals:} & 1429 & \\textbf{ BIC: } & 2.475e+04 \\\\\n",
"\\textbf{Df Model:} & 6 & \\textbf{ } & \\\\\n",
"\\textbf{Covariance Type:} & nonrobust & \\textbf{ } & \\\\\n",
"\\bottomrule\n",
"\\end{tabular}\n",
"\\begin{tabular}{lcccccc}\n",
" & \\textbf{coef} & \\textbf{std err} & \\textbf{t} & \\textbf{P$> |$t$|$} & \\textbf{[0.025} & \\textbf{0.975]} \\\\\n",
"\\midrule\n",
"\\textbf{Intercept} & -7162.2958 & 1186.423 & -6.037 & 0.000 & -9489.613 & -4834.979 \\\\\n",
"\\textbf{Fuel\\_Type\\_Petrol[T.True]} & 1940.6025 & 250.039 & 7.761 & 0.000 & 1450.119 & 2431.086 \\\\\n",
"\\textbf{Age\\_08\\_04} & -122.4599 & 2.571 & -47.626 & 0.000 & -127.504 & -117.416 \\\\\n",
"\\textbf{KM} & -0.0172 & 0.001 & -13.208 & 0.000 & -0.020 & -0.015 \\\\\n",
"\\textbf{HP} & 21.2704 & 3.095 & 6.872 & 0.000 & 15.199 & 27.342 \\\\\n",
"\\textbf{Quarterly\\_Tax} & 12.1300 & 1.650 & 7.351 & 0.000 & 8.893 & 15.367 \\\\\n",
"\\textbf{Weight} & 19.5809 & 1.074 & 18.240 & 0.000 & 17.475 & 21.687 \\\\\n",
"\\bottomrule\n",
"\\end{tabular}\n",
"\\begin{tabular}{lclc}\n",
"\\textbf{Omnibus:} & 209.991 & \\textbf{ Durbin-Watson: } & 1.588 \\\\\n",
"\\textbf{Prob(Omnibus):} & 0.000 & \\textbf{ Jarque-Bera (JB): } & 2292.692 \\\\\n",
"\\textbf{Skew:} & -0.271 & \\textbf{ Prob(JB): } & 0.00 \\\\\n",
"\\textbf{Kurtosis:} & 9.166 & \\textbf{ Cond. No. } & 2.68e+06 \\\\\n",
"\\bottomrule\n",
"\\end{tabular}\n",
"%\\caption{OLS Regression Results}\n",
"\\end{center}\n",
"\n",
"Notes: \\newline\n",
" [1] Standard Errors assume that the covariance matrix of the errors is correctly specified. \\newline\n",
" [2] The condition number is large, 2.68e+06. This might indicate that there are \\newline\n",
" strong multicollinearity or other numerical problems."
],
"text/plain": [
"\n",
"\"\"\"\n",
" OLS Regression Results \n",
"==============================================================================\n",
"Dep. Variable: Price R-squared: 0.868\n",
"Model: OLS Adj. R-squared: 0.868\n",
"Method: Least Squares F-statistic: 1569.\n",
"Date: Mon, 17 Mar 2025 Prob (F-statistic): 0.00\n",
"Time: 19:01:35 Log-Likelihood: -12352.\n",
"No. Observations: 1436 AIC: 2.472e+04\n",
"Df Residuals: 1429 BIC: 2.475e+04\n",
"Df Model: 6 \n",
"Covariance Type: nonrobust \n",
"============================================================================================\n",
" coef std err t P>|t| [0.025 0.975]\n",
"--------------------------------------------------------------------------------------------\n",
"Intercept -7162.2958 1186.423 -6.037 0.000 -9489.613 -4834.979\n",
"Fuel_Type_Petrol[T.True] 1940.6025 250.039 7.761 0.000 1450.119 2431.086\n",
"Age_08_04 -122.4599 2.571 -47.626 0.000 -127.504 -117.416\n",
"KM -0.0172 0.001 -13.208 0.000 -0.020 -0.015\n",
"HP 21.2704 3.095 6.872 0.000 15.199 27.342\n",
"Quarterly_Tax 12.1300 1.650 7.351 0.000 8.893 15.367\n",
"Weight 19.5809 1.074 18.240 0.000 17.475 21.687\n",
"==============================================================================\n",
"Omnibus: 209.991 Durbin-Watson: 1.588\n",
"Prob(Omnibus): 0.000 Jarque-Bera (JB): 2292.692\n",
"Skew: -0.271 Prob(JB): 0.00\n",
"Kurtosis: 9.166 Cond. No. 2.68e+06\n",
"==============================================================================\n",
"\n",
"Notes:\n",
"[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.\n",
"[2] The condition number is large, 2.68e+06. This might indicate that there are\n",
"strong multicollinearity or other numerical problems.\n",
"\"\"\""
]
},
"execution_count": 115,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"OLS_model = sm.ols(formula = formula, data = df1).fit()\n",
"OLS_model.summary()"
]
},
{
"cell_type": "code",
"execution_count": 119,
"id": "ca4faf6a-629f-4d71-8276-9b24a9c2dd8a",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"Performance Measures\n",
"Mean Absolute Error: 975.97\n",
"Mean Absolute Percentage Error: 9.64%\n",
"Root Mean Squared Error: 1316.14\n"
]
}
],
"source": [
"mae = metrics.mean_absolute_error(y,OLS_model.predict(X))\n",
"mape = metrics.mean_absolute_percentage_error(y, OLS_model.predict(X))\n",
"mse = metrics.mean_squared_error(y, OLS_model.predict(X))\n",
"rmse = np.sqrt(mse)\n",
"print('\\nPerformance Measures')\n",
"print(f'Mean Absolute Error: {mae:.2f}')\n",
"print(f'Mean Absolute Percentage Error: {mape*100:.2f}%')\n",
"print(f'Root Mean Squared Error: {rmse:.2f}')"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "7fa74bcf-3fbe-4a93-b7a7-5be1bd326ffe",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python [conda env:base] *",
"language": "python",
"name": "conda-base-py"
},
"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.12.7"
}
},
"nbformat": 4,
"nbformat_minor": 5
}