diff --git a/lab_4/lab_4.ipynb b/lab_4/lab_4.ipynb index d9069a0..50ade99 100644 --- a/lab_4/lab_4.ipynb +++ b/lab_4/lab_4.ipynb @@ -2,384 +2,9 @@ "cells": [ { "cell_type": "code", - "execution_count": 337, + "execution_count": 157, "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
iddatepricebedroomsbathroomssqft_livingsqft_lotfloorswaterfrontview...gradesqft_abovesqft_basementyr_builtyr_renovatedzipcodelatlongsqft_living15sqft_lot15
0712930052020141013T000000221900.031.00118056501.000...711800195509817847.5112-122.25713405650
1641410019220141209T000000538000.032.25257072422.000...72170400195119919812547.7210-122.31916907639
2563150040020150225T000000180000.021.00770100001.000...67700193309802847.7379-122.23327208062
3248720087520141209T000000604000.043.00196050001.000...71050910196509813647.5208-122.39313605000
4195440051020150218T000000510000.032.00168080801.000...816800198709807447.6168-122.04518007503
..................................................................
999532205926420140926T000000279000.021.001020470441.000...710200190419589804247.4206-122.155193012139
9996555750027020150209T000000262000.031.50170095791.000...71100600196209802347.3209-122.33817009628
9997916410012520140807T000000533000.041.00155047501.500...715500191909811747.6824-122.38913204750
9998737060004520150402T000000640000.031.75168081001.002...816800195009817747.7212-122.36418807750
9999859440006020140609T000000285000.032.251680351272.000...716800198709809247.3025-122.067182035166
\n", - "

10000 rows × 21 columns

\n", - "
" - ], - "text/plain": [ - " id date price bedrooms bathrooms sqft_living \\\n", - "0 7129300520 20141013T000000 221900.0 3 1.00 1180 \n", - "1 6414100192 20141209T000000 538000.0 3 2.25 2570 \n", - "2 5631500400 20150225T000000 180000.0 2 1.00 770 \n", - "3 2487200875 20141209T000000 604000.0 4 3.00 1960 \n", - "4 1954400510 20150218T000000 510000.0 3 2.00 1680 \n", - "... ... ... ... ... ... ... \n", - "9995 322059264 20140926T000000 279000.0 2 1.00 1020 \n", - "9996 5557500270 20150209T000000 262000.0 3 1.50 1700 \n", - "9997 9164100125 20140807T000000 533000.0 4 1.00 1550 \n", - "9998 7370600045 20150402T000000 640000.0 3 1.75 1680 \n", - "9999 8594400060 20140609T000000 285000.0 3 2.25 1680 \n", - "\n", - " sqft_lot floors waterfront view ... grade sqft_above \\\n", - "0 5650 1.0 0 0 ... 7 1180 \n", - "1 7242 2.0 0 0 ... 7 2170 \n", - "2 10000 1.0 0 0 ... 6 770 \n", - "3 5000 1.0 0 0 ... 7 1050 \n", - "4 8080 1.0 0 0 ... 8 1680 \n", - "... ... ... ... ... ... ... ... \n", - "9995 47044 1.0 0 0 ... 7 1020 \n", - "9996 9579 1.0 0 0 ... 7 1100 \n", - "9997 4750 1.5 0 0 ... 7 1550 \n", - "9998 8100 1.0 0 2 ... 8 1680 \n", - "9999 35127 2.0 0 0 ... 7 1680 \n", - "\n", - " sqft_basement yr_built yr_renovated zipcode lat long \\\n", - "0 0 1955 0 98178 47.5112 -122.257 \n", - "1 400 1951 1991 98125 47.7210 -122.319 \n", - "2 0 1933 0 98028 47.7379 -122.233 \n", - "3 910 1965 0 98136 47.5208 -122.393 \n", - "4 0 1987 0 98074 47.6168 -122.045 \n", - "... ... ... ... ... ... ... \n", - "9995 0 1904 1958 98042 47.4206 -122.155 \n", - "9996 600 1962 0 98023 47.3209 -122.338 \n", - "9997 0 1919 0 98117 47.6824 -122.389 \n", - "9998 0 1950 0 98177 47.7212 -122.364 \n", - "9999 0 1987 0 98092 47.3025 -122.067 \n", - "\n", - " sqft_living15 sqft_lot15 \n", - "0 1340 5650 \n", - "1 1690 7639 \n", - "2 2720 8062 \n", - "3 1360 5000 \n", - "4 1800 7503 \n", - "... ... ... \n", - "9995 1930 12139 \n", - "9996 1700 9628 \n", - "9997 1320 4750 \n", - "9998 1880 7750 \n", - "9999 1820 35166 \n", - "\n", - "[10000 rows x 21 columns]" - ] - }, - "execution_count": 337, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "import numpy as np\n", "import pandas as pd\n", @@ -387,9 +12,12 @@ "import seaborn as sns\n", "from sklearn.model_selection import train_test_split\n", "from sklearn import set_config\n", + "set_config(transform_output=\"pandas\")\n", "\n", - "df = pd.read_csv(\"data/house_data.csv\", sep=\",\", nrows=10000)\n", - "df.dropna()" + "random_state = 42\n", + "\n", + "# Подключим датафрейм и выгрузим данные\n", + "df = pd.read_csv(\"data/house_data.csv\")" ] }, { @@ -401,7 +29,7 @@ }, { "cell_type": "code", - "execution_count": 338, + "execution_count": 158, "metadata": {}, "outputs": [ { @@ -450,483 +78,483 @@ " \n", " \n", " \n", - " 9980\n", - " 6840700036\n", - " 20140728T000000\n", - " 497000.0\n", + " 21593\n", + " 8672200110\n", + " 20150317T000000\n", + " 1088000.0\n", + " 5\n", + " 3.75\n", + " 4170\n", + " 8142\n", + " 2.0\n", + " 0\n", " 2\n", - " 1.00\n", - " 770\n", - " 3325\n", - " 1.0\n", - " 0\n", - " 0\n", " ...\n", - " 770\n", - " 0\n", - " 1918\n", - " 0\n", - " 98122\n", - " 47.6102\n", - " -122.299\n", - " 960\n", - " 4800\n", - " middle\n", - " \n", - " \n", - " 9981\n", - " 1824069083\n", - " 20150429T000000\n", - " 835000.0\n", - " 3\n", - " 1.00\n", - " 3060\n", - " 30166\n", - " 1.0\n", - " 0\n", - " 0\n", - " ...\n", - " 3060\n", - " 0\n", - " 1959\n", - " 0\n", - " 98027\n", - " 47.5656\n", - " -122.093\n", - " 1880\n", - " 19602\n", - " high\n", - " \n", - " \n", - " 9982\n", - " 1836980240\n", - " 20141015T000000\n", - " 730000.0\n", - " 4\n", - " 2.75\n", - " 2920\n", - " 4500\n", - " 2.0\n", - " 0\n", - " 0\n", - " ...\n", - " 2920\n", - " 0\n", - " 1999\n", - " 0\n", - " 98006\n", - " 47.5646\n", - " -122.124\n", - " 2920\n", - " 4505\n", - " high\n", - " \n", - " \n", - " 9983\n", - " 3528900160\n", - " 20141001T000000\n", - " 655000.0\n", - " 3\n", - " 1.00\n", - " 1370\n", - " 5250\n", - " 1.0\n", - " 0\n", - " 0\n", - " ...\n", - " 1070\n", - " 300\n", - " 1939\n", - " 0\n", - " 98109\n", - " 47.6421\n", - " -122.348\n", - " 2410\n", - " 4200\n", - " high\n", - " \n", - " \n", - " 9984\n", - " 1442800060\n", - " 20141120T000000\n", - " 205000.0\n", - " 3\n", - " 2.50\n", - " 1870\n", - " 3118\n", - " 2.0\n", - " 0\n", - " 0\n", - " ...\n", - " 1870\n", - " 0\n", - " 1993\n", - " 0\n", - " 98038\n", - " 47.3739\n", - " -122.056\n", - " 1580\n", - " 3601\n", - " low\n", - " \n", - " \n", - " 9985\n", - " 8722100030\n", - " 20150407T000000\n", - " 632750.0\n", - " 4\n", - " 2.00\n", - " 1800\n", - " 4800\n", - " 1.5\n", - " 0\n", - " 0\n", - " ...\n", - " 1800\n", - " 0\n", - " 1918\n", - " 0\n", - " 98112\n", - " 47.6388\n", - " -122.302\n", - " 1950\n", - " 4800\n", - " high\n", - " \n", - " \n", - " 9986\n", - " 1723049624\n", - " 20140512T000000\n", - " 330000.0\n", - " 5\n", - " 3.00\n", - " 2100\n", - " 7715\n", - " 1.0\n", - " 0\n", - " 0\n", - " ...\n", - " 1250\n", - " 850\n", - " 2013\n", - " 0\n", - " 98168\n", - " 47.4866\n", - " -122.319\n", - " 2100\n", - " 7959\n", - " low\n", - " \n", - " \n", - " 9987\n", - " 4040400200\n", - " 20141007T000000\n", - " 527500.0\n", - " 5\n", - " 2.25\n", - " 2530\n", - " 8250\n", - " 2.0\n", - " 0\n", - " 0\n", - " ...\n", - " 2530\n", - " 0\n", - " 1961\n", - " 0\n", - " 98007\n", - " 47.6117\n", - " -122.134\n", - " 2020\n", - " 8250\n", - " middle\n", - " \n", - " \n", - " 9988\n", - " 8691391090\n", - " 20140508T000000\n", - " 716500.0\n", - " 4\n", - " 2.50\n", - " 3290\n", - " 6465\n", - " 2.0\n", - " 0\n", - " 0\n", - " ...\n", - " 3290\n", - " 0\n", - " 2002\n", - " 0\n", - " 98075\n", - " 47.5981\n", - " -121.976\n", - " 3100\n", - " 5929\n", - " high\n", - " \n", - " \n", - " 9989\n", - " 7853302190\n", - " 20141217T000000\n", - " 388500.0\n", - " 4\n", - " 2.50\n", - " 1890\n", - " 5395\n", - " 2.0\n", - " 0\n", - " 0\n", - " ...\n", - " 1890\n", + " 4170\n", " 0\n", " 2006\n", " 0\n", - " 98065\n", - " 47.5415\n", - " -121.883\n", - " 2060\n", - " 5395\n", - " middle\n", - " \n", - " \n", - " 9990\n", - " 3260000700\n", - " 20140904T000000\n", - " 530000.0\n", - " 3\n", - " 1.75\n", - " 1680\n", - " 7770\n", - " 1.0\n", - " 0\n", - " 0\n", - " ...\n", - " 1680\n", - " 0\n", - " 1967\n", - " 0\n", - " 98005\n", - " 47.6028\n", - " -122.167\n", - " 1880\n", - " 7770\n", - " middle\n", - " \n", - " \n", - " 9991\n", - " 5126300510\n", - " 20150108T000000\n", - " 419000.0\n", - " 3\n", - " 2.50\n", - " 2170\n", - " 4517\n", - " 2.0\n", - " 0\n", - " 0\n", - " ...\n", - " 2170\n", - " 0\n", - " 2002\n", - " 0\n", - " 98059\n", - " 47.4819\n", - " -122.140\n", - " 2610\n", - " 4770\n", - " middle\n", - " \n", - " \n", - " 9992\n", - " 7199330370\n", - " 20150309T000000\n", - " 385000.0\n", - " 3\n", - " 1.75\n", - " 1200\n", - " 7360\n", - " 1.0\n", - " 0\n", - " 0\n", - " ...\n", - " 1200\n", - " 0\n", - " 1978\n", - " 0\n", - " 98052\n", - " 47.6979\n", - " -122.130\n", - " 1200\n", - " 7500\n", - " middle\n", - " \n", - " \n", - " 9993\n", - " 1854900240\n", - " 20140528T000000\n", - " 655000.0\n", - " 4\n", - " 2.50\n", - " 2990\n", - " 5669\n", - " 2.0\n", - " 0\n", - " 0\n", - " ...\n", - " 2990\n", - " 0\n", - " 2003\n", - " 0\n", - " 98074\n", - " 47.6119\n", - " -122.011\n", - " 3110\n", - " 5058\n", - " high\n", - " \n", - " \n", - " 9994\n", - " 6738700335\n", - " 20140701T000000\n", - " 1127312.5\n", - " 4\n", - " 2.75\n", - " 3770\n", - " 10900\n", - " 2.0\n", - " 0\n", - " 2\n", - " ...\n", - " 3070\n", - " 700\n", - " 1924\n", - " 0\n", - " 98144\n", - " 47.5849\n", - " -122.290\n", - " 3000\n", - " 5000\n", + " 98056\n", + " 47.5354\n", + " -122.181\n", + " 3030\n", + " 7980\n", " very_high\n", " \n", " \n", - " 9995\n", - " 322059264\n", - " 20140926T000000\n", - " 279000.0\n", - " 2\n", - " 1.00\n", - " 1020\n", - " 47044\n", - " 1.0\n", - " 0\n", - " 0\n", - " ...\n", - " 1020\n", - " 0\n", - " 1904\n", - " 1958\n", - " 98042\n", - " 47.4206\n", - " -122.155\n", - " 1930\n", - " 12139\n", - " low\n", - " \n", - " \n", - " 9996\n", - " 5557500270\n", - " 20150209T000000\n", - " 262000.0\n", - " 3\n", - " 1.50\n", - " 1700\n", - " 9579\n", - " 1.0\n", - " 0\n", - " 0\n", - " ...\n", - " 1100\n", - " 600\n", - " 1962\n", - " 0\n", - " 98023\n", - " 47.3209\n", - " -122.338\n", - " 1700\n", - " 9628\n", - " low\n", - " \n", - " \n", - " 9997\n", - " 9164100125\n", - " 20140807T000000\n", - " 533000.0\n", + " 21594\n", + " 5087900040\n", + " 20141017T000000\n", + " 350000.0\n", " 4\n", - " 1.00\n", - " 1550\n", - " 4750\n", - " 1.5\n", - " 0\n", - " 0\n", - " ...\n", - " 1550\n", - " 0\n", - " 1919\n", - " 0\n", - " 98117\n", - " 47.6824\n", - " -122.389\n", - " 1320\n", - " 4750\n", - " middle\n", - " \n", - " \n", - " 9998\n", - " 7370600045\n", - " 20150402T000000\n", - " 640000.0\n", - " 3\n", - " 1.75\n", - " 1680\n", - " 8100\n", - " 1.0\n", - " 0\n", - " 2\n", - " ...\n", - " 1680\n", - " 0\n", - " 1950\n", - " 0\n", - " 98177\n", - " 47.7212\n", - " -122.364\n", - " 1880\n", - " 7750\n", - " high\n", - " \n", - " \n", - " 9999\n", - " 8594400060\n", - " 20140609T000000\n", - " 285000.0\n", - " 3\n", - " 2.25\n", - " 1680\n", - " 35127\n", + " 2.75\n", + " 2500\n", + " 5995\n", " 2.0\n", " 0\n", " 0\n", " ...\n", - " 1680\n", + " 2500\n", " 0\n", - " 1987\n", + " 2008\n", " 0\n", - " 98092\n", - " 47.3025\n", - " -122.067\n", - " 1820\n", - " 35166\n", + " 98042\n", + " 47.3749\n", + " -122.107\n", + " 2530\n", + " 5988\n", + " middle\n", + " \n", + " \n", + " 21595\n", + " 1972201967\n", + " 20141031T000000\n", + " 520000.0\n", + " 2\n", + " 2.25\n", + " 1530\n", + " 981\n", + " 3.0\n", + " 0\n", + " 0\n", + " ...\n", + " 1480\n", + " 50\n", + " 2006\n", + " 0\n", + " 98103\n", + " 47.6533\n", + " -122.346\n", + " 1530\n", + " 1282\n", + " middle\n", + " \n", + " \n", + " 21596\n", + " 7502800100\n", + " 20140813T000000\n", + " 679950.0\n", + " 5\n", + " 2.75\n", + " 3600\n", + " 9437\n", + " 2.0\n", + " 0\n", + " 0\n", + " ...\n", + " 3600\n", + " 0\n", + " 2014\n", + " 0\n", + " 98059\n", + " 47.4822\n", + " -122.131\n", + " 3550\n", + " 9421\n", + " high\n", + " \n", + " \n", + " 21597\n", + " 191100405\n", + " 20150421T000000\n", + " 1575000.0\n", + " 4\n", + " 3.25\n", + " 3410\n", + " 10125\n", + " 2.0\n", + " 0\n", + " 0\n", + " ...\n", + " 3410\n", + " 0\n", + " 2007\n", + " 0\n", + " 98040\n", + " 47.5653\n", + " -122.223\n", + " 2290\n", + " 10125\n", + " NaN\n", + " \n", + " \n", + " 21598\n", + " 8956200760\n", + " 20141013T000000\n", + " 541800.0\n", + " 4\n", + " 2.50\n", + " 3118\n", + " 7866\n", + " 2.0\n", + " 0\n", + " 2\n", + " ...\n", + " 3118\n", + " 0\n", + " 2014\n", + " 0\n", + " 98001\n", + " 47.2931\n", + " -122.264\n", + " 2673\n", + " 6500\n", + " middle\n", + " \n", + " \n", + " 21599\n", + " 7202300110\n", + " 20140915T000000\n", + " 810000.0\n", + " 4\n", + " 3.00\n", + " 3990\n", + " 7838\n", + " 2.0\n", + " 0\n", + " 0\n", + " ...\n", + " 3990\n", + " 0\n", + " 2003\n", + " 0\n", + " 98053\n", + " 47.6857\n", + " -122.046\n", + " 3370\n", + " 6814\n", + " high\n", + " \n", + " \n", + " 21600\n", + " 249000205\n", + " 20141015T000000\n", + " 1537000.0\n", + " 5\n", + " 3.75\n", + " 4470\n", + " 8088\n", + " 2.0\n", + " 0\n", + " 0\n", + " ...\n", + " 4470\n", + " 0\n", + " 2008\n", + " 0\n", + " 98004\n", + " 47.6321\n", + " -122.200\n", + " 2780\n", + " 8964\n", + " NaN\n", + " \n", + " \n", + " 21601\n", + " 5100403806\n", + " 20150407T000000\n", + " 467000.0\n", + " 3\n", + " 2.50\n", + " 1425\n", + " 1179\n", + " 3.0\n", + " 0\n", + " 0\n", + " ...\n", + " 1425\n", + " 0\n", + " 2008\n", + " 0\n", + " 98125\n", + " 47.6963\n", + " -122.318\n", + " 1285\n", + " 1253\n", + " middle\n", + " \n", + " \n", + " 21602\n", + " 844000965\n", + " 20140626T000000\n", + " 224000.0\n", + " 3\n", + " 1.75\n", + " 1500\n", + " 11968\n", + " 1.0\n", + " 0\n", + " 0\n", + " ...\n", + " 1500\n", + " 0\n", + " 2014\n", + " 0\n", + " 98010\n", + " 47.3095\n", + " -122.002\n", + " 1320\n", + " 11303\n", + " low\n", + " \n", + " \n", + " 21603\n", + " 7852140040\n", + " 20140825T000000\n", + " 507250.0\n", + " 3\n", + " 2.50\n", + " 2270\n", + " 5536\n", + " 2.0\n", + " 0\n", + " 0\n", + " ...\n", + " 2270\n", + " 0\n", + " 2003\n", + " 0\n", + " 98065\n", + " 47.5389\n", + " -121.881\n", + " 2270\n", + " 5731\n", + " middle\n", + " \n", + " \n", + " 21604\n", + " 9834201367\n", + " 20150126T000000\n", + " 429000.0\n", + " 3\n", + " 2.00\n", + " 1490\n", + " 1126\n", + " 3.0\n", + " 0\n", + " 0\n", + " ...\n", + " 1490\n", + " 0\n", + " 2014\n", + " 0\n", + " 98144\n", + " 47.5699\n", + " -122.288\n", + " 1400\n", + " 1230\n", + " middle\n", + " \n", + " \n", + " 21605\n", + " 3448900210\n", + " 20141014T000000\n", + " 610685.0\n", + " 4\n", + " 2.50\n", + " 2520\n", + " 6023\n", + " 2.0\n", + " 0\n", + " 0\n", + " ...\n", + " 2520\n", + " 0\n", + " 2014\n", + " 0\n", + " 98056\n", + " 47.5137\n", + " -122.167\n", + " 2520\n", + " 6023\n", + " high\n", + " \n", + " \n", + " 21606\n", + " 7936000429\n", + " 20150326T000000\n", + " 1007500.0\n", + " 4\n", + " 3.50\n", + " 3510\n", + " 7200\n", + " 2.0\n", + " 0\n", + " 0\n", + " ...\n", + " 2600\n", + " 910\n", + " 2009\n", + " 0\n", + " 98136\n", + " 47.5537\n", + " -122.398\n", + " 2050\n", + " 6200\n", + " very_high\n", + " \n", + " \n", + " 21607\n", + " 2997800021\n", + " 20150219T000000\n", + " 475000.0\n", + " 3\n", + " 2.50\n", + " 1310\n", + " 1294\n", + " 2.0\n", + " 0\n", + " 0\n", + " ...\n", + " 1180\n", + " 130\n", + " 2008\n", + " 0\n", + " 98116\n", + " 47.5773\n", + " -122.409\n", + " 1330\n", + " 1265\n", + " middle\n", + " \n", + " \n", + " 21608\n", + " 263000018\n", + " 20140521T000000\n", + " 360000.0\n", + " 3\n", + " 2.50\n", + " 1530\n", + " 1131\n", + " 3.0\n", + " 0\n", + " 0\n", + " ...\n", + " 1530\n", + " 0\n", + " 2009\n", + " 0\n", + " 98103\n", + " 47.6993\n", + " -122.346\n", + " 1530\n", + " 1509\n", + " middle\n", + " \n", + " \n", + " 21609\n", + " 6600060120\n", + " 20150223T000000\n", + " 400000.0\n", + " 4\n", + " 2.50\n", + " 2310\n", + " 5813\n", + " 2.0\n", + " 0\n", + " 0\n", + " ...\n", + " 2310\n", + " 0\n", + " 2014\n", + " 0\n", + " 98146\n", + " 47.5107\n", + " -122.362\n", + " 1830\n", + " 7200\n", + " middle\n", + " \n", + " \n", + " 21610\n", + " 1523300141\n", + " 20140623T000000\n", + " 402101.0\n", + " 2\n", + " 0.75\n", + " 1020\n", + " 1350\n", + " 2.0\n", + " 0\n", + " 0\n", + " ...\n", + " 1020\n", + " 0\n", + " 2009\n", + " 0\n", + " 98144\n", + " 47.5944\n", + " -122.299\n", + " 1020\n", + " 2007\n", + " middle\n", + " \n", + " \n", + " 21611\n", + " 291310100\n", + " 20150116T000000\n", + " 400000.0\n", + " 3\n", + " 2.50\n", + " 1600\n", + " 2388\n", + " 2.0\n", + " 0\n", + " 0\n", + " ...\n", + " 1600\n", + " 0\n", + " 2004\n", + " 0\n", + " 98027\n", + " 47.5345\n", + " -122.069\n", + " 1410\n", + " 1287\n", + " middle\n", + " \n", + " \n", + " 21612\n", + " 1523300157\n", + " 20141015T000000\n", + " 325000.0\n", + " 2\n", + " 0.75\n", + " 1020\n", + " 1076\n", + " 2.0\n", + " 0\n", + " 0\n", + " ...\n", + " 1020\n", + " 0\n", + " 2008\n", + " 0\n", + " 98144\n", + " 47.5941\n", + " -122.299\n", + " 1020\n", + " 1357\n", " low\n", " \n", " \n", @@ -935,113 +563,104 @@ "" ], "text/plain": [ - " id date price bedrooms bathrooms \\\n", - "9980 6840700036 20140728T000000 497000.0 2 1.00 \n", - "9981 1824069083 20150429T000000 835000.0 3 1.00 \n", - "9982 1836980240 20141015T000000 730000.0 4 2.75 \n", - "9983 3528900160 20141001T000000 655000.0 3 1.00 \n", - "9984 1442800060 20141120T000000 205000.0 3 2.50 \n", - "9985 8722100030 20150407T000000 632750.0 4 2.00 \n", - "9986 1723049624 20140512T000000 330000.0 5 3.00 \n", - "9987 4040400200 20141007T000000 527500.0 5 2.25 \n", - "9988 8691391090 20140508T000000 716500.0 4 2.50 \n", - "9989 7853302190 20141217T000000 388500.0 4 2.50 \n", - "9990 3260000700 20140904T000000 530000.0 3 1.75 \n", - "9991 5126300510 20150108T000000 419000.0 3 2.50 \n", - "9992 7199330370 20150309T000000 385000.0 3 1.75 \n", - "9993 1854900240 20140528T000000 655000.0 4 2.50 \n", - "9994 6738700335 20140701T000000 1127312.5 4 2.75 \n", - "9995 322059264 20140926T000000 279000.0 2 1.00 \n", - "9996 5557500270 20150209T000000 262000.0 3 1.50 \n", - "9997 9164100125 20140807T000000 533000.0 4 1.00 \n", - "9998 7370600045 20150402T000000 640000.0 3 1.75 \n", - "9999 8594400060 20140609T000000 285000.0 3 2.25 \n", + " id date price bedrooms bathrooms \\\n", + "21593 8672200110 20150317T000000 1088000.0 5 3.75 \n", + "21594 5087900040 20141017T000000 350000.0 4 2.75 \n", + "21595 1972201967 20141031T000000 520000.0 2 2.25 \n", + "21596 7502800100 20140813T000000 679950.0 5 2.75 \n", + "21597 191100405 20150421T000000 1575000.0 4 3.25 \n", + "21598 8956200760 20141013T000000 541800.0 4 2.50 \n", + "21599 7202300110 20140915T000000 810000.0 4 3.00 \n", + "21600 249000205 20141015T000000 1537000.0 5 3.75 \n", + "21601 5100403806 20150407T000000 467000.0 3 2.50 \n", + "21602 844000965 20140626T000000 224000.0 3 1.75 \n", + "21603 7852140040 20140825T000000 507250.0 3 2.50 \n", + "21604 9834201367 20150126T000000 429000.0 3 2.00 \n", + "21605 3448900210 20141014T000000 610685.0 4 2.50 \n", + "21606 7936000429 20150326T000000 1007500.0 4 3.50 \n", + "21607 2997800021 20150219T000000 475000.0 3 2.50 \n", + "21608 263000018 20140521T000000 360000.0 3 2.50 \n", + "21609 6600060120 20150223T000000 400000.0 4 2.50 \n", + "21610 1523300141 20140623T000000 402101.0 2 0.75 \n", + "21611 291310100 20150116T000000 400000.0 3 2.50 \n", + "21612 1523300157 20141015T000000 325000.0 2 0.75 \n", "\n", - " sqft_living sqft_lot floors waterfront view ... sqft_above \\\n", - "9980 770 3325 1.0 0 0 ... 770 \n", - "9981 3060 30166 1.0 0 0 ... 3060 \n", - "9982 2920 4500 2.0 0 0 ... 2920 \n", - "9983 1370 5250 1.0 0 0 ... 1070 \n", - "9984 1870 3118 2.0 0 0 ... 1870 \n", - "9985 1800 4800 1.5 0 0 ... 1800 \n", - "9986 2100 7715 1.0 0 0 ... 1250 \n", - "9987 2530 8250 2.0 0 0 ... 2530 \n", - "9988 3290 6465 2.0 0 0 ... 3290 \n", - "9989 1890 5395 2.0 0 0 ... 1890 \n", - "9990 1680 7770 1.0 0 0 ... 1680 \n", - "9991 2170 4517 2.0 0 0 ... 2170 \n", - "9992 1200 7360 1.0 0 0 ... 1200 \n", - "9993 2990 5669 2.0 0 0 ... 2990 \n", - "9994 3770 10900 2.0 0 2 ... 3070 \n", - "9995 1020 47044 1.0 0 0 ... 1020 \n", - "9996 1700 9579 1.0 0 0 ... 1100 \n", - "9997 1550 4750 1.5 0 0 ... 1550 \n", - "9998 1680 8100 1.0 0 2 ... 1680 \n", - "9999 1680 35127 2.0 0 0 ... 1680 \n", + " sqft_living sqft_lot floors waterfront view ... sqft_above \\\n", + "21593 4170 8142 2.0 0 2 ... 4170 \n", + "21594 2500 5995 2.0 0 0 ... 2500 \n", + "21595 1530 981 3.0 0 0 ... 1480 \n", + "21596 3600 9437 2.0 0 0 ... 3600 \n", + "21597 3410 10125 2.0 0 0 ... 3410 \n", + "21598 3118 7866 2.0 0 2 ... 3118 \n", + "21599 3990 7838 2.0 0 0 ... 3990 \n", + "21600 4470 8088 2.0 0 0 ... 4470 \n", + "21601 1425 1179 3.0 0 0 ... 1425 \n", + "21602 1500 11968 1.0 0 0 ... 1500 \n", + "21603 2270 5536 2.0 0 0 ... 2270 \n", + "21604 1490 1126 3.0 0 0 ... 1490 \n", + "21605 2520 6023 2.0 0 0 ... 2520 \n", + "21606 3510 7200 2.0 0 0 ... 2600 \n", + "21607 1310 1294 2.0 0 0 ... 1180 \n", + "21608 1530 1131 3.0 0 0 ... 1530 \n", + "21609 2310 5813 2.0 0 0 ... 2310 \n", + "21610 1020 1350 2.0 0 0 ... 1020 \n", + "21611 1600 2388 2.0 0 0 ... 1600 \n", + "21612 1020 1076 2.0 0 0 ... 1020 \n", "\n", - " sqft_basement yr_built yr_renovated zipcode lat long \\\n", - "9980 0 1918 0 98122 47.6102 -122.299 \n", - "9981 0 1959 0 98027 47.5656 -122.093 \n", - "9982 0 1999 0 98006 47.5646 -122.124 \n", - "9983 300 1939 0 98109 47.6421 -122.348 \n", - "9984 0 1993 0 98038 47.3739 -122.056 \n", - "9985 0 1918 0 98112 47.6388 -122.302 \n", - "9986 850 2013 0 98168 47.4866 -122.319 \n", - "9987 0 1961 0 98007 47.6117 -122.134 \n", - "9988 0 2002 0 98075 47.5981 -121.976 \n", - "9989 0 2006 0 98065 47.5415 -121.883 \n", - "9990 0 1967 0 98005 47.6028 -122.167 \n", - "9991 0 2002 0 98059 47.4819 -122.140 \n", - "9992 0 1978 0 98052 47.6979 -122.130 \n", - "9993 0 2003 0 98074 47.6119 -122.011 \n", - "9994 700 1924 0 98144 47.5849 -122.290 \n", - "9995 0 1904 1958 98042 47.4206 -122.155 \n", - "9996 600 1962 0 98023 47.3209 -122.338 \n", - "9997 0 1919 0 98117 47.6824 -122.389 \n", - "9998 0 1950 0 98177 47.7212 -122.364 \n", - "9999 0 1987 0 98092 47.3025 -122.067 \n", + " sqft_basement yr_built yr_renovated zipcode lat long \\\n", + "21593 0 2006 0 98056 47.5354 -122.181 \n", + "21594 0 2008 0 98042 47.3749 -122.107 \n", + "21595 50 2006 0 98103 47.6533 -122.346 \n", + "21596 0 2014 0 98059 47.4822 -122.131 \n", + "21597 0 2007 0 98040 47.5653 -122.223 \n", + "21598 0 2014 0 98001 47.2931 -122.264 \n", + "21599 0 2003 0 98053 47.6857 -122.046 \n", + "21600 0 2008 0 98004 47.6321 -122.200 \n", + "21601 0 2008 0 98125 47.6963 -122.318 \n", + "21602 0 2014 0 98010 47.3095 -122.002 \n", + "21603 0 2003 0 98065 47.5389 -121.881 \n", + "21604 0 2014 0 98144 47.5699 -122.288 \n", + "21605 0 2014 0 98056 47.5137 -122.167 \n", + "21606 910 2009 0 98136 47.5537 -122.398 \n", + "21607 130 2008 0 98116 47.5773 -122.409 \n", + "21608 0 2009 0 98103 47.6993 -122.346 \n", + "21609 0 2014 0 98146 47.5107 -122.362 \n", + "21610 0 2009 0 98144 47.5944 -122.299 \n", + "21611 0 2004 0 98027 47.5345 -122.069 \n", + "21612 0 2008 0 98144 47.5941 -122.299 \n", "\n", - " sqft_living15 sqft_lot15 price_category \n", - "9980 960 4800 middle \n", - "9981 1880 19602 high \n", - "9982 2920 4505 high \n", - "9983 2410 4200 high \n", - "9984 1580 3601 low \n", - "9985 1950 4800 high \n", - "9986 2100 7959 low \n", - "9987 2020 8250 middle \n", - "9988 3100 5929 high \n", - "9989 2060 5395 middle \n", - "9990 1880 7770 middle \n", - "9991 2610 4770 middle \n", - "9992 1200 7500 middle \n", - "9993 3110 5058 high \n", - "9994 3000 5000 very_high \n", - "9995 1930 12139 low \n", - "9996 1700 9628 low \n", - "9997 1320 4750 middle \n", - "9998 1880 7750 high \n", - "9999 1820 35166 low \n", + " sqft_living15 sqft_lot15 price_category \n", + "21593 3030 7980 very_high \n", + "21594 2530 5988 middle \n", + "21595 1530 1282 middle \n", + "21596 3550 9421 high \n", + "21597 2290 10125 NaN \n", + "21598 2673 6500 middle \n", + "21599 3370 6814 high \n", + "21600 2780 8964 NaN \n", + "21601 1285 1253 middle \n", + "21602 1320 11303 low \n", + "21603 2270 5731 middle \n", + "21604 1400 1230 middle \n", + "21605 2520 6023 high \n", + "21606 2050 6200 very_high \n", + "21607 1330 1265 middle \n", + "21608 1530 1509 middle \n", + "21609 1830 7200 middle \n", + "21610 1020 2007 middle \n", + "21611 1410 1287 middle \n", + "21612 1020 1357 low \n", "\n", "[20 rows x 22 columns]" ] }, - "execution_count": 338, + "execution_count": 158, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "q1 = df['price'].quantile(0.25) # Находим 1-й квартиль (Q1)\n", - "q3 = df['price'].quantile(0.75) # Находим 3-й квартиль (Q3)\n", - "iqr = q3 - q1 # Вычисляем межквартильный размах (IQR)\n", "\n", - "# Определяем границы для выбросов\n", - "lower_bound = q1 - 1.5 * iqr # Нижняя граница\n", - "upper_bound = q3 + 1.5 * iqr # Верхняя граница\n", - "\n", - "# Устраняем выбросы: заменяем значения ниже нижней границы на саму нижнюю границу, а выше верхней — на верхнюю\n", - "df['price'] = df['price'].apply(lambda x: lower_bound if x < lower_bound else upper_bound if x > upper_bound else x)\n", "\n", "# Добавляем столбец с категорями цены\n", "df['price_category'] = pd.cut(df['price'], bins=[75000,338750,602750,866750,1130750], labels=['low','middle','high','very_high'], include_lowest=True)\n", @@ -1053,16 +672,17 @@ "metadata": {}, "source": [ "### Бизнес-цели\n", - "1. Прогноз класса цены недвижимости (Классификация)\n", - "2. Оценка состояния недвижимости (Регрессия)\n", + "1. Задача регрессии – предсказание цены дома (price). Это может помочь риэлторам и аналитикам определить справедливую рыночную стоимость недвижимости.\n", "\n", - "### Определение достижимого уровня качества модели для первой задачи\n", - "#### Разделение набора данных на обучающую и тестовые выборки (80/20) для задачи классификации (Целевой признак - price)" + "2. Задача классификации – определение вероятности того, что цена дома будет выше/ниже медианы рынка. Классифицировать дома по ценовым категориям (например, низкая, средняя, высокая цена). Это может помочь определить, какие дома популярны у покупателей.\n", + "\n", + "### Определение достижимого уровня качества модели для задачи классификации\n", + "#### Разделение набора данных на обучающую и тестовые выборки (80/20) для задачи классификации (Целевой признак - median_price)" ] }, { "cell_type": "code", - "execution_count": 339, + "execution_count": 159, "metadata": {}, "outputs": [ { @@ -1106,7 +726,6 @@ " waterfront\n", " view\n", " ...\n", - " sqft_above\n", " sqft_basement\n", " yr_built\n", " yr_renovated\n", @@ -1116,128 +735,129 @@ " sqft_living15\n", " sqft_lot15\n", " price_category\n", + " median_price\n", " \n", " \n", " \n", " \n", - " 9843\n", - " 3260000340\n", - " 20140622T000000\n", - " 732600.0\n", + " 20962\n", + " 1278000210\n", + " 20150311T000000\n", + " 110000.0\n", + " 2\n", + " 1.00\n", + " 828\n", + " 4524\n", + " 1.0\n", + " 0\n", + " 0\n", + " ...\n", + " 0\n", + " 1968\n", + " 2007\n", + " 98001\n", + " 47.2655\n", + " -122.244\n", + " 828\n", + " 5402\n", + " 0\n", + " 0\n", + " \n", + " \n", + " 12284\n", + " 2193300390\n", + " 20140923T000000\n", + " 624000.0\n", " 4\n", - " 2.50\n", - " 2130\n", - " 7300\n", + " 3.25\n", + " 2810\n", + " 11250\n", " 1.0\n", " 0\n", " 0\n", " ...\n", - " 1230\n", - " 900\n", - " 1963\n", + " 1130\n", + " 1980\n", " 0\n", - " 98005\n", - " 47.6050\n", - " -122.167\n", - " 2130\n", - " 7560\n", - " high\n", + " 98052\n", + " 47.6920\n", + " -122.099\n", + " 2110\n", + " 11250\n", + " 1\n", + " 1\n", " \n", " \n", - " 9623\n", - " 9828702055\n", - " 20140508T000000\n", - " 358000.0\n", - " 2\n", - " 1.50\n", - " 960\n", - " 1808\n", + " 7343\n", + " 4289900005\n", + " 20141230T000000\n", + " 1535000.0\n", + " 4\n", + " 3.25\n", + " 2850\n", + " 4100\n", " 2.0\n", " 0\n", - " 0\n", + " 3\n", " ...\n", - " 960\n", - " 0\n", - " 1993\n", - " 0\n", + " 1030\n", + " 1908\n", + " 2003\n", " 98122\n", - " 47.6183\n", - " -122.298\n", - " 1290\n", - " 1668\n", - " middle\n", - " \n", - " \n", - " 3095\n", - " 3438500625\n", - " 20140519T000000\n", - " 210000.0\n", - " 3\n", - " 1.00\n", - " 1080\n", - " 21043\n", - " 1.0\n", - " 0\n", - " 0\n", - " ...\n", - " 1080\n", - " 0\n", - " 1942\n", - " 0\n", - " 98106\n", - " 47.5515\n", - " -122.357\n", - " 1380\n", - " 7620\n", - " low\n", - " \n", - " \n", - " 411\n", - " 2422029094\n", - " 20140716T000000\n", - " 517534.0\n", + " 47.6147\n", + " -122.285\n", + " 2130\n", + " 4200\n", " 2\n", + " 1\n", + " \n", + " \n", + " 14247\n", + " 316000145\n", + " 20150325T000000\n", + " 235000.0\n", + " 4\n", " 1.00\n", - " 833\n", - " 143947\n", - " 1.0\n", + " 1360\n", + " 7132\n", + " 1.5\n", " 0\n", " 0\n", " ...\n", - " 833\n", " 0\n", - " 2006\n", + " 1941\n", + " 0\n", + " 98168\n", + " 47.5054\n", + " -122.301\n", + " 1280\n", + " 7175\n", + " 0\n", " 0\n", - " 98070\n", - " 47.3889\n", - " -122.482\n", - " 1380\n", - " 143947\n", - " middle\n", " \n", " \n", - " 3060\n", - " 7462900015\n", - " 20150108T000000\n", - " 387000.0\n", - " 3\n", - " 2.25\n", - " 1760\n", - " 45133\n", + " 16670\n", + " 629400480\n", + " 20140619T000000\n", + " 775000.0\n", + " 4\n", + " 2.75\n", + " 3010\n", + " 15992\n", " 2.0\n", " 0\n", " 0\n", " ...\n", - " 1760\n", " 0\n", - " 1984\n", + " 1996\n", " 0\n", - " 98065\n", - " 47.5124\n", - " -121.866\n", - " 1910\n", - " 51773\n", - " middle\n", + " 98075\n", + " 47.5895\n", + " -121.994\n", + " 3330\n", + " 12333\n", + " 2\n", + " 1\n", " \n", " \n", " ...\n", @@ -1264,184 +884,184 @@ " ...\n", " \n", " \n", - " 1750\n", - " 2787720140\n", - " 20150407T000000\n", - " 416000.0\n", - " 3\n", - " 2.50\n", - " 1790\n", - " 11542\n", - " 1.0\n", - " 0\n", - " 0\n", - " ...\n", - " 1190\n", - " 600\n", - " 1969\n", - " 0\n", - " 98059\n", - " 47.5124\n", - " -122.160\n", - " 1790\n", - " 9131\n", - " middle\n", - " \n", - " \n", - " 2354\n", - " 6192400400\n", - " 20140728T000000\n", - " 775000.0\n", - " 4\n", - " 2.50\n", - " 3090\n", - " 7112\n", + " 88\n", + " 1332700270\n", + " 20140519T000000\n", + " 215000.0\n", + " 2\n", + " 2.25\n", + " 1610\n", + " 2040\n", " 2.0\n", " 0\n", " 0\n", " ...\n", - " 3090\n", " 0\n", - " 2001\n", - " 0\n", - " 98052\n", - " 47.7050\n", - " -122.118\n", - " 3050\n", - " 6000\n", - " high\n", - " \n", - " \n", - " 857\n", - " 2296500036\n", - " 20150310T000000\n", - " 450000.0\n", - " 4\n", - " 2.75\n", - " 2980\n", - " 13260\n", - " 1.0\n", - " 0\n", - " 0\n", - " ...\n", - " 1800\n", - " 1180\n", " 1979\n", " 0\n", " 98056\n", - " 47.5152\n", - " -122.197\n", - " 1920\n", - " 10731\n", - " middle\n", + " 47.5180\n", + " -122.194\n", + " 1950\n", + " 2025\n", + " 0\n", + " 0\n", " \n", " \n", - " 6181\n", - " 2787310130\n", - " 20141212T000000\n", - " 289950.0\n", + " 15031\n", + " 7129303070\n", + " 20140820T000000\n", + " 735000.0\n", + " 4\n", + " 2.75\n", + " 3040\n", + " 2415\n", + " 2.0\n", + " 1\n", " 4\n", - " 1.75\n", - " 2090\n", - " 7416\n", - " 1.0\n", - " 0\n", - " 0\n", " ...\n", - " 1050\n", - " 1040\n", - " 1970\n", " 0\n", - " 98031\n", - " 47.4107\n", - " -122.179\n", - " 1710\n", - " 7527\n", - " low\n", + " 1966\n", + " 0\n", + " 98118\n", + " 47.5188\n", + " -122.256\n", + " 2620\n", + " 2433\n", + " 2\n", + " 1\n", " \n", " \n", - " 3141\n", - " 8567300110\n", - " 20140604T000000\n", - " 485000.0\n", + " 5234\n", + " 2432000130\n", + " 20150414T000000\n", + " 675000.0\n", " 3\n", - " 2.50\n", - " 2340\n", - " 59058\n", + " 1.75\n", + " 1660\n", + " 9549\n", " 1.0\n", " 0\n", " 0\n", " ...\n", - " 2340\n", " 0\n", - " 1985\n", + " 1956\n", " 0\n", - " 98038\n", - " 47.4052\n", - " -122.028\n", - " 2700\n", - " 37263\n", - " middle\n", + " 98033\n", + " 47.6503\n", + " -122.198\n", + " 2090\n", + " 9549\n", + " 1\n", + " 1\n", + " \n", + " \n", + " 19980\n", + " 774100475\n", + " 20140627T000000\n", + " 415000.0\n", + " 3\n", + " 2.75\n", + " 2600\n", + " 64626\n", + " 1.5\n", + " 0\n", + " 0\n", + " ...\n", + " 0\n", + " 2009\n", + " 0\n", + " 98014\n", + " 47.7185\n", + " -121.405\n", + " 1740\n", + " 64626\n", + " 1\n", + " 0\n", + " \n", + " \n", + " 3671\n", + " 8847400115\n", + " 20140723T000000\n", + " 590000.0\n", + " 3\n", + " 2.00\n", + " 2420\n", + " 208652\n", + " 1.5\n", + " 0\n", + " 0\n", + " ...\n", + " 0\n", + " 2005\n", + " 0\n", + " 98010\n", + " 47.3666\n", + " -121.978\n", + " 3180\n", + " 212137\n", + " 1\n", + " 1\n", " \n", " \n", "\n", - "

8000 rows × 22 columns

\n", + "

17290 rows × 23 columns

\n", "" ], "text/plain": [ - " id date price bedrooms bathrooms sqft_living \\\n", - "9843 3260000340 20140622T000000 732600.0 4 2.50 2130 \n", - "9623 9828702055 20140508T000000 358000.0 2 1.50 960 \n", - "3095 3438500625 20140519T000000 210000.0 3 1.00 1080 \n", - "411 2422029094 20140716T000000 517534.0 2 1.00 833 \n", - "3060 7462900015 20150108T000000 387000.0 3 2.25 1760 \n", - "... ... ... ... ... ... ... \n", - "1750 2787720140 20150407T000000 416000.0 3 2.50 1790 \n", - "2354 6192400400 20140728T000000 775000.0 4 2.50 3090 \n", - "857 2296500036 20150310T000000 450000.0 4 2.75 2980 \n", - "6181 2787310130 20141212T000000 289950.0 4 1.75 2090 \n", - "3141 8567300110 20140604T000000 485000.0 3 2.50 2340 \n", + " id date price bedrooms bathrooms \\\n", + "20962 1278000210 20150311T000000 110000.0 2 1.00 \n", + "12284 2193300390 20140923T000000 624000.0 4 3.25 \n", + "7343 4289900005 20141230T000000 1535000.0 4 3.25 \n", + "14247 316000145 20150325T000000 235000.0 4 1.00 \n", + "16670 629400480 20140619T000000 775000.0 4 2.75 \n", + "... ... ... ... ... ... \n", + "88 1332700270 20140519T000000 215000.0 2 2.25 \n", + "15031 7129303070 20140820T000000 735000.0 4 2.75 \n", + "5234 2432000130 20150414T000000 675000.0 3 1.75 \n", + "19980 774100475 20140627T000000 415000.0 3 2.75 \n", + "3671 8847400115 20140723T000000 590000.0 3 2.00 \n", "\n", - " sqft_lot floors waterfront view ... sqft_above sqft_basement \\\n", - "9843 7300 1.0 0 0 ... 1230 900 \n", - "9623 1808 2.0 0 0 ... 960 0 \n", - "3095 21043 1.0 0 0 ... 1080 0 \n", - "411 143947 1.0 0 0 ... 833 0 \n", - "3060 45133 2.0 0 0 ... 1760 0 \n", - "... ... ... ... ... ... ... ... \n", - "1750 11542 1.0 0 0 ... 1190 600 \n", - "2354 7112 2.0 0 0 ... 3090 0 \n", - "857 13260 1.0 0 0 ... 1800 1180 \n", - "6181 7416 1.0 0 0 ... 1050 1040 \n", - "3141 59058 1.0 0 0 ... 2340 0 \n", + " sqft_living sqft_lot floors waterfront view ... sqft_basement \\\n", + "20962 828 4524 1.0 0 0 ... 0 \n", + "12284 2810 11250 1.0 0 0 ... 1130 \n", + "7343 2850 4100 2.0 0 3 ... 1030 \n", + "14247 1360 7132 1.5 0 0 ... 0 \n", + "16670 3010 15992 2.0 0 0 ... 0 \n", + "... ... ... ... ... ... ... ... \n", + "88 1610 2040 2.0 0 0 ... 0 \n", + "15031 3040 2415 2.0 1 4 ... 0 \n", + "5234 1660 9549 1.0 0 0 ... 0 \n", + "19980 2600 64626 1.5 0 0 ... 0 \n", + "3671 2420 208652 1.5 0 0 ... 0 \n", "\n", - " yr_built yr_renovated zipcode lat long sqft_living15 \\\n", - "9843 1963 0 98005 47.6050 -122.167 2130 \n", - "9623 1993 0 98122 47.6183 -122.298 1290 \n", - "3095 1942 0 98106 47.5515 -122.357 1380 \n", - "411 2006 0 98070 47.3889 -122.482 1380 \n", - "3060 1984 0 98065 47.5124 -121.866 1910 \n", - "... ... ... ... ... ... ... \n", - "1750 1969 0 98059 47.5124 -122.160 1790 \n", - "2354 2001 0 98052 47.7050 -122.118 3050 \n", - "857 1979 0 98056 47.5152 -122.197 1920 \n", - "6181 1970 0 98031 47.4107 -122.179 1710 \n", - "3141 1985 0 98038 47.4052 -122.028 2700 \n", + " yr_built yr_renovated zipcode lat long sqft_living15 \\\n", + "20962 1968 2007 98001 47.2655 -122.244 828 \n", + "12284 1980 0 98052 47.6920 -122.099 2110 \n", + "7343 1908 2003 98122 47.6147 -122.285 2130 \n", + "14247 1941 0 98168 47.5054 -122.301 1280 \n", + "16670 1996 0 98075 47.5895 -121.994 3330 \n", + "... ... ... ... ... ... ... \n", + "88 1979 0 98056 47.5180 -122.194 1950 \n", + "15031 1966 0 98118 47.5188 -122.256 2620 \n", + "5234 1956 0 98033 47.6503 -122.198 2090 \n", + "19980 2009 0 98014 47.7185 -121.405 1740 \n", + "3671 2005 0 98010 47.3666 -121.978 3180 \n", "\n", - " sqft_lot15 price_category \n", - "9843 7560 high \n", - "9623 1668 middle \n", - "3095 7620 low \n", - "411 143947 middle \n", - "3060 51773 middle \n", - "... ... ... \n", - "1750 9131 middle \n", - "2354 6000 high \n", - "857 10731 middle \n", - "6181 7527 low \n", - "3141 37263 middle \n", + " sqft_lot15 price_category median_price \n", + "20962 5402 0 0 \n", + "12284 11250 1 1 \n", + "7343 4200 2 1 \n", + "14247 7175 0 0 \n", + "16670 12333 2 1 \n", + "... ... ... ... \n", + "88 2025 0 0 \n", + "15031 2433 2 1 \n", + "5234 9549 1 1 \n", + "19980 64626 1 0 \n", + "3671 212137 1 1 \n", "\n", - "[8000 rows x 22 columns]" + "[17290 rows x 23 columns]" ] }, "metadata": {}, @@ -1477,74 +1097,74 @@ " \n", " \n", " \n", - " price_category\n", + " median_price\n", " \n", " \n", " \n", " \n", - " 9843\n", - " high\n", + " 20962\n", + " 0\n", " \n", " \n", - " 9623\n", - " middle\n", + " 12284\n", + " 1\n", " \n", " \n", - " 3095\n", - " low\n", + " 7343\n", + " 1\n", " \n", " \n", - " 411\n", - " middle\n", + " 14247\n", + " 0\n", " \n", " \n", - " 3060\n", - " middle\n", + " 16670\n", + " 1\n", " \n", " \n", " ...\n", " ...\n", " \n", " \n", - " 1750\n", - " middle\n", + " 88\n", + " 0\n", " \n", " \n", - " 2354\n", - " high\n", + " 15031\n", + " 1\n", " \n", " \n", - " 857\n", - " middle\n", + " 5234\n", + " 1\n", " \n", " \n", - " 6181\n", - " low\n", + " 19980\n", + " 0\n", " \n", " \n", - " 3141\n", - " middle\n", + " 3671\n", + " 1\n", " \n", " \n", "\n", - "

8000 rows × 1 columns

\n", + "

17290 rows × 1 columns

\n", "" ], "text/plain": [ - " price_category\n", - "9843 high\n", - "9623 middle\n", - "3095 low\n", - "411 middle\n", - "3060 middle\n", + " median_price\n", + "20962 0\n", + "12284 1\n", + "7343 1\n", + "14247 0\n", + "16670 1\n", "... ...\n", - "1750 middle\n", - "2354 high\n", - "857 middle\n", - "6181 low\n", - "3141 middle\n", + "88 0\n", + "15031 1\n", + "5234 1\n", + "19980 0\n", + "3671 1\n", "\n", - "[8000 rows x 1 columns]" + "[17290 rows x 1 columns]" ] }, "metadata": {}, @@ -1591,7 +1211,6 @@ " waterfront\n", " view\n", " ...\n", - " sqft_above\n", " sqft_basement\n", " yr_built\n", " yr_renovated\n", @@ -1601,128 +1220,129 @@ " sqft_living15\n", " sqft_lot15\n", " price_category\n", + " median_price\n", " \n", " \n", " \n", " \n", - " 5341\n", - " 6632900574\n", - " 20150225T000000\n", - " 595000.0\n", - " 5\n", - " 3.00\n", - " 2980\n", - " 10064\n", + " 11592\n", + " 2028701000\n", + " 20140529T000000\n", + " 635200.0\n", + " 4\n", + " 1.75\n", + " 1640\n", + " 4240\n", " 1.0\n", " 0\n", " 0\n", " ...\n", - " 1680\n", - " 1300\n", - " 1940\n", + " 720\n", + " 1921\n", " 0\n", - " 98155\n", - " 47.7372\n", - " -122.316\n", - " 1590\n", - " 7800\n", - " middle\n", + " 98117\n", + " 47.6766\n", + " -122.368\n", + " 1300\n", + " 4240\n", + " 1\n", + " 1\n", " \n", " \n", - " 4384\n", - " 2423029245\n", - " 20140617T000000\n", - " 550000.0\n", - " 3\n", - " 1.75\n", - " 2240\n", - " 78225\n", + " 8984\n", + " 9406500530\n", + " 20140912T000000\n", + " 249000.0\n", + " 2\n", + " 2.00\n", + " 1090\n", + " 1357\n", " 2.0\n", " 0\n", " 0\n", " ...\n", - " 2240\n", " 0\n", - " 1976\n", + " 1990\n", + " 0\n", + " 98028\n", + " 47.7526\n", + " -122.244\n", + " 1078\n", + " 1318\n", + " 0\n", " 0\n", - " 98070\n", - " 47.4638\n", - " -122.484\n", - " 2030\n", - " 202554\n", - " middle\n", " \n", " \n", - " 5795\n", - " 2473370050\n", - " 20140604T000000\n", - " 327500.0\n", - " 4\n", - " 1.75\n", - " 1650\n", - " 7800\n", - " 1.0\n", + " 8280\n", + " 8097000330\n", + " 20140721T000000\n", + " 359950.0\n", + " 3\n", + " 2.75\n", + " 2540\n", + " 8604\n", + " 2.0\n", " 0\n", " 0\n", " ...\n", - " 1650\n", " 0\n", - " 1968\n", + " 1991\n", + " 0\n", + " 98092\n", + " 47.3209\n", + " -122.185\n", + " 2260\n", + " 7438\n", + " 1\n", " 0\n", - " 98058\n", - " 47.4507\n", - " -122.139\n", - " 1750\n", - " 10400\n", - " low\n", " \n", " \n", - " 4956\n", - " 9528104985\n", - " 20141104T000000\n", - " 611000.0\n", + " 792\n", + " 8081020370\n", + " 20140709T000000\n", + " 1355000.0\n", + " 4\n", + " 3.50\n", + " 3550\n", + " 11000\n", + " 1.0\n", + " 0\n", + " 2\n", + " ...\n", + " 1290\n", + " 1999\n", + " 0\n", + " 98006\n", + " 47.5506\n", + " -122.134\n", + " 4100\n", + " 10012\n", + " 2\n", + " 1\n", + " \n", + " \n", + " 10371\n", + " 7518507580\n", + " 20150502T000000\n", + " 581000.0\n", " 2\n", " 1.00\n", - " 1270\n", - " 5100\n", + " 1170\n", + " 4080\n", " 1.0\n", " 0\n", " 0\n", " ...\n", - " 1100\n", - " 170\n", - " 1900\n", " 0\n", - " 98115\n", - " 47.6771\n", - " -122.328\n", - " 1670\n", - " 3900\n", - " high\n", - " \n", - " \n", - " 7723\n", - " 3972900025\n", - " 20150313T000000\n", - " 499000.0\n", - " 6\n", - " 1.75\n", - " 2400\n", - " 7500\n", - " 1.5\n", + " 1909\n", " 0\n", - " 0\n", - " ...\n", - " 1400\n", - " 1000\n", - " 1975\n", - " 0\n", - " 98155\n", - " 47.7661\n", - " -122.313\n", - " 1980\n", - " 7500\n", - " middle\n", + " 98117\n", + " 47.6784\n", + " -122.386\n", + " 1560\n", + " 4586\n", + " 1\n", + " 1\n", " \n", " \n", " ...\n", @@ -1749,184 +1369,184 @@ " ...\n", " \n", " \n", - " 8517\n", - " 3876600120\n", - " 20150422T000000\n", - " 265000.0\n", - " 3\n", - " 1.50\n", - " 1780\n", - " 10196\n", - " 1.0\n", - " 0\n", - " 0\n", - " ...\n", - " 1270\n", - " 510\n", - " 1967\n", - " 0\n", - " 98001\n", - " 47.3375\n", - " -122.291\n", - " 1320\n", - " 7875\n", - " low\n", - " \n", - " \n", - " 6914\n", - " 6821600005\n", - " 20150403T000000\n", - " 710000.0\n", - " 4\n", - " 1.75\n", - " 2120\n", - " 5400\n", - " 1.0\n", - " 0\n", - " 0\n", - " ...\n", - " 1060\n", - " 1060\n", - " 1941\n", - " 0\n", - " 98199\n", - " 47.6501\n", - " -122.395\n", - " 2052\n", - " 6000\n", - " high\n", - " \n", - " \n", - " 4499\n", - " 2767603931\n", - " 20140818T000000\n", - " 469000.0\n", - " 3\n", - " 3.25\n", - " 1370\n", - " 1194\n", - " 3.0\n", - " 0\n", - " 0\n", - " ...\n", - " 1370\n", - " 0\n", - " 2004\n", - " 0\n", - " 98107\n", - " 47.6718\n", - " -122.388\n", - " 1800\n", - " 2678\n", - " middle\n", - " \n", - " \n", - " 8651\n", - " 8802400411\n", - " 20140619T000000\n", - " 249000.0\n", - " 3\n", - " 1.00\n", - " 1050\n", - " 8498\n", - " 1.0\n", - " 0\n", - " 0\n", - " ...\n", - " 1050\n", - " 0\n", - " 1959\n", - " 0\n", - " 98031\n", - " 47.4043\n", - " -122.202\n", - " 1050\n", - " 8498\n", - " low\n", - " \n", - " \n", - " 4234\n", - " 5452800735\n", - " 20140722T000000\n", - " 780000.0\n", + " 16733\n", + " 7212650950\n", + " 20140708T000000\n", + " 336000.0\n", " 4\n", " 2.50\n", - " 2270\n", - " 13449\n", + " 2530\n", + " 8169\n", + " 2.0\n", + " 0\n", + " 0\n", + " ...\n", + " 0\n", + " 1993\n", + " 0\n", + " 98003\n", + " 47.2634\n", + " -122.312\n", + " 2220\n", + " 8013\n", + " 1\n", + " 0\n", + " \n", + " \n", + " 13151\n", + " 4365200620\n", + " 20150312T000000\n", + " 394000.0\n", + " 3\n", + " 1.00\n", + " 1450\n", + " 7930\n", " 1.0\n", " 0\n", " 0\n", " ...\n", - " 1310\n", - " 960\n", - " 1975\n", + " 300\n", + " 1923\n", " 0\n", - " 98040\n", - " 47.5416\n", - " -122.232\n", - " 2810\n", - " 13475\n", - " high\n", + " 98126\n", + " 47.5212\n", + " -122.371\n", + " 1040\n", + " 7740\n", + " 1\n", + " 0\n", + " \n", + " \n", + " 11667\n", + " 4083304355\n", + " 20150318T000000\n", + " 675000.0\n", + " 4\n", + " 1.75\n", + " 1530\n", + " 3615\n", + " 1.5\n", + " 0\n", + " 0\n", + " ...\n", + " 0\n", + " 1913\n", + " 0\n", + " 98103\n", + " 47.6529\n", + " -122.334\n", + " 1650\n", + " 4200\n", + " 1\n", + " 1\n", + " \n", + " \n", + " 3683\n", + " 2891100820\n", + " 20140825T000000\n", + " 213500.0\n", + " 3\n", + " 1.00\n", + " 1220\n", + " 6000\n", + " 1.0\n", + " 0\n", + " 0\n", + " ...\n", + " 0\n", + " 1968\n", + " 0\n", + " 98002\n", + " 47.3245\n", + " -122.209\n", + " 1420\n", + " 6000\n", + " 0\n", + " 0\n", + " \n", + " \n", + " 12059\n", + " 952000640\n", + " 20141027T000000\n", + " 715000.0\n", + " 3\n", + " 1.50\n", + " 1670\n", + " 5060\n", + " 2.0\n", + " 0\n", + " 2\n", + " ...\n", + " 0\n", + " 1925\n", + " 0\n", + " 98126\n", + " 47.5671\n", + " -122.379\n", + " 1670\n", + " 5118\n", + " 2\n", + " 1\n", " \n", " \n", "\n", - "

2000 rows × 22 columns

\n", + "

4323 rows × 23 columns

\n", "" ], "text/plain": [ - " id date price bedrooms bathrooms sqft_living \\\n", - "5341 6632900574 20150225T000000 595000.0 5 3.00 2980 \n", - "4384 2423029245 20140617T000000 550000.0 3 1.75 2240 \n", - "5795 2473370050 20140604T000000 327500.0 4 1.75 1650 \n", - "4956 9528104985 20141104T000000 611000.0 2 1.00 1270 \n", - "7723 3972900025 20150313T000000 499000.0 6 1.75 2400 \n", - "... ... ... ... ... ... ... \n", - "8517 3876600120 20150422T000000 265000.0 3 1.50 1780 \n", - "6914 6821600005 20150403T000000 710000.0 4 1.75 2120 \n", - "4499 2767603931 20140818T000000 469000.0 3 3.25 1370 \n", - "8651 8802400411 20140619T000000 249000.0 3 1.00 1050 \n", - "4234 5452800735 20140722T000000 780000.0 4 2.50 2270 \n", + " id date price bedrooms bathrooms \\\n", + "11592 2028701000 20140529T000000 635200.0 4 1.75 \n", + "8984 9406500530 20140912T000000 249000.0 2 2.00 \n", + "8280 8097000330 20140721T000000 359950.0 3 2.75 \n", + "792 8081020370 20140709T000000 1355000.0 4 3.50 \n", + "10371 7518507580 20150502T000000 581000.0 2 1.00 \n", + "... ... ... ... ... ... \n", + "16733 7212650950 20140708T000000 336000.0 4 2.50 \n", + "13151 4365200620 20150312T000000 394000.0 3 1.00 \n", + "11667 4083304355 20150318T000000 675000.0 4 1.75 \n", + "3683 2891100820 20140825T000000 213500.0 3 1.00 \n", + "12059 952000640 20141027T000000 715000.0 3 1.50 \n", "\n", - " sqft_lot floors waterfront view ... sqft_above sqft_basement \\\n", - "5341 10064 1.0 0 0 ... 1680 1300 \n", - "4384 78225 2.0 0 0 ... 2240 0 \n", - "5795 7800 1.0 0 0 ... 1650 0 \n", - "4956 5100 1.0 0 0 ... 1100 170 \n", - "7723 7500 1.5 0 0 ... 1400 1000 \n", - "... ... ... ... ... ... ... ... \n", - "8517 10196 1.0 0 0 ... 1270 510 \n", - "6914 5400 1.0 0 0 ... 1060 1060 \n", - "4499 1194 3.0 0 0 ... 1370 0 \n", - "8651 8498 1.0 0 0 ... 1050 0 \n", - "4234 13449 1.0 0 0 ... 1310 960 \n", + " sqft_living sqft_lot floors waterfront view ... sqft_basement \\\n", + "11592 1640 4240 1.0 0 0 ... 720 \n", + "8984 1090 1357 2.0 0 0 ... 0 \n", + "8280 2540 8604 2.0 0 0 ... 0 \n", + "792 3550 11000 1.0 0 2 ... 1290 \n", + "10371 1170 4080 1.0 0 0 ... 0 \n", + "... ... ... ... ... ... ... ... \n", + "16733 2530 8169 2.0 0 0 ... 0 \n", + "13151 1450 7930 1.0 0 0 ... 300 \n", + "11667 1530 3615 1.5 0 0 ... 0 \n", + "3683 1220 6000 1.0 0 0 ... 0 \n", + "12059 1670 5060 2.0 0 2 ... 0 \n", "\n", - " yr_built yr_renovated zipcode lat long sqft_living15 \\\n", - "5341 1940 0 98155 47.7372 -122.316 1590 \n", - "4384 1976 0 98070 47.4638 -122.484 2030 \n", - "5795 1968 0 98058 47.4507 -122.139 1750 \n", - "4956 1900 0 98115 47.6771 -122.328 1670 \n", - "7723 1975 0 98155 47.7661 -122.313 1980 \n", - "... ... ... ... ... ... ... \n", - "8517 1967 0 98001 47.3375 -122.291 1320 \n", - "6914 1941 0 98199 47.6501 -122.395 2052 \n", - "4499 2004 0 98107 47.6718 -122.388 1800 \n", - "8651 1959 0 98031 47.4043 -122.202 1050 \n", - "4234 1975 0 98040 47.5416 -122.232 2810 \n", + " yr_built yr_renovated zipcode lat long sqft_living15 \\\n", + "11592 1921 0 98117 47.6766 -122.368 1300 \n", + "8984 1990 0 98028 47.7526 -122.244 1078 \n", + "8280 1991 0 98092 47.3209 -122.185 2260 \n", + "792 1999 0 98006 47.5506 -122.134 4100 \n", + "10371 1909 0 98117 47.6784 -122.386 1560 \n", + "... ... ... ... ... ... ... \n", + "16733 1993 0 98003 47.2634 -122.312 2220 \n", + "13151 1923 0 98126 47.5212 -122.371 1040 \n", + "11667 1913 0 98103 47.6529 -122.334 1650 \n", + "3683 1968 0 98002 47.3245 -122.209 1420 \n", + "12059 1925 0 98126 47.5671 -122.379 1670 \n", "\n", - " sqft_lot15 price_category \n", - "5341 7800 middle \n", - "4384 202554 middle \n", - "5795 10400 low \n", - "4956 3900 high \n", - "7723 7500 middle \n", - "... ... ... \n", - "8517 7875 low \n", - "6914 6000 high \n", - "4499 2678 middle \n", - "8651 8498 low \n", - "4234 13475 high \n", + " sqft_lot15 price_category median_price \n", + "11592 4240 1 1 \n", + "8984 1318 0 0 \n", + "8280 7438 1 0 \n", + "792 10012 2 1 \n", + "10371 4586 1 1 \n", + "... ... ... ... \n", + "16733 8013 1 0 \n", + "13151 7740 1 0 \n", + "11667 4200 1 1 \n", + "3683 6000 0 0 \n", + "12059 5118 2 1 \n", "\n", - "[2000 rows x 22 columns]" + "[4323 rows x 23 columns]" ] }, "metadata": {}, @@ -1962,78 +1582,108 @@ " \n", " \n", " \n", - " price_category\n", + " median_price\n", " \n", " \n", " \n", " \n", - " 5341\n", - " middle\n", + " 11592\n", + " 1\n", " \n", " \n", - " 4384\n", - " middle\n", + " 8984\n", + " 0\n", " \n", " \n", - " 5795\n", - " low\n", + " 8280\n", + " 0\n", " \n", " \n", - " 4956\n", - " high\n", + " 792\n", + " 1\n", " \n", " \n", - " 7723\n", - " middle\n", + " 10371\n", + " 1\n", " \n", " \n", " ...\n", " ...\n", " \n", " \n", - " 8517\n", - " low\n", + " 16733\n", + " 0\n", " \n", " \n", - " 6914\n", - " high\n", + " 13151\n", + " 0\n", " \n", " \n", - " 4499\n", - " middle\n", + " 11667\n", + " 1\n", " \n", " \n", - " 8651\n", - " low\n", + " 3683\n", + " 0\n", " \n", " \n", - " 4234\n", - " high\n", + " 12059\n", + " 1\n", " \n", " \n", "\n", - "

2000 rows × 1 columns

\n", + "

4323 rows × 1 columns

\n", "" ], "text/plain": [ - " price_category\n", - "5341 middle\n", - "4384 middle\n", - "5795 low\n", - "4956 high\n", - "7723 middle\n", + " median_price\n", + "11592 1\n", + "8984 0\n", + "8280 0\n", + "792 1\n", + "10371 1\n", "... ...\n", - "8517 low\n", - "6914 high\n", - "4499 middle\n", - "8651 low\n", - "4234 high\n", + "16733 0\n", + "13151 0\n", + "11667 1\n", + "3683 0\n", + "12059 1\n", "\n", - "[2000 rows x 1 columns]" + "[4323 rows x 1 columns]" ] }, "metadata": {}, "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "id int64\n", + "date object\n", + "price float64\n", + "bedrooms int64\n", + "bathrooms float64\n", + "sqft_living int64\n", + "sqft_lot int64\n", + "floors float64\n", + "waterfront int64\n", + "view int64\n", + "condition int64\n", + "grade int64\n", + "sqft_above int64\n", + "sqft_basement int64\n", + "yr_built int64\n", + "yr_renovated int64\n", + "zipcode int64\n", + "lat float64\n", + "long float64\n", + "sqft_living15 int64\n", + "sqft_lot15 int64\n", + "price_category category\n", + "median_price int64\n", + "dtype: object\n" + ] } ], "source": [ @@ -2042,6 +1692,21 @@ "from pandas import DataFrame\n", "from sklearn.model_selection import train_test_split\n", "\n", + "# Создание целевого признака\n", + "median_price = df['price'].median()\n", + "df['median_price'] = np.where(df['price'] > median_price, 1, 0)\n", + "\n", + "# Разделение на признаки и целевую переменную\n", + "X = df.drop(columns=['id', 'date', 'price', 'median_price'])\n", + "y = df['median_price']\n", + "\n", + "# Примерная категоризация\n", + "df['price_category'] = pd.cut(df['price'], bins=[0, 300000, 700000, np.inf], labels=[0, 1, 2])\n", + "\n", + "# Выбор признаков и целевых переменных\n", + "X = df.drop(columns=['id', 'date', 'price', 'price_category'])\n", + "\n", + "\n", "def split_stratified_into_train_val_test(\n", " df_input,\n", " stratify_colname=\"y\",\n", @@ -2056,21 +1721,25 @@ " \"fractions %f, %f, %f do not add up to 1.0\"\n", " % (frac_train, frac_val, frac_test)\n", " )\n", + " \n", " if stratify_colname not in df_input.columns:\n", " raise ValueError(\"%s is not a column in the dataframe\" % (stratify_colname))\n", " X = df_input # Contains all columns.\n", " y = df_input[\n", " [stratify_colname]\n", " ] # Dataframe of just the column on which to stratify.\n", + " \n", " # Split original dataframe into train and temp dataframes.\n", " df_train, df_temp, y_train, y_temp = train_test_split(\n", " X, y, stratify=y, test_size=(1.0 - frac_train), random_state=random_state\n", " )\n", + "\n", " if frac_val <= 0:\n", " assert len(df_input) == len(df_train) + len(df_temp)\n", " return df_train, pd.DataFrame(), df_temp, y_train, pd.DataFrame(), y_temp\n", " # Split the temp dataframe into val and test dataframes.\n", " relative_frac_test = frac_test / (frac_val + frac_test)\n", + "\n", " df_val, df_test, y_val, y_test = train_test_split(\n", " df_temp,\n", " y_temp,\n", @@ -2078,18 +1747,21 @@ " test_size=relative_frac_test,\n", " random_state=random_state,\n", " )\n", + "\n", " assert len(df_input) == len(df_train) + len(df_val) + len(df_test)\n", " return df_train, df_val, df_test, y_train, y_val, y_test\n", "\n", "X_train, X_val, X_test, y_train, y_val, y_test = split_stratified_into_train_val_test(\n", - " df, stratify_colname=\"price_category\", frac_train=0.80, frac_val=0, frac_test=0.20, random_state=42\n", + " df, stratify_colname=\"median_price\", frac_train=0.80, frac_val=0, frac_test=0.20, random_state=42\n", ")\n", "\n", "display(\"X_train\", X_train)\n", "display(\"y_train\", y_train)\n", "\n", "display(\"X_test\", X_test)\n", - "display(\"y_test\", y_test)" + "display(\"y_test\", y_test)\n", + "\n", + "print(df.dtypes)" ] }, { @@ -2110,7 +1782,91 @@ }, { "cell_type": "code", - "execution_count": 340, + "execution_count": 160, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "from sklearn.base import BaseEstimator, TransformerMixin\n", + "from sklearn.compose import ColumnTransformer\n", + "from sklearn.discriminant_analysis import StandardScaler\n", + "from sklearn.impute import SimpleImputer\n", + "from sklearn.pipeline import Pipeline\n", + "from sklearn.preprocessing import OneHotEncoder\n", + "from sklearn.ensemble import RandomForestRegressor # Пример регрессионной модели\n", + "from sklearn.model_selection import train_test_split\n", + "from sklearn.pipeline import make_pipeline\n", + "\n", + "pipeline_end = StandardScaler()\n", + "\n", + "\n", + "class HouseFeatures(BaseEstimator, TransformerMixin):\n", + " def __init__(self):\n", + " pass\n", + " def fit(self, X, y=None):\n", + " return self\n", + " def transform(self, X, y=None):\n", + " # Создание новых признаков\n", + " X = X.copy()\n", + " X[\"Living_area_to_Lot_ratio\"] = X[\"sqft_living\"] / X[\"sqft_lot\"]\n", + " return X\n", + " def get_feature_names_out(self, features_in):\n", + " # Добавление имен новых признаков\n", + " new_features = [\"Living_area_to_Lot_ratio\"]\n", + " return np.append(features_in, new_features, axis=0)\n", + "\n", + "#Предобработка числовых значений. Заполнение пустых значений на медиану.\n", + "preprocessing_num_class = Pipeline(steps=[\n", + " ('imputer', SimpleImputer(strategy='median')),\n", + " ('scaler', StandardScaler())\n", + "])\n", + "\n", + "#Предобработка категориальных значений\n", + "preprocessing_cat_class = Pipeline(steps=[\n", + " ('imputer', SimpleImputer(strategy='most_frequent')),\n", + " ('onehot', OneHotEncoder(handle_unknown='ignore'))\n", + "])\n", + "\n", + "columns_to_drop = [\"date\"]\n", + "numeric_columns = [\"sqft_living\", \"sqft_lot\", \"median_price\"]\n", + "cat_columns = []\n", + "\n", + "features_preprocessing = ColumnTransformer(\n", + " verbose_feature_names_out=False,\n", + " transformers=[\n", + " (\"prepocessing_num\", preprocessing_num_class, numeric_columns),\n", + " (\"prepocessing_cat\", preprocessing_cat_class, cat_columns),\n", + " ],\n", + " remainder=\"passthrough\"\n", + ")\n", + "\n", + "drop_columns = ColumnTransformer(\n", + " verbose_feature_names_out=False,\n", + " transformers=[\n", + " (\"drop_columns\", \"drop\", columns_to_drop),\n", + " ],\n", + " remainder=\"passthrough\",\n", + ")\n", + "\n", + "pipeline_end = Pipeline(\n", + " [\n", + " (\"features_preprocessing\", features_preprocessing),\n", + " (\"custom_features\", HouseFeatures()),\n", + " (\"drop_columns\", drop_columns),\n", + " ]\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Пример работы конвейера." + ] + }, + { + "cell_type": "code", + "execution_count": 161, "metadata": {}, "outputs": [ { @@ -2134,681 +1890,368 @@ " \n", " \n", " \n", + " sqft_living\n", + " sqft_lot\n", + " median_price\n", " id\n", " price\n", " bedrooms\n", " bathrooms\n", - " sqft_living\n", - " sqft_lot\n", " floors\n", - " condition\n", - " grade\n", - " sqft_above\n", + " waterfront\n", + " view\n", " ...\n", + " sqft_basement\n", + " yr_built\n", " yr_renovated\n", " zipcode\n", " lat\n", " long\n", " sqft_living15\n", " sqft_lot15\n", - " price_h\n", - " price_l\n", - " price_m\n", - " price_vh\n", + " price_category\n", + " Living_area_to_Lot_ratio\n", " \n", " \n", " \n", " \n", - " 0\n", - " -0.451103\n", - " 0.916381\n", - " 0.700559\n", - " 0.573416\n", - " 0.081706\n", - " -0.187493\n", - " -0.838739\n", - " 0.839159\n", - " -0.512647\n", - " -0.638064\n", - " ...\n", - " -0.2158\n", - " -1.349962\n", - " 0.32254\n", - " 0.340593\n", - " 0.223199\n", - " -0.210584\n", + " 20962\n", + " -1.360742\n", + " -0.262132\n", + " -0.994693\n", + " 1278000210\n", + " 110000.0\n", + " 2\n", + " 1.00\n", " 1.0\n", - " 0.0\n", - " 0.0\n", - " 0.0\n", + " 0\n", + " 0\n", + " ...\n", + " 0\n", + " 1968\n", + " 2007\n", + " 98001\n", + " 47.2655\n", + " -122.244\n", + " 828\n", + " 5402\n", + " 0\n", + " 5.191063\n", " \n", " \n", - " 1\n", - " 1.845014\n", - " -0.589326\n", - " -1.49426\n", - " -0.72971\n", - " -1.191326\n", - " -0.302999\n", - " 1.120073\n", - " -0.666734\n", - " -0.512647\n", - " -0.969739\n", - " ...\n", - " -0.2158\n", - " 0.820656\n", - " 0.417588\n", - " -0.601419\n", - " -1.022503\n", - " -0.421966\n", - " 0.0\n", - " 0.0\n", + " 12284\n", + " 0.794390\n", + " -0.094121\n", + " 1.005335\n", + " 2193300390\n", + " 624000.0\n", + " 4\n", + " 3.25\n", " 1.0\n", - " 0.0\n", + " 0\n", + " 0\n", + " ...\n", + " 1130\n", + " 1980\n", + " 0\n", + " 98052\n", + " 47.6920\n", + " -122.099\n", + " 2110\n", + " 11250\n", + " 1\n", + " -8.440052\n", " \n", " \n", - " 2\n", - " -0.388708\n", - " -1.184213\n", - " -0.396851\n", - " -1.381273\n", - " -1.060759\n", - " 0.101544\n", - " -0.838739\n", - " -0.666734\n", - " -1.369558\n", - " -0.822328\n", + " 7343\n", + " 0.837884\n", + " -0.272723\n", + " 1.005335\n", + " 4289900005\n", + " 1535000.0\n", + " 4\n", + " 3.25\n", + " 2.0\n", + " 0\n", + " 3\n", " ...\n", - " -0.2158\n", - " 0.523819\n", - " -0.059795\n", - " -1.025683\n", - " -0.889035\n", - " -0.208431\n", - " 0.0\n", - " 1.0\n", - " 0.0\n", - " 0.0\n", + " 1030\n", + " 1908\n", + " 2003\n", + " 98122\n", + " 47.6147\n", + " -122.285\n", + " 2130\n", + " 4200\n", + " 2\n", + " -3.072292\n", " \n", " \n", - " 3\n", - " -0.74402\n", - " 0.051922\n", - " -1.49426\n", - " -1.381273\n", - " -1.32951\n", - " 2.686416\n", - " -0.838739\n", - " -0.666734\n", - " -2.22647\n", - " -1.125749\n", + " 14247\n", + " -0.782270\n", + " -0.196986\n", + " -0.994693\n", + " 316000145\n", + " 235000.0\n", + " 4\n", + " 1.00\n", + " 1.5\n", + " 0\n", + " 0\n", " ...\n", - " -0.2158\n", - " -0.144063\n", - " -1.221808\n", - " -1.924549\n", - " -0.889035\n", - " 4.682444\n", - " 0.0\n", - " 0.0\n", - " 1.0\n", - " 0.0\n", + " 0\n", + " 1941\n", + " 0\n", + " 98168\n", + " 47.5054\n", + " -122.301\n", + " 1280\n", + " 7175\n", + " 0\n", + " 3.971201\n", " \n", " \n", - " 4\n", - " 1.018038\n", - " -0.47276\n", - " -0.396851\n", - " 0.247635\n", - " -0.320877\n", - " 0.608196\n", - " 1.120073\n", - " -0.666734\n", - " -0.512647\n", - " 0.013003\n", + " 16670\n", + " 1.011860\n", + " 0.024330\n", + " 1.005335\n", + " 629400480\n", + " 775000.0\n", + " 4\n", + " 2.75\n", + " 2.0\n", + " 0\n", + " 0\n", " ...\n", - " -0.2158\n", - " -0.236825\n", - " -0.339221\n", - " 2.505062\n", - " -0.103056\n", - " 1.375604\n", - " 0.0\n", - " 0.0\n", - " 1.0\n", - " 0.0\n", + " 0\n", + " 1996\n", + " 0\n", + " 98075\n", + " 47.5895\n", + " -121.994\n", + " 3330\n", + " 12333\n", + " 2\n", + " 41.589045\n", " \n", " \n", - " 5\n", - " -0.083826\n", - " -0.492858\n", - " -0.396851\n", - " 1.550761\n", - " -0.701698\n", - " -0.314672\n", - " 3.078884\n", - " -0.666734\n", - " 0.344264\n", - " -0.416947\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", " ...\n", - " -0.2158\n", - " 0.468162\n", - " 0.987875\n", - " -0.903438\n", - " -0.844546\n", - " -0.436854\n", - " 0.0\n", - " 0.0\n", - " 1.0\n", - " 0.0\n", " \n", " \n", - " 6\n", - " 0.301277\n", - " -0.953091\n", - " -0.396851\n", - " 0.573416\n", - " -0.712579\n", - " -0.180574\n", - " -0.838739\n", - " -0.666734\n", - " -0.512647\n", - " -0.773191\n", + " 88\n", + " -0.510432\n", + " -0.324180\n", + " -0.994693\n", + " 1332700270\n", + " 215000.0\n", + " 2\n", + " 2.25\n", + " 2.0\n", + " 0\n", + " 0\n", " ...\n", - " -0.2158\n", - " -0.886155\n", - " -1.293987\n", - " 0.254302\n", - " -0.666588\n", - " -0.205992\n", - " 0.0\n", - " 1.0\n", - " 0.0\n", - " 0.0\n", + " 0\n", + " 1979\n", + " 0\n", + " 98056\n", + " 47.5180\n", + " -122.194\n", + " 1950\n", + " 2025\n", + " 0\n", + " 1.574534\n", " \n", " \n", - " 7\n", - " -0.086798\n", - " -1.148038\n", - " -1.49426\n", - " -1.381273\n", - " -1.25661\n", - " -0.232501\n", - " -0.838739\n", - " -0.666734\n", - " -1.369558\n", - " -1.043445\n", + " 15031\n", + " 1.044481\n", + " -0.314813\n", + " 1.005335\n", + " 7129303070\n", + " 735000.0\n", + " 4\n", + " 2.75\n", + " 2.0\n", + " 1\n", + " 4\n", " ...\n", - " -0.2158\n", - " 0.523819\n", - " -0.249176\n", - " -1.018493\n", - " -1.600865\n", - " -0.296686\n", - " 0.0\n", - " 1.0\n", - " 0.0\n", - " 0.0\n", + " 0\n", + " 1966\n", + " 0\n", + " 98118\n", + " 47.5188\n", + " -122.256\n", + " 2620\n", + " 2433\n", + " 2\n", + " -3.317784\n", " \n", " \n", - " 8\n", - " -0.824567\n", - " -1.148038\n", - " -1.49426\n", - " -1.381273\n", - " -1.0934\n", - " -0.15174\n", - " 0.140667\n", - " 0.839159\n", - " -0.512647\n", - " -0.859181\n", - " ...\n", - " -0.2158\n", - " -1.387066\n", - " -1.937882\n", - " -0.60861\n", - " -0.636929\n", - " -0.137397\n", - " 0.0\n", + " 5234\n", + " -0.456065\n", + " -0.136611\n", + " 1.005335\n", + " 2432000130\n", + " 675000.0\n", + " 3\n", + " 1.75\n", " 1.0\n", - " 0.0\n", - " 0.0\n", + " 0\n", + " 0\n", + " ...\n", + " 0\n", + " 1956\n", + " 0\n", + " 98033\n", + " 47.6503\n", + " -122.198\n", + " 2090\n", + " 9549\n", + " 1\n", + " 3.338418\n", " \n", " \n", - " 9\n", - " 1.647935\n", - " -0.762165\n", - " 2.895378\n", - " 0.899198\n", - " 0.963036\n", - " -0.186442\n", - " -0.838739\n", - " -0.666734\n", - " 0.344264\n", - " 0.037571\n", + " 19980\n", + " 0.566046\n", + " 1.239169\n", + " -0.994693\n", + " 774100475\n", + " 415000.0\n", + " 3\n", + " 2.75\n", + " 1.5\n", + " 0\n", + " 0\n", " ...\n", - " -0.2158\n", - " -1.016021\n", - " -1.783519\n", - " -0.896247\n", - " 0.208369\n", - " -0.186332\n", - " 0.0\n", - " 1.0\n", - " 0.0\n", - " 0.0\n", + " 0\n", + " 2009\n", + " 0\n", + " 98014\n", + " 47.7185\n", + " -121.405\n", + " 1740\n", + " 64626\n", + " 1\n", + " 0.456795\n", " \n", " \n", - " 10\n", - " -1.159614\n", - " -0.581287\n", - " -1.49426\n", - " -1.381273\n", - " -1.321893\n", - " -0.185096\n", - " -0.838739\n", - " 0.839159\n", - " -1.369558\n", - " -1.11715\n", + " 3671\n", + " 0.370323\n", + " 4.836825\n", + " 1.005335\n", + " 8847400115\n", + " 590000.0\n", + " 3\n", + " 2.00\n", + " 1.5\n", + " 0\n", + " 0\n", " ...\n", - " -0.2158\n", - " -0.830498\n", - " 0.837799\n", - " 0.304638\n", - " -0.355163\n", - " -0.130796\n", - " 0.0\n", - " 0.0\n", - " 1.0\n", - " 0.0\n", - " \n", - " \n", - " 11\n", - " -1.329183\n", - " -0.681775\n", - " -1.49426\n", - " -1.381273\n", - " -1.071639\n", - " -0.200575\n", - " -0.838739\n", - " 0.839159\n", - " -0.512647\n", - " -0.834612\n", - " ...\n", - " -0.2158\n", - " 1.024731\n", - " 1.226566\n", - " -1.025683\n", - " -0.444141\n", - " -0.202404\n", - " 0.0\n", - " 1.0\n", - " 0.0\n", - " 0.0\n", - " \n", - " \n", - " 12\n", - " 0.377864\n", - " 0.286926\n", - " 0.700559\n", - " 0.573416\n", - " 0.419005\n", - " 0.256379\n", - " 1.120073\n", - " -0.666734\n", - " 0.344264\n", - " 0.848334\n", - " ...\n", - " -0.2158\n", - " -0.923259\n", - " 1.277306\n", - " -0.169963\n", - " 0.742242\n", - " -0.071779\n", - " 0.0\n", - " 0.0\n", - " 1.0\n", - " 0.0\n", - " \n", - " \n", - " 13\n", - " 0.289882\n", - " -0.88677\n", - " -0.396851\n", - " 0.573416\n", - " 0.103467\n", - " -0.143853\n", - " -0.838739\n", - " -0.666734\n", - " 0.344264\n", - " -0.244967\n", - " ...\n", - " -0.2158\n", - " 2.045107\n", - " -0.729417\n", - " -0.428836\n", - " -0.043737\n", - " -0.155335\n", - " 0.0\n", - " 1.0\n", - " 0.0\n", - " 0.0\n", - " \n", - " \n", - " 14\n", - " 1.613049\n", - " 0.282907\n", - " -0.396851\n", - " -0.078147\n", - " 0.103467\n", - " -0.259422\n", - " -0.838739\n", - " -0.666734\n", - " 0.344264\n", - " -0.822328\n", - " ...\n", - " -0.2158\n", - " 0.727894\n", - " 0.868529\n", - " -1.277366\n", - " 0.223199\n", - " -0.338303\n", - " 0.0\n", - " 0.0\n", - " 1.0\n", - " 0.0\n", - " \n", - " \n", - " 15\n", - " -0.962885\n", - " 0.285118\n", - " 0.700559\n", - " 0.573416\n", - " 0.005542\n", - " -0.183813\n", - " -0.838739\n", - " -0.666734\n", - " 0.344264\n", - " -0.380094\n", - " ...\n", - " -0.2158\n", - " -0.478004\n", - " 1.195837\n", - " 0.78643\n", - " 0.445646\n", - " -0.180592\n", - " 0.0\n", - " 0.0\n", - " 1.0\n", - " 0.0\n", - " \n", - " \n", - " 16\n", - " 1.722145\n", - " -0.259726\n", - " -0.396851\n", - " -0.403928\n", - " -0.571131\n", - " -0.18865\n", - " -0.838739\n", - " 0.839159\n", - " -0.512647\n", - " -0.269535\n", - " ...\n", - " -0.2158\n", - " -0.811945\n", - " 1.222993\n", - " 0.168011\n", - " -0.666588\n", - " -0.213095\n", - " 0.0\n", - " 0.0\n", - " 1.0\n", - " 0.0\n", - " \n", - " \n", - " 17\n", - " 0.740562\n", - " 1.589247\n", - " 0.700559\n", - " 1.550761\n", - " 2.878025\n", - " 0.466843\n", - " 1.120073\n", - " -0.666734\n", - " 2.058087\n", - " 2.052192\n", - " ...\n", - " -0.2158\n", - " -1.349962\n", - " 0.604825\n", - " 0.340593\n", - " 2.462498\n", - " 0.79434\n", - " 0.0\n", - " 0.0\n", - " 0.0\n", - " 1.0\n", - " \n", - " \n", - " 18\n", - " -1.555659\n", - " -0.922945\n", - " -0.396851\n", - " -1.381273\n", - " -0.799624\n", - " -0.107784\n", - " -0.838739\n", - " -0.666734\n", - " -0.512647\n", - " -0.527505\n", - " ...\n", - " -0.2158\n", - " 1.432881\n", - " 1.536008\n", - " -0.644564\n", - " -0.978014\n", - " -0.183354\n", - " 0.0\n", - " 1.0\n", - " 0.0\n", - " 0.0\n", - " \n", - " \n", - " 19\n", - " -0.953738\n", - " 0.142224\n", - " 2.895378\n", - " 1.224979\n", - " 0.886872\n", - " 4.00146\n", - " 1.120073\n", - " -0.666734\n", - " -0.512647\n", - " 0.713207\n", - " ...\n", - " 4.605736\n", - " -0.663527\n", - " -1.135335\n", - " 0.85834\n", - " 0.593944\n", - " 1.659169\n", - " 0.0\n", - " 0.0\n", - " 1.0\n", - " 0.0\n", + " 0\n", + " 2005\n", + " 0\n", + " 98010\n", + " 47.3666\n", + " -121.978\n", + " 3180\n", + " 212137\n", + " 1\n", + " 0.076563\n", " \n", " \n", "\n", - "

20 rows × 22 columns

\n", + "

17290 rows × 23 columns

\n", "" ], "text/plain": [ - " id price bedrooms bathrooms sqft_living sqft_lot floors \\\n", - "0 -0.451103 0.916381 0.700559 0.573416 0.081706 -0.187493 -0.838739 \n", - "1 1.845014 -0.589326 -1.49426 -0.72971 -1.191326 -0.302999 1.120073 \n", - "2 -0.388708 -1.184213 -0.396851 -1.381273 -1.060759 0.101544 -0.838739 \n", - "3 -0.74402 0.051922 -1.49426 -1.381273 -1.32951 2.686416 -0.838739 \n", - "4 1.018038 -0.47276 -0.396851 0.247635 -0.320877 0.608196 1.120073 \n", - "5 -0.083826 -0.492858 -0.396851 1.550761 -0.701698 -0.314672 3.078884 \n", - "6 0.301277 -0.953091 -0.396851 0.573416 -0.712579 -0.180574 -0.838739 \n", - "7 -0.086798 -1.148038 -1.49426 -1.381273 -1.25661 -0.232501 -0.838739 \n", - "8 -0.824567 -1.148038 -1.49426 -1.381273 -1.0934 -0.15174 0.140667 \n", - "9 1.647935 -0.762165 2.895378 0.899198 0.963036 -0.186442 -0.838739 \n", - "10 -1.159614 -0.581287 -1.49426 -1.381273 -1.321893 -0.185096 -0.838739 \n", - "11 -1.329183 -0.681775 -1.49426 -1.381273 -1.071639 -0.200575 -0.838739 \n", - "12 0.377864 0.286926 0.700559 0.573416 0.419005 0.256379 1.120073 \n", - "13 0.289882 -0.88677 -0.396851 0.573416 0.103467 -0.143853 -0.838739 \n", - "14 1.613049 0.282907 -0.396851 -0.078147 0.103467 -0.259422 -0.838739 \n", - "15 -0.962885 0.285118 0.700559 0.573416 0.005542 -0.183813 -0.838739 \n", - "16 1.722145 -0.259726 -0.396851 -0.403928 -0.571131 -0.18865 -0.838739 \n", - "17 0.740562 1.589247 0.700559 1.550761 2.878025 0.466843 1.120073 \n", - "18 -1.555659 -0.922945 -0.396851 -1.381273 -0.799624 -0.107784 -0.838739 \n", - "19 -0.953738 0.142224 2.895378 1.224979 0.886872 4.00146 1.120073 \n", + " sqft_living sqft_lot median_price id price bedrooms \\\n", + "20962 -1.360742 -0.262132 -0.994693 1278000210 110000.0 2 \n", + "12284 0.794390 -0.094121 1.005335 2193300390 624000.0 4 \n", + "7343 0.837884 -0.272723 1.005335 4289900005 1535000.0 4 \n", + "14247 -0.782270 -0.196986 -0.994693 316000145 235000.0 4 \n", + "16670 1.011860 0.024330 1.005335 629400480 775000.0 4 \n", + "... ... ... ... ... ... ... \n", + "88 -0.510432 -0.324180 -0.994693 1332700270 215000.0 2 \n", + "15031 1.044481 -0.314813 1.005335 7129303070 735000.0 4 \n", + "5234 -0.456065 -0.136611 1.005335 2432000130 675000.0 3 \n", + "19980 0.566046 1.239169 -0.994693 774100475 415000.0 3 \n", + "3671 0.370323 4.836825 1.005335 8847400115 590000.0 3 \n", "\n", - " condition grade sqft_above ... yr_renovated zipcode lat \\\n", - "0 0.839159 -0.512647 -0.638064 ... -0.2158 -1.349962 0.32254 \n", - "1 -0.666734 -0.512647 -0.969739 ... -0.2158 0.820656 0.417588 \n", - "2 -0.666734 -1.369558 -0.822328 ... -0.2158 0.523819 -0.059795 \n", - "3 -0.666734 -2.22647 -1.125749 ... -0.2158 -0.144063 -1.221808 \n", - "4 -0.666734 -0.512647 0.013003 ... -0.2158 -0.236825 -0.339221 \n", - "5 -0.666734 0.344264 -0.416947 ... -0.2158 0.468162 0.987875 \n", - "6 -0.666734 -0.512647 -0.773191 ... -0.2158 -0.886155 -1.293987 \n", - "7 -0.666734 -1.369558 -1.043445 ... -0.2158 0.523819 -0.249176 \n", - "8 0.839159 -0.512647 -0.859181 ... -0.2158 -1.387066 -1.937882 \n", - "9 -0.666734 0.344264 0.037571 ... -0.2158 -1.016021 -1.783519 \n", - "10 0.839159 -1.369558 -1.11715 ... -0.2158 -0.830498 0.837799 \n", - "11 0.839159 -0.512647 -0.834612 ... -0.2158 1.024731 1.226566 \n", - "12 -0.666734 0.344264 0.848334 ... -0.2158 -0.923259 1.277306 \n", - "13 -0.666734 0.344264 -0.244967 ... -0.2158 2.045107 -0.729417 \n", - "14 -0.666734 0.344264 -0.822328 ... -0.2158 0.727894 0.868529 \n", - "15 -0.666734 0.344264 -0.380094 ... -0.2158 -0.478004 1.195837 \n", - "16 0.839159 -0.512647 -0.269535 ... -0.2158 -0.811945 1.222993 \n", - "17 -0.666734 2.058087 2.052192 ... -0.2158 -1.349962 0.604825 \n", - "18 -0.666734 -0.512647 -0.527505 ... -0.2158 1.432881 1.536008 \n", - "19 -0.666734 -0.512647 0.713207 ... 4.605736 -0.663527 -1.135335 \n", + " bathrooms floors waterfront view ... sqft_basement yr_built \\\n", + "20962 1.00 1.0 0 0 ... 0 1968 \n", + "12284 3.25 1.0 0 0 ... 1130 1980 \n", + "7343 3.25 2.0 0 3 ... 1030 1908 \n", + "14247 1.00 1.5 0 0 ... 0 1941 \n", + "16670 2.75 2.0 0 0 ... 0 1996 \n", + "... ... ... ... ... ... ... ... \n", + "88 2.25 2.0 0 0 ... 0 1979 \n", + "15031 2.75 2.0 1 4 ... 0 1966 \n", + "5234 1.75 1.0 0 0 ... 0 1956 \n", + "19980 2.75 1.5 0 0 ... 0 2009 \n", + "3671 2.00 1.5 0 0 ... 0 2005 \n", "\n", - " long sqft_living15 sqft_lot15 price_h price_l price_m price_vh \n", - "0 0.340593 0.223199 -0.210584 1.0 0.0 0.0 0.0 \n", - "1 -0.601419 -1.022503 -0.421966 0.0 0.0 1.0 0.0 \n", - "2 -1.025683 -0.889035 -0.208431 0.0 1.0 0.0 0.0 \n", - "3 -1.924549 -0.889035 4.682444 0.0 0.0 1.0 0.0 \n", - "4 2.505062 -0.103056 1.375604 0.0 0.0 1.0 0.0 \n", - "5 -0.903438 -0.844546 -0.436854 0.0 0.0 1.0 0.0 \n", - "6 0.254302 -0.666588 -0.205992 0.0 1.0 0.0 0.0 \n", - "7 -1.018493 -1.600865 -0.296686 0.0 1.0 0.0 0.0 \n", - "8 -0.60861 -0.636929 -0.137397 0.0 1.0 0.0 0.0 \n", - "9 -0.896247 0.208369 -0.186332 0.0 1.0 0.0 0.0 \n", - "10 0.304638 -0.355163 -0.130796 0.0 0.0 1.0 0.0 \n", - "11 -1.025683 -0.444141 -0.202404 0.0 1.0 0.0 0.0 \n", - "12 -0.169963 0.742242 -0.071779 0.0 0.0 1.0 0.0 \n", - "13 -0.428836 -0.043737 -0.155335 0.0 1.0 0.0 0.0 \n", - "14 -1.277366 0.223199 -0.338303 0.0 0.0 1.0 0.0 \n", - "15 0.78643 0.445646 -0.180592 0.0 0.0 1.0 0.0 \n", - "16 0.168011 -0.666588 -0.213095 0.0 0.0 1.0 0.0 \n", - "17 0.340593 2.462498 0.79434 0.0 0.0 0.0 1.0 \n", - "18 -0.644564 -0.978014 -0.183354 0.0 1.0 0.0 0.0 \n", - "19 0.85834 0.593944 1.659169 0.0 0.0 1.0 0.0 \n", + " yr_renovated zipcode lat long sqft_living15 sqft_lot15 \\\n", + "20962 2007 98001 47.2655 -122.244 828 5402 \n", + "12284 0 98052 47.6920 -122.099 2110 11250 \n", + "7343 2003 98122 47.6147 -122.285 2130 4200 \n", + "14247 0 98168 47.5054 -122.301 1280 7175 \n", + "16670 0 98075 47.5895 -121.994 3330 12333 \n", + "... ... ... ... ... ... ... \n", + "88 0 98056 47.5180 -122.194 1950 2025 \n", + "15031 0 98118 47.5188 -122.256 2620 2433 \n", + "5234 0 98033 47.6503 -122.198 2090 9549 \n", + "19980 0 98014 47.7185 -121.405 1740 64626 \n", + "3671 0 98010 47.3666 -121.978 3180 212137 \n", "\n", - "[20 rows x 22 columns]" + " price_category Living_area_to_Lot_ratio \n", + "20962 0 5.191063 \n", + "12284 1 -8.440052 \n", + "7343 2 -3.072292 \n", + "14247 0 3.971201 \n", + "16670 2 41.589045 \n", + "... ... ... \n", + "88 0 1.574534 \n", + "15031 2 -3.317784 \n", + "5234 1 3.338418 \n", + "19980 1 0.456795 \n", + "3671 1 0.076563 \n", + "\n", + "[17290 rows x 23 columns]" ] }, - "execution_count": 340, + "execution_count": 161, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "import numpy as np\n", - "from sklearn.base import BaseEstimator, TransformerMixin\n", - "from sklearn.compose import ColumnTransformer\n", - "from sklearn.discriminant_analysis import StandardScaler\n", - "from sklearn.impute import SimpleImputer\n", - "from sklearn.pipeline import Pipeline\n", - "from sklearn.preprocessing import OneHotEncoder\n", - "from sklearn.ensemble import RandomForestRegressor # Пример регрессионной модели\n", - "from sklearn.model_selection import train_test_split\n", - "from sklearn.pipeline import make_pipeline\n", - "\n", - "random_state = 42\n", - "\n", - "# Указываем столбцы, которые нужно удалить и обрабатывать\n", - "columns_to_drop = [\"date\", \"view\", \"waterfront\"]\n", - "num_columns = [\n", - " column\n", - " for column in df.columns\n", - " if column not in columns_to_drop and df[column].dtype != \"object\" and df[column].dtype != \"category\"\n", - "]\n", - "cat_columns = [\n", - " column\n", - " for column in df.columns\n", - " if column not in columns_to_drop and df[column].dtype == \"object\" or df[column].dtype == \"category\"\n", - "]\n", - "\n", - "# Определяем предобработку для численных данных\n", - "num_imputer = SimpleImputer(strategy=\"median\")\n", - "num_scaler = StandardScaler()\n", - "preprocessing_num = Pipeline(\n", - " [\n", - " (\"imputer\", num_imputer),\n", - " (\"scaler\", num_scaler),\n", - " ]\n", + "preprocessing_result = pipeline_end.fit_transform(X_train)\n", + "preprocessed_df = pd.DataFrame(\n", + " preprocessing_result,\n", + " columns=pipeline_end.get_feature_names_out(),\n", ")\n", "\n", - "# Определяем предобработку для категориальных данных\n", - "cat_imputer = SimpleImputer(strategy=\"constant\")\n", - "cat_encoder = OneHotEncoder(handle_unknown=\"ignore\", sparse_output=False)\n", - "preprocessing_cat = Pipeline(\n", - " [\n", - " (\"imputer\", cat_imputer),\n", - " (\"encoder\", cat_encoder),\n", - " ]\n", - ")\n", - "\n", - "features_preprocessing = ColumnTransformer(\n", - " verbose_feature_names_out=False,\n", - " transformers=[\n", - " (\"prepocessing_num\", preprocessing_num, num_columns),\n", - " (\"prepocessing_cat\", preprocessing_cat, cat_columns),\n", - " (\"prepocessing_features\", cat_imputer, [\"price_category\"]),\n", - " ],\n", - " remainder=\"passthrough\"\n", - ")\n", - "\n", - "drop_columns = ColumnTransformer(\n", - " verbose_feature_names_out=False,\n", - " transformers=[\n", - " (\"drop_columns\", \"drop\", columns_to_drop),\n", - " ],\n", - " remainder=\"passthrough\",\n", - ")\n", - "\n", - "features_postprocessing = ColumnTransformer(\n", - " verbose_feature_names_out=False,\n", - " transformers=[\n", - " (\"prepocessing_cat\", preprocessing_cat, [\"price_category\"]),\n", - " ],\n", - " remainder=\"passthrough\",\n", - ")\n", - "\n", - "pipeline_end = Pipeline(\n", - " [\n", - " (\"features_preprocessing\", features_preprocessing),\n", - " (\"drop_columns\", drop_columns),\n", - " (\"features_postprocessing\", features_postprocessing),\n", - " ]\n", - "\n", - ")\n", - "# preprocessing_result = pipeline_end.fit_transform(X_train.values)\n", - "cols = ['price_h', 'price_l', 'price_m', 'price_vh']\n", - "preprocessing_result = features_preprocessing.fit_transform(X_train)\n", - "preprocessing_result = pd.DataFrame(preprocessing_result, columns=num_columns + cat_columns + cols + columns_to_drop)\n", - "\n", - "preprocessing_result = drop_columns.fit_transform(preprocessing_result)\n", - "preprocessing_result = pd.DataFrame(preprocessing_result, columns=num_columns + cols + cat_columns)\n", - "\n", - "preprocessing_result = preprocessing_result.drop(columns=[\"price_category\"])\n", - "preprocessing_result.head(20)" + "preprocessed_df" ] }, { @@ -2835,33 +2278,36 @@ }, { "cell_type": "code", - "execution_count": 341, + "execution_count": 162, "metadata": {}, "outputs": [], "source": [ - "from sklearn import ensemble, linear_model, naive_bayes, neighbors, neural_network, tree\n", + "from sklearn import ensemble, linear_model, naive_bayes, neighbors, neural_network, tree, svm\n", "\n", "class_models = {\n", - " \"logistic\": {\"model\": linear_model.LogisticRegression()},\n", - " # \"ridge\": {\"model\": linear_model.RidgeClassifierCV(cv=5, class_weight=\"balanced\")},\n", - " \"ridge\": {\"model\": linear_model.LogisticRegression(penalty=\"l2\", class_weight=\"balanced\")},\n", + " \"logistic\": {\"model\": linear_model.LogisticRegression(max_iter=150)},\n", + " \"ridge\": {\"model\": linear_model.RidgeClassifierCV(cv=5, class_weight=\"balanced\")},\n", + " \"ridge\": {\"model\": linear_model.LogisticRegression(max_iter=150, solver='lbfgs', penalty=\"l2\", class_weight=\"balanced\")},\n", " \"decision_tree\": {\n", - " \"model\": tree.DecisionTreeClassifier(max_depth=7, random_state=random_state)\n", + " \"model\": tree.DecisionTreeClassifier(max_depth=5, min_samples_split=10, random_state=random_state)\n", " },\n", + "\n", " \"knn\": {\"model\": neighbors.KNeighborsClassifier(n_neighbors=7)},\n", " \"naive_bayes\": {\"model\": naive_bayes.GaussianNB()},\n", " \"gradient_boosting\": {\n", " \"model\": ensemble.GradientBoostingClassifier(n_estimators=210)\n", " },\n", + "\n", " \"random_forest\": {\n", " \"model\": ensemble.RandomForestClassifier(\n", - " max_depth=11, class_weight=\"balanced\", random_state=random_state\n", + " max_depth=5, class_weight=\"balanced\", random_state=random_state\n", " )\n", " },\n", + "\n", " \"mlp\": {\n", " \"model\": neural_network.MLPClassifier(\n", " hidden_layer_sizes=(7,),\n", - " max_iter=500,\n", + " max_iter=200,\n", " early_stopping=True,\n", " random_state=random_state,\n", " )\n", @@ -2878,44 +2324,21 @@ }, { "cell_type": "code", - "execution_count": 343, + "execution_count": 163, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Model: logistic\n" - ] - }, - { - "ename": "ValueError", - "evalue": "Specifying the columns using strings is only supported for dataframes.", - "output_type": "error", - "traceback": [ - "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[1;31mAttributeError\u001b[0m Traceback (most recent call last)", - "File \u001b[1;32md:\\Study\\3 курс 5 семестр\\AIM\\AIM-PIbd-31-Yakovlev-M-G\\kernel\\Lib\\site-packages\\sklearn\\utils\\_indexing.py:338\u001b[0m, in \u001b[0;36m_get_column_indices\u001b[1;34m(X, key)\u001b[0m\n\u001b[0;32m 337\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m--> 338\u001b[0m all_columns \u001b[38;5;241m=\u001b[39m \u001b[43mX\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mcolumns\u001b[49m\n\u001b[0;32m 339\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mAttributeError\u001b[39;00m:\n", - "\u001b[1;31mAttributeError\u001b[0m: 'numpy.ndarray' object has no attribute 'columns'", - "\nDuring handling of the above exception, another exception occurred:\n", - "\u001b[1;31mValueError\u001b[0m Traceback (most recent call last)", - "Cell \u001b[1;32mIn[343], line 9\u001b[0m\n\u001b[0;32m 6\u001b[0m model \u001b[38;5;241m=\u001b[39m class_models[model_name][\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mmodel\u001b[39m\u001b[38;5;124m\"\u001b[39m]\n\u001b[0;32m 8\u001b[0m model_pipeline \u001b[38;5;241m=\u001b[39m Pipeline([(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mpipeline\u001b[39m\u001b[38;5;124m\"\u001b[39m, pipeline_end), (\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mmodel\u001b[39m\u001b[38;5;124m\"\u001b[39m, model)])\n\u001b[1;32m----> 9\u001b[0m model_pipeline \u001b[38;5;241m=\u001b[39m \u001b[43mmodel_pipeline\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mfit\u001b[49m\u001b[43m(\u001b[49m\u001b[43mX_train\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mvalues\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43my_train\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mvalues\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mravel\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 11\u001b[0m y_train_predict \u001b[38;5;241m=\u001b[39m model_pipeline\u001b[38;5;241m.\u001b[39mpredict(X_train)\n\u001b[0;32m 12\u001b[0m y_test_probs \u001b[38;5;241m=\u001b[39m model_pipeline\u001b[38;5;241m.\u001b[39mpredict_proba(X_test)[:, \u001b[38;5;241m1\u001b[39m]\n", - "File \u001b[1;32md:\\Study\\3 курс 5 семестр\\AIM\\AIM-PIbd-31-Yakovlev-M-G\\kernel\\Lib\\site-packages\\sklearn\\base.py:1473\u001b[0m, in \u001b[0;36m_fit_context..decorator..wrapper\u001b[1;34m(estimator, *args, **kwargs)\u001b[0m\n\u001b[0;32m 1466\u001b[0m estimator\u001b[38;5;241m.\u001b[39m_validate_params()\n\u001b[0;32m 1468\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m config_context(\n\u001b[0;32m 1469\u001b[0m skip_parameter_validation\u001b[38;5;241m=\u001b[39m(\n\u001b[0;32m 1470\u001b[0m prefer_skip_nested_validation \u001b[38;5;129;01mor\u001b[39;00m global_skip_validation\n\u001b[0;32m 1471\u001b[0m )\n\u001b[0;32m 1472\u001b[0m ):\n\u001b[1;32m-> 1473\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mfit_method\u001b[49m\u001b[43m(\u001b[49m\u001b[43mestimator\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n", - "File \u001b[1;32md:\\Study\\3 курс 5 семестр\\AIM\\AIM-PIbd-31-Yakovlev-M-G\\kernel\\Lib\\site-packages\\sklearn\\pipeline.py:469\u001b[0m, in \u001b[0;36mPipeline.fit\u001b[1;34m(self, X, y, **params)\u001b[0m\n\u001b[0;32m 426\u001b[0m \u001b[38;5;250m\u001b[39m\u001b[38;5;124;03m\"\"\"Fit the model.\u001b[39;00m\n\u001b[0;32m 427\u001b[0m \n\u001b[0;32m 428\u001b[0m \u001b[38;5;124;03mFit all the transformers one after the other and sequentially transform the\u001b[39;00m\n\u001b[1;32m (...)\u001b[0m\n\u001b[0;32m 466\u001b[0m \u001b[38;5;124;03m Pipeline with fitted steps.\u001b[39;00m\n\u001b[0;32m 467\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[0;32m 468\u001b[0m routed_params \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_check_method_params(method\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mfit\u001b[39m\u001b[38;5;124m\"\u001b[39m, props\u001b[38;5;241m=\u001b[39mparams)\n\u001b[1;32m--> 469\u001b[0m Xt \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_fit\u001b[49m\u001b[43m(\u001b[49m\u001b[43mX\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43my\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mrouted_params\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 470\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m _print_elapsed_time(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mPipeline\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_log_message(\u001b[38;5;28mlen\u001b[39m(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39msteps) \u001b[38;5;241m-\u001b[39m \u001b[38;5;241m1\u001b[39m)):\n\u001b[0;32m 471\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_final_estimator \u001b[38;5;241m!=\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mpassthrough\u001b[39m\u001b[38;5;124m\"\u001b[39m:\n", - "File \u001b[1;32md:\\Study\\3 курс 5 семестр\\AIM\\AIM-PIbd-31-Yakovlev-M-G\\kernel\\Lib\\site-packages\\sklearn\\pipeline.py:406\u001b[0m, in \u001b[0;36mPipeline._fit\u001b[1;34m(self, X, y, routed_params)\u001b[0m\n\u001b[0;32m 404\u001b[0m cloned_transformer \u001b[38;5;241m=\u001b[39m clone(transformer)\n\u001b[0;32m 405\u001b[0m \u001b[38;5;66;03m# Fit or load from cache the current transformer\u001b[39;00m\n\u001b[1;32m--> 406\u001b[0m X, fitted_transformer \u001b[38;5;241m=\u001b[39m \u001b[43mfit_transform_one_cached\u001b[49m\u001b[43m(\u001b[49m\n\u001b[0;32m 407\u001b[0m \u001b[43m \u001b[49m\u001b[43mcloned_transformer\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 408\u001b[0m \u001b[43m \u001b[49m\u001b[43mX\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 409\u001b[0m \u001b[43m \u001b[49m\u001b[43my\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 410\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43;01mNone\u001b[39;49;00m\u001b[43m,\u001b[49m\n\u001b[0;32m 411\u001b[0m \u001b[43m \u001b[49m\u001b[43mmessage_clsname\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mPipeline\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\n\u001b[0;32m 412\u001b[0m \u001b[43m \u001b[49m\u001b[43mmessage\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_log_message\u001b[49m\u001b[43m(\u001b[49m\u001b[43mstep_idx\u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 413\u001b[0m \u001b[43m \u001b[49m\u001b[43mparams\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mrouted_params\u001b[49m\u001b[43m[\u001b[49m\u001b[43mname\u001b[49m\u001b[43m]\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 414\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 415\u001b[0m \u001b[38;5;66;03m# Replace the transformer of the step with the fitted\u001b[39;00m\n\u001b[0;32m 416\u001b[0m \u001b[38;5;66;03m# transformer. This is necessary when loading the transformer\u001b[39;00m\n\u001b[0;32m 417\u001b[0m \u001b[38;5;66;03m# from the cache.\u001b[39;00m\n\u001b[0;32m 418\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39msteps[step_idx] \u001b[38;5;241m=\u001b[39m (name, fitted_transformer)\n", - "File \u001b[1;32md:\\Study\\3 курс 5 семестр\\AIM\\AIM-PIbd-31-Yakovlev-M-G\\kernel\\Lib\\site-packages\\joblib\\memory.py:312\u001b[0m, in \u001b[0;36mNotMemorizedFunc.__call__\u001b[1;34m(self, *args, **kwargs)\u001b[0m\n\u001b[0;32m 311\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m__call__\u001b[39m(\u001b[38;5;28mself\u001b[39m, \u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs):\n\u001b[1;32m--> 312\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mfunc\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n", - "File \u001b[1;32md:\\Study\\3 курс 5 семестр\\AIM\\AIM-PIbd-31-Yakovlev-M-G\\kernel\\Lib\\site-packages\\sklearn\\pipeline.py:1310\u001b[0m, in \u001b[0;36m_fit_transform_one\u001b[1;34m(transformer, X, y, weight, message_clsname, message, params)\u001b[0m\n\u001b[0;32m 1308\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m _print_elapsed_time(message_clsname, message):\n\u001b[0;32m 1309\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mhasattr\u001b[39m(transformer, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mfit_transform\u001b[39m\u001b[38;5;124m\"\u001b[39m):\n\u001b[1;32m-> 1310\u001b[0m res \u001b[38;5;241m=\u001b[39m \u001b[43mtransformer\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mfit_transform\u001b[49m\u001b[43m(\u001b[49m\u001b[43mX\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43my\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mparams\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mget\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mfit_transform\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43m{\u001b[49m\u001b[43m}\u001b[49m\u001b[43m)\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 1311\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m 1312\u001b[0m res \u001b[38;5;241m=\u001b[39m transformer\u001b[38;5;241m.\u001b[39mfit(X, y, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mparams\u001b[38;5;241m.\u001b[39mget(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mfit\u001b[39m\u001b[38;5;124m\"\u001b[39m, {}))\u001b[38;5;241m.\u001b[39mtransform(\n\u001b[0;32m 1313\u001b[0m X, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mparams\u001b[38;5;241m.\u001b[39mget(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mtransform\u001b[39m\u001b[38;5;124m\"\u001b[39m, {})\n\u001b[0;32m 1314\u001b[0m )\n", - "File \u001b[1;32md:\\Study\\3 курс 5 семестр\\AIM\\AIM-PIbd-31-Yakovlev-M-G\\kernel\\Lib\\site-packages\\sklearn\\base.py:1473\u001b[0m, in \u001b[0;36m_fit_context..decorator..wrapper\u001b[1;34m(estimator, *args, **kwargs)\u001b[0m\n\u001b[0;32m 1466\u001b[0m estimator\u001b[38;5;241m.\u001b[39m_validate_params()\n\u001b[0;32m 1468\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m config_context(\n\u001b[0;32m 1469\u001b[0m skip_parameter_validation\u001b[38;5;241m=\u001b[39m(\n\u001b[0;32m 1470\u001b[0m prefer_skip_nested_validation \u001b[38;5;129;01mor\u001b[39;00m global_skip_validation\n\u001b[0;32m 1471\u001b[0m )\n\u001b[0;32m 1472\u001b[0m ):\n\u001b[1;32m-> 1473\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mfit_method\u001b[49m\u001b[43m(\u001b[49m\u001b[43mestimator\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n", - "File \u001b[1;32md:\\Study\\3 курс 5 семестр\\AIM\\AIM-PIbd-31-Yakovlev-M-G\\kernel\\Lib\\site-packages\\sklearn\\pipeline.py:533\u001b[0m, in \u001b[0;36mPipeline.fit_transform\u001b[1;34m(self, X, y, **params)\u001b[0m\n\u001b[0;32m 490\u001b[0m \u001b[38;5;250m\u001b[39m\u001b[38;5;124;03m\"\"\"Fit the model and transform with the final estimator.\u001b[39;00m\n\u001b[0;32m 491\u001b[0m \n\u001b[0;32m 492\u001b[0m \u001b[38;5;124;03mFit all the transformers one after the other and sequentially transform\u001b[39;00m\n\u001b[1;32m (...)\u001b[0m\n\u001b[0;32m 530\u001b[0m \u001b[38;5;124;03m Transformed samples.\u001b[39;00m\n\u001b[0;32m 531\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[0;32m 532\u001b[0m routed_params \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_check_method_params(method\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mfit_transform\u001b[39m\u001b[38;5;124m\"\u001b[39m, props\u001b[38;5;241m=\u001b[39mparams)\n\u001b[1;32m--> 533\u001b[0m Xt \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_fit\u001b[49m\u001b[43m(\u001b[49m\u001b[43mX\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43my\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mrouted_params\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 535\u001b[0m last_step \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_final_estimator\n\u001b[0;32m 536\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m _print_elapsed_time(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mPipeline\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_log_message(\u001b[38;5;28mlen\u001b[39m(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39msteps) \u001b[38;5;241m-\u001b[39m \u001b[38;5;241m1\u001b[39m)):\n", - "File \u001b[1;32md:\\Study\\3 курс 5 семестр\\AIM\\AIM-PIbd-31-Yakovlev-M-G\\kernel\\Lib\\site-packages\\sklearn\\pipeline.py:406\u001b[0m, in \u001b[0;36mPipeline._fit\u001b[1;34m(self, X, y, routed_params)\u001b[0m\n\u001b[0;32m 404\u001b[0m cloned_transformer \u001b[38;5;241m=\u001b[39m clone(transformer)\n\u001b[0;32m 405\u001b[0m \u001b[38;5;66;03m# Fit or load from cache the current transformer\u001b[39;00m\n\u001b[1;32m--> 406\u001b[0m X, fitted_transformer \u001b[38;5;241m=\u001b[39m \u001b[43mfit_transform_one_cached\u001b[49m\u001b[43m(\u001b[49m\n\u001b[0;32m 407\u001b[0m \u001b[43m \u001b[49m\u001b[43mcloned_transformer\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 408\u001b[0m \u001b[43m \u001b[49m\u001b[43mX\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 409\u001b[0m \u001b[43m \u001b[49m\u001b[43my\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 410\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43;01mNone\u001b[39;49;00m\u001b[43m,\u001b[49m\n\u001b[0;32m 411\u001b[0m \u001b[43m \u001b[49m\u001b[43mmessage_clsname\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mPipeline\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\n\u001b[0;32m 412\u001b[0m \u001b[43m \u001b[49m\u001b[43mmessage\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_log_message\u001b[49m\u001b[43m(\u001b[49m\u001b[43mstep_idx\u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 413\u001b[0m \u001b[43m \u001b[49m\u001b[43mparams\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mrouted_params\u001b[49m\u001b[43m[\u001b[49m\u001b[43mname\u001b[49m\u001b[43m]\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 414\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 415\u001b[0m \u001b[38;5;66;03m# Replace the transformer of the step with the fitted\u001b[39;00m\n\u001b[0;32m 416\u001b[0m \u001b[38;5;66;03m# transformer. This is necessary when loading the transformer\u001b[39;00m\n\u001b[0;32m 417\u001b[0m \u001b[38;5;66;03m# from the cache.\u001b[39;00m\n\u001b[0;32m 418\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39msteps[step_idx] \u001b[38;5;241m=\u001b[39m (name, fitted_transformer)\n", - "File \u001b[1;32md:\\Study\\3 курс 5 семестр\\AIM\\AIM-PIbd-31-Yakovlev-M-G\\kernel\\Lib\\site-packages\\joblib\\memory.py:312\u001b[0m, in \u001b[0;36mNotMemorizedFunc.__call__\u001b[1;34m(self, *args, **kwargs)\u001b[0m\n\u001b[0;32m 311\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m__call__\u001b[39m(\u001b[38;5;28mself\u001b[39m, \u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs):\n\u001b[1;32m--> 312\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mfunc\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n", - "File \u001b[1;32md:\\Study\\3 курс 5 семестр\\AIM\\AIM-PIbd-31-Yakovlev-M-G\\kernel\\Lib\\site-packages\\sklearn\\pipeline.py:1310\u001b[0m, in \u001b[0;36m_fit_transform_one\u001b[1;34m(transformer, X, y, weight, message_clsname, message, params)\u001b[0m\n\u001b[0;32m 1308\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m _print_elapsed_time(message_clsname, message):\n\u001b[0;32m 1309\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mhasattr\u001b[39m(transformer, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mfit_transform\u001b[39m\u001b[38;5;124m\"\u001b[39m):\n\u001b[1;32m-> 1310\u001b[0m res \u001b[38;5;241m=\u001b[39m \u001b[43mtransformer\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mfit_transform\u001b[49m\u001b[43m(\u001b[49m\u001b[43mX\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43my\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mparams\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mget\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mfit_transform\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43m{\u001b[49m\u001b[43m}\u001b[49m\u001b[43m)\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 1311\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m 1312\u001b[0m res \u001b[38;5;241m=\u001b[39m transformer\u001b[38;5;241m.\u001b[39mfit(X, y, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mparams\u001b[38;5;241m.\u001b[39mget(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mfit\u001b[39m\u001b[38;5;124m\"\u001b[39m, {}))\u001b[38;5;241m.\u001b[39mtransform(\n\u001b[0;32m 1313\u001b[0m X, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mparams\u001b[38;5;241m.\u001b[39mget(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mtransform\u001b[39m\u001b[38;5;124m\"\u001b[39m, {})\n\u001b[0;32m 1314\u001b[0m )\n", - "File \u001b[1;32md:\\Study\\3 курс 5 семестр\\AIM\\AIM-PIbd-31-Yakovlev-M-G\\kernel\\Lib\\site-packages\\sklearn\\utils\\_set_output.py:316\u001b[0m, in \u001b[0;36m_wrap_method_output..wrapped\u001b[1;34m(self, X, *args, **kwargs)\u001b[0m\n\u001b[0;32m 314\u001b[0m \u001b[38;5;129m@wraps\u001b[39m(f)\n\u001b[0;32m 315\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mwrapped\u001b[39m(\u001b[38;5;28mself\u001b[39m, X, \u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs):\n\u001b[1;32m--> 316\u001b[0m data_to_wrap \u001b[38;5;241m=\u001b[39m \u001b[43mf\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mX\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 317\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(data_to_wrap, \u001b[38;5;28mtuple\u001b[39m):\n\u001b[0;32m 318\u001b[0m \u001b[38;5;66;03m# only wrap the first output for cross decomposition\u001b[39;00m\n\u001b[0;32m 319\u001b[0m return_tuple \u001b[38;5;241m=\u001b[39m (\n\u001b[0;32m 320\u001b[0m _wrap_data_with_container(method, data_to_wrap[\u001b[38;5;241m0\u001b[39m], X, \u001b[38;5;28mself\u001b[39m),\n\u001b[0;32m 321\u001b[0m \u001b[38;5;241m*\u001b[39mdata_to_wrap[\u001b[38;5;241m1\u001b[39m:],\n\u001b[0;32m 322\u001b[0m )\n", - "File \u001b[1;32md:\\Study\\3 курс 5 семестр\\AIM\\AIM-PIbd-31-Yakovlev-M-G\\kernel\\Lib\\site-packages\\sklearn\\base.py:1473\u001b[0m, in \u001b[0;36m_fit_context..decorator..wrapper\u001b[1;34m(estimator, *args, **kwargs)\u001b[0m\n\u001b[0;32m 1466\u001b[0m estimator\u001b[38;5;241m.\u001b[39m_validate_params()\n\u001b[0;32m 1468\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m config_context(\n\u001b[0;32m 1469\u001b[0m skip_parameter_validation\u001b[38;5;241m=\u001b[39m(\n\u001b[0;32m 1470\u001b[0m prefer_skip_nested_validation \u001b[38;5;129;01mor\u001b[39;00m global_skip_validation\n\u001b[0;32m 1471\u001b[0m )\n\u001b[0;32m 1472\u001b[0m ):\n\u001b[1;32m-> 1473\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mfit_method\u001b[49m\u001b[43m(\u001b[49m\u001b[43mestimator\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n", - "File \u001b[1;32md:\\Study\\3 курс 5 семестр\\AIM\\AIM-PIbd-31-Yakovlev-M-G\\kernel\\Lib\\site-packages\\sklearn\\compose\\_column_transformer.py:968\u001b[0m, in \u001b[0;36mColumnTransformer.fit_transform\u001b[1;34m(self, X, y, **params)\u001b[0m\n\u001b[0;32m 965\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_validate_transformers()\n\u001b[0;32m 966\u001b[0m n_samples \u001b[38;5;241m=\u001b[39m _num_samples(X)\n\u001b[1;32m--> 968\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_validate_column_callables\u001b[49m\u001b[43m(\u001b[49m\u001b[43mX\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 969\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_validate_remainder(X)\n\u001b[0;32m 971\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m _routing_enabled():\n", - "File \u001b[1;32md:\\Study\\3 курс 5 семестр\\AIM\\AIM-PIbd-31-Yakovlev-M-G\\kernel\\Lib\\site-packages\\sklearn\\compose\\_column_transformer.py:536\u001b[0m, in \u001b[0;36mColumnTransformer._validate_column_callables\u001b[1;34m(self, X)\u001b[0m\n\u001b[0;32m 534\u001b[0m columns \u001b[38;5;241m=\u001b[39m columns(X)\n\u001b[0;32m 535\u001b[0m all_columns\u001b[38;5;241m.\u001b[39mappend(columns)\n\u001b[1;32m--> 536\u001b[0m transformer_to_input_indices[name] \u001b[38;5;241m=\u001b[39m \u001b[43m_get_column_indices\u001b[49m\u001b[43m(\u001b[49m\u001b[43mX\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcolumns\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 538\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_columns \u001b[38;5;241m=\u001b[39m all_columns\n\u001b[0;32m 539\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_transformer_to_input_indices \u001b[38;5;241m=\u001b[39m transformer_to_input_indices\n", - "File \u001b[1;32md:\\Study\\3 курс 5 семестр\\AIM\\AIM-PIbd-31-Yakovlev-M-G\\kernel\\Lib\\site-packages\\sklearn\\utils\\_indexing.py:340\u001b[0m, in \u001b[0;36m_get_column_indices\u001b[1;34m(X, key)\u001b[0m\n\u001b[0;32m 338\u001b[0m all_columns \u001b[38;5;241m=\u001b[39m X\u001b[38;5;241m.\u001b[39mcolumns\n\u001b[0;32m 339\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mAttributeError\u001b[39;00m:\n\u001b[1;32m--> 340\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\n\u001b[0;32m 341\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mSpecifying the columns using strings is only supported for dataframes.\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m 342\u001b[0m )\n\u001b[0;32m 343\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(key, \u001b[38;5;28mstr\u001b[39m):\n\u001b[0;32m 344\u001b[0m columns \u001b[38;5;241m=\u001b[39m [key]\n", - "\u001b[1;31mValueError\u001b[0m: Specifying the columns using strings is only supported for dataframes." + "Model: logistic\n", + "Model: ridge\n", + "Model: decision_tree\n", + "Model: knn\n", + "Model: naive_bayes\n", + "Model: gradient_boosting\n", + "Model: random_forest\n", + "Model: mlp\n" ] } ], @@ -2928,7 +2351,7 @@ " model = class_models[model_name][\"model\"]\n", "\n", " model_pipeline = Pipeline([(\"pipeline\", pipeline_end), (\"model\", model)])\n", - " model_pipeline = model_pipeline.fit(X_train.values, y_train.values.ravel())\n", + " model_pipeline = model_pipeline.fit(X_train, y_train.values.ravel())\n", "\n", " y_train_predict = model_pipeline.predict(X_train)\n", " y_test_probs = model_pipeline.predict_proba(X_test)[:, 1]\n", @@ -2939,10 +2362,10 @@ " class_models[model_name][\"preds\"] = y_test_predict\n", "\n", " class_models[model_name][\"Precision_train\"] = metrics.precision_score(\n", - " y_train, y_train_predict\n", + " y_train, y_train_predict, zero_division=1\n", " )\n", " class_models[model_name][\"Precision_test\"] = metrics.precision_score(\n", - " y_test, y_test_predict\n", + " y_test, y_test_predict, zero_division=1\n", " )\n", " class_models[model_name][\"Recall_train\"] = metrics.recall_score(\n", " y_train, y_train_predict\n", @@ -2971,6 +2394,2943 @@ " y_test, y_test_predict\n", " )" ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Сводная таблица оценок качества для использованных моделей классификации. Матрица неточностей" + ] + }, + { + "cell_type": "code", + "execution_count": 164, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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0b9/f2M3Q3aCg4MhCALefvvtImUTJkyAIAgIDg5+9g0jIiKjYzYbB7OZKgM7R0Rl5OHhgZ07d+LJkyfSupycHOzYsQP169cv93ZFUUR+fr4hmkhERCQrzGYyNHaOapBLly4hKCgI1tbWcHZ2xptvvon79+9L5d9++y1atWoFS0tL1K5dG/7+/sjOzgYAREZG4vnnn4eVlRXs7e3RqVMn3Lhxw1iHUiW1b98eHh4e+P7776V133//PerXr4927dpJ63Jzc/HOO+/AyckJFhYW6Ny5M/7880+pPDIyEoIgYP/+/fD19YW5uTl+++03aDQahIeHo2HDhrC0tESbNm3w7bffPtNjJCIiw2I2Vy5mMxkaO0c1RHp6Ol566SW0a9cOp0+fxoEDB5CSkoJBgwYBAJKSkjBkyBCMHj0acXFxiIyMxIABA6QrI/3790e3bt1w4cIFREdHY9y4cRAEwchHVfWMHj0amzdvlj5v2rSpyJudZ86cie+++w5bt27F2bNn4eXlhcDAQKSlpWnVmz17NhYvXoy4uDi0bt0a4eHh2LZtG9avX4/Y2FhMnToVw4cPx7Fjx57JsRERkWExm58NZjMZlEjVysiRI8V+/foVWf/BBx+IAQEBWutu3bolAhDj4+PFM2fOiADE69evF/nZBw8eiADEyMjIymp2tVf4vaemporm5ubi9evXxevXr4sWFhbivXv3xH79+okjR44Us7KyRDMzM3H79u3Sz+bl5Ylubm7ikiVLRFEUxaNHj4oAxD179kh1cnJyxFq1aoknT57U2m9ISIg4ZMiQZ3OQRERULsxm42A2U2UwNV63jAzp/PnzOHr0KKytrYuUXb16FQEBAejZsydatWqFwMBABAQE4PXXX4eDgwMcHR0RHByMwMBAvPzyy/D398egQYPg6upqhCOp2urWrYvevXtjy5YtEEURvXv3Rp06daTyq1evQqVSoVOnTtI6MzMzPP/884iLi9PaVocOHaQ/JyQk4PHjx3j55Ze16uTl5WndFkBERNUHs/nZYDaTIbFzVENkZWWhT58++Pjjj4uUubq6wsTEBBERETh58iQOHTqE1atXY+7cuTh16hQaNmyIzZs345133sGBAwewa9cuvP/++4iIiMALL7xghKOp2kaPHo2JEycCANasWVPu7VhZWUl/zsrKAgDs27cP9erV06pnbm5e7n0Q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zKzU76Rx48bIysrS+7sjIiJ61pYuXQpTU1P85z//gY2NDYYOHWrsJhE9c7ytroYxMTFBYGAg9uzZg5s3b0rr4+LicPDgQenzgAEDYGJigrCwsCJXcURRxIMHDwAA7du3R8OGDbFixQqkp6cXqVeStLS0Iuvatm0LAMjNzS32Z1xdXdG2bVts3bpVa1+XLl3CoUOH8Morr5S4v4oo7HD9+/hK4uTkhO7du+Pzzz9HUlJSkfJ79+5Jfx40aBCio6O1vvtC6enpyM/PL1+jiYiIDEwQBGzYsAGvv/46Ro4cWezrKYhqOo4c1UBhYWE4cOAAunTpgv/85z/Iz8/H6tWr0aJFC1y4cAFAwYjGhx9+iDlz5uD69evo378/bGxskJiYiB9++AHjxo3D9OnToVAosG7dOvTp0wdt27bFqFGj4OrqisuXLyM2NrbYf/QDwMKFCxEVFYXevXvD09MTqampWLt2Ldzd3dG5c+cS27506VIEBQXBz88PISEh0lTednZ2CA0NrYyvC76+vgCAd955B4GBgTAxMcHgwYN1/syaNWvQuXNntGrVCmPHjkWjRo2QkpKC6Oho3L59G+fPnwcAzJgxAz/99BNeffVVBAcHw9fXF9nZ2bh48SK+/fZbXL9+XZoilYiIyNgUCgW++uor9O/fH4MGDcIvv/yCl156ydjNInpm2DmqgVq3bo2DBw9i2rRpmD9/Ptzd3REWFoakpCSpcwQAs2fPRtOmTbF8+XKEhYUBADw8PBAQEIC+fftK9QIDA3H06FGEhYXh008/hUajQePGjTF27NgS29C3b19cv34dmzZtwv3791GnTh1069YNYWFhsLOzK/Hn/P39ceDAASxYsADz58+HmZkZunXrho8//rjIxAiGMmDAAEyaNAk7d+7EV199BVEUS+0c+fj44PTp0wgLC8OWLVvw4MEDODk5oV27dpg/f75Ur1atWjh27BgWLVqEb775Btu2bYOtrS2aNm1a6ndBRERkDGZmZvj2228RFBSEfv364ddffzV2k4ieGUHkk3FERERERER85oiIiIiIiAjgbXVUg2VkZODJkyc667i4uDyj1hARERFRVcfb6qjGCg4OxtatW3XW4X/+RERERFSInSOqsf766y/cvXtXZx2+f4iIiIiICrFzREREREREBE7IQEREREREBIATMpSJRqPB3bt3YWNjA0EQ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FkBERBUHY/OLwdhMusTkqJJIS0tD165d8fnnnxeoc3V1hbGxMfbu3YujR49iz549+Prrr/Hhhx/ixIkTqFmzJsLCwjBmzBjs3r0bGzduxEcffYS9e/eiZcuWejgawzZ48GCMHj0aALB48eJn7sfS0lL6OS0tDQCwY8cOVK1aVaudSqV65n0QEZH+MDa/OIzNpCu856iSaNasGaKiolCjRg14enpqbfm/6AqFAq1atcLMmTNx9uxZKJVK/PLLL1IfTZs2xZQpU3D06FE0aNAA69ev19fhGLTOnTsjKysL2dnZCAgI0KqrXbs2lEolIiIipLLs7GycPHkS3t7eRfbp7e0NlUqFGzduFPj/5+7uXm7HQkRE5Yex+cVhbCZd4cxRBZScnIzIyEitsmHDhmH58uXo06cPJk2aBHt7e8TGxmLDhg1YsWIFTp06hf3798Pf3x9OTk44ceIE7t+/j3r16uHq1av47rvv0K1bN7i5uSEmJgaXL1/GwIED9XOABs7Y2Fiahjc2Ntaqs7S0xIgRIzBx4kTY29ujevXqmDt3LtLT0zFkyJAi+7S2tsaECRMQEhICjUaD1q1bIzk5GREREVCr1QgKCirXYyIioufD2KxfjM2kK0yOKqDw8PAC17oOGTIEERERmDx5Mvz9/ZGZmQkPDw907twZRkZGUKvVOHToEBYuXIiUlBR4eHhg3rx56NKlC+7du4eLFy9izZo1ePjwIVxdXTFq1Ci89957ejpCw6dWq4us++yzz6DRaDBgwACkpqaiefPm+P3332FnZ1dsn7Nnz4ajoyNCQ0Nx5coV2NraolmzZpg6daquh09ERDrG2Kx/jM2kCwohhND3IIiIiIiIiPSN9xwRERERERGByREREREREREAJkdEREREREQAmBwREREREREBYHJEREREREQEgMkRERERERERACZHREREREREAJgckY4EBwejR48e0uv27dtj3LhxL3wc4eHhUCgUSEpKKrKNQqHA1q1bS93njBkz0KRJk+ca17Vr16BQKAo8PZ2IiKi8MDYXj7GZCsPkqBILDg6GQqGAQqGAUqmEp6cnZs2ahZycnHLf95YtWzB79uxStS3NlyYREVFlwNhMZNhM9D0AKl+dO3dGWFgYMjMzsXPnTowaNQqmpqaYMmVKgbZZWVlQKpU62a+9vb1O+iEiIqpsGJuJDBdnjio5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bcL06dO16jZu3AhjY2P83//9H4C8afp27drh9u3beO+991C9enUcPXoUU6ZMwd27d8t8DfCjR4/w+uuvo3fv3ujTpw82bdqEESNGQKlUYvDgwQCAlJQUrFixAn369MHQoUORmpqKlStXIiAgAH/++SeaNGkChUKB/v37Y+7cuUhMTIS9vb20j99++w0pKSno378/gLyzgd26dcORI0cwbNgw1KtXD3/99RcWLFiAS5cuYevWrQCAqKgovPHGG2jUqBFmzZoFlUqF2NhYRERElOkYiYhIf86ePYvOnTvD1dUVM2fORG5uLmbNmiUlD//1xx9/YNOmTRg9ejQcHBykP7q/+uordOvWDf369UNWVhY2bNiA//u//8P27dsRGBgovf/dd9/FDz/8gL59++LVV1/FH3/8oVVfnO+//x5BQUEICAjA559/jvT0dCxduhStW7fG2bNnpbEAeUlLQEAAWrRogS+//BL79u3DvHnzULt2bYwYMQKOjo5YunQpRowYgTfffBM9e/YEADRq1KhMn92nn34KhUKByZMnIyEhAQsXLoSfnx8iIyNhbm4OIC/RGzRoEF5++WWEhobi3r17+OqrrxAREYGzZ8/C1tYWALBv3z506dIFtWrVwowZM/DkyRN8/fXXaNWqFc6cOSMd3/Dhw7F582aMHj0a3t7eePjwIY4cOYLo6Gg0a9YMH374IZKTk3Hr1i0sWLAAAGBlZVXscZT0eQF5fxt07doVf/75J0aMGIG6devi119/RVBQUJk+MzIggiq16dOnCwBi8ODBWuVvvvmmqFKlivQ6PT29wHsDAgJErVq1tMratWsn2rVrJ73+9ttvBQDx119/abXz9vYWHTp0kF7Pnj1bWFpaikuXLmm1++CDD4SxsbG4ceNGqY+pXbt2AoCYN2+eVJaZmSmaNGkinJycRFZWlhBCiJycHJGZman13kePHglnZ2etzyMmJkYAEEuXLtVq261bN1GjRg2h0WiEEEJ8//33wsjISBw+fFir3bJlywQAERERIYQQYsGCBQKAuH//fqmPiYiIDEvXrl2FhYWFuH37tlR2+fJlYWJiIv775xMAYWRkJKKiogr08XRszcrKEg0aNNCKj5GRkQKAGDlypFbbvn37CgBi+vTpUllYWJgAIK5evSqEECI1NVXY2tqKoUOHar03Pj5e2NjYaJUHBQUJAGLW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3r0bGzduxEcffYS9e/eiZcuWejgawzZ48GCMHj0aALB48eJn7sfS0lL6OS0tDQCwY8cOVK1aVaudSqV65n0QEZH+MDa/OIzNpCu856iSaNasGaKiolCjRg14enpqbfm/6AqFAq1atcLMmTNx9uxZKJVK/PLLL1IfTZs2xZQpU3D06FE0aNAA69ev19fhGLTOnTsjKysL2dnZCAgI0KqrXbs2lEolIiIipLLs7GycPHkS3t7eRfbp7e0NlUqFGzduFPj/5+7uXm7HQkRE5Yex+cVhbCZd4cxRBZScnIzIyEitsmHDhmH58uXo06cPJk2aBHt7e8TGxmLDhg1YsWIFTp06hf3798Pf3x9OTk44ceIE7t+/j3r16uHq1av47rvv0K1bN7i5uSEmJgaXL1/GwIED9XOABs7Y2Fiahjc2Ntaqs7S0xIgRIzBx4kTY29ujevXqmDt3LtLT0zFkyJAi+7S2tsaECRMQEhICjUaD1q1bIzk5GREREVCr1QgKCirXYyIioufD2KxfjM2kK0yOKqDw8PAC17oOGTIEERERmDx5Mvz9/ZGZmQkPDw907twZRkZGUKvVOHToEBYuXIiUlBR4eHhg3rx56NKlC+7du4eLFy9izZo1ePjwIVxdXTFq1Ci89957ejpCw6dWq4us++yzz6DRaDBgwACkpqaiefPm+P3332FnZ1dsn7Nnz4ajoyNCQ0Nx5coV2NraolmzZpg6daquh09ERDrG2Kx/jM2kCwohhND3IIiIiIiIiPSN9xwRERERERGByREREREREREAJkdEREREREQAmBwREREREREBYHJEREREREQEgMkRERERERERACZHREREREREAJgckY4EBwejR48e0uv27dtj3LhxL3wc4eHhUCgUSEpKKrKNQqHA1q1bS93njBkz0KRJk+ca17Vr16BQKAo8PZ2IiKi8MDYXj7GZCsPkqBILDg6GQqGAQqGAUqmEp6cnZs2ahZycnHLf95YtWzB79uxStS3NlyYREVFlwNhMZNhM9D0AKl+dO3dGWFgYMjMzsXPnTowaNQqmpqaYMmVKgbZZWVlQKpU62a+9vb1O+iEiIqpsGJuJDBdnjio5lUoFFxcXeHh4YMSIEfDz88O2bdsA/Dvd/umnn8LNzQ1eXl4AgJs3b6J3796wtbWFvb09unfvjmvXrkl95ubmYvz48bC1tUWVKlUwadIkCCG09vv01H1mZiYmT54Md3d3qFQqeHp6YuXKlbh27Rpee+01AICdnR0UCgWCg4MBABqNBqGhoahZsybMzc3RuHFjbN68WWs/O3fuRJ06dWBubo7XXntNa5ylNXnyZNSpUwcWFhaoVasWPv74Y2RnZxdo9+2338Ld3R0WFhbo3bs3kpOTtepXrFiBevXqwczMDHXr1sWSJUvKPBYiIqr8GJtLxthM+sLkSGbMzc2RlZUlvd6/fz9iYmKwd+9ebN++HdnZ2QgICIC1tTUOHz6MiIgIWFlZoXPnztL75s2bh9WrV2PVqlU4cuQIEhMT8csvvxS734EDB+LHH3/EokWLEB0djW+//RZWVlZwd3fHzz//DACIiYnB3bt38dVXXwEAQkNDsXbtWixbtgxRUVEICQlB//79cfDgQQB5gaJnz57o2rUrIiMj8e677+KDDz4o82dibW2N1atX4++//8ZXX32F5cuXY8GCBVptYmNjsWnTJvz222/YvXs3zp49i5EjR0r169atw7Rp0/Dpp58iOjoac+bMwccff4w1a9aUeTxERCQvjM0FMTaT3giqtIKCgkT37t2FEEJoNBqxd+9eoVKpxIQJE6R6Z2dnkZmZKb3n+++/F15eXkKj0UhlmZmZwtzcXPz+++9CCCFcXV3F3Llzpfrs7GxRrVo1aV9CCNGuXTsxduxYIYQQMTExAoDYu3dvoeM8cOCAACAePXoklWVkZAgLCwtx9OhRrbZDhgwRffr0EUIIMWXKFOHt7a1VP3ny5AJ9PQ2A+OWXX4qs/+KLL4SPj4/0evr06cLY2FjcunVLKtu1a5cwMjISd+/eFUIIUbt2bbF+/XqtfmbPni18fX2FEEJcvXpVABBnz54tcr9ERFT5MTYXjrGZDAXvOarktm/fDisrK2RnZ0Oj0aBv376YMWOGVN+wYUOta5nPnTuH2NhYWFtba/WTkZGBuLg4JCcn4+7du2jRooVUZ2JigubNmxeYvs8XGRkJY2NjtGvXrtTjjo2NRXp6Ojp16qRVnpWVhaZNmwIAoqOjtcYBAL6+vqXeR76NGzdi0aJFiIuLQ1paGnJycqBWq7XaVK9eHVWrVtXaj0ajQUxMDKytrREXF4chQ4Zg6NChUpucnBzY2NiUeTxERFS5mA00rAAAVR5JREFUMTaXjLGZ9IXJUSX32muvYenSpVAqlXBzc4OJifb/cktLS63XaWlp8PHxwbp16wr05ejo+ExjMDc3L/N70tLSAAA7duzQ+uID8q7V1pVjx46hX79+mDlzJgICAmBjY4MNGzZg3rx5ZR7r8uXLCwQEY2NjnY2ViIgqB8bm4jE2kz4xOarkLC0t4enpWer2zZo1w8aNG+Hk5FTgDE0+V1dXnDhxAm3btgWQdxbm9OnTaNasWaHtGzZsCI1Gg4MHD8LPz69Aff7ZsdzcXKnM29sbKpUKN27cKPKsVr169aQbWPMdP3685IP8j6NHj8LDwwMffvihVHb9+vUC7W7cuIE7d+7Azc1N2o+RkRG8vLzg7OwMNzc3XLlyBf369SvT/omISH4Ym4vH2Ez6xAUZSEu/fv3g4OCA7t274/Dhw7h69SrCw8MxZswY3Lp1CwAwduxYfPbZZ9i6dSsuXryIkSNHFvschBo1aiAoKAiDBw/G1q1bpT43bdoEAPDw8IBCocD27dtx//59pKWlwdraGhMmTEBISAjWrFmDuLg4nDlzBl9//bV0I+Xw4cNx+fJlTJw4ETExMVi/fj1Wr15dpuN96aWXcOPGDWzYsAFxcXFYtGhRoTewmpmZISgoCOfOncPhw4cxZswY9O7dGy4uLgCAmTNnIjQ0FIsWLcKlS5fw119/ISwsDPPnzy/TeIiIiJ7G2MzYTC+Qvm96ovLz35s+y1J/9+5dMXDgQOHg4CBUKpWoVauWGDp0qEhOThZC5N3kOXbsWKFWq4Wtra0YP368GDhwYJE3fQohxJMnT0RISIhwdXUVSqVSeHp6ilWrVkn1s2bNEi4uLkKhUIigoCAhRN6NqgsXLhReXl7C1NRUODo6ioCAAHHw4EHpfb/99pvw9PQUKpVKtGnTRqxatarMN31OnDhRVKlSRVhZWYm3335bLFiwQNjY2Ej106dPF40bNxZLliwRbm5uwszMTLz11lsiMTFRq99169aJJk2aCKVSKezs7ETbtm3Fli1bhBC86ZOIiPIwNheOsZkMhUKIIu7UIyIiIiIikhFeVkdERERERAQmR0RERERERACYHBEREREREQFgckRERERERASAyREREREREREAJkdEREREREQAmBwREREREREBYHJEREREREQEgMkRERERERERACZHREREREREAJgcERERERERAWByREREREREBIDJEREREREREQAmR0RERERERACYHNFzUigUmDFjhr6HUaTvv/8edevWhampKWxtbfU9HCIiokrl2rVrUCgUWL16tb6HQqQTTI6o0rp48SKCg4NRu3ZtLF++HN99952+h1TAnTt3MGPGDERGRup7KERERESyZ6LvARCVl/DwcGg0Gnz11Vfw9PTU93AKdefOHcycORM1atRAkyZN9D0cIiIiIlnjzFEl8/jxY30PwWAkJCQAgE4vp0tPT9dZX0RERERkWJgcVWAzZsyAQqHA33//jb59+8LOzg6tW7fG+fPnERwcjFq1asHMzAwuLi4YPHgwHj58WOj7Y2NjERwcDFtbW9jY2GDQoEEFkoDMzEyEhITA0dER1tbW6NatG27dulXouM6ePYsuXbpArVbDysoKHTt2xPHjx7XarF69GgqFAkeOHMGYMWPg6OgIW1tbvPfee8jKykJSUhIGDhwIOzs72NnZYdKkSRBClPqzqVGjBqZPnw4AcHR0LHBv1JIlS1C/fn2oVCq4ublh1KhRSEpK0uqjffv2aNCgAU6fPo22bdvCwsICU6dOlT6P6dOnw9PTEyqVCu7u7pg0aRIyMzO1+ti7dy9at24NW1tbWFlZwcvLS+ojPDwcL7/8MgBg0KBBUCgUvG6biIheuPy/By5duoT+/fvDxsYGjo6O+PjjjyGEwM2bN9G9e3eo1Wq4uLhg3rx5xfYXHBwMKysrXLlyBQEBAbC0tISbmxtmzZpVplhOpA+8rK4S+L//+z+89NJLmDNnDoQQ2Lt3L65cuYJBgwbBxcUFUVFR+O677xAVFYXjx49DoVBovb93796oWbMmQkNDcebMGaxYsQJOTk74/PPPpTbvvvsufvjhB/Tt2xevvvoq/vjjDwQGBhYYS1RUFNq0aQO1Wo1JkybB1NQU3377Ldq3b4+DBw+iRYsWWu3ff/99uLi4YObMmTh+/Di+++472Nra4ujRo6hevTrmzJmDnTt34osvvkCDBg0wcODAUn0mCxcuxNq1a/HLL79g6dKlsLKyQqNGjQDkBYGZM2fCz88PI0aMQExMDJYuXYqTJ08iIiICpqamUj8PHz5Ely5d8M4776B///5wdnaGRqNBt27dcOTIEQwbNgz16tXDX3/9hQULFuDSpUvYunWr9Fm88cYbaNSoEWbNmgWVSoXY2FhEREQAAOrVq4dZs2Zh2rRpGDZsGNq0aQMAePXVV0t1jERERLr09ttvo169evjss8+wY8cOfPLJJ7C3t8e3336LDh064PPPP8e6deswYcIEvPzyy2jbtm2RfeXm5qJz585o2bIl5s6di927d2P69OnIycnBrFmzXuBREZWRoApr+vTpAoDo06ePVnl6enqBtj/++KMAIA4dOlTg/YMHD9Zq++abb4oqVapIryMjIwUAMXLkSK12ffv2FQDE9OnTpbIePXoIpVIp4uLipLI7d+4Ia2tr0bZtW6ksLCxMABABAQFCo9FI5b6+vkKhUIjhw4dLZTk5OaJatWqiXbt2JXwi2vKP7/79+1JZQkKCUCqVwt/fX+Tm5krl33zzjQAgVq1aJZW1a9dOABDLli3T6vf7778XRkZG4vDhw1rly5YtEwBERESEEEKIBQsWFNj/006ePCkAiLCwsDIdGxERka7kx8thw4ZJZfmxV6FQiM8++0wqf/TokTA3NxdBQUFCCCGuXr1aII4FBQUJAOL999+XyjQajQgMDBRKpbLYuEikb7ysrhIYPny41mtzc3Pp54yMDDx48AAtW7YEAJw5c6bE97dp0wYPHz5ESkoKAGDnzp0AgDFjxmi1GzdunNbr3Nxc7NmzBz169ECtWrWkcldXV/Tt2xdHjhyR+sw3ZMgQrZmsFi1aQAiBIUOGSGXGxsZo3rw5rly5UvgHUAb79u1DVlYWxo0bByOjf//5Dx06FGq1Gjt27NBqr1KpMGjQIK2yn376CfXq1UPdunXx4MEDaevQoQMA4MCBAwD+vdfp119/hUajee6xExERlad3331X+jk/9j4dk21tbeHl5VWqmDx69GjpZ4VCgdGjRyMrKwv79u3T7cCJdIjJUSVQs2ZNrdeJiYkYO3YsnJ2dYW5uDkdHR6lNcnJygfdXr15d67WdnR0A4NGjRwCA69evw8jICLVr19Zq5+XlpfX6/v37SE9PL1AO5F1CptFocPPmzWL3bWNjAwBwd3cvUJ4/nudx/fr1QseuVCpRq1YtqT5f1apVoVQqtcouX76MqKgoODo6am116tQB8O9CEG+//TZatWqFd999F87OznjnnXewadMmJkpERGSQCovJZmZmcHBwKFBeUkw2MjLSOlEKQIqT165de/7BEpUT3nNUCfx3pgjIu4fo6NGjmDhxIpo0aQIrKytoNBp07ty50D/MjY2NC+1XvICbJovad2HlL2I8T3v6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PREZGYnw8HB0794doaGheO2111C7dm0J9sSy1apVC7169cLq1ashCAJ69eqFmjVr6tsvXLgAjUaD9u3b69fZ29vjhRdeQHJyssG22rZtq/9zamoq7t27h+7duxv0KS4uNrgsgIiIqg9m87PBbCYxsTiyEvn5+ejduzf+7//+77G22rVrw9bWFnFxcThy5Ah2796NxYsX44MPPsCxY8dQv359rFq1CqNHj8bOnTuxceNGfPjhh4iLi8OLL74owd5YtmHDhmHUqFEAgCVLllR6O87Ozvo/5+fnAwB27NiBOnXqGPRTqVSV/gwiIpIOs/nZYTaTWHjPkZVo3bo1zp49i3r16iEwMNBgKftFVygUaN++PaZPn47ffvsNSqUSW7du1W+jVatWmDx5Mo4cOYLnn38e69evl2p3LFqPHj1QXFwMjUaD8PBwg7aGDRtCqVTi8OHD+nUajQbHjx9HcHBwudsMDg6GSqVCenr6Y39/fn5+VbYvRERUdZjNzw6zmcTCmaNqKDc3F0lJSQbrRowYgRUrVmDAgAGYOHEiPD09kZqaig0bNuDLL7/EiRMnsGfPHoSFhcHLywvHjh3DzZs30bRpU6SlpeGLL77AK6+8Al9fX6SkpOD8+fMYMmSINDto4WxtbfXT8La2tgZtzs7OGDlyJCZMmABPT0/4+/tjzpw5uHfvHqKiosrdpqurK8aPH4+YmBjodDp06NABubm5OHz4MNRqNSIiIqp0n4iI6Okwm6XFbCaxsDiqhuLj4x+71jUqKgqHDx/Ge++9h7CwMBQVFSEgIAA9evSAjY0N1Go1Dhw4gAULFiAvLw8BAQGYO3cuevbsiaysLJw7dw5r1qzB7du3Ubt2bURHR+Pf//63RHto+dRqdblts2fPhk6nw+DBg3H37l20bdsWu3btgoeHh9Ftzpw5E7Vq1UJsbCwuXrwId3d3tG7dGu+//77YwyciIpExm6XHbCYxKARBEKQeBBERERERkdR4zxERERERERFYHBEREREREQFgcURERERERASAxREREREREREAFkdEREREREQAWBwREREREREBYHFEREREREQEgMURERERERERABZHJJLIyEj07dtX/3WXLl0wduzYZz6O+Ph4KBQK5OTklNtHoVBg27ZtJm9z2rRpaNmy5VON69KlS1AoFEhKSnqq7RAREZmK2Wwcs5mehMWR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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "from sklearn.metrics import ConfusionMatrixDisplay\n", + "import matplotlib.pyplot as plt\n", + "\n", + "_, ax = plt.subplots(int(len(class_models) / 2), 2, figsize=(12, 10), sharex=False, sharey=False)\n", + "for index, key in enumerate(class_models.keys()):\n", + " c_matrix = class_models[key][\"Confusion_matrix\"]\n", + " disp = ConfusionMatrixDisplay(\n", + " confusion_matrix=c_matrix, display_labels=[\"Less\", \"More\"]\n", + " ).plot(ax=ax.flat[index])\n", + " disp.ax_.set_title(key)\n", + "\n", + "plt.subplots_adjust(top=1, bottom=0, hspace=0.4, wspace=0.1)\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "На данных графиках, левый нижний квадрат обозначает, кол-во правильно классифицированных значениях, относимых к классу \"Less\", чем больше число в этом квадрате, тем лучше модель может классифицировать этот класс. Нижний левый квадрат отвечает за кол-во правильно классифицированных значениях \"More\". Здесь так же как и в левом верхнем, чем выше значение, тем лучше.\n", + "\n", + "### Точность, полнота, верность (аккуратность), F-мера" + ] + }, + { + "cell_type": "code", + "execution_count": 165, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
 Precision_trainPrecision_testRecall_trainRecall_testAccuracy_trainAccuracy_testF1_trainF1_test
logistic1.0000001.0000000.9997671.0000000.9998841.0000000.9998841.000000
ridge1.0000001.0000000.9996511.0000000.9998261.0000000.9998261.000000
decision_tree1.0000001.0000001.0000001.0000001.0000001.0000001.0000001.000000
gradient_boosting1.0000001.0000001.0000001.0000001.0000001.0000001.0000001.000000
random_forest1.0000001.0000001.0000001.0000001.0000001.0000001.0000001.000000
naive_bayes1.0000001.0000000.7867190.7939530.8939270.8975250.8806300.885144
knn0.8724860.8274730.8577740.8209300.8669170.8258150.8650680.824189
mlp0.6875000.6153850.0025580.0037210.5033550.5033540.0050980.007397
\n" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 165, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "class_metrics = pd.DataFrame.from_dict(class_models, \"index\")[\n", + " [\n", + " \"Precision_train\",\n", + " \"Precision_test\",\n", + " \"Recall_train\",\n", + " \"Recall_test\",\n", + " \"Accuracy_train\",\n", + " \"Accuracy_test\",\n", + " \"F1_train\",\n", + " \"F1_test\",\n", + " ]\n", + "]\n", + "class_metrics.sort_values(\n", + " by=\"Accuracy_test\", ascending=False\n", + ").style.background_gradient(\n", + " cmap=\"plasma\",\n", + " low=0.3,\n", + " high=1,\n", + " subset=[\"Accuracy_train\", \"Accuracy_test\", \"F1_train\", \"F1_test\"],\n", + ").background_gradient(\n", + " cmap=\"viridis\",\n", + " low=1,\n", + " high=0.3,\n", + " subset=[\n", + " \"Precision_train\",\n", + " \"Precision_test\",\n", + " \"Recall_train\",\n", + " \"Recall_test\",\n", + " ],\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "100% точности у модели может свидетельствовать о ее переобучении, то есть модели обучилась классифицировать значения только для обучающей выборки, но на тестовой выборке результаты будут плохими.\n", + "\n", + "### ROC-кривая, каппа Коэна, коэффициент корреляции Мэтьюса" + ] + }, + { + "cell_type": "code", + "execution_count": 166, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
 Accuracy_testF1_testROC_AUC_testCohen_kappa_testMCC_test
logistic1.0000001.0000001.0000001.0000001.000000
ridge1.0000001.0000001.0000001.0000001.000000
decision_tree1.0000001.0000001.0000001.0000001.000000
gradient_boosting1.0000001.0000001.0000001.0000001.000000
random_forest1.0000001.0000001.0000001.0000001.000000
naive_bayes0.8975250.8851440.9995660.7948200.812098
knn0.8258150.8241890.9108230.6516060.651627
mlp0.5033540.0073970.4970710.0014270.012966
\n" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 166, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "class_metrics = pd.DataFrame.from_dict(class_models, \"index\")[\n", + " [\n", + " \"Accuracy_test\",\n", + " \"F1_test\",\n", + " \"ROC_AUC_test\",\n", + " \"Cohen_kappa_test\",\n", + " \"MCC_test\",\n", + " ]\n", + "]\n", + "class_metrics.sort_values(by=\"ROC_AUC_test\", ascending=False).style.background_gradient(\n", + " cmap=\"plasma\",\n", + " low=0.3,\n", + " high=1,\n", + " subset=[\n", + " \"ROC_AUC_test\",\n", + " \"MCC_test\",\n", + " \"Cohen_kappa_test\",\n", + " ],\n", + ").background_gradient(\n", + " cmap=\"viridis\",\n", + " low=1,\n", + " high=0.3,\n", + " subset=[\n", + " \"Accuracy_test\",\n", + " \"F1_test\",\n", + " ],\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Вывод лучшей модели" + ] + }, + { + "cell_type": "code", + "execution_count": 167, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'logistic'" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "best_model = str(class_metrics.sort_values(by=\"MCC_test\", ascending=False).iloc[0].name)\n", + "\n", + "display(best_model)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Вывод данных с ошибкой предсказания для оценки" + ] + }, + { + "cell_type": "code", + "execution_count": 168, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'Error items count: 0'" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
idPredicteddatepricebedroomsbathroomssqft_livingsqft_lotfloorswaterfront...sqft_basementyr_builtyr_renovatedzipcodelatlongsqft_living15sqft_lot15price_categorymedian_price
\n", + "

0 rows × 24 columns

\n", + "
" + ], + "text/plain": [ + "Empty DataFrame\n", + "Columns: [id, Predicted, date, price, bedrooms, bathrooms, sqft_living, sqft_lot, floors, waterfront, view, condition, grade, sqft_above, sqft_basement, yr_built, yr_renovated, zipcode, lat, long, sqft_living15, sqft_lot15, price_category, median_price]\n", + "Index: []\n", + "\n", + "[0 rows x 24 columns]" + ] + }, + "execution_count": 168, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "preprocessing_result = pipeline_end.transform(X_test)\n", + "preprocessed_df = pd.DataFrame(\n", + " preprocessing_result,\n", + " columns=pipeline_end.get_feature_names_out(),\n", + ")\n", + "\n", + "y_pred = class_models[best_model][\"preds\"]\n", + "\n", + "error_index = y_test[y_test[\"median_price\"] != y_pred].index.tolist()\n", + "display(f\"Error items count: {len(error_index)}\")\n", + "\n", + "error_predicted = pd.Series(y_pred, index=y_test.index).loc[error_index]\n", + "error_df = X_test.loc[error_index].copy()\n", + "error_df.insert(loc=1, column=\"Predicted\", value=error_predicted)\n", + "error_df.sort_index()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Пример использования обученной модели (конвейера) для предсказания" + ] + }, + { + "cell_type": "code", + "execution_count": 169, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
iddatepricebedroomsbathroomssqft_livingsqft_lotfloorswaterfrontview...sqft_basementyr_builtyr_renovatedzipcodelatlongsqft_living15sqft_lot15price_categorymedian_price
11592202870100020140529T000000635200.041.75164042401.000...720192109811747.6766-122.3681300424011
\n", + "

1 rows × 23 columns

\n", + "
" + ], + "text/plain": [ + " id date price bedrooms bathrooms sqft_living \\\n", + "11592 2028701000 20140529T000000 635200.0 4 1.75 1640 \n", + "\n", + " sqft_lot floors waterfront view ... sqft_basement yr_built \\\n", + "11592 4240 1.0 0 0 ... 720 1921 \n", + "\n", + " yr_renovated zipcode lat long sqft_living15 sqft_lot15 \\\n", + "11592 0 98117 47.6766 -122.368 1300 4240 \n", + "\n", + " price_category median_price \n", + "11592 1 1 \n", + "\n", + "[1 rows x 23 columns]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
sqft_livingsqft_lotmedian_priceidpricebedroomsbathroomsfloorswaterfrontview...sqft_basementyr_builtyr_renovatedzipcodelatlongsqft_living15sqft_lot15price_categoryLiving_area_to_Lot_ratio
11592-0.477812-0.2692261.0053352.028701e+09635200.04.01.751.00.00.0...720.01921.00.098117.047.6766-122.3681300.04240.01.01.774763
\n", + "

1 rows × 23 columns

\n", + "
" + ], + "text/plain": [ + " sqft_living sqft_lot median_price id price bedrooms \\\n", + "11592 -0.477812 -0.269226 1.005335 2.028701e+09 635200.0 4.0 \n", + "\n", + " bathrooms floors waterfront view ... sqft_basement yr_built \\\n", + "11592 1.75 1.0 0.0 0.0 ... 720.0 1921.0 \n", + "\n", + " yr_renovated zipcode lat long sqft_living15 sqft_lot15 \\\n", + "11592 0.0 98117.0 47.6766 -122.368 1300.0 4240.0 \n", + "\n", + " price_category Living_area_to_Lot_ratio \n", + "11592 1.0 1.774763 \n", + "\n", + "[1 rows x 23 columns]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "'predicted: 1 (proba: [0. 1.])'" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "'real: 1'" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "model = class_models[best_model][\"pipeline\"]\n", + "\n", + "example_id = 11592\n", + "test = pd.DataFrame(X_test.loc[example_id, :]).T\n", + "test_preprocessed = pd.DataFrame(preprocessed_df.loc[example_id, :]).T\n", + "display(test)\n", + "display(test_preprocessed)\n", + "result_proba = model.predict_proba(test)[0]\n", + "result = model.predict(test)[0]\n", + "real = int(y_test.loc[example_id].values[0])\n", + "display(f\"predicted: {result} (proba: {result_proba})\")\n", + "display(f\"real: {real}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Подбор гиперпараметров методом поиска по сетке" + ] + }, + { + "cell_type": "code", + "execution_count": 170, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'model__criterion': 'gini',\n", + " 'model__max_depth': 5,\n", + " 'model__max_features': 'sqrt',\n", + " 'model__n_estimators': 10}" + ] + }, + "execution_count": 170, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from sklearn.model_selection import GridSearchCV\n", + "\n", + "optimized_model_type = \"random_forest\"\n", + "\n", + "random_forest_model = class_models[optimized_model_type][\"pipeline\"]\n", + "\n", + "param_grid = {\n", + " \"model__n_estimators\": [10, 50, 100],\n", + " \"model__max_features\": [\"sqrt\", \"log2\"],\n", + " \"model__max_depth\": [5, 7, 10],\n", + " \"model__criterion\": [\"gini\", \"entropy\"],\n", + "}\n", + "\n", + "gs_optomizer = GridSearchCV(\n", + " estimator=random_forest_model, param_grid=param_grid, n_jobs=-1\n", + ")\n", + "gs_optomizer.fit(X_train, y_train.values.ravel())\n", + "gs_optomizer.best_params_" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Обучение модели с новыми гиперпараметрами" + ] + }, + { + "cell_type": "code", + "execution_count": 171, + "metadata": {}, + "outputs": [], + "source": [ + "optimized_model = ensemble.RandomForestClassifier(\n", + " random_state=random_state,\n", + " criterion=\"gini\",\n", + " max_depth=5,\n", + " max_features=\"sqrt\",\n", + " n_estimators=10,\n", + ")\n", + "\n", + "result = {}\n", + "\n", + "result[\"pipeline\"] = Pipeline([(\"pipeline\", pipeline_end), (\"model\", optimized_model)]).fit(X_train, y_train.values.ravel())\n", + "result[\"train_preds\"] = result[\"pipeline\"].predict(X_train)\n", + "result[\"probs\"] = result[\"pipeline\"].predict_proba(X_test)[:, 1]\n", + "result[\"preds\"] = np.where(result[\"probs\"] > 0.5, 1, 0)\n", + "\n", + "result[\"Precision_train\"] = metrics.precision_score(y_train, result[\"train_preds\"])\n", + "result[\"Precision_test\"] = metrics.precision_score(y_test, result[\"preds\"])\n", + "result[\"Recall_train\"] = metrics.recall_score(y_train, result[\"train_preds\"])\n", + "result[\"Recall_test\"] = metrics.recall_score(y_test, result[\"preds\"])\n", + "result[\"Accuracy_train\"] = metrics.accuracy_score(y_train, result[\"train_preds\"])\n", + "result[\"Accuracy_test\"] = metrics.accuracy_score(y_test, result[\"preds\"])\n", + "result[\"ROC_AUC_test\"] = metrics.roc_auc_score(y_test, result[\"probs\"])\n", + "result[\"F1_train\"] = metrics.f1_score(y_train, result[\"train_preds\"])\n", + "result[\"F1_test\"] = metrics.f1_score(y_test, result[\"preds\"])\n", + "result[\"MCC_test\"] = metrics.matthews_corrcoef(y_test, result[\"preds\"])\n", + "result[\"Cohen_kappa_test\"] = metrics.cohen_kappa_score(y_test, result[\"preds\"])\n", + "result[\"Confusion_matrix\"] = metrics.confusion_matrix(y_test, result[\"preds\"])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Формирование данных для оценки старой и новой версии модели" + ] + }, + { + "cell_type": "code", + "execution_count": 172, + "metadata": {}, + "outputs": [], + "source": [ + "optimized_metrics = pd.DataFrame(columns=list(result.keys()))\n", + "optimized_metrics.loc[len(optimized_metrics)] = pd.Series(\n", + " data=class_models[optimized_model_type]\n", + ")\n", + "optimized_metrics.loc[len(optimized_metrics)] = pd.Series(\n", + " data=result\n", + ")\n", + "optimized_metrics.insert(loc=0, column=\"Name\", value=[\"Old\", \"New\"])\n", + "optimized_metrics = optimized_metrics.set_index(\"Name\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Оценка параметров старой и новой модели" + ] + }, + { + "cell_type": "code", + "execution_count": 173, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
 Precision_trainPrecision_testRecall_trainRecall_testAccuracy_trainAccuracy_testF1_trainF1_test
Name        
Old1.0000001.0000001.0000001.0000001.0000001.0000001.0000001.000000
New1.0000001.0000001.0000001.0000001.0000001.0000001.0000001.000000
\n" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 173, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "optimized_metrics[\n", + " [\n", + " \"Precision_train\",\n", + " \"Precision_test\",\n", + " \"Recall_train\",\n", + " \"Recall_test\",\n", + " \"Accuracy_train\",\n", + " \"Accuracy_test\",\n", + " \"F1_train\",\n", + " \"F1_test\",\n", + " ]\n", + "].style.background_gradient(\n", + " cmap=\"plasma\",\n", + " low=0.3,\n", + " high=1,\n", + " subset=[\"Accuracy_train\", \"Accuracy_test\", \"F1_train\", \"F1_test\"],\n", + ").background_gradient(\n", + " cmap=\"viridis\",\n", + " low=1,\n", + " high=0.3,\n", + " subset=[\n", + " \"Precision_train\",\n", + " \"Precision_test\",\n", + " \"Recall_train\",\n", + " \"Recall_test\",\n", + " ],\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Значения 1 в кажой ячейке обосзначают, что модели очень точно классифицируют положительные образцы, не пропуская их." + ] + }, + { + "cell_type": "code", + "execution_count": 174, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
 Accuracy_testF1_testROC_AUC_testCohen_kappa_testMCC_test
Name     
Old1.0000001.0000001.0000001.0000001.000000
New1.0000001.0000001.0000001.0000001.000000
\n" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 174, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "optimized_metrics[\n", + " [\n", + " \"Accuracy_test\",\n", + " \"F1_test\",\n", + " \"ROC_AUC_test\",\n", + " \"Cohen_kappa_test\",\n", + " \"MCC_test\",\n", + " ]\n", + "].style.background_gradient(\n", + " cmap=\"plasma\",\n", + " low=0.3,\n", + " high=1,\n", + " subset=[\n", + " \"ROC_AUC_test\",\n", + " \"MCC_test\",\n", + " \"Cohen_kappa_test\",\n", + " ],\n", + ").background_gradient(\n", + " cmap=\"viridis\",\n", + " low=1,\n", + " high=0.3,\n", + " subset=[\n", + " \"Accuracy_test\",\n", + " \"F1_test\",\n", + " ],\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Значения 1 в кажой ячейке обосзначают, что модели точно классифицировали все тестовые примеры, не допустив никаких ошибок в предсказаниях." + ] + }, + { + "cell_type": "code", + "execution_count": 175, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAA2kAAAGsCAYAAABHMu+IAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAABTp0lEQVR4nO3deXwU9f3H8fcmkAPIJgRIQiSES4FouCumKIdiAlKUgvUnN4KgNmgFOcQqBmkJxWoVpeDFYYWC9aCKigIaEIhW0IAiRC4BhQQUSAhIrt3fH5jVJRyzZJKd3byej8c8fuzM7Dff4Ufz9jvfz3zH5nQ6nQIAAAAAWEKAtzsAAAAAAPgFgzQAAAAAsBAGaQAAAABgIQzSAAAAAMBCGKQBAAAAgIUwSAMAAAAAC2GQBgAAAAAWwiANAAAAACykhrc7AAA4t9OnT6uoqMi09oKCghQSEmJaewAAeIJcM45BGgBY0OnTp9U0vo5yDpea1mZMTIz27t3rt4EGALAucs0zDNIAwIKKioqUc7hUezfHyx5W8cr0/BMONe24T0VFRX4ZZgAAayPXPMMgDQAszB4WYEqYAQBgBeSaMQzSAMDCSp0OlTrNaQcAAG8j14xhkAYAFuaQUw5VPM3MaAMAgIoi14xhrhEAAAAALISZNACwMIccMqOgw5xWAACoGHLNGAZpAGBhpU6nSp0VL+kwow0AACqKXDOGckcAAAAAsBBm0gDAwnjAGgDgT8g1YxikAYCFOeRUKWEGAPAT5JoxlDsCAAAAgIUwkwYAFkZZCADAn5BrxjCTBgAAAAAWwkwaAFgYSxUDAPwJuWYMgzQAsDDHz5sZ7QAA4G3kmjGUOwIAAACAhTCTBgAWVmrSUsVmtAEAQEWRa8YwSAMACyt1ntnMaAcAAG8j14yh3BEAAAAALISZNACwMB6wBgD4E3LNGAZpAGBhDtlUKpsp7QAA4G3kmjGUOwIAAACAhTCTBgAW5nCe2cxoBwAAbyPXjGEmDQAAAAAshJk0ALCwUpNq981oAwCAiiLXjGGQBgAWRpgBAPwJuWYM5Y4AgHLS09P1m9/8RmFhYYqKilK/fv2UnZ3tds7p06eVmpqqevXqqU6dOhowYIByc3Pdztm/f7/69OmjWrVqKSoqShMnTlRJSYnbORkZGerQoYOCg4PVokULLVy4sLIvDwBQzfharjFIAwALczhtpm2eWLt2rVJTU/XJJ59o1apVKi4uVnJysk6ePOk6Z9y4cXr77bf1n//8R2vXrtXBgwfVv39/1/HS0lL16dNHRUVF2rhxoxYtWqSFCxdq6tSprnP27t2rPn36qEePHsrKytL999+vO++8U++//37F//IAAJZDrhljczqdfr42CgD4nvz8fIWHh2vtV5epTljF76cVnHCo21XfKy8vT3a73ePvHzlyRFFRUVq7dq26du2qvLw8NWjQQEuWLNGtt94qSdqxY4dat26tzMxMXXPNNXrvvff0u9/9TgcPHlR0dLQkad68eZo8ebKOHDmioKAgTZ48We+8846++uor18+6/fbbdfz4ca1cubLC1w0AsAZyzbNcYyYNAKqR/Px8t62wsNDQ9/Ly8iRJkZGRkqTNmzeruLhYPXv2dJ3TqlUrNW7cWJmZmZKkzMxMJSYmuoJMklJSUpSfn69t27a5zvl1G2XnlLUBAMCF+GuuMUgDAAsrVYBpmyTFxcUpPDzctaWnp1+0Dw6HQ/fff7+6dOmiq666SpKUk5OjoKAgRUREuJ0bHR2tnJwc1zm/DrKy42XHLnROfn6+fvrpJ8//wgAAlkauGcPqjgBgYc5LqLs/XzuSdODAAbeykODg4It+NzU1VV999ZXWr19f4X4AAKo3cs0YZtIAoBqx2+1u28XCbOzYsVqxYoU++ugjNWrUyLU/JiZGRUVFOn78uNv5ubm5iomJcZ1z9qpYZZ8vdo7dbldoaOglXSMAoPrw11xjkAYAFlb2PhkzNk84nU6NHTtWb775pj788EM1bdrU7XjHjh1Vs2ZNrVmzxrUvOztb+/fvV1JSkiQpKSlJX375pQ4fPuw6Z9WqVbLb7UpISHCd8+s2ys4pawMA4F/INWModwQACyt1BqjUWfH7aaUeruObmpqqJUuW6L///a/CwsJctfbh4eEKDQ1VeHi4Ro0apfHjxysyMlJ2u1333nuvkpKSdM0110iSkpOTlZCQoKFDh2rWrFnKycnRww8/rNTUVNedzrvvvlvPPvusJk2apJEjR+rDDz/Uq6++qnfeeafC1wwAsB5yzRiW4AcACypbqvi9rU1V24Slik+ecKh3m72Glyq22c59h3LBggUaMWKEpDMv/XzggQf073//W4WFhUpJSdE///lPV8mHJO3bt0/33HOPMjIyVLt2bQ0fPlwzZ85UjRq/3CPMyMjQuHHj9PXXX6tRo0Z65JFHXD8DAOAfyLURHl0fgzQAsKCyMHtnazPVDguscHsnT5SqT5s9l/w+GQAAKoJc8wzPpAEAAACAhfBMGgBY2KU8HH2+dgAA8DZyzRgGaQBgYeY9YE1lOwDA+8g1Yyh3BAAAAAALYSYNACzMIZscJpR0mNEGAAAVRa4ZwyANACzMoQCVmlD04JB/l4UAAHwDuWYM5Y4AAAAAYCHMpAGAhfGANQDAn5BrxjBIAwALcyhADspCAAB+glwzhnJHAAAAALAQZtIAwMJKnTaVOk146acJbQAAUFHkmjHMpAEAAACAhTCTBgAWVmrSUsWlfl67DwDwDeSaMQzSAMDCHM4AOUxYBcvh56tgAQB8A7lmDOWOAAAAAGAhzKQBgIVRFgIA8CfkmjEM0gDAwhwyZwUrR8W7AgBAhZFrxlDuCAAAAAAWwkwaAFiYQwFymHA/zYw2AACoKHLNGAZpAGBhpc4AlZqwCpYZbQAAUFHkmjH+fXUAAAAA4GOYSQMAC3PIJofMeMC64m0AAFBR5JoxDNIAwMIoCwEA+BNyzRj/vjoAAAAA8DHMpAGAhZn30k/uyQEAvI9cM8a/rw4AAAAAfAwzaQY4HA4dPHhQYWFhstn8+yFFABXndDp14sQJxcbGKiCgYvfCHE6bHE4THrA2oQ34D3INgCfItarHIM2AgwcPKi4uztvdAOBjDhw4oEaNGlWoDYdJZSH+/tJPeIZcA3ApyLWqwyDNgLCwMEnSvs+byF7Hv/9BwHO/vyLR212AxZSoWOv1rut3B2A15BouhFzD2ci1qscgzYCyUhB7nQDZwwgzuKthq+ntLsBqnGf+jxllZA5ngBwmLDNsRhvwH+QaLoRcQznkWpVjkAYAFlYqm0pNeGGnGW0AAFBR5Jox/j0EBQAAAAAfw0waAFgYZSEAAH9CrhnDIA0ALKxU5pR0lFa8KwAAVBi5Zox/D0EBAAAAwMcwSAMACysrCzFj88S6devUt29fxcbGymazafny5W7HbTbbObfHH3/cdU6TJk3KHZ85c6ZbO1u3btV1112nkJAQxcXFadasWZf8dwUAsD5v5ZrkW9nGIA0AUM7JkyfVtm1bzZkz55zHDx065LbNnz9fNptNAwYMcDvvscceczvv3nvvdR3Lz89XcnKy4uPjtXnzZj3++ONKS0vT888/X6nXBgConnwp23gmDQAsrNQZoFITHo72tI3evXurd+/e5z0eExPj9vm///2vevTooWbNmrntDwsLK3dumcWLF6uoqEjz589XUFCQrrzySmVlZenJJ5/UmDFjPOovAMA3eCvXJN/KNmbSAMDCnLLJYcLm/Pkh7fz8fLetsLCwwn3Mzc3VO++8o1GjRpU7NnPmTNWrV0/t27fX448/rpKSEtexzMxMde3aVUFBQa59KSkpys7O1rFjxyrcLwCA9fhCrknezzYGaQBQjcTFxSk8PNy1paenV7jNRYsWKSwsTP3793fbf99992np0qX66KOPdNddd2nGjBmaNGmS63hOTo6io6PdvlP2OScnp8L9AgD4v8rINcn72Ua5IwBYmNllIQcOHJDdbnftDw4OrnDb8+fP1+DBgxUSEuK2f/z48a4/t2nTRkFBQbrrrruUnp5uys8FAPgeX8g1yfvZxiANACzM4bTJ4az4+2TK2rDb7W5hVlEff/yxsrOztWzZsoue27lzZ5WUlOjbb79Vy5YtFRMTo9zcXLdzyj6fr9YfAODbrJ5rkjWyjXJHAMAle+mll9SxY0e1bdv2oudmZWUpICBAUVFRkqSkpCStW7dOxcXFrnNWrVqlli1bqm7dupXWZwAALsQK2cYgDQAsrFQBpm2eKCgoUFZWlrKysiRJe/fuVVZWlvbv3+86Jz8/X//5z3905513lvt+ZmamnnrqKW3ZskV79uzR4sWLNW7cOA0ZMsQVUoMGDVJQUJBGjRqlbdu2admyZXr66afdSkkAAP7FW7km+Va2Ue4IABZmdlmIUZs2bVKPHj1cn8vCZfjw4Vq4cKEkaenSpXI6nRo4cGC57wcHB2vp0qVKS0tTYWGhmjZtqnHjxrmFVHh4uD744AOlpqaqY8eOql+/vqZOncry+wDgx7yVa5JvZZvN6XQ6Pb7CaiY/P1/h4eE69k0z2cOYfIS7lNh23u4CLKbEWawM/Vd5eXmXXCdf9nvnvvW3KLhOzQr3qbCgWLOvrVif4D/INVwIuYazkWtVj5k0ALAwhwLkMKEy3Yw2AACoKHLNGAZpAGBhpU6bSk0oCzGjDQAAKopcM8a/h6AAAAAA4GOYSQMAC/PmA9YAAJiNXDOGmTQAAAAAsBBm0gDAwpzOADmcFb+f5jShDQAAKopcM4ZBGgBYWKlsKpUJD1ib0AYAABVFrhnj30NQAAAAAPAxzKQBgIU5nOY8HO1wmtAZAAAqiFwzhkEaAFiYw6TafTPaAACgosg1Y/z76gAAAADAxzCTBgAW5pBNDhMejjajDQAAKopcM4ZBGgBYWKnTplITavfNaAMAgIoi14yh3BEAAAAALISZNACwMB6wBgD4E3LNGP++OgAAAADwMcykAYCFOWQz530yfv6ANQDAN5BrxjBIAwALc5q0CpbTz8MMAOAbyDVjKHcEAAAAAAthJg0ALMzhNKksxM+XKgYA+AZyzRgGaQBgYayCBQDwJ+SaMf59dQAAAADgY5hJAwALoywEAOBPyDVjGKQBgIU5TFoFy9+XKgYA+AZyzRjKHQEAAADAQphJAwALoywEAOBPyDVjGKQBgIURZgAAf0KuGUO5IwAAAABYCDNpAGBh3HEEAPgTcs0YZtIAAAAAwEKYSQMAC+OOIwDAn5BrxjBIAwALc8qcd8E4K94VAAAqjFwzhnJHAAAAALAQZtIAwMIoCwEA+BNyzRgGaQBgYYQZAMCfkGvGUO4IAChn3bp16tu3r2JjY2Wz2bR8+XK34yNGjJDNZnPbevXq5XbO0aNHNXjwYNntdkVERGjUqFEqKChwO2fr1q267rrrFBISori4OM2aNauyLw0AUE35UrYxSAMACyu742jG5omTJ0+qbdu2mjNnznnP6dWrlw4dOuTa/v3vf7sdHzx4sLZt26ZVq1ZpxYoVWrduncaMGeM6np+fr+TkZMXHx2vz5s16/PHHlZaWpueff96zvyQAgM/wVq5JvpVtlDsCgIV5qyykd+/e6t279wXPCQ4OVkxMzDmPbd++XStXrtRnn32mTp06SZKeeeYZ3XTTTfr73/+u2NhYLV68WEVFRZo/f76CgoJ05ZVXKisrS08++aRb4AEA/Ic3yx19KduYSQOAaiQ/P99tKywsvOS2MjIyFBUVpZYtW+qee+7Rjz/+6DqWmZmpiIgIV4hJUs+ePRUQEKBPP/3UdU7Xrl0VFBTkOiclJUXZ2dk6duzYJfcLAFB9mJlrknWyjUEaAFiY02kzbZOkuLg4hYeHu7b09PRL6levXr308ssva82aNfrb3/6mtWvXqnfv3iotLZUk5eTkKCoqyu07NWrUUGRkpHJyclznREdHu51T9rnsHACAf7FqrknWyjbKHQGgGjlw4IDsdrvrc3Bw8CW1c/vtt7v+nJiYqDZt2qh58+bKyMjQDTfcUOF+AgBghFm5Jlkr25hJAwALc8hm2iZJdrvdbatImP1as2bNVL9+fe3atUuSFBMTo8OHD7udU1JSoqNHj7pq/WNiYpSbm+t2Ttnn8z0PAADwbb6Sa5J3s41BGgBYmDdXwfLEd999px9//FENGzaUJCUlJen48ePavHmz65wPP/xQDodDnTt3dp2zbt06FRcXu85ZtWqVWrZsqbp161ZqfwEA3uEruSZ5N9sod6yGlj4TpQ3vRujArmAFhTiU0OmURv35oOJa/PKg5buv1NNHb9bVri9DdaogUK9v/1J1wktdx7dsrKNJt7Y4Z/uz381Wy3Y/6cCuYM1+sJH2fxOikycCVS+6WD1+f0xDxueoRs1Kv0xUob4jftCt9xxWZIMS7fk6VP98+DJlZ9XydrdQAQUFBa47h5K0d+9eZWVlKTIyUpGRkZo2bZoGDBigmJgY7d69W5MmTVKLFi2UkpIiSWrdurV69eql0aNHa968eSouLtbYsWN1++23KzY2VpI0aNAgTZs2TaNGjdLkyZP11Vdf6emnn9Y//vEPr1wzfBe5BrORa/7Jl7LNUoO0ESNG6Pjx4+VeLAdzbc2so74jftAV7U6ptERaOLOhHhrYXC+s3aGQWg5J0umfAtSpe746dc/X/PTYcm0kdDqpf2d95bZv0ayGylpfR1e0/UmSVKOmUz1vPaYWiadUJ7xUe7aF6qmJcXI4bBo55VDlXyiqRLebj2nMowf1zIONtOPzWvr96CP665I9GnVdS+X9yH+1VNSvH46uaDue2LRpk3r06OH6PH78eEnS8OHDNXfuXG3dulWLFi3S8ePHFRsbq+TkZE2fPt2tzGTx4sUaO3asbrjhBgUEBGjAgAGaPXu263h4eLg++OADpaamqmPHjqpfv76mTp3qV8vvk2tVg1yDmci1yuWtXJN8K9ssNUhD1ZixZI/b5wee2q//S0zUzq2hSrzmpCSp/+gjks7cWTyXmkFORUaVuD6XFEuZ79t1y8gfZPv5fzMN44vUMP6o65zoRsXamnlMX31a28zLgZf1H/ODVi6J1AfLIiVJsyc30tU35Ctl4FG9+mz0Rb6Ni/HW+2S6d+8up9N53uPvv//+RduIjIzUkiVLLnhOmzZt9PHHH3vUN+Bs5BrMRK5VLm++J82Xss1nnkn76quv1Lt3b9WpU0fR0dEaOnSofvjhB9fx1157TYmJiQoNDVW9evXUs2dPnTx55hdzRkaGrr76atWuXVsRERHq0qWL9u3b561LsZyT+YGSpLCI0ouceX6ZH4TrxLEaSv6/o+c95/u9Qdr0kV1tkgou+efAWmrUdOjyNqf0+cdhrn1Op01ffBymhI6nvNgzwPrItcpDruFSkWuwCp8YpB0/flzXX3+92rdvr02bNmnlypXKzc3VbbfdJkk6dOiQBg4cqJEjR2r79u3KyMhQ//795XQ6VVJSon79+qlbt27aunWrMjMzNWbMGNls5x99FxYWlnsxnr9yOKR5j16mK39ToCatTl9yO+//u546dj+hBrHF5Y7d3/dy/a5pG43skqCrOhdo2ETef+Qv7JGlCqwhHT/iPil/7Icaqtug5DzfgifMfp8MrIFcqzzkGiqCXKt85JoxPlHu+Oyzz6p9+/aaMWOGa9/8+fMVFxenb775RgUFBSopKVH//v0VHx8v6cy7DSTp6NGjysvL0+9+9zs1b95c0pmH/i4kPT1d06ZNq6SrsZZnH2qkfTtC9cTynZfcxpGDNbU5I0wPPfftOY8/NO9b/XQyQHu2herFv8TqtblRui318DnPBeDOaVJZiL+Hma8h1yoPuQZYG7lmjE/MpG3ZskUfffSR6tSp49patWolSdq9e7fatm2rG264QYmJifrDH/6gF154QceOHZN0pm50xIgRSklJUd++ffX000/r0KELP9w7ZcoU5eXlubYDBw5U+jV6w7MPXaZPV9k167Vd57xTaNQHyyIVVrdEScl55zwedVmx4q8oVI/fH9fIhw7plSdiVHrpFSiwkPyjgSotkSLOurtYt36Jjh3xiXtAgFeQa5WDXENFkWuwCp8YpBUUFKhv377Kyspy23bu3KmuXbsqMDBQq1at0nvvvaeEhAQ988wzatmypfbu3StJWrBggTIzM/Xb3/5Wy5Yt0xVXXKFPPvnkvD8vODi43Ivx/InTeSbINq4M16z/7FJM46IKtfXBskj1vPWYoeWHHQ6ppMQmp+OSfyQspKQ4QDu31lL7a0+49tlsTrW7tkBfb2apYjM4deZ/ZxXevH0hcEOumYtcg1nItcpHrhnjE7cEOnTooNdff11NmjRRjRrn7rLNZlOXLl3UpUsXTZ06VfHx8XrzzTddS2u2b99e7du315QpU5SUlKQlS5bommuuqcrLsIxnH2qkj96sq7QFexRax6Gjh8/8ndYOK1Vw6Jl/8kcP19CxwzV1cG+QJGnvjhDVqu1Qg8uKZK/7y+3CrPV1lLM/WL0G/Vju53z4Rl0F1nCqaeufVDPIqW+21NKC9IbqdrOx4INveOP5+prw1AF9s6WWsr84s1RxSC2HPlga6e2u+QWHbLLJhFWwTGgD5iHXzEWuwUzkWuUi14yx3CAtLy9PWVlZbvvGjBmjF154QQMHDtSkSZMUGRmpXbt2aenSpXrxxRe1adMmrVmzRsnJyYqKitKnn36qI0eOqHXr1tq7d6+ef/553XzzzYqNjVV2drZ27typYcOGeecCLWDFovqSpIkDLnfb/8A/9rtWsXrn5fp65ckY17EJv7+83DmStPLf9ZTQqUCNLy/U2QICnXp1TpS+3xMsp1OKalSkm+/4wbUMMvzD2rfqKrxeqYZNzFHdBiXasy1Ufx7cVMd/4L9YAIlcqwrkGsxErsEKLDdIy8jIUPv27d32jRo1Shs2bNDkyZOVnJyswsJCxcfHq1evXgoICJDdbte6dev01FNPKT8/X/Hx8XriiSfUu3dv5ebmaseOHVq0aJF+/PFHNWzYUKmpqbrrrru8dIXe9/7BrIueM3RCjoZOuPhqVVP+ef4ln7vfclzdbznuQc/gq95aUF9vLajv7W74JW++9BPmINcqH7kGs5FrlYdcM8bmvNAb3SBJys/PV3h4uI5900z2MJ94jA9VKCW2nbe7AIspcRYrQ/9VXl7eJT/7U/Z7p81/JiiwVnCF+1R6qlBb//D3CvUJ/oNcw4WQazgbuVb1LDeTBgD4hcNpk82Eu4VmLHcMAEBFkWvGMEgDAAsrW8XKjHYAAPA2cs0YahwAAAAAwEKYSQMAC+MBawCAPyHXjGGQBgAWRpgBAPwJuWYM5Y4AAAAAYCHMpAGAhbEKFgDAn5BrxjBIAwALYxUsAIA/IdeModwRAAAAACyEmTQAsLAzdxzNeMDahM4AAFBB5JoxDNIAwMJYBQsA4E/INWModwQAAAAAC2EmDQAszPnzZkY7AAB4G7lmDDNpAAAAAGAhzKQBgIVRuw8A8CfkmjEM0gDAyqgLAQD4E3LNEModAQAAAMBCmEkDACszqSxEfl4WAgDwEeSaIQzSAMDCzrz005x2AADwNnLNGModAQAAAMBCmEkDAAtjFSwAgD8h14xhkAYAVua0mVN37+dhBgDwEeSaIZQ7AgAAAICFMJMGABbGA9YAAH9CrhnDTBoAAAAAWAgzaQBgZc6fNzPaAQDA28g1Q5hJAwALK1sFy4zNE+vWrVPfvn0VGxsrm82m5cuXu44VFxdr8uTJSkxMVO3atRUbG6thw4bp4MGDbm00adJENpvNbZs5c6bbOVu3btV1112nkJAQxcXFadasWZf8dwUAsD5v5ZrkW9nGIA0AUM7JkyfVtm1bzZkzp9yxU6dO6fPPP9cjjzyizz//XG+88Yays7N18803lzv3scce06FDh1zbvffe6zqWn5+v5ORkxcfHa/PmzXr88ceVlpam559/vlKvDQBQPflStlHuCABW54WSjt69e6t3797nPBYeHq5Vq1a57Xv22Wd19dVXa//+/WrcuLFrf1hYmGJiYs7ZzuLFi1VUVKT58+crKChIV155pbKysvTkk09qzJgx5l0MAMBavFSq6EvZZmiQ9tZbbxlu8FyjTQDApTH7pZ/5+flu+4ODgxUcHFzh9vPy8mSz2RQREeG2f+bMmZo+fboaN26sQYMGady4capR40z0ZGZmqmvXrgoKCnKdn5KSor/97W86duyY6tatW+F+nQ+5BgDe4Su5Jnk32wwN0vr162eoMZvNptLSUkPnAgCqXlxcnNvnRx99VGlpaRVq8/Tp05o8ebIGDhwou93u2n/fffepQ4cOioyM1MaNGzVlyhQdOnRITz75pCQpJydHTZs2dWsrOjradawyB2nkGgD4h8rINcn72WZokOZwOAw1BgAwmcmrYB04cMAtbCp6t7G4uFi33XabnE6n5s6d63Zs/Pjxrj+3adNGQUFBuuuuu5Senm7aXc5LRa4BgJdYPNcka2RbhRYOOX36tFn9AACck83ETbLb7W5bRQKlLMT27dunVatWuYXkuXTu3FklJSX69ttvJUkxMTHKzc11O6fs8/lq/SsbuQYAlc26uSZZJ9s8HqSVlpZq+vTpuuyyy1SnTh3t2bNHkvTII4/opZde8rQ5AIAPKguxnTt3avXq1apXr95Fv5OVlaWAgABFRUVJkpKSkrRu3ToVFxe7zlm1apVatmxZqaWOZyPXAACStbLN40HaX//6Vy1cuFCzZs1yeyDuqquu0osvvuhpcwCAC3GauHmgoKBAWVlZysrKkiTt3btXWVlZ2r9/v4qLi3Xrrbdq06ZNWrx4sUpLS5WTk6OcnBwVFRVJOvPg9FNPPaUtW7Zoz549Wrx4scaNG6chQ4a4QmrQoEEKCgrSqFGjtG3bNi1btkxPP/20WylJVSDXAKAKeSnXJN/KNo+X4H/55Zf1/PPP64YbbtDdd9/t2t+2bVvt2LHD0+YAABa0adMm9ejRw/W5LFyGDx+utLQ01+qI7dq1c/veRx99pO7duys4OFhLly5VWlqaCgsL1bRpU40bN84tpMLDw/XBBx8oNTVVHTt2VP369TV16tQqX36fXAOA6sGXss3jQdr333+vFi1alNvvcDjcpvUAACYw+QFro7p37y6n8/xfutAxSerQoYM++eSTi/6cNm3a6OOPP/ascyYj1wCgCnkp1yTfyjaPyx0TEhLO+UNfe+01tW/fvkKdAQCcxWkzb8M5kWsAUIXINUM8nkmbOnWqhg8fru+//14Oh0NvvPGGsrOz9fLLL2vFihWV0UcAACoNuQYAsBqPZ9JuueUWvf3221q9erVq166tqVOnavv27Xr77bd14403VkYfAaDacjrN23Bu5BoAVB1yzRiPZ9Ik6brrrtOqVavM7gsA4GxerN2vTsg1AKgi5JohlzRIk86sjrJ9+3ZJZ+r5O3bsaFqnAACoauQaAMAqPB6kfffddxo4cKA2bNigiIgISdLx48f129/+VkuXLlWjRo3M7iMAVF9mPRzt5w9YVwS5BgBViFwzxONn0u68804VFxdr+/btOnr0qI4ePart27fL4XDozjvvrIw+AkC1ZXOat+HcyDUAqDrkmjEez6StXbtWGzduVMuWLV37WrZsqWeeeUbXXXedqZ0DAKCykWsAAKvxeJAWFxd3zpd7lpaWKjY21pROAQB+xgPWlY5cA4AqRK4Z4nG54+OPP657771XmzZtcu3btGmT/vSnP+nvf/+7qZ0DgGqPl35WOnINAKoQuWaIoZm0unXrymb75S/i5MmT6ty5s2rUOPP1kpIS1ahRQyNHjlS/fv0qpaMAAJiFXAMAWJmhQdpTTz1Vyd0AAJwTZSGVglwDAC8h1wwxNEgbPnx4ZfcDAIAqQ64BAKzskl9mLUmnT59WUVGR2z673V6hDgEAfoU7jlWKXAOASkauGeLxwiEnT57U2LFjFRUVpdq1a6tu3bpuGwDARE4TN5wTuQYAVYhcM8TjQdqkSZP04Ycfau7cuQoODtaLL76oadOmKTY2Vi+//HJl9BEAgEpDrgEArMbjcse3335bL7/8srp376477rhD1113nVq0aKH4+HgtXrxYgwcProx+AkD1ZNYyw36+VHFFkGsAUIXINUM8nkk7evSomjVrJulMnf7Ro0clSddee63WrVtnbu8AoJqzOc3bcG7kGgBUHXLNGI8Hac2aNdPevXslSa1atdKrr74q6cydyIiICFM7BwBAZSPXAABW4/Eg7Y477tCWLVskSQ8++KDmzJmjkJAQjRs3ThMnTjS9gwBQrfGAdaUj1wCgCpFrhnj8TNq4ceNcf+7Zs6d27NihzZs3q0WLFmrTpo2pnQMAoLKRawAAq6nQe9IkKT4+XvHx8Wb0BQAAryPXAADeZmiQNnv2bMMN3nfffZfcGQCAO5vMeTjav9fA8hy5BgDeQa4ZY2iQ9o9//MNQYzabza/D7PdXJKqGraa3uwGLWfH9Zm93ARaTf8KhqJbe7gUuhFw7g1zDuZBrOBu5VvUMDdLKVr0CAFQx3idTKcg1APAScs2QCj+TBgCoRGatYOXnq2ABAHwEuWaIx0vwAwAAAAAqDzNpAGBl3HEEAPgTcs0QBmkAYGE2p0mrYPl5mAEAfAO5ZgzljgAAAABgIZc0SPv44481ZMgQJSUl6fvvv5ck/etf/9L69etN7RwAVHtOEzecF7kGAFWEXDPE40Ha66+/rpSUFIWGhuqLL75QYWGhJCkvL08zZswwvYMAUK0RZpWOXAOAKkSuGeLxIO0vf/mL5s2bpxdeeEE1a/7yAswuXbro888/N7VzAABUNnINAGA1Hi8ckp2dra5du5bbHx4eruPHj5vRJwDAz3jAuvKRawBQdcg1YzyeSYuJidGuXbvK7V+/fr2aNWtmSqcAAD9z2szbcE7kGgBUIXLNEI8HaaNHj9af/vQnffrpp7LZbDp48KAWL16sCRMm6J577qmMPgIAqti6devUt29fxcbGymazafny5W7HnU6npk6dqoYNGyo0NFQ9e/bUzp073c45evSoBg8eLLvdroiICI0aNUoFBQVu52zdulXXXXedQkJCFBcXp1mzZlX2pZVDrgFA9eBL2ebxIO3BBx/UoEGDdMMNN6igoEBdu3bVnXfeqbvuukv33nuvxx0AAFyAlx6wPnnypNq2bas5c+ac8/isWbM0e/ZszZs3T59++qlq166tlJQUnT592nXO4MGDtW3bNq1atUorVqzQunXrNGbMGNfx/Px8JScnKz4+Xps3b9bjjz+utLQ0Pf/88551toLINQCoQl5cOMSXss3mdDovqaKzqKhIu3btUkFBgRISElSnTp1LacYn5OfnKzw8XN11i2rYal78C6hWVny/2dtdgMXkn3AoquU+5eXlyW63X1obP//eaZo2QwEhIRXuk+P0ae1Ne+iS+mSz2fTmm2+qX79+ks7caYyNjdUDDzygCRMmSDqzEmJ0dLQWLlyo22+/Xdu3b1dCQoI+++wzderUSZK0cuVK3XTTTfruu+8UGxuruXPn6s9//rNycnIUFBQk6cyAafny5dqxY0eFr9lT5BpwBrmGs/lbrknWz7ZLfpl1UFCQEhISdPXVV/t1kAGAN5U9YG3GJp0JyV9vZcvNe2Lv3r3KyclRz549XfvCw8PVuXNnZWZmSpIyMzMVERHhCjFJ6tmzpwICAvTpp5+6zunatasrxCQpJSVF2dnZOnbs2KX8dVUIuQYAlc+KuSZZL9s8Xt2xR48estnO/6Dehx9+6GmTAIDzMetdMD+3ERcX57b70UcfVVpamkdN5eTkSJKio6Pd9kdHR7uO5eTkKCoqyu14jRo1FBkZ6XZO06ZNy7VRdqxu3boe9etSkWsAUIUsmGuS9bLN40Fau3bt3D4XFxcrKytLX331lYYPH+5pcwCAKnTgwAG3spDg4GAv9sYayDUA8F3+mmseD9L+8Y9/nHN/WlpauZVNAAAVZNL7ZMruONrt9kt+nqBMTEyMJCk3N1cNGzZ07c/NzXUNeGJiYnT48GG375WUlOjo0aOu78fExCg3N9ftnLLPZedUBXINAKqQBXNNsl62XfIzaWcbMmSI5s+fb1ZzAADJq6tgnU/Tpk0VExOjNWvWuPbl5+fr008/VVJSkiQpKSlJx48f1+bNvyxA8OGHH8rhcKhz586uc9atW6fi4mLXOatWrVLLli2rrNTxQsg1AKgEFsw1yXrZZtogLTMzUyEmrNQCAPC+goICZWVlKSsrS9KZB6qzsrK0f/9+2Ww23X///frLX/6it956S19++aWGDRum2NhY1ypZrVu3Vq9evTR69Gj973//04YNGzR27Fjdfvvtio2NlSQNGjRIQUFBGjVqlLZt26Zly5bp6aef1vjx47101e7INQDwL76UbR6XO/bv39/ts9Pp1KFDh7Rp0yY98sgjnjYHALgQkx+wNmrTpk3q0aOH63NZuAwfPlwLFy7UpEmTdPLkSY0ZM0bHjx/Xtddeq5UrV7oNahYvXqyxY8fqhhtuUEBAgAYMGKDZs2e7joeHh+uDDz5QamqqOnbsqPr162vq1Klu75upCuQaAFQhL+Wa5FvZ5vF70u644w63zwEBAWrQoIGuv/56JScne/TDfQXvk8GF8D4ZnM3M98k0f2iGAk2YzSk9fVq7Z1z6+2T8GblGrsEduYazkWtVz6OZtNLSUt1xxx1KTEy0xPMCAABUBLkGALAij55JCwwMVHJyso4fP15J3QEAoOqQawAAK/J44ZCrrrpKe/bsqYy+AABQ5cg1AIDVeDxI+8tf/qIJEyZoxYoVOnTokPLz8902AICJLLpUsT8h1wCgCpFrhhh+Ju2xxx7TAw88oJtuukmSdPPNN8tms7mOO51O2Ww2lZaWmt9LAKimbCa99NOUF4f6GXINAKoeuWaM4UHatGnTdPfdd+ujjz6qzP4AAFAlyDUAgFUZHqSVrdTfrVu3SusMAOAc/PxuobeQawDgJeTaRXm0BP+vy0AAAFXAiy/9rA7INQCoYuSaIR4N0q644oqLBtrRo0cr1CEAAKoKuQYAsCKPBmnTpk1TeHh4ZfUFAHAWHrCuXOQaAFQtcs0YjwZpt99+u6KioiqrLwCAs1EWUqnINQCoYuSaIYbfk0bdPgDAn5BrAACr8nh1RwBA1aEspPKQawBQ9cg1YwwP0hwOR2X2AwBwLpSFVBpyDQC8gFwzxHC5IwAAAACg8nm0cAgAoIpxxxEA4E/INUOYSQMAAAAAC2EmDQAsjAesAQD+hFwzhkEaAFgZZSEAAH9CrhlCuSMAAAAAWAgzaQBgZdxxBAD4E3LNEAZpAGBh1O4DAPwJuWYM5Y4AAAAAYCHMpAGAlVEWAgDwJ+SaIQzSAMDCKAsBAPgTcs0Yyh0BAAAAwEKYSQMAK6MsBADgT8g1Q5hJAwAAAAALYSYNAKyMO44AAH9CrhnCIA0ALMz282ZGOwAAeBu5ZgzljgAAAABgIcykAYCVURYCAPAn5JohDNIAwMJ4nwwAwJ+Qa8ZQ7ggAAAAAFsJMGgBYGWUhAAB/Qq4ZwkwaAFid04TNQ02aNJHNZiu3paamSpK6d+9e7tjdd9/t1sb+/fvVp08f1apVS1FRUZo4caJKSkou5W8AAOBPyLWLYiYNAFDOZ599ptLSUtfnr776SjfeeKP+8Ic/uPaNHj1ajz32mOtzrVq1XH8uLS1Vnz59FBMTo40bN+rQoUMaNmyYatasqRkzZlTNRQAA8DNfyzUGaQBgYd56wLpBgwZun2fOnKnmzZurW7durn21atVSTEzMOb//wQcf6Ouvv9bq1asVHR2tdu3aafr06Zo8ebLS0tIUFBTk8TUAAHwfuWYM5Y4AYGVmlIT8qjQkPz/fbSssLLxoF4qKivTKK69o5MiRstl+eX3o4sWLVb9+fV111VWaMmWKTp065TqWmZmpxMRERUdHu/alpKQoPz9f27Ztu9S/DQCAryPXDGEmDR7pO+IH3XrPYUU2KNGer0P1z4cvU3ZWrYt/EZb36jMxynwvQt/tClFQiEOtO53UiIe+U6MWv/yyW/lKfWUsj9TuL2vpp4JALf06S3XCS93aGdn5Kh3+Ltht3/Ap3+kPY3Ndn/d+Haq5f47Tzi21FR5Zot+NPKxb/5grVL64uDi3z48++qjS0tIu+J3ly5fr+PHjGjFihGvfoEGDFB8fr9jYWG3dulWTJ09Wdna23njjDUlSTk6OW5BJcn3Oycmp+IUAJiHX/Be5Vj34a64xSINh3W4+pjGPHtQzDzbSjs9r6fejj+ivS/Zo1HUtlfdjTW93DxX01Sd11Gf4EV3e7qRKS2x6eeZlemTQ5Zqb8bVCajkkSYU/Bahj9zx17J6nRemNztvW4Anfq9fgH1yfQ+s4XH8+dSJAjwy6XO2uy1fqzP36dkeoZo9vojr2UvUa8sO5mqvWzC4LOXDggOx2u2t/cHDweb7xi5deekm9e/dWbGysa9+YMWNcf05MTFTDhg11ww03aPfu3WrevHnFOwxUAXLNv5Fr1kSuGePVcscRI0acc+UUSUpNTZXNZnMb4cK7+o/5QSuXROqDZZHavzNEsyc3UuFPNqUMPOrtrsEEjy3epZ7/96PiW55Wsyt/0rinvtWR74O1a+svd5RvGX1Yfxibq5YdTl6wrVp1HKobVeLaysJQkjLeiFRJsU1/emKf4lueVrdbjqnvqMNa/nz0BVqEWex2u9t2sTDbt2+fVq9erTvvvPOC53Xu3FmStGvXLklSTEyMcnPd7yKXfT5fvb8/INd8C7nm38i16sFfc83rz6TFxcVp6dKl+umnn1z7Tp8+rSVLlqhx48aX3K7T6WSpZxPVqOnQ5W1O6fOPw1z7nE6bvvg4TAkdT13gm/BVJ/MDJUl1Ijz/39F/5sRo4JVtdV9ya70+N1qlv2pi++Y6uqpzgWoG/XIbrUO3PH23O0QFxwMr3G+/Y3LtvqcWLFigqKgo9enT54LnZWVlSZIaNmwoSUpKStKXX36pw4cPu85ZtWqV7Ha7EhISLq0zPoJc8w3kWvVDrlkEuWaI1wdpHTp0UFxcnKveU5LeeOMNNW7cWO3bt3ftKyws1H333aeoqCiFhITo2muv1WeffeY6npGRIZvNpvfee08dO3ZUcHCw1q9fL4fDofT0dDVt2lShoaFq27atXnvttSq9Rn9gjyxVYA3p+BH3CtljP9RQ3Qb8R4O/cTikFx5tpITfFKhJq9MefbfvyMOa9M89mvGfb9RryBG9+kyM5v/llxKS40dqKqJ+sdt3In7+N3TsCOVFZysrCzFj85TD4dCCBQs0fPhw1ajxy//2d+/erenTp2vz5s369ttv9dZbb2nYsGHq2rWr2rRpI0lKTk5WQkKChg4dqi1btuj999/Xww8/rNTUVEOlKL6MXPMN5Fr1Qq5ZB7lmjNcHaZI0cuRILViwwPV5/vz5uuOOO9zOmTRpkl5//XUtWrRIn3/+uVq0aKGUlBQdPepekvDggw9q5syZ2r59u9q0aaP09HS9/PLLmjdvnrZt26Zx48ZpyJAhWrt27Xn7U1hYWG6lGKA6mftQY+3LDtWkf+7x+Lu/v+uw2vy2QE0TftJNw37QqKnfacWCKBUX2i7+ZVjK6tWrtX//fo0cOdJtf1BQkFavXq3k5GS1atVKDzzwgAYMGKC3337bdU5gYKBWrFihwMBAJSUlaciQIRo2bJjb+2f8GbkGWAu5Bsm3cs0SC4cMGTJEU6ZM0b59+yRJGzZs0NKlS5WRkSFJOnnypObOnauFCxeqd+/ekqQXXnhBq1at0ksvvaSJEye62nrsscd04403SjoTSjNmzNDq1auVlJQkSWrWrJnWr1+v5557zu29CL+Wnp6uadOmVdbl+qT8o4EqLfnlzlCZuvVLdOyIJf4ZwSRz/xynz1aHa+Yb2aofW3zxL1xEy/ZnHtjOPRCkRi0KFdGgWMd/cL+zWHYnu26Div88v1OBko5y7XgoOTlZTmf5L8bFxV1wQFAmPj5e7777ruc/2A+Qa9ZHrlUf5JrFkGuGWOK3UIMGDdSnTx8tXLhQTqdTffr0Uf369V3Hd+/ereLiYnXp0sW1r2bNmrr66qu1fft2t7Y6derk+vOuXbt06tQpV7iVKSoqcis5OduUKVM0fvx41+f8/Pxyy3tWNyXFAdq5tZbaX3tCmSvDJUk2m1Ptri3QWwvrebl3MIPTKc17OE6ZKyOU/p9vFNO4yJR292yrpYAApyLqn/kPodYdC/TyrMtUUizV+DnTvlhnV6Pmp1UnovQCLVVTXgwzXDpyzfrINf9HrlkUuWaIJQZp0pnSkLFjx0qS5syZc8nt1K5d2/XngoICSdI777yjyy67zO28C9WOBgcH+/0zE5fijefra8JTB/TNllrK/uLMUsUhtRz6YGmkt7sGE8x9KE5rl0fq4fm7VatOqY4dPvProVZYqYJDz/wmPHa4ho4drqlD357538e3O0JVq3apGlxWpLC6pdq+qba++aK2En97QrXqlGr75jp6Ma2Ruvc/6gqqbr8/qiX/iNXTDzTRrak52rcjVG+9FKXRad9558KBSkKuWR+55t/INfgyywzSevXqpaKiItlsNqWkpLgda968uYKCgrRhwwbFx8dLkoqLi/XZZ5/p/vvvP2+bCQkJCg4O1v79+89bAgLj1r5VV+H1SjVsYo7qNijRnm2h+vPgpuWm+OGb3n05SpI05daWbvvvf/Jb9fy/H8+c868G+veTv7xT5MH+Ld3OqRns0Lr/1tWSJxuquChA0XGFumX0Yf1+zC9L1ta2OzR9yU7N/XOc7u/dWva6JRo47hDvkjkPs98ng6pDrlkfuebfyDVrIteMscwgLTAw0FXiERjovlxp7dq1dc8992jixImKjIxU48aNNWvWLJ06dUqjRo06b5thYWGaMGGCxo0bJ4fDoWuvvVZ5eXnasGGD7Ha7hg8fXqnX5I/eWlBfby2of/ET4XNWfL/5oucMfuCQBj9w6LzHWyT+pCdWZF+0naYJP2nWm9941L9qi7IQn0Wu+QZyzX+RaxZFrhlimUGaJLe3hZ9t5syZcjgcGjp0qE6cOKFOnTrp/fffV926dS/Y5vTp09WgQQOlp6drz549ioiIUIcOHfTQQw+Z3X0AANyQawCAS2FznmuJE7jJz89XeHi4uusW1bBRAgF3Ru7UoXrJP+FQVMt9ysvLu+B/pF+wjZ9/77Qb+lcFBoVUuE+lRaeV9a8/V6hP8B/kGi6EXMPZyLWqZ4n3pAEAAAAAzrBUuSMA4CzU7gMA/Am5ZgiDNACwMFbBAgD4E3LNGModAQAAAMBCmEkDACujLAQA4E/INUMYpAGAhVEWAgDwJ+SaMZQ7AgAAAICFMJMGAFZGWQgAwJ+Qa4YwSAMAC6MsBADgT8g1Yyh3BAAAAAALYSYNAKyMshAAgD8h1wxhkAYAFufvJR0AgOqFXLs4yh0BAAAAwEKYSQMAK3M6z2xmtAMAgLeRa4YwkwYAAAAAFsJMGgBYGEsVAwD8CblmDIM0ALAyVsECAPgTcs0Qyh0BAAAAwEKYSQMAC7M5zmxmtAMAgLeRa8YwSAMAK6MsBADgT8g1Qyh3BAAAAAALYSYNACyMVbAAAP6EXDOGQRoAWBkv/QQA+BNyzRDKHQEAAADAQphJAwALoywEAOBPyDVjmEkDAAAAAAthJg0ArIyligEA/oRcM4RBGgBYGGUhAAB/Qq4ZQ7kjAAAAAFgIgzQAsLKypYrN2DyQlpYmm83mtrVq1cp1/PTp00pNTVW9evVUp04dDRgwQLm5uW5t7N+/X3369FGtWrUUFRWliRMnqqSkxJS/FgCAjyLXDKHcEQAszJtlIVdeeaVWr17t+lyjxi+RMW7cOL3zzjv6z3/+o/DwcI0dO1b9+/fXhg0bJEmlpaXq06ePYmJitHHjRh06dEjDhg1TzZo1NWPGjApfDwDAN5FrxjBIAwCcU40aNRQTE1Nuf15enl566SUtWbJE119/vSRpwYIFat26tT755BNdc801+uCDD/T1119r9erVio6OVrt27TR9+nRNnjxZaWlpCgoKqurLAQBUc76Ua5Q7AoCVOU3cJOXn57tthYWF5/3RO3fuVGxsrJo1a6bBgwdr//79kqTNmzeruLhYPXv2dJ3bqlUrNW7cWJmZmZKkzMxMJSYmKjo62nVOSkqK8vPztW3btgr/tQAAfBS5ZgiDNACwsLKyEDM2SYqLi1N4eLhrS09PP+fP7dy5sxYuXKiVK1dq7ty52rt3r6677jqdOHFCOTk5CgoKUkREhNt3oqOjlZOTI0nKyclxC7Ky42XHAADVE7lmDOWOAFCNHDhwQHa73fU5ODj4nOf17t3b9ec2bdqoc+fOio+P16uvvqrQ0NBK7ycAAEb4a64xkwYAVuZwmrdJstvtbtv5wuxsERERuuKKK7Rr1y7FxMSoqKhIx48fdzsnNzfXVesfExNTblWsss/neh4AAFBNkGuGMEgDACszuXb/UhUUFGj37t1q2LChOnbsqJo1a2rNmjWu49nZ2dq/f7+SkpIkSUlJSfryyy91+PBh1zmrVq2S3W5XQkJCxToDAPBd5JohlDsCAMqZMGGC+vbtq/j4eB08eFCPPvqoAgMDNXDgQIWHh2vUqFEaP368IiMjZbfbde+99yopKUnXXHONJCk5OVkJCQkaOnSoZs2apZycHD388MNKTU01fJcTAACz+FquMUgDAAuzyaT3yXh4/nfffaeBAwfqxx9/VIMGDXTttdfqk08+UYMGDSRJ//jHPxQQEKABAwaosLBQKSkp+uc//+n6fmBgoFasWKF77rlHSUlJql27toYPH67HHnus4hcDAPBZ5JoxDNIAAOUsXbr0gsdDQkI0Z84czZkz57znxMfH69133zW7awAAeMzXco1BGgBYmdN5ZjOjHQAAvI1cM4RBGgBY2K/fBVPRdgAA8DZyzRhWdwQAAAAAC2EmDQCszIRlhl3tAADgbeSaIQzSAMDCbE6nbCbU3ZvRBgAAFUWuGUO5IwAAAABYCDNpAGBljp83M9oBAMDbyDVDGKQBgIVRFgIA8CfkmjGUOwIAAACAhTCTBgBWxipYAAB/Qq4ZwkwaAAAAAFgIM2kAYGVO55nNjHYAAPA2cs0QBmkAYGE255nNjHYAAPA2cs0Yyh0BAAAAwEKYSQMAK6MsBADgT8g1QxikAYCF2RxnNjPaAQDA28g1Yyh3BAAAAAALYSYNAKyMshAAgD8h1wxhkAYAVsZLPwEA/oRcM4RBmgHOn0fqJSr2+38Q8Fz+CT8viobHThSc+Tfh9PO7fPBd5BouhFzD2ci1qscgzYATJ05IktbrXS/3BFYU1dLbPYBVnThxQuHh4RVqw+Z0ymZCKJrRBvwHuYYLIddwPuRa1WGQZkBsbKwOHDigsLAw2Ww2b3fHq/Lz8xUXF6cDBw7Ibrd7uzuwEP5t/MLpdOrEiROKjY01ozFq92E6cu0X/O7C+fBv4xfkWtVjkGZAQECAGjVq5O1uWIrdbq/2v7BwbvzbOKOidxqBykSulcfvLpwP/zbOINeqFoM0ALAypyQzHg/x7xuOAABfQa4ZwnvSAAAAAMBCmEmDR4KDg/Xoo48qODjY212BxfBvo3LwgDVQufjdhfPh30blINeMsTlZSxMALCc/P1/h4eG6vt2DqhFY8f9AKCkt1IdZM5WXl8ezFQCAKkeueYZyRwAAAACwEModAcDKWKoYAOBPyDVDGKQBgJU5JJnxGiszVtICAKCiyDVDKHcEAAAAAAthJg0ALIxVsAAA/oRcM4aZtGpsxIgR6tevn7e7AQsZMWKEbDab7r777nLHUlNTZbPZNGLEiKrvWHVWVrtvxgb4OXINZyPXLIhcM4RBGgA3cXFxWrp0qX766SfXvtOnT2vJkiVq3LjxJbfrdDpVUlJiRhcBADCMXIMvYpCGc/rqq6/Uu3dv1alTR9HR0Ro6dKh++OEH1/HXXntNiYmJCg0NVb169dSzZ0+dPHlSkpSRkaGrr75atWvXVkREhLp06aJ9+/Z561LgoQ4dOiguLk5vvPGGa98bb7yhxo0bq3379q59hYWFuu+++xQVFaWQkBBde+21+uyzz1zHMzIyZLPZ9N5776ljx44KDg7W+vXr5XA4lJ6erqZNmyo0NFRt27bVa6+9VqXX6FO44wiYglyrvsg1iyHXDGGQhnKOHz+u66+/Xu3bt9emTZu0cuVK5ebm6rbbbpMkHTp0SAMHDtTIkSO1fft2ZWRkqH///q47Sv369VO3bt20detWZWZmasyYMbLZzFjGB1Vl5MiRWrBggevz/Pnzdccdd7idM2nSJL3++utatGiRPv/8c7Vo0UIpKSk6evSo23kPPvigZs6cqe3bt6tNmzZKT0/Xyy+/rHnz5mnbtm0aN26chgwZorVr11bJtcGY9PR0/eY3v1FYWJiioqLUr18/ZWdnu53TvXt32Ww2t+3skqL9+/erT58+qlWrlqKiojRx4kTuPKPKkWsg1+BrucbCISjn2WefVfv27TVjxgzXvvnz5ysuLk7ffPONCgoKVFJSov79+ys+Pl6SlJiYKEk6evSo8vLy9Lvf/U7NmzeXJLVu3brqLwIVMmTIEE2ZMsV1p3jDhg1aunSpMjIyJEknT57U3LlztXDhQvXu3VuS9MILL2jVqlV66aWXNHHiRFdbjz32mG688UZJZ+5SzpgxQ6tXr1ZSUpIkqVmzZlq/fr2ee+45devWrQqv0kd46X0ya9euVWpqqn7zm9+opKREDz30kJKTk/X111+rdu3arvNGjx6txx57zPW5Vq1arj+XlpaqT58+iomJ0caNG3Xo0CENGzZMNWvWdPv9AlQ2cg3kmoWQa4YwSEM5W7Zs0UcffaQ6deqUO7Z7924lJyfrhhtuUGJiolJSUpScnKxbb71VdevWVWRkpEaMGKGUlBTdeOON6tmzp2677TY1bNjQC1eCS9WgQQP16dNHCxculNPpVJ8+fVS/fn3X8d27d6u4uFhdunRx7atZs6auvvpqbd++3a2tTp06uf68a9cunTp1yhVuZYqKitxKTvArXnqfzMqVK90+L1y4UFFRUdq8ebO6du3q2l+rVi3FxMScs40PPvhAX3/9tVavXq3o6Gi1a9dO06dP1+TJk5WWlqagoCCPLwO4FOQayDULIdcModwR5RQUFKhv377Kyspy23bu3KmuXbsqMDBQq1at0nvvvaeEhAQ988wzatmypfbu3StJWrBggTIzM/Xb3/5Wy5Yt0xVXXKFPPvnEy1cFT40cOVILFy7UokWLNHLkyEtu59d3pwoKCiRJ77zzjtu/ra+//pr6/SqSn5/vthUWFhr6Xl5eniQpMjLSbf/ixYtVv359XXXVVZoyZYpOnTrlOpaZmanExERFR0e79qWkpCg/P1/btm0z4WoAY8g1SOSav/LXXGOQhnI6dOigbdu2qUmTJmrRooXbVvaLyWazqUuXLpo2bZq++OILBQUF6c0333S10b59e02ZMkUbN27UVVddpSVLlnjrcnCJevXqpaKiIhUXFyslJcXtWPPmzRUUFKQNGza49hUXF+uzzz5TQkLCedtMSEhQcHCw9u/fX+7fVlxcXKVdiy8re5+MGZt0ZpWz8PBw15aenn7RPjgcDt1///3q0qWLrrrqKtf+QYMG6ZVXXtFHH32kKVOm6F//+peGDBniOp6Tk+MWZJJcn3Nycsz46wEMIdcgkWtWQa4ZQ7ljNZeXl6esrCy3fWPGjNELL7yggQMHatKkSYqMjNSuXbu0dOlSvfjii9q0aZPWrFmj5ORkRUVF6dNPP9WRI0fUunVr7d27V88//7xuvvlmxcbGKjs7Wzt37tSwYcO8c4G4ZIGBga4Sj8DAQLdjtWvX1j333KOJEycqMjJSjRs31qxZs3Tq1CmNGjXqvG2GhYVpwoQJGjdunBwOh6699lrl5eVpw4YNstvtGj58eKVek08yuXb/wIEDstvtrt3BwcEX/Wpqaqq++uorrV+/3m3/mDFjXH9OTExUw4YNdcMNN2j37t2uZ3eAqkau4XzINYsg1wxhkFbNZWRklKuZHjVqlDZs2KDJkycrOTlZhYWFio+PV69evRQQECC73a5169bpqaeeUn5+vuLj4/XEE0+od+/eys3N1Y4dO7Ro0SL9+OOPatiwoVJTU3XXXXd56QpREb/+pXe2mTNnyuFwaOjQoTpx4oQ6deqk999/X3Xr1r1gm9OnT1eDBg2Unp6uPXv2KCIiQh06dNBDDz1kdvdxDna7/YL/fz3b2LFjtWLFCq1bt06NGjW64LmdO3eWdOYZjebNmysmJkb/+9//3M7Jzc2VpPPW+wMVRa7hQsg1/+OvuWZzOv38JQMA4IPy8/MVHh6uns3vV43Ai98VvJiS0kKt3v2U8vLyDIWZ0+nUvffeqzfffFMZGRm6/PLLL/qdDRs26Nprr9WWLVvUpk0bvffee/rd736nQ4cOKSoqSpL0/PPPa+LEiTp8+LChu50AAP9ArnmGmTQAsDIvLVWcmpqqJUuW6L///a/CwsJctfbh4eEKDQ3V7t27tWTJEt10002qV6+etm7dqnHjxqlr165q06aNJCk5OVkJCQkaOnSoZs2apZycHD388MNKTU1lgAYA1RW5ZggLhwAAypk7d67y8vLUvXt3NWzY0LUtW7ZMkhQUFKTVq1crOTlZrVq10gMPPKABAwbo7bffdrURGBioFStWKDAwUElJSRoyZIiGDRvm9v4ZAACqgq/lGjNpAGBpJt1xlGdtXKwSPi4uTmvXrr1oO/Hx8Xr33Xc9+tkAAH9GrhnBIA0ArMxLZSEAAFQKcs0Qyh0BAAAAwEKYSQMAK3M45WlJx/nbAQDAy8g1Q5hJAwAAAAALYZAGvzdixAj169fP9bl79+66//77q7wfGRkZstlsOn78+HnPsdlsWr58ueE209LS1K5duwr169tvv5XNZlNWVlaF2kElcTrM2wD4BXLtwsg1iyPXDGGQBq8YMWKEbDabbDabgoKC1KJFCz322GMqKSmp9J/9xhtvaPr06YbONRJAQKUqe8DajA1ApSHXAIPINUN4Jg1e06tXLy1YsECFhYV69913lZqaqpo1a2rKlCnlzi0qKlJQUJApPzcyMtKUdgAA+DVyDYBZmEmD1wQHBysmJkbx8fG655571LNnT7311luSfinl+Otf/6rY2Fi1bNlSknTgwAHddtttioiIUGRkpG655RZ9++23rjZLS0s1fvx4RUREqF69epo0aVK592KcXRZSWFioyZMnKy4uTsHBwWrRooVeeuklffvtt+rRo4ckqW7durLZbBoxYoQkyeFwKD09XU2bNlVoaKjatm2r1157ze3nvPvuu7riiisUGhqqHj16uPXTqMmTJ+uKK65QrVq11KxZMz3yyCMqLi4ud95zzz2nuLg41apVS7fddpvy8vLcjr/44otq3bq1QkJC1KpVK/3zn//0uC/wEofTvA1ApSLXLo5cA7lmDDNpsIzQ0FD9+OOPrs9r1qyR3W7XqlWrJEnFxcVKSUlRUlKSPv74Y9WoUUN/+ctf1KtXL23dulVBQUF64okntHDhQs2fP1+tW7fWE088oTfffFPXX3/9eX/usGHDlJmZqdmzZ6tt27bau3evfvjhB8XFxen111/XgAEDlJ2dLbvdrtDQUElSenq6XnnlFc2bN0+XX3651q1bpyFDhqhBgwbq1q2bDhw4oP79+ys1NVVjxozRpk2b9MADD3j8dxIWFqaFCxcqNjZWX375pUaPHq2wsDBNmjTJdc6uXbv06quv6u2331Z+fr5GjRqlP/7xj1q8eLEkafHixZo6daqeffZZtW/fXl988YVGjx6t2rVra/jw4R73CVWM98kAPotcK49cA7lmDIM0eJ3T6dSaNWv0/vvv695773Xtr127tl588UVXOcgrr7wih8OhF198UTabTZK0YMECRUREKCMjQ8nJyXrqqac0ZcoU9e/fX5I0b948vf/+++f92d98841effVVrVq1Sj179pQkNWvWzHW8rIQkKipKERERks7coZwxY4ZWr16tpKQk13fWr1+v5557Tt26ddPcuXPVvHlzPfHEE5Kkli1b6ssvv9Tf/vY3j/5uHn74YdefmzRpogkTJmjp0qVuYXb69Gm9/PLLuuyyyyRJzzzzjPr06aMnnnhCMTExevTRR/XEE0+4/k6aNm2qr7/+Ws899xxhBgCVgFw7P3INMIZBGrxmxYoVqlOnjoqLi+VwODRo0CClpaW5jicmJrrV62/ZskW7du1SWFiYWzunT5/W7t27lZeXp0OHDqlz586uYzVq1FCnTp3KlYaUycrKUmBgoLp162a437t27dKpU6d04403uu0vKipS+/btJUnbt29364ckV/B5YtmyZZo9e7Z2796tgoIClZSUyG63u53TuHFjV5CV/RyHw6Hs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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "_, ax = plt.subplots(1, 2, figsize=(10, 4), sharex=False, sharey=False\n", + ")\n", + "\n", + "for index in range(0, len(optimized_metrics)):\n", + " c_matrix = optimized_metrics.iloc[index][\"Confusion_matrix\"]\n", + " disp = ConfusionMatrixDisplay(\n", + " confusion_matrix=c_matrix, display_labels=[\"Less\", \"More\"]\n", + " ).plot(ax=ax.flat[index])\n", + "\n", + "plt.subplots_adjust(top=1, bottom=0, hspace=0.4, wspace=0.3)\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Задача регресии: предсказание цены дома (price)." + ] + }, + { + "cell_type": "code", + "execution_count": 176, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Среднее значение поля: 2079.8997362698374\n" + ] + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
iddatepricebedroomsbathroomssqft_livingsqft_lotfloorswaterfrontview...yr_builtyr_renovatedzipcodelatlongsqft_living15sqft_lot15price_categorymedian_priceaverage_price
0712930052020141013T000000221900.031.00118056501.000...195509817847.5112-122.25713405650000
1641410019220141209T000000538000.032.25257072422.000...195119919812547.7210-122.31916907639111
2563150040020150225T000000180000.021.00770100001.000...193309802847.7379-122.23327208062000
3248720087520141209T000000604000.043.00196050001.000...196509813647.5208-122.39313605000110
4195440051020150218T000000510000.032.00168080801.000...198709807447.6168-122.04518007503110
\n", + "

5 rows × 24 columns

\n", + "
" + ], + "text/plain": [ + " id date price bedrooms bathrooms sqft_living \\\n", + "0 7129300520 20141013T000000 221900.0 3 1.00 1180 \n", + "1 6414100192 20141209T000000 538000.0 3 2.25 2570 \n", + "2 5631500400 20150225T000000 180000.0 2 1.00 770 \n", + "3 2487200875 20141209T000000 604000.0 4 3.00 1960 \n", + "4 1954400510 20150218T000000 510000.0 3 2.00 1680 \n", + "\n", + " sqft_lot floors waterfront view ... yr_built yr_renovated zipcode \\\n", + "0 5650 1.0 0 0 ... 1955 0 98178 \n", + "1 7242 2.0 0 0 ... 1951 1991 98125 \n", + "2 10000 1.0 0 0 ... 1933 0 98028 \n", + "3 5000 1.0 0 0 ... 1965 0 98136 \n", + "4 8080 1.0 0 0 ... 1987 0 98074 \n", + "\n", + " lat long sqft_living15 sqft_lot15 price_category median_price \\\n", + "0 47.5112 -122.257 1340 5650 0 0 \n", + "1 47.7210 -122.319 1690 7639 1 1 \n", + "2 47.7379 -122.233 2720 8062 0 0 \n", + "3 47.5208 -122.393 1360 5000 1 1 \n", + "4 47.6168 -122.045 1800 7503 1 1 \n", + "\n", + " average_price \n", + "0 0 \n", + "1 1 \n", + "2 0 \n", + "3 0 \n", + "4 0 \n", + "\n", + "[5 rows x 24 columns]" + ] + }, + "execution_count": 176, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Вычисление среднего значения поля \"sqft_living\"\n", + "average_price = df['sqft_living'].mean()\n", + "print(f\"Среднее значение поля: {average_price}\")\n", + "\n", + "# Создание новой колонки, указывающей, выше или ниже среднего значение цена закрытия\n", + "df['average_price'] = (df['sqft_living'] > average_price).astype(int)\n", + "\n", + "df.dropna(inplace=True)\n", + "df.head()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Делим DF на выборки" + ] + }, + { + "cell_type": "code", + "execution_count": 179, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'X_train'" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
iddatepricebedroomsbathroomssqft_livingsqft_lotfloorswaterfrontview...sqft_basementyr_builtyr_renovatedzipcodelatlongsqft_living15sqft_lot15price_categorymedian_price
6325546791019020140527T000000325000.031.751780130951.000...0198309804247.3670-122.15227501309510
13473933180058020150310T000000257000.021.00100037001.000...200192909811847.5520-122.2901270500000
17614240700040520150226T000000228500.031.00108074861.500...90194209814647.4838-122.3351170780000
16970546670029020150108T000000288000.032.25209075001.000...810197709803147.3951-122.1721800735000
20868302605936120150417T000000479000.022.50174114392.000...295200709803447.7043-122.20920901045411
..................................................................
11964527220004520141113T000000378000.031.50100069141.000...0194709812547.7144-122.3191000694710
21575957850079020141111T000000399950.032.50308750022.000...0201409802347.2974-122.3492927518310
5390720235048020140930T000000575000.032.50212047802.000...0200409805347.6810-122.0321690265011
860172304903320140620T000000245000.010.75380150001.000...0196309816847.4810-122.32311701500000
15795614765028020150325T000000315000.042.50313059992.000...0200609804247.3837-122.0993020599710
\n", + "

17290 rows × 23 columns

\n", + "
" + ], + "text/plain": [ + " id date price bedrooms bathrooms \\\n", + "6325 5467910190 20140527T000000 325000.0 3 1.75 \n", + "13473 9331800580 20150310T000000 257000.0 2 1.00 \n", + "17614 2407000405 20150226T000000 228500.0 3 1.00 \n", + "16970 5466700290 20150108T000000 288000.0 3 2.25 \n", + "20868 3026059361 20150417T000000 479000.0 2 2.50 \n", + "... ... ... ... ... ... \n", + "11964 5272200045 20141113T000000 378000.0 3 1.50 \n", + "21575 9578500790 20141111T000000 399950.0 3 2.50 \n", + "5390 7202350480 20140930T000000 575000.0 3 2.50 \n", + "860 1723049033 20140620T000000 245000.0 1 0.75 \n", + "15795 6147650280 20150325T000000 315000.0 4 2.50 \n", + "\n", + " sqft_living sqft_lot floors waterfront view ... sqft_basement \\\n", + "6325 1780 13095 1.0 0 0 ... 0 \n", + "13473 1000 3700 1.0 0 0 ... 200 \n", + "17614 1080 7486 1.5 0 0 ... 90 \n", + "16970 2090 7500 1.0 0 0 ... 810 \n", + "20868 1741 1439 2.0 0 0 ... 295 \n", + "... ... ... ... ... ... ... ... \n", + "11964 1000 6914 1.0 0 0 ... 0 \n", + "21575 3087 5002 2.0 0 0 ... 0 \n", + "5390 2120 4780 2.0 0 0 ... 0 \n", + "860 380 15000 1.0 0 0 ... 0 \n", + "15795 3130 5999 2.0 0 0 ... 0 \n", + "\n", + " yr_built yr_renovated zipcode lat long sqft_living15 \\\n", + "6325 1983 0 98042 47.3670 -122.152 2750 \n", + "13473 1929 0 98118 47.5520 -122.290 1270 \n", + "17614 1942 0 98146 47.4838 -122.335 1170 \n", + "16970 1977 0 98031 47.3951 -122.172 1800 \n", + "20868 2007 0 98034 47.7043 -122.209 2090 \n", + "... ... ... ... ... ... ... \n", + "11964 1947 0 98125 47.7144 -122.319 1000 \n", + "21575 2014 0 98023 47.2974 -122.349 2927 \n", + "5390 2004 0 98053 47.6810 -122.032 1690 \n", + "860 1963 0 98168 47.4810 -122.323 1170 \n", + "15795 2006 0 98042 47.3837 -122.099 3020 \n", + "\n", + " sqft_lot15 price_category median_price \n", + "6325 13095 1 0 \n", + "13473 5000 0 0 \n", + "17614 7800 0 0 \n", + "16970 7350 0 0 \n", + "20868 10454 1 1 \n", + "... ... ... ... \n", + "11964 6947 1 0 \n", + "21575 5183 1 0 \n", + "5390 2650 1 1 \n", + "860 15000 0 0 \n", + "15795 5997 1 0 \n", + "\n", + "[17290 rows x 23 columns]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "'y_train'" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
average_price
63250
134730
176140
169701
208680
......
119640
215751
53901
8600
157951
\n", + "

17290 rows × 1 columns

\n", + "
" + ], + "text/plain": [ + " average_price\n", + "6325 0\n", + "13473 0\n", + "17614 0\n", + "16970 1\n", + "20868 0\n", + "... ...\n", + "11964 0\n", + "21575 1\n", + "5390 1\n", + "860 0\n", + "15795 1\n", + "\n", + "[17290 rows x 1 columns]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "'X_test'" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
iddatepricebedroomsbathroomssqft_livingsqft_lotfloorswaterfrontview...sqft_basementyr_builtyr_renovatedzipcodelatlongsqft_living15sqft_lot15price_categorymedian_price
735259182031020141006T000000365000.042.25207088932.000...0198609805847.4388-122.1622390770010
2830797420082020140821T000000865000.053.00290067301.000...1070197709811547.6784-122.2852370628321
4106770145011020140815T0000001038000.042.503770108932.002...0199709800647.5646-122.1293710968521
16218952230001020150331T0000001490000.033.504560146082.002...0199009803447.6995-122.22840501422621
19964951086114020140714T000000711000.032.50255053762.000...0200409805247.6647-122.0832250405021
..................................................................
13674616390033320141110T000000338000.031.75125077101.000...0194709815547.7623-122.3171340771010
20377352896002020140708T000000673000.032.75283034962.000...0201209802947.5606-122.0112160350111
8805168700022020141016T000000285000.042.50243444002.000...0200709800147.2874-122.2832434440000
10168414140003020141201T000000605000.041.752250101081.000...0196709800847.5922-122.1182050975011
2522182250016020141212T000000356500.042.502570114732.000...0200809800347.2809-122.2962430599710
\n", + "

4323 rows × 23 columns

\n", + "
" + ], + "text/plain": [ + " id date price bedrooms bathrooms \\\n", + "735 2591820310 20141006T000000 365000.0 4 2.25 \n", + "2830 7974200820 20140821T000000 865000.0 5 3.00 \n", + "4106 7701450110 20140815T000000 1038000.0 4 2.50 \n", + "16218 9522300010 20150331T000000 1490000.0 3 3.50 \n", + "19964 9510861140 20140714T000000 711000.0 3 2.50 \n", + "... ... ... ... ... ... \n", + "13674 6163900333 20141110T000000 338000.0 3 1.75 \n", + "20377 3528960020 20140708T000000 673000.0 3 2.75 \n", + "8805 1687000220 20141016T000000 285000.0 4 2.50 \n", + "10168 4141400030 20141201T000000 605000.0 4 1.75 \n", + "2522 1822500160 20141212T000000 356500.0 4 2.50 \n", + "\n", + " sqft_living sqft_lot floors waterfront view ... sqft_basement \\\n", + "735 2070 8893 2.0 0 0 ... 0 \n", + "2830 2900 6730 1.0 0 0 ... 1070 \n", + "4106 3770 10893 2.0 0 2 ... 0 \n", + "16218 4560 14608 2.0 0 2 ... 0 \n", + "19964 2550 5376 2.0 0 0 ... 0 \n", + "... ... ... ... ... ... ... ... \n", + "13674 1250 7710 1.0 0 0 ... 0 \n", + "20377 2830 3496 2.0 0 0 ... 0 \n", + "8805 2434 4400 2.0 0 0 ... 0 \n", + "10168 2250 10108 1.0 0 0 ... 0 \n", + "2522 2570 11473 2.0 0 0 ... 0 \n", + "\n", + " yr_built yr_renovated zipcode lat long sqft_living15 \\\n", + "735 1986 0 98058 47.4388 -122.162 2390 \n", + "2830 1977 0 98115 47.6784 -122.285 2370 \n", + "4106 1997 0 98006 47.5646 -122.129 3710 \n", + "16218 1990 0 98034 47.6995 -122.228 4050 \n", + "19964 2004 0 98052 47.6647 -122.083 2250 \n", + "... ... ... ... ... ... ... \n", + "13674 1947 0 98155 47.7623 -122.317 1340 \n", + "20377 2012 0 98029 47.5606 -122.011 2160 \n", + "8805 2007 0 98001 47.2874 -122.283 2434 \n", + "10168 1967 0 98008 47.5922 -122.118 2050 \n", + "2522 2008 0 98003 47.2809 -122.296 2430 \n", + "\n", + " sqft_lot15 price_category median_price \n", + "735 7700 1 0 \n", + "2830 6283 2 1 \n", + "4106 9685 2 1 \n", + "16218 14226 2 1 \n", + "19964 4050 2 1 \n", + "... ... ... ... \n", + "13674 7710 1 0 \n", + "20377 3501 1 1 \n", + "8805 4400 0 0 \n", + "10168 9750 1 1 \n", + "2522 5997 1 0 \n", + "\n", + "[4323 rows x 23 columns]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "'y_test'" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
average_price
7350
28301
41061
162181
199641
......
136740
203771
88051
101681
25221
\n", + "

4323 rows × 1 columns

\n", + "
" + ], + "text/plain": [ + " average_price\n", + "735 0\n", + "2830 1\n", + "4106 1\n", + "16218 1\n", + "19964 1\n", + "... ...\n", + "13674 0\n", + "20377 1\n", + "8805 1\n", + "10168 1\n", + "2522 1\n", + "\n", + "[4323 rows x 1 columns]" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "from typing import Tuple\n", + "from pandas import DataFrame\n", + "from sklearn.model_selection import train_test_split\n", + "\n", + "def split_into_train_test(\n", + " df_input: DataFrame,\n", + " target_colname: str = \"average_price\",\n", + " frac_train: float = 0.8,\n", + " random_state: int = None,\n", + ") -> Tuple[DataFrame, DataFrame, DataFrame, DataFrame]:\n", + " \n", + " if not (0 < frac_train < 1):\n", + " raise ValueError(\"Fraction must be between 0 and 1.\")\n", + " \n", + " # Проверка наличия целевого признака\n", + " if target_colname not in df_input.columns:\n", + " raise ValueError(f\"{target_colname} is not a column in the DataFrame.\")\n", + " \n", + " # Разделяем данные на признаки и целевую переменную\n", + " X = df_input.drop(columns=[target_colname]) # Признаки\n", + " y = df_input[[target_colname]] # Целевая переменная\n", + "\n", + " # Разделяем данные на обучающую и тестовую выборки\n", + " X_train, X_test, y_train, y_test = train_test_split(\n", + " X, y,\n", + " test_size=(1.0 - frac_train),\n", + " random_state=random_state\n", + " )\n", + " \n", + " return X_train, X_test, y_train, y_test\n", + "\n", + "X_train, X_test, y_train, y_test = split_into_train_test(\n", + " df, \n", + " target_colname=\"average_price\", \n", + " frac_train=0.8, \n", + " random_state=42\n", + ")\n", + "\n", + "display(\"X_train\", X_train)\n", + "display(\"y_train\", y_train)\n", + "\n", + "display(\"X_test\", X_test)\n", + "display(\"y_test\", y_test)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Формирование конвейера для решения задачи регрессии" + ] + }, + { + "cell_type": "code", + "execution_count": 180, + "metadata": {}, + "outputs": [], + "source": [ + "class HouseFeatures(BaseEstimator, TransformerMixin):\n", + " def __init__(self):\n", + " pass\n", + " def fit(self, X, y=None):\n", + " return self\n", + " def transform(self, X, y=None):\n", + " # Создание новых признаков\n", + " X = X.copy()\n", + " X[\"Square\"] = X[\"sqft_living\"] / X[\"sqft_lot\"]\n", + " return X\n", + " def get_feature_names_out(self, features_in):\n", + " # Добавление имен новых признаков\n", + " new_features = [\"Square\"]\n", + " return np.append(features_in, new_features, axis=0)\n", + "\n", + "# Указываем столбцы, которые нужно удалить и обрабатывать\n", + "columns_to_drop = [\"date\"]\n", + "num_columns = [\"bathrooms\", \"floors\", \"waterfront\", \"view\"]\n", + "cat_columns = [] \n", + "\n", + "# Определяем предобработку для численных данных\n", + "num_imputer = SimpleImputer(strategy=\"median\")\n", + "num_scaler = StandardScaler()\n", + "preprocessing_num = Pipeline(\n", + " [\n", + " (\"imputer\", num_imputer),\n", + " (\"scaler\", num_scaler),\n", + " ]\n", + ")\n", + "\n", + "# Определяем предобработку для категориальных данных\n", + "cat_imputer = SimpleImputer(strategy=\"constant\", fill_value=\"unknown\")\n", + "cat_encoder = OneHotEncoder(handle_unknown=\"ignore\", sparse_output=False, drop=\"first\")\n", + "preprocessing_cat = Pipeline(\n", + " [\n", + " (\"imputer\", cat_imputer),\n", + " (\"encoder\", cat_encoder),\n", + " ]\n", + ")\n", + "\n", + "# Подготовка признаков с использованием ColumnTransformer\n", + "features_preprocessing = ColumnTransformer(\n", + " verbose_feature_names_out=False,\n", + " transformers=[\n", + " (\"preprocessing_num\", preprocessing_num, num_columns),\n", + " (\"preprocessing_cat\", preprocessing_cat, cat_columns),\n", + " ],\n", + " remainder=\"passthrough\"\n", + ")\n", + "\n", + "# Удаление нежелательных столбцов\n", + "drop_columns = ColumnTransformer(\n", + " verbose_feature_names_out=False,\n", + " transformers=[\n", + " (\"drop_columns\", \"drop\", columns_to_drop),\n", + " ],\n", + " remainder=\"passthrough\",\n", + ")\n", + "\n", + "# Постобработка признаков\n", + "features_postprocessing = ColumnTransformer(\n", + " verbose_feature_names_out=False,\n", + " transformers=[\n", + " (\"preprocessing_cat\", preprocessing_cat, [\"price_category\"]), \n", + " ],\n", + " remainder=\"passthrough\",\n", + ")\n", + "\n", + "# Создание окончательного конвейера\n", + "pipeline = Pipeline(\n", + " [\n", + " (\"features_preprocessing\", features_preprocessing),\n", + " (\"drop_columns\", drop_columns),\n", + " (\"custom_features\", HouseFeatures()),\n", + " (\"model\", RandomForestRegressor()) # Выбор модели для обучения\n", + " ]\n", + ")\n", + "\n", + "# Использование конвейера\n", + "def train_pipeline(X, y):\n", + " pipeline.fit(X, y)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Определение перечня алгоритмов решения задачи аппроксимации (регрессии)" + ] + }, + { + "cell_type": "code", + "execution_count": 181, + "metadata": {}, + "outputs": [], + "source": [ + "from sklearn.pipeline import make_pipeline\n", + "from sklearn.preprocessing import PolynomialFeatures\n", + "from sklearn import linear_model, tree, neighbors, ensemble, neural_network\n", + "\n", + "random_state = 9\n", + "\n", + "models = {\n", + " \"linear\": {\"model\": linear_model.LinearRegression(n_jobs=-1)},\n", + " \"linear_poly\": {\n", + " \"model\": make_pipeline(\n", + " PolynomialFeatures(degree=2),\n", + " linear_model.LinearRegression(fit_intercept=False, n_jobs=-1),\n", + " )\n", + " },\n", + " \"linear_interact\": {\n", + " \"model\": make_pipeline(\n", + " PolynomialFeatures(interaction_only=True),\n", + " linear_model.LinearRegression(fit_intercept=False, n_jobs=-1),\n", + " )\n", + " },\n", + " \"ridge\": {\"model\": linear_model.RidgeCV()},\n", + " \"decision_tree\": {\n", + " \"model\": tree.DecisionTreeRegressor(max_depth=7, random_state=random_state)\n", + " },\n", + " \"knn\": {\"model\": neighbors.KNeighborsRegressor(n_neighbors=7, n_jobs=-1)},\n", + " \"random_forest\": {\n", + " \"model\": ensemble.RandomForestRegressor(\n", + " max_depth=7, random_state=random_state, n_jobs=-1\n", + " )\n", + " },\n", + " \"mlp\": {\n", + " \"model\": neural_network.MLPRegressor(\n", + " activation=\"tanh\",\n", + " hidden_layer_sizes=(3,),\n", + " max_iter=500,\n", + " early_stopping=True,\n", + " random_state=random_state,\n", + " )\n", + " },\n", + "}" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Обучение и оценка моделей с помощью различных алгоритмов" + ] + }, + { + "cell_type": "code", + "execution_count": 182, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Model: logistic\n", + "MSE (train): 0.24060150375939848\n", + "MSE (test): 0.23455933379597502\n", + "MAE (train): 0.24060150375939848\n", + "MAE (test): 0.23455933379597502\n", + "R2 (train): 0.015780807725750634\n", + "R2 (test): 0.045807954005714024\n", + "STD (train): 0.48387852043102103\n", + "STD (test): 0.4780359236045559\n", + "----------------------------------------\n", + "Model: ridge\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "d:\\Study\\3 курс 5 семестр\\AIM\\AIM-PIbd-31-Yakovlev-M-G\\kernel\\Lib\\site-packages\\sklearn\\linear_model\\_logistic.py:469: ConvergenceWarning: lbfgs failed to converge (status=1):\n", + "STOP: TOTAL NO. of ITERATIONS REACHED LIMIT.\n", + "\n", + "Increase the number of iterations (max_iter) or scale the data as shown in:\n", + " https://scikit-learn.org/stable/modules/preprocessing.html\n", + "Please also refer to the documentation for alternative solver options:\n", + " https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression\n", + " n_iter_i = _check_optimize_result(\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "MSE (train): 0.210989010989011\n", + "MSE (test): 0.2035623409669211\n", + "MAE (train): 0.210989010989011\n", + "MAE (test): 0.2035623409669211\n", + "R2 (train): 0.1369154775441198\n", + "R2 (test): 0.17190433878207922\n", + "STD (train): 0.45781332911823247\n", + "STD (test): 0.4499815316182845\n", + "----------------------------------------\n", + "Model: decision_tree\n", + "MSE (train): 0.0\n", + "MSE (test): 0.0\n", + "MAE (train): 0.0\n", + "MAE (test): 0.0\n", + "R2 (train): 1.0\n", + "R2 (test): 1.0\n", + "STD (train): 0.0\n", + "STD (test): 0.0\n", + "----------------------------------------\n", + "Model: knn\n", + "MSE (train): 0.1949681897050318\n", + "MSE (test): 0.27989821882951654\n", + "MAE (train): 0.1949681897050318\n", + "MAE (test): 0.27989821882951654\n", + "R2 (train): 0.20245122664507342\n", + "R2 (test): -0.13863153417464114\n", + "STD (train): 0.43948973967967464\n", + "STD (test): 0.5264647910268833\n", + "----------------------------------------\n", + "Model: naive_bayes\n", + "MSE (train): 0.26928860613071137\n", + "MSE (test): 0.2690261392551469\n", + "MAE (train): 0.26928860613071137\n", + "MAE (test): 0.2690261392551469\n", + "R2 (train): -0.10156840366079445\n", + "R2 (test): -0.09440369772322943\n", + "STD (train): 0.47316941542228536\n", + "STD (test): 0.47206502931490235\n", + "----------------------------------------\n", + "Model: gradient_boosting\n", + "MSE (train): 0.0\n", + "MSE (test): 0.0\n", + "MAE (train): 0.0\n", + "MAE (test): 0.0\n", + "R2 (train): 1.0\n", + "R2 (test): 1.0\n", + "STD (train): 0.0\n", + "STD (test): 0.0\n", + "----------------------------------------\n", + "Model: random_forest\n", + "MSE (train): 0.0\n", + "MSE (test): 0.0\n", + "MAE (train): 0.0\n", + "MAE (test): 0.0\n", + "R2 (train): 1.0\n", + "R2 (test): 1.0\n", + "STD (train): 0.0\n", + "STD (test): 0.0\n", + "----------------------------------------\n", + "Model: mlp\n", + "MSE (train): 0.4253903990746096\n", + "MSE (test): 0.4353458246588018\n", + "MAE (train): 0.4253903990746096\n", + "MAE (test): 0.4353458246588018\n", + "R2 (train): -0.7401279228791116\n", + "R2 (test): -0.7709954936501442\n", + "STD (train): 0.4959884986820156\n", + "STD (test): 0.49782384226978177\n", + "----------------------------------------\n" + ] + } + ], + "source": [ + "import numpy as np\n", + "from sklearn import metrics\n", + "from sklearn.pipeline import Pipeline\n", + "\n", + "# Проверка наличия необходимых переменных\n", + "if 'class_models' not in locals():\n", + " raise ValueError(\"class_models is not defined\")\n", + "if 'X_train' not in locals() or 'X_test' not in locals() or 'y_train' not in locals() or 'y_test' not in locals():\n", + " raise ValueError(\"Train/test data is not defined\")\n", + "\n", + "\n", + "y_train = np.ravel(y_train) \n", + "y_test = np.ravel(y_test) \n", + "\n", + "# Инициализация списка для хранения результатов\n", + "results = []\n", + "\n", + "# Проход по моделям и оценка их качества\n", + "for model_name in class_models.keys():\n", + " print(f\"Model: {model_name}\")\n", + " \n", + " # Извлечение модели из словаря\n", + " model = class_models[model_name][\"model\"]\n", + " \n", + " # Создание пайплайна\n", + " model_pipeline = Pipeline([(\"pipeline\", pipeline_end), (\"model\", model)])\n", + " \n", + " # Обучение модели\n", + " model_pipeline.fit(X_train, y_train)\n", + "\n", + " # Предсказание для обучающей и тестовой выборки\n", + " y_train_predict = model_pipeline.predict(X_train)\n", + " y_test_predict = model_pipeline.predict(X_test)\n", + "\n", + " # Сохранение пайплайна и предсказаний\n", + " class_models[model_name][\"pipeline\"] = model_pipeline\n", + " class_models[model_name][\"preds\"] = y_test_predict\n", + "\n", + " # Вычисление метрик для регрессии\n", + " class_models[model_name][\"MSE_train\"] = metrics.mean_squared_error(y_train, y_train_predict)\n", + " class_models[model_name][\"MSE_test\"] = metrics.mean_squared_error(y_test, y_test_predict)\n", + " class_models[model_name][\"MAE_train\"] = metrics.mean_absolute_error(y_train, y_train_predict)\n", + " class_models[model_name][\"MAE_test\"] = metrics.mean_absolute_error(y_test, y_test_predict)\n", + " class_models[model_name][\"R2_train\"] = metrics.r2_score(y_train, y_train_predict)\n", + " class_models[model_name][\"R2_test\"] = metrics.r2_score(y_test, y_test_predict)\n", + "\n", + " # Дополнительные метрики\n", + " class_models[model_name][\"STD_train\"] = np.std(y_train - y_train_predict)\n", + " class_models[model_name][\"STD_test\"] = np.std(y_test - y_test_predict)\n", + "\n", + " # Вывод результатов для текущей модели\n", + " print(f\"MSE (train): {class_models[model_name]['MSE_train']}\")\n", + " print(f\"MSE (test): {class_models[model_name]['MSE_test']}\")\n", + " print(f\"MAE (train): {class_models[model_name]['MAE_train']}\")\n", + " print(f\"MAE (test): {class_models[model_name]['MAE_test']}\")\n", + " print(f\"R2 (train): {class_models[model_name]['R2_train']}\")\n", + " print(f\"R2 (test): {class_models[model_name]['R2_test']}\")\n", + " print(f\"STD (train): {class_models[model_name]['STD_train']}\")\n", + " print(f\"STD (test): {class_models[model_name]['STD_test']}\")\n", + " print(\"-\" * 40) # Разделитель для разных моделей" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Подбор гиперпараметров методом поиска по сетке" + ] + }, + { + "cell_type": "code", + "execution_count": 184, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Fitting 5 folds for each of 36 candidates, totalling 180 fits\n", + "Best parameters: {'max_depth': 10, 'min_samples_split': 10, 'n_estimators': 200}\n", + "Best MSE: 0.1476816399382576\n" + ] + } + ], + "source": [ + "df['date'] = pd.to_datetime(df['date'], errors='coerce') # Coerce invalid dates to NaT\n", + "df.dropna(subset=['date'], inplace=True) # Drop rows with invalid dates\n", + "df['year'] = df['date'].dt.year\n", + "df['month'] = df['date'].dt.month\n", + "df['day'] = df['date'].dt.day\n", + "\n", + "X = df[['yr_built', 'year', 'month', 'day', 'price', 'price_category']]\n", + "y = df['average_price']\n", + "\n", + "X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)\n", + "\n", + "model = RandomForestRegressor()\n", + "param_grid = {\n", + " 'n_estimators': [50, 100, 200],\n", + " 'max_depth': [None, 10, 20, 30],\n", + " 'min_samples_split': [2, 5, 10]\n", + "}\n", + "\n", + "grid_search = GridSearchCV(estimator=model, param_grid=param_grid,\n", + " scoring='neg_mean_squared_error', cv=5, n_jobs=-1, verbose=2)\n", + "\n", + "grid_search.fit(X_train, y_train)\n", + "\n", + "print(\"Best parameters:\", grid_search.best_params_)\n", + "print(\"Best MSE:\", -grid_search.best_score_)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Обучение модели с новыми гиперпараметрами и сравнение новых и старых данных" + ] + }, + { + "cell_type": "code", + "execution_count": 186, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Fitting 5 folds for each of 36 candidates, totalling 180 fits\n", + "Старые параметры: {'max_depth': 10, 'min_samples_split': 15, 'n_estimators': 200}\n", + "Лучший результат (MSE) на старых параметрах: 0.1472657852824936\n", + "\n", + "Новые параметры: {'max_depth': 10, 'min_samples_split': 10, 'n_estimators': 200}\n", + "Лучший результат (MSE) на новых параметрах: 0.14907357358498077\n", + "Среднеквадратическая ошибка (MSE) на тестовых данных: 0.1443569152033931\n", + "Корень среднеквадратичной ошибки (RMSE) на тестовых данных: 0.37994330524881353\n" + ] + } + ], + "source": [ + "# 1. Настройка параметров для старых значений\n", + "old_param_grid = {\n", + " 'n_estimators': [50, 100, 200], # Количество деревьев\n", + " 'max_depth': [None, 10, 20, 30], # Максимальная глубина дерева\n", + " 'min_samples_split': [2, 10, 15] # Минимальное количество образцов для разбиения узла\n", + "}\n", + "\n", + "# Подбор гиперпараметров с помощью Grid Search для старых параметров\n", + "old_grid_search = GridSearchCV(estimator=RandomForestRegressor(), \n", + " param_grid=old_param_grid, scoring='neg_mean_squared_error', cv=5, n_jobs=-1, verbose=2)\n", + "\n", + "# Обучение модели на тренировочных данных\n", + "old_grid_search.fit(X_train, y_train)\n", + "\n", + "# 2. Результаты подбора для старых параметров\n", + "old_best_params = old_grid_search.best_params_\n", + "old_best_mse = -old_grid_search.best_score_ # Меняем знак, так как берем отрицательное значение MSE\n", + "\n", + "# 3. Настройка параметров для новых значений\n", + "new_param_grid = {\n", + " 'n_estimators': [200],\n", + " 'max_depth': [10],\n", + " 'min_samples_split': [10]\n", + "}\n", + "\n", + "# Подбор гиперпараметров с помощью Grid Search для новых параметров\n", + "new_grid_search = GridSearchCV(estimator=RandomForestRegressor(), \n", + " param_grid=new_param_grid, scoring='neg_mean_squared_error', cv=2)\n", + "\n", + "# Обучение модели на тренировочных данных\n", + "new_grid_search.fit(X_train, y_train)\n", + "\n", + "# 4. Результаты подбора для новых параметров\n", + "new_best_params = new_grid_search.best_params_\n", + "new_best_mse = -new_grid_search.best_score_ # Меняем знак, так как берем отрицательное значение MSE\n", + "\n", + "# 5. Обучение модели с лучшими параметрами для новых значений\n", + "model_best = RandomForestRegressor(**new_best_params)\n", + "model_best.fit(X_train, y_train)\n", + "\n", + "# Прогнозирование на тестовой выборке\n", + "y_pred = model_best.predict(X_test)\n", + "\n", + "# Оценка производительности модели\n", + "mse = metrics.mean_squared_error(y_test, y_pred)\n", + "rmse = np.sqrt(mse)\n", + "\n", + "# Вывод результатов\n", + "print(\"Старые параметры:\", old_best_params)\n", + "print(\"Лучший результат (MSE) на старых параметрах:\", old_best_mse)\n", + "print(\"\\nНовые параметры:\", new_best_params)\n", + "print(\"Лучший результат (MSE) на новых параметрах:\", new_best_mse)\n", + "print(\"Среднеквадратическая ошибка (MSE) на тестовых данных:\", mse)\n", + "print(\"Корень среднеквадратичной ошибки (RMSE) на тестовых данных:\", rmse)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Посмотрев на результат, можно сказать, что старая модель имеет меньшую среднеквадратичную ошибку, следовательно она оказалась лучше модели с новыми настройками.\n", + "Т.к. старые параметры дали наилучший результат, можно сказать, что модель способна выдать высокую точность при настройке гиперпараметров. Попытка с новыми параметрами позволила оценить, как модель реагирует на изменения параметров." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": {