{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "geographic-celebrity",
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "from sklearn.neighbors import KNeighborsClassifier\n",
    "from sklearn.model_selection import train_test_split, GridSearchCV\n",
    "import sklearn.preprocessing as prep\n",
    "import sklearn.metrics as met"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "catholic-hungary",
   "metadata": {},
   "outputs": [],
   "source": [
    "#ucitavanje skupa\n",
    "df = pd.read_csv(\"C:/Users/student/Desktop/ipIndustija4/vezbe7/iris.csv\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "variable-pakistan",
   "metadata": {},
   "outputs": [],
   "source": [
    "#izdvajanje skupa sa atributima za predvidjanje\n",
    "features = df.columns[:4].tolist()\n",
    "\n",
    "#ako zelimo da izdvojimo odredjene atribute za klasifikaciju\n",
    "#featurs = [\"Petal_Length\",  \"Petal_Width\"]\n",
    "\n",
    "x_original=df[features]\n",
    "\n",
    "#normalizacija vrednosti u atributima za predvidjanje\n",
    "x=pd.DataFrame(prep.MinMaxScaler().fit_transform(x_original))\n",
    "\n",
    "#dodeljivanje imena kolonama\n",
    "x.columns = features\n",
    "\n",
    "#izdvajanje skupa sa ciljnim atributom\n",
    "y=df[\"Species\"]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "announced-spider",
   "metadata": {},
   "outputs": [],
   "source": [
    "#podela na trening i test skup\n",
    "#U primeru je zadato da 95% instanci ide u trening skup samo da bi izvestaj o\n",
    "#test instancama bio kraci.\n",
    "x_train, x_test, y_train, y_test = train_test_split(x, y, train_size=0.95, stratify=y)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "desperate-pleasure",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "GridSearchCV(cv=5, estimator=KNeighborsClassifier(),\n",
       "             param_grid={'n_neighbors': range(3, 10), 'p': [1, 2],\n",
       "                         'weights': ['uniform', 'distance']})"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "\"\"\"\n",
    "Paramerti za KNN:\n",
    "n_neighbors : broj suseda\n",
    "              default=5\n",
    "weights : tezine suseda\n",
    "              default='uniform'\n",
    "              moguce:\n",
    "              'uniform' : svi susedi imaju podjednak uticaj\n",
    "              'distance' : blizi susedi imaju veci uticaj na odredjivanje klase\n",
    "metric:  metrika\n",
    "       default : 'minkowski'\n",
    "p: parametar za rastojanje Minkowski (p=1 za Menhetn, p=2 za Euklidsko)\n",
    "\"\"\"\n",
    "\n",
    "#pomocu unakrsne validacije traze se najbolje vrednosti parametara\n",
    "#medju zadatim vrednostima\n",
    "parameters = {'n_neighbors':range(3,10),\n",
    "               'p': [1, 2],\n",
    "               'weights':['uniform', 'distance'] }\n",
    "\n",
    "clf = GridSearchCV(KNeighborsClassifier(), parameters, cv=5)\n",
    "\n",
    "#pravi se model sa najboljim vrednostima za parametre\n",
    "clf.fit(x_train, y_train)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "equipped-steel",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Matrica konfuzije\n",
      "            setosa  versicolor  virginica\n",
      "setosa           2           0          0\n",
      "versicolor       0           3          0\n",
      "virginica        0           0          3\n",
      "\n",
      "\n",
      "Preciznost 1.0\n",
      "\n",
      "\n",
      "Izvestaj klasifikacije\n",
      "              precision    recall  f1-score   support\n",
      "\n",
      "      setosa       1.00      1.00      1.00         2\n",
      "  versicolor       1.00      1.00      1.00         3\n",
      "   virginica       1.00      1.00      1.00         3\n",
      "\n",
      "    accuracy                           1.00         8\n",
      "   macro avg       1.00      1.00      1.00         8\n",
      "weighted avg       1.00      1.00      1.00         8\n",
      "\n"
     ]
    }
   ],
   "source": [
    "#primena modela na test skupu\n",
    "y_pred = clf.predict(x_test)\n",
    "\n",
    "#izvestaj o klasifikaciji test instanci\n",
    "cnf_matrix = met.confusion_matrix(y_test, y_pred)\n",
    "print(\"Matrica konfuzije\", pd.DataFrame(cnf_matrix, index=clf.classes_, columns=clf.classes_), sep=\"\\n\")\n",
    "print(\"\\n\")\n",
    "\n",
    "accuracy = met.accuracy_score(y_test, y_pred)\n",
    "print(\"Preciznost\", accuracy)\n",
    "print(\"\\n\")\n",
    "\n",
    "class_report = met.classification_report(y_test, y_pred)\n",
    "print(\"Izvestaj klasifikacije\", class_report, sep=\"\\n\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "distinguished-pipeline",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Da li zelite informacije o klasifikaciji svake instance? (1 za da, 0 za ne)0\n",
      "0\n"
     ]
    }
   ],
   "source": [
    "option = input(\"Da li zelite informacije o klasifikaciji svake instance? (1 za da, 0 za ne)\")\n",
    "print(option)\n",
    "if(option==\"1\"):\n",
    "    #sa clf.best_estimator_ se pristupa klasifikatoru (u ovom primeru KNN) i\n",
    "    #onda se mogu koristiti njegovi atributi i metode\n",
    "    #za test instance se izdvajaju rastojanja do suseda, kao i pozicije suseda u trening skupu\n",
    "    distances, indices = clf.best_estimator_.kneighbors(x_test)\n",
    "\n",
    "    \n",
    "    print(distances)\n",
    "    print(indices)\n",
    "    k = len(indices[0])\n",
    "    for i in range(0, len(x_test)):\n",
    "\n",
    "        #izdvajanje podataka o test instanci\n",
    "        print(\"test instanca: \", x_test.iloc[i], sep=\"\\n\")\n",
    "\n",
    "        #prikaz prave i dodeljene klase test instance\n",
    "        print(\"prava klasa: \", y_test.iloc[i])\n",
    "        print(\"dodeljena klasa: \", y_pred[i])\n",
    "        print(\"\\n\")\n",
    "        \n",
    "        #izvestaj o susedima\n",
    "        print(\"susedi: \")\n",
    "        for j in range(0, k):\n",
    "            print(x_train.iloc[indices[i][j]])\n",
    "            print(\"class:\", y_train.iloc[indices[i][j]])\n",
    "            print(\"distance: \", distances[i][j], \"\\n\")\n",
    "\n",
    "        print(\"\\n\")\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
