Skip to content

Instantly share code, notes, and snippets.

@evrenarslan
Created May 19, 2020 14:04
Show Gist options
  • Save evrenarslan/0043e5422823e82b33c25d1fb58f64f3 to your computer and use it in GitHub Desktop.
Save evrenarslan/0043e5422823e82b33c25d1fb58f64f3 to your computer and use it in GitHub Desktop.

Revisions

  1. evrenarslan created this gist May 19, 2020.
    650 changes: 650 additions & 0 deletions KNN Algoritması.ipynb
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,650 @@
    {
    "cells": [
    {
    "cell_type": "markdown",
    "metadata": {},
    "source": [
    "# K-Nearest Neighbors (KNN) Algoritması"
    ]
    },
    {
    "cell_type": "markdown",
    "metadata": {},
    "source": [
    "KNN sınıflandırma algoritmalarından biridir. KNN içerisinde tahmin edilecek değerin bağımsız değişkenlerinin oluşturduğu vektörün en yakın komşularının hangi sınıfta yoğun olduğu bilgisi üzerinden sınıfını tahmin etmeye dayanır. \n",
    "\n",
    "Sınıflandırma yapmak için iki değer kullanırılır:\n",
    "* Distance (Uzaklık): Tahmin edilecek vektörürün diğer noktalara uzaklığı hesaplanır. Bunun için Minkowski uzaklık hesaplama fonksiyonu kullanılır. \n",
    "* K (komuşuluk sayısı): En yakın kaç komşu üzerinden hesaplama yapılacağını söyleriz. K değeri sonucu direkt etkileceyecektir. K 1 olursa overfit etme olasılığı çok yüksek olacaktır. Çok büyük olursada çok genel sonuçlar verecektir. Bu sebeple optimum K değerini tahmin etmek problemin asıl konusu olarak karşımızda durmaktadır. K değerinin önemini aşağıdaki grafik çok güzel bir şekilde göstermektedir. Eğer K=3 seçersek yıldız ile gösterilen nokta Class B olarak sınıflandırılır. Fakat K=6 seçersek sınıflandırma algoritması yıldız noktasını Class A olarak tanımlayacaktır.\n",
    "\n",
    "<img src=\"https://ibm.box.com/shared/static/mgkn92xck0z05v7yjq8pqziukxvc2461.png\">\n",
    "\n",
    "KNN ile yaratılmış bir modelin başarımını ölçmek için 3 adet Indikatör vardır.\n",
    "\n",
    "* Jaccard Index: Doğru tahmin kümesi ile gerçek değer kümesinin kesişim kümesinin bunların birleşim kümesine oranıdır.1 ile 0 arası değer alır. ***Büyük*** değer daha iyi başarım anlamına gelir. \n",
    "* F1-Score: Confusion Matriks üzerinden hesaplanan Precission ve Recall değerlerinden hesaplanır. Pre=TP/(TP+FP) Rec=TP/(TP+FN) F1-Score= 2*((Pre*Rec)/(Pre+Rec)) 1 ile 0 arası değer alır. ***Büyük*** değer daha iyi başarım anlamına gelir.\n",
    "* LogLoss: Logistic Regresyon sonunda tahminlerin olasılıkları üzerinden LogLoss değeri hesaplanır. 1 ile 0 arası değer alır. ***Küçük*** değer daha iyi başarım anlamına gelir. "
    ]
    },
    {
    "cell_type": "markdown",
    "metadata": {},
    "source": [
    "## KNN ile Müşteri Segmantasyonu"
    ]
    },
    {
    "cell_type": "markdown",
    "metadata": {},
    "source": [
    "Örnek olarak bir telefon şirketinin örnek verileri üzerinden müşteri kategorisini tahmin eden bir model inşa etmeye çalışacağız. Tahmin etmeye çalışacağımız veri \"custcat\" kolonunda bulunuyor. Her bir sayısala değerin karşılığı aşağıdaki gibidir;\n",
    "* 1- Basic Service \n",
    "* 2- E-Service \n",
    "* 3- Plus Service \n",
    "* 4- Total Service"
    ]
    },
    {
    "cell_type": "markdown",
    "metadata": {},
    "source": [
    "## Verinin yüklenmesi ve incelenmesi"
    ]
    },
    {
    "cell_type": "code",
    "execution_count": 1,
    "metadata": {},
    "outputs": [],
    "source": [
    "import itertools\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "from matplotlib.ticker import NullFormatter\n",
    "import pandas as pd\n",
    "import numpy as np\n",
    "import matplotlib.ticker as ticker\n",
    "from sklearn import preprocessing\n",
    "%matplotlib inline"
    ]
    },
    {
    "cell_type": "code",
    "execution_count": 2,
    "metadata": {
    "scrolled": true
    },
    "outputs": [
    {
    "data": {
    "text/html": [
    "<div>\n",
    "<style scoped>\n",
    " .dataframe tbody tr th:only-of-type {\n",
    " vertical-align: middle;\n",
    " }\n",
    "\n",
    " .dataframe tbody tr th {\n",
    " vertical-align: top;\n",
    " }\n",
    "\n",
    " .dataframe thead th {\n",
    " text-align: right;\n",
    " }\n",
    "</style>\n",
    "<table border=\"1\" class=\"dataframe\">\n",
    " <thead>\n",
    " <tr style=\"text-align: right;\">\n",
    " <th></th>\n",
    " <th>region</th>\n",
    " <th>tenure</th>\n",
    " <th>age</th>\n",
    " <th>marital</th>\n",
    " <th>address</th>\n",
    " <th>income</th>\n",
    " <th>ed</th>\n",
    " <th>employ</th>\n",
    " <th>retire</th>\n",
    " <th>gender</th>\n",
    " <th>reside</th>\n",
    " <th>custcat</th>\n",
    " </tr>\n",
    " </thead>\n",
    " <tbody>\n",
    " <tr>\n",
    " <th>0</th>\n",
    " <td>2</td>\n",
    " <td>13</td>\n",
    " <td>44</td>\n",
    " <td>1</td>\n",
    " <td>9</td>\n",
    " <td>64.0</td>\n",
    " <td>4</td>\n",
    " <td>5</td>\n",
    " <td>0.0</td>\n",
    " <td>0</td>\n",
    " <td>2</td>\n",
    " <td>1</td>\n",
    " </tr>\n",
    " <tr>\n",
    " <th>1</th>\n",
    " <td>3</td>\n",
    " <td>11</td>\n",
    " <td>33</td>\n",
    " <td>1</td>\n",
    " <td>7</td>\n",
    " <td>136.0</td>\n",
    " <td>5</td>\n",
    " <td>5</td>\n",
    " <td>0.0</td>\n",
    " <td>0</td>\n",
    " <td>6</td>\n",
    " <td>4</td>\n",
    " </tr>\n",
    " <tr>\n",
    " <th>2</th>\n",
    " <td>3</td>\n",
    " <td>68</td>\n",
    " <td>52</td>\n",
    " <td>1</td>\n",
    " <td>24</td>\n",
    " <td>116.0</td>\n",
    " <td>1</td>\n",
    " <td>29</td>\n",
    " <td>0.0</td>\n",
    " <td>1</td>\n",
    " <td>2</td>\n",
    " <td>3</td>\n",
    " </tr>\n",
    " <tr>\n",
    " <th>3</th>\n",
    " <td>2</td>\n",
    " <td>33</td>\n",
    " <td>33</td>\n",
    " <td>0</td>\n",
    " <td>12</td>\n",
    " <td>33.0</td>\n",
    " <td>2</td>\n",
    " <td>0</td>\n",
    " <td>0.0</td>\n",
    " <td>1</td>\n",
    " <td>1</td>\n",
    " <td>1</td>\n",
    " </tr>\n",
    " <tr>\n",
    " <th>4</th>\n",
    " <td>2</td>\n",
    " <td>23</td>\n",
    " <td>30</td>\n",
    " <td>1</td>\n",
    " <td>9</td>\n",
    " <td>30.0</td>\n",
    " <td>1</td>\n",
    " <td>2</td>\n",
    " <td>0.0</td>\n",
    " <td>0</td>\n",
    " <td>4</td>\n",
    " <td>3</td>\n",
    " </tr>\n",
    " </tbody>\n",
    "</table>\n",
    "</div>"
    ],
    "text/plain": [
    " region tenure age marital address income ed employ retire gender \\\n",
    "0 2 13 44 1 9 64.0 4 5 0.0 0 \n",
    "1 3 11 33 1 7 136.0 5 5 0.0 0 \n",
    "2 3 68 52 1 24 116.0 1 29 0.0 1 \n",
    "3 2 33 33 0 12 33.0 2 0 0.0 1 \n",
    "4 2 23 30 1 9 30.0 1 2 0.0 0 \n",
    "\n",
    " reside custcat \n",
    "0 2 1 \n",
    "1 6 4 \n",
    "2 2 3 \n",
    "3 1 1 \n",
    "4 4 3 "
    ]
    },
    "execution_count": 2,
    "metadata": {},
    "output_type": "execute_result"
    }
    ],
    "source": [
    "df = pd.read_csv('teleCust1000t.csv')\n",
    "df.head()"
    ]
    },
    {
    "cell_type": "markdown",
    "metadata": {},
    "source": [
    "Hangi sınıfta kaç tane müşteri olduğuna bakalım. Bu inceleme ele aldığımız verinin model oluşturmak için uygunluğu konusunda bize fikir verecektir. Eğer sınıflara göre dağılımı düzgün olmayan bir veri setimiz var ise doğru bir model geliştirmemiz mümkün olmayacaktır."
    ]
    },
    {
    "cell_type": "code",
    "execution_count": 3,
    "metadata": {},
    "outputs": [
    {
    "data": {
    "text/plain": [
    "3 281\n",
    "1 266\n",
    "4 236\n",
    "2 217\n",
    "Name: custcat, dtype: int64"
    ]
    },
    "execution_count": 3,
    "metadata": {},
    "output_type": "execute_result"
    }
    ],
    "source": [
    "df['custcat'].value_counts()"
    ]
    },
    {
    "cell_type": "markdown",
    "metadata": {},
    "source": [
    "### Feature Set\n",
    "\n",
    "Öncelikli olarak verimizi analiz için hazırlamak gerekiyor. Scikit-learn ile çalışabilmek için bağımlı değişken ve bağımsız değişkenlerimizi ayrı ayrı numpy array tipine dönüştürmemiz gerekiyor."
    ]
    },
    {
    "cell_type": "code",
    "execution_count": 4,
    "metadata": {},
    "outputs": [
    {
    "data": {
    "text/plain": [
    "Index(['region', 'tenure', 'age', 'marital', 'address', 'income', 'ed',\n",
    " 'employ', 'retire', 'gender', 'reside', 'custcat'],\n",
    " dtype='object')"
    ]
    },
    "execution_count": 4,
    "metadata": {},
    "output_type": "execute_result"
    }
    ],
    "source": [
    "df.columns # Bir sonraki kod satırında kullanmak için kolon isimlerini yazdırıyorum. "
    ]
    },
    {
    "cell_type": "code",
    "execution_count": 5,
    "metadata": {},
    "outputs": [
    {
    "data": {
    "text/plain": [
    "array([[ 2., 13., 44., 1., 9., 64., 4., 5., 0., 0., 2.],\n",
    " [ 3., 11., 33., 1., 7., 136., 5., 5., 0., 0., 6.],\n",
    " [ 3., 68., 52., 1., 24., 116., 1., 29., 0., 1., 2.],\n",
    " [ 2., 33., 33., 0., 12., 33., 2., 0., 0., 1., 1.],\n",
    " [ 2., 23., 30., 1., 9., 30., 1., 2., 0., 0., 4.]])"
    ]
    },
    "execution_count": 5,
    "metadata": {},
    "output_type": "execute_result"
    }
    ],
    "source": [
    "# custcat kolonu hariç diğer kolonlardan bağımısız değişkenlerden oluşan bir numpy array yarattım.\n",
    "X = df[['region', 'tenure','age', 'marital', 'address', 'income', 'ed', 'employ','retire', 'gender', 'reside']] .values\n",
    "X[0:5]"
    ]
    },
    {
    "cell_type": "code",
    "execution_count": 6,
    "metadata": {},
    "outputs": [
    {
    "data": {
    "text/plain": [
    "array([1, 4, 3, 1, 3], dtype=int64)"
    ]
    },
    "execution_count": 6,
    "metadata": {},
    "output_type": "execute_result"
    }
    ],
    "source": [
    "# custcat feature kullanarak numpy array yarattım.\n",
    "y = df['custcat'].values\n",
    "y[0:5]"
    ]
    },
    {
    "cell_type": "markdown",
    "metadata": {},
    "source": [
    "### Normalized Data\n",
    "\n",
    "Verinin KNN gibi noktalar arası mesafe temelli algoritmalarda daha başarılı sonuç elde etmek için veriler normalize edilir. "
    ]
    },
    {
    "cell_type": "code",
    "execution_count": 7,
    "metadata": {},
    "outputs": [
    {
    "data": {
    "text/plain": [
    "array([[-0.02696767, -1.055125 , 0.18450456, 1.0100505 , -0.25303431,\n",
    " -0.12650641, 1.0877526 , -0.5941226 , -0.22207644, -1.03459817,\n",
    " -0.23065004],\n",
    " [ 1.19883553, -1.14880563, -0.69181243, 1.0100505 , -0.4514148 ,\n",
    " 0.54644972, 1.9062271 , -0.5941226 , -0.22207644, -1.03459817,\n",
    " 2.55666158],\n",
    " [ 1.19883553, 1.52109247, 0.82182601, 1.0100505 , 1.23481934,\n",
    " 0.35951747, -1.36767088, 1.78752803, -0.22207644, 0.96655883,\n",
    " -0.23065004],\n",
    " [-0.02696767, -0.11831864, -0.69181243, -0.9900495 , 0.04453642,\n",
    " -0.41625141, -0.54919639, -1.09029981, -0.22207644, 0.96655883,\n",
    " -0.92747794],\n",
    " [-0.02696767, -0.58672182, -0.93080797, 1.0100505 , -0.25303431,\n",
    " -0.44429125, -1.36767088, -0.89182893, -0.22207644, -1.03459817,\n",
    " 1.16300577]])"
    ]
    },
    "execution_count": 7,
    "metadata": {},
    "output_type": "execute_result"
    }
    ],
    "source": [
    "X=preprocessing.StandardScaler().fit(X).transform(X.astype(float))\n",
    "X[0:5]"
    ]
    },
    {
    "cell_type": "markdown",
    "metadata": {},
    "source": [
    "### Train/Test Split - Eğitim ve Test verilerin hazırlanması\n",
    "\n",
    "Bir model geliştirdikten sonra sonuçlarını bildiğimiz veriler ile modelin test edilmesi oldukça önemlidir. Bu testin ise eğitim yaparken kullanılan veri seti dışında bir veri seti olması, bize gerçek hayatta modelimizin nasıl bir performans göstereceğini söyleyecektir. Bu amaçla elimizdeki toplam veri setini train/test (eğitim/test) olarak ikiye ayıracağız."
    ]
    },
    {
    "cell_type": "code",
    "execution_count": 8,
    "metadata": {
    "scrolled": true
    },
    "outputs": [
    {
    "name": "stdout",
    "output_type": "stream",
    "text": [
    "Train set: (800, 11) (800,)\n",
    "Test set: (200, 11) (200,)\n"
    ]
    }
    ],
    "source": [
    "from sklearn.model_selection import train_test_split\n",
    "X_train,X_test,y_train,y_test=train_test_split(X,y,test_size=0.2, random_state=4)\n",
    "print(\"Train set:\", X_train.shape, y_train.shape)\n",
    "print(\"Test set:\",X_test.shape,y_test.shape)"
    ]
    },
    {
    "cell_type": "markdown",
    "metadata": {},
    "source": [
    "### Modelin oluşturulması\n",
    "\n",
    "KNN algoritmasını kullanarak sınıflandırma işlemine başlayacağız. İlk olarak ***k=4 (En yakın 4 komşu içerisindeki yoğunluğa göre karar verecek)*** olarak modelimizi eğitelim "
    ]
    },
    {
    "cell_type": "code",
    "execution_count": 9,
    "metadata": {},
    "outputs": [
    {
    "data": {
    "text/plain": [
    "KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',\n",
    " metric_params=None, n_jobs=None, n_neighbors=4, p=2,\n",
    " weights='uniform')"
    ]
    },
    "execution_count": 9,
    "metadata": {},
    "output_type": "execute_result"
    }
    ],
    "source": [
    "from sklearn.neighbors import KNeighborsClassifier\n",
    "\n",
    "k=4\n",
    "neigh=KNeighborsClassifier(n_neighbors=k).fit(X_train,y_train)\n",
    "neigh"
    ]
    },
    {
    "cell_type": "markdown",
    "metadata": {},
    "source": [
    "### Tahmin yapılması\n",
    "***neigh*** ismini verdiğimiz modelimizi eğittik. Şimdi bu model ile prediction yapalım ve sonuçların performansına bakalım."
    ]
    },
    {
    "cell_type": "code",
    "execution_count": 10,
    "metadata": {},
    "outputs": [
    {
    "data": {
    "text/plain": [
    "array([1, 1, 3, 2, 4], dtype=int64)"
    ]
    },
    "execution_count": 10,
    "metadata": {},
    "output_type": "execute_result"
    }
    ],
    "source": [
    "y_hat=neigh.predict(X_test)\n",
    "y_hat[0:5]"
    ]
    },
    {
    "cell_type": "markdown",
    "metadata": {},
    "source": [
    "### Tahminin değerlendirilmesi\n",
    "\n",
    "Multilabel (Çoklu sonuç) tahmin yapılması durumunda bunun accuracy (doğruluğu) değerlendirmesi için ***accuracy classification score*** fonksiyonu kullanılabilir. Bu fonksiyon ***jaccard index*** benzeri bir sonuç verir."
    ]
    },
    {
    "cell_type": "code",
    "execution_count": 11,
    "metadata": {},
    "outputs": [
    {
    "name": "stdout",
    "output_type": "stream",
    "text": [
    "Eğitim verisi doğruluğu: 0.5475\n",
    "Test verisi doğruluğu: 0.32\n"
    ]
    }
    ],
    "source": [
    "from sklearn import metrics\n",
    "print(\"Eğitim verisi doğruluğu:\", metrics.accuracy_score(y_train,neigh.predict(X_train)))\n",
    "print(\"Test verisi doğruluğu:\", metrics.accuracy_score(y_test,y_hat))"
    ]
    },
    {
    "cell_type": "markdown",
    "metadata": {},
    "source": [
    "Çok iyi bir sonuç değil. ***k=6*** için modeli tekrar eğitip sonuç karşılaştırması yapalım."
    ]
    },
    {
    "cell_type": "code",
    "execution_count": 12,
    "metadata": {},
    "outputs": [
    {
    "name": "stdout",
    "output_type": "stream",
    "text": [
    "Eğitim verisi doğruluğu: 0.51625\n",
    "Test verisi doğruluğu: 0.31\n"
    ]
    }
    ],
    "source": [
    "k=6\n",
    "neigh_6=KNeighborsClassifier(n_neighbors=k).fit(X_train,y_train)\n",
    "print(\"Eğitim verisi doğruluğu:\", metrics.accuracy_score(y_train,neigh_6.predict(X_train)))\n",
    "print(\"Test verisi doğruluğu:\", metrics.accuracy_score(y_test,neigh_6.predict(X_test)))"
    ]
    },
    {
    "cell_type": "markdown",
    "metadata": {},
    "source": [
    "Sonuç daha iyi olmadı. Peki doğru k değerini seçtiğimizden nasıl emin olabiliriz. Daha iyi bir soru ile optimum k değerini nasıl bulabiliriz. Bunun için bir aralık için tüm k değerleri için modelimizi eğitim accuracy score üzerinden bir karşılaştırma yapıp olası en iyi k değeri bulunabilir.\n",
    "\n",
    "Örnek olsun diye k değerinin 1-10 arasındaki durumlarını inceleyelim."
    ]
    },
    {
    "cell_type": "code",
    "execution_count": 13,
    "metadata": {},
    "outputs": [
    {
    "data": {
    "text/plain": [
    "array([0.3 , 0.29 , 0.315, 0.32 , 0.315, 0.31 , 0.335, 0.325, 0.34 ])"
    ]
    },
    "execution_count": 13,
    "metadata": {},
    "output_type": "execute_result"
    }
    ],
    "source": [
    "Ks = 10\n",
    "mean_acc = np.zeros((Ks-1))\n",
    "std_acc = np.zeros((Ks-1))\n",
    "ConfustionMx = [];\n",
    "for n in range(1,Ks):\n",
    " \n",
    " #Train Model and Predict \n",
    " neigh = KNeighborsClassifier(n_neighbors = n).fit(X_train,y_train)\n",
    " yhat=neigh.predict(X_test)\n",
    " mean_acc[n-1] = metrics.accuracy_score(y_test, yhat)\n",
    "\n",
    " \n",
    " std_acc[n-1]=np.std(yhat==y_test)/np.sqrt(yhat.shape[0])\n",
    "\n",
    "mean_acc"
    ]
    },
    {
    "cell_type": "markdown",
    "metadata": {},
    "source": [
    "***Accuracy ile K değeri arasındaki ilişkinin grafiğini çizelim***"
    ]
    },
    {
    "cell_type": "code",
    "execution_count": 14,
    "metadata": {},
    "outputs": [
    {
    "data": {
    "image/png": "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\n",
    "text/plain": [
    "<Figure size 432x288 with 1 Axes>"
    ]
    },
    "metadata": {
    "needs_background": "light"
    },
    "output_type": "display_data"
    }
    ],
    "source": [
    "plt.plot(range(1,Ks),mean_acc,'g')\n",
    "plt.fill_between(range(1,Ks),mean_acc - 1 * std_acc,mean_acc + 1 * std_acc, alpha=0.10)\n",
    "plt.legend(('Accuracy ', '+/- 3xstd'))\n",
    "plt.ylabel('Accuracy ')\n",
    "plt.xlabel('Number of Nabors (K)')\n",
    "plt.tight_layout()\n",
    "plt.show()"
    ]
    },
    {
    "cell_type": "markdown",
    "metadata": {},
    "source": [
    "Yukarıdaki grafikten gözle gördüğümüzü sonucu direkt array içerisinden seçebiliriz."
    ]
    },
    {
    "cell_type": "code",
    "execution_count": 15,
    "metadata": {},
    "outputs": [
    {
    "name": "stdout",
    "output_type": "stream",
    "text": [
    "En yüksek Doğruluk= 0.34 K= 9 olduğunda gerçekleşti.\n"
    ]
    }
    ],
    "source": [
    "print( \"En yüksek Doğruluk=\", mean_acc.max(), \"K=\", mean_acc.argmax()+1,\"olduğunda gerçekleşti.\") "
    ]
    }
    ],
    "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.2"
    }
    },
    "nbformat": 4,
    "nbformat_minor": 4
    }