Modul 4 Sains Data: Model Klasifikasi

Decision Tree, Support Vector Machine

Online Melalui Zoom
Published

March 24, 2025

Kembali ke Sains Data

Metrik Evaluasi pada Klasifikasi

1. Jaccard Index

Mengukur akurasi dari model menggunakan irisan dari hasil prediksi dengan value sebenarnya. \[J(y, \hat{y}) = \frac{|y \cap \hat{y}|}{|y|+|\hat{y}|-|y \cap \hat{y}|}\]

\(y=\) actual label

\(\hat{y}=\) predicted label

Contoh:

\(y = [0,0,0,0,0,1,1,1,1,1]\)

\(\hat{y} = [1,1,0,0,0,1,1,1,1,1]\)

\(|y| = 10\)

\(|\hat{y}| = 10\)

\(|\hat{y}|-|y \cap \hat{y}| = 8\)

\(J(y, \hat{y}) = \frac{|y \cap \hat{y}|}{|y|+|\hat{y}|-|y \cap \hat{y}|} = \frac{8}{10+10-8} = 0.66\)

  • Rentang Jaccard index antara 0 hingga 1
  • Semakin tinggi Jaccard Index, peforma model semakin baik

2. Confusion Matrix

Confusion Matrix merupakan tabel yang mengevaluasi performa model klasifikasi dengan membandingkan prediksi vs hasil aktual.

\[\begin{array}{|c|c|c|} \hline & \text{Prediksi Positif} & \text{Prediksi Negatif} \\ \hline \text{Aktual Positif} & TP & FN \\ \hline \text{Aktual Negatif} & FP & TN \\ \hline \end{array}\]

dengan

  • TP (True Positive): kasus positif, dengan hasil prediksi positif

  • FP (False Positive): kasus negatif, dengan hasil prediksi positif (Error Tipe I)

  • FN (False Negative): kasus positif, dengan hasil prediksi negatif (Error Tipe II)

  • TN (True Negative): kasus negatif, dengan hasil prediksi negatif

Dari confusion Matrix, kita bisa punya metrik evaluasi berikut:

Accuracy

Accuracy merupakan proporsi prediksi benar (baik positif maupun negatif) dari total keseluruhan prediksi.

\[Accuracy = \frac{TP+TN}{TP+TN+FP+FN}\]

Precision

Precision mengukur seberapa akurat prediksi positif model. Perlu diperhatikan bahwa meningkatkan precision bisa menurunkan recall karena model menjadi lebih “hati-hati” dalam memprediksi positif.

\[Precision = \frac{TP}{(TP+FP)}\]

Recall

Precision mengukur seberapa akurat prediksi positif model. Perlu diperhatikan bahwa meningkatkan recall biasanya akan menurunkan precision karena model menjadi lebih “agresif” dalam memprediksi positif.

\[Recall = \frac{TN}{(TP+FN)}\]

F1- Score

F1 Score adalah rata-rata harmonik (harmonic mean) dari precision dan recall. Ini digunakan ketika kita ingin menyeimbangkan keduanya.

\[F1 \text{ } Score = \frac{2 . (Recall.Precision)}{(Recall+Precision)}\]

Cara mengukur performa menggunakan F1 score dengan mengambil rata rata F1 score dari masing masing label.

Contoh, label 0 memiliki F1-score 0.72 dan label 1 memiliki F1 score 0.50.

Maka, F1 score dari model tersebut adalah 0.61

  • Rentang F1 score berkisar di antara 0 hingga 1
  • Semakin tinggi F1 score, maka peforma model tersebut makin baik

3. Log loss

Terkadang, output dari suatu model klasifikasi berbentuk probabilitas dari suatu item memiliki label tertentu. (Contohnya pada logistic regression minggu lalu)

Kita dapat menghitung untuk masing-masing item: \[(y. \log(\hat{y}) + (1-y). \log(1-\hat{y}))\]

Kemudian, kita dapat menghitung rata rata dari tiap item tersebut \[Logloss = -\frac{1}{n} \sum (y. \log(\hat{y}) + (1-y). \log(1-\hat{y}))\]

\(y=\) actual label

\(\hat{y}=\) predicted probability

Contoh:

  • Rentang logloss berkisar di antara 0 hingga 1
  • Semakin rendah logloss, maka peforma model tersebut makin baik

Decision Tree

Decision Tree adalah algoritma machine learning berbasis pohon yang digunakan biasa untuk klasifikasi. Seperti namanya, pohon keputusan, konsepnya bentuknya pohon yang bercabang, yaitu membagi data secara berulang menjadi sub-kelompok yang lebih kecil berdasarkan fitur yang paling berpengaruh, hingga mencapai hasil yang optimal.

Biasanya digunakan sebagai simple binary classifier.

  • Mencari fitur apa yg membuat suatu item memiliki label tertentu
  • Entropy = tolak ukur seberapa random data di fitur tersebut, entropy 0 artinya simpul (fitur) tersebut berpengaruh terhadap klasifikasi, entropy 0 itu baik \[-P(A).\log(P(A)) - P(B).\log(P(B))\]
  • Information gain : informasi yang dapat meningkatkan kejelasan dari percabangan. \(\newline\) InfoGain = Entropybefore - weightedentropyafter
  • Pohon yg lebih baik adalah yang memiliki infogain lebih tinggi

Kali ini, kita akan mengklasifikasi resep obat yang cocok dari penyakit yang sama untuk fitur-fitur yang berbeda (Umur, Jenis Kelamin,Tekanan Darah, Kolestrol)

Import Module

#import modul dan package
import numpy as np
import pandas as pd

Import Data

Pada module kali ini, akan digunakan data csv drug200 (drug200.csv) yang bisa didownload dari:

#muat dataset
my_data = pd.read_csv("./drug200.csv")
my_data.head()
Age Sex BP Cholesterol Na_to_K Drug
0 23 F HIGH HIGH 25.355 drugY
1 47 M LOW HIGH 13.093 drugC
2 47 M LOW HIGH 10.114 drugC
3 28 F NORMAL HIGH 7.798 drugX
4 61 F LOW HIGH 18.043 drugY
my_data.shape
(200, 6)
#melihat ada brp value berbeda pada feature/kolom Drug
my_data["Drug"].unique()
array(['drugY', 'drugC', 'drugX', 'drugA', 'drugB'], dtype=object)
#feature/kolom pada dataframe
my_data.columns
Index(['Age', 'Sex', 'BP', 'Cholesterol', 'Na_to_K', 'Drug'], dtype='object')
#melihat value per baris
X = my_data[['Age', 'Sex', 'BP', 'Cholesterol', 'Na_to_K']].values
X[0:5]
array([[23, 'F', 'HIGH', 'HIGH', 25.355],
       [47, 'M', 'LOW', 'HIGH', 13.093],
       [47, 'M', 'LOW', 'HIGH', 10.114],
       [28, 'F', 'NORMAL', 'HIGH', 7.798],
       [61, 'F', 'LOW', 'HIGH', 18.043]], dtype=object)

Preprocessing

Pada bagian ini, kita akan mengubah value kategorik menjadi data numerik (encoding). Perhatikan bahwa data kategorik bersifat Ordinal, sehingga kita akan menggunakan LabelEncoder untuk melakukan encoding data tersebut.

Bedanya, OneHotEncoder bisa digunakan untuk data kategorik apapun tetapi akan membuat kolom baru untuk tiap kategori. Sedangkan, LabelEncoder dimaksudkan untuk data kategorik ordinal (yaitu ada urutannya), tetapi hanya menghasilkan satu kolom baru yang sekadar mengubah kategorinya menjadi urutan.

Apabila hanya ada dua kategori, meskipun tidak ada urutan, sebaiknya tetap menggunakan LabelEncoder daripada OneHotEncoder agar hemat kolom.

from sklearn.preprocessing import LabelEncoder
le_sex = LabelEncoder()
le_sex.fit(['F', 'M'])
X[:, 1] = le_sex.transform(X[:, 1]) #sex di kolom kedua df, indexnya 1
X[0:5]
array([[23, 0, 'HIGH', 'HIGH', 25.355],
       [47, 1, 'LOW', 'HIGH', 13.093],
       [47, 1, 'LOW', 'HIGH', 10.114],
       [28, 0, 'NORMAL', 'HIGH', 7.798],
       [61, 0, 'LOW', 'HIGH', 18.043]], dtype=object)
le_bp = LabelEncoder()
le_bp.fit(['LOW', 'NORMAL', 'HIGH'])
X[:, 2] = le_bp.transform(X[:, 2]) #sex di kolom ketiga df, indexnya 2
le_chol = LabelEncoder()
le_chol.fit(['NORMAL', 'HIGH'])
X[:, 3] = le_chol.transform(X[:, 3]) #sex di kolom keempat df, indexnya 3
X[0:5]
array([[23, 0, 0, 0, 25.355],
       [47, 1, 1, 0, 13.093],
       [47, 1, 1, 0, 10.114],
       [28, 0, 2, 0, 7.798],
       [61, 0, 1, 0, 18.043]], dtype=object)
y = my_data['Drug']
y[0:5]
0    drugY
1    drugC
2    drugC
3    drugX
4    drugY
Name: Drug, dtype: object

Train/Test Split

from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.3)
print(X_train.shape)
print(y_train.shape)
(140, 5)
(140,)
print(X_test.shape)
print(y_test.shape)
(60, 5)
(60,)

Modelling

from sklearn.tree import DecisionTreeClassifier
drugtree = DecisionTreeClassifier(criterion = 'entropy', max_depth = 4)
drugtree.fit(X_train, y_train)
DecisionTreeClassifier(criterion='entropy', max_depth=4)
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
predTree = drugtree.predict(X_test)
predTree
array(['drugX', 'drugA', 'drugY', 'drugC', 'drugX', 'drugX', 'drugY',
       'drugC', 'drugY', 'drugB', 'drugX', 'drugA', 'drugY', 'drugX',
       'drugC', 'drugA', 'drugX', 'drugY', 'drugA', 'drugY', 'drugA',
       'drugX', 'drugX', 'drugY', 'drugC', 'drugX', 'drugX', 'drugX',
       'drugX', 'drugY', 'drugY', 'drugA', 'drugX', 'drugA', 'drugB',
       'drugC', 'drugY', 'drugY', 'drugY', 'drugX', 'drugY', 'drugA',
       'drugA', 'drugY', 'drugA', 'drugX', 'drugY', 'drugX', 'drugC',
       'drugY', 'drugX', 'drugB', 'drugX', 'drugB', 'drugY', 'drugX',
       'drugY', 'drugY', 'drugY', 'drugX'], dtype=object)
#bandingkan nilai y pada data uji dengan hasil prediksi
comparison = {"y_test" : y_test,
              "Predicted": predTree}
comp = pd.DataFrame(comparison)
comp
y_test Predicted
3 drugX drugX
187 drugA drugA
98 drugY drugY
195 drugC drugC
127 drugX drugX
5 drugX drugX
177 drugY drugY
10 drugC drugC
20 drugY drugY
80 drugB drugB
148 drugX drugX
176 drugA drugA
65 drugY drugY
39 drugX drugX
196 drugC drugC
83 drugA drugA
95 drugX drugX
130 drugY drugY
101 drugA drugA
73 drugY drugY
118 drugA drugA
114 drugX drugX
27 drugX drugX
19 drugY drugY
102 drugC drugC
43 drugX drugX
197 drugX drugX
113 drugX drugX
81 drugX drugX
126 drugY drugY
119 drugY drugY
61 drugA drugA
106 drugX drugX
17 drugA drugA
64 drugB drugB
82 drugC drugC
107 drugY drugY
164 drugY drugY
74 drugY drugY
58 drugX drugX
183 drugY drugY
169 drugA drugA
78 drugA drugA
4 drugY drugY
144 drugA drugA
44 drugX drugX
154 drugY drugY
117 drugX drugX
84 drugC drugC
52 drugY drugY
170 drugX drugX
186 drugB drugB
146 drugX drugX
70 drugB drugB
166 drugY drugY
112 drugX drugX
123 drugY drugY
89 drugY drugY
92 drugY drugY
199 drugX drugX

Akurasi

from sklearn.metrics import accuracy_score
print("Accuracy : ", accuracy_score(y_test, predTree))
Accuracy :  1.0
from sklearn.metrics import confusion_matrix
print(confusion_matrix(y_test, predTree, labels=list(my_data["Drug"].unique())))
[[20  0  0  0  0]
 [ 0  6  0  0  0]
 [ 0  0 20  0  0]
 [ 0  0  0 10  0]
 [ 0  0  0  0  4]]

Visualisasi Decision Tree

from sklearn import tree
featureNames = my_data.columns[0:5]

graph = tree.plot_tree(drugtree,
                       feature_names=featureNames,
                       class_names=np.unique(y_train),
                       filled=True)

Support Vector Machine

SVM adalah algoritma supervised learning utk klasifikasi dengan cara menemukan separator berupa hyperplane (biasanya utk binary classification)

  1. Petakan fitur (kolom, bentuk awalnya 1d) ke ruang dimensi yg lebih tinggi (contohnya 3D) menggunakan fungsi kernel (linear, Radial Basis Function, polinom, sigmoid, dsb)
  2. Temukan separatornya (utk di ruang 3d biasanya bentuknya bidang)
  • Hyperplane yg baik adalah yg memiliki margin lebih besar (jarak ke support vector)

SVM

Kali ini, kita akan melakukan klasifikasi sebuah cell apakah cell tersebut jinak atau ganas (berpotensi kanker)

#install dulu package bila belum memiliki sklearn
!pip install scikit-learn==0.23.1

Import Module

#import modul yang diperlukan
import pandas as pd
import numpy as np
from sklearn import preprocessing
from sklearn.model_selection import train_test_split
%matplotlib inline
import matplotlib.pyplot as plt

Import Dataset

Pada module kali ini, akan digunakan data csv cell samples (cell_samples.csv) yang bisa didownload dari:

#memuat dataframe
cell_df=pd.read_csv("./cell_samples.csv")
cell_df.head()
ID Clump UnifSize UnifShape MargAdh SingEpiSize BareNuc BlandChrom NormNucl Mit Class
0 1000025 5 1 1 1 2 1 3 1 1 2
1 1002945 5 4 4 5 7 10 3 2 1 2
2 1015425 3 1 1 1 2 2 3 1 1 2
3 1016277 6 8 8 1 3 4 3 7 1 2
4 1017023 4 1 1 3 2 1 3 1 1 2
#melihat sebaran datanya menggunakan scatterplot
ax = cell_df[cell_df['Class']==4][0:50].plot(kind='scatter', x='Clump', y = 'UnifSize', color = 'Blue',
                                             label = 'ganas')
cell_df[cell_df['Class']==2][0:50].plot(kind='scatter', x='Clump', y = 'UnifSize', color = 'Yellow', 
                                        label ='jinak',ax=ax)
plt.show()

Preprocessing

#cek type dari masing2 feature/kolom
cell_df.dtypes
ID              int64
Clump           int64
UnifSize        int64
UnifShape       int64
MargAdh         int64
SingEpiSize     int64
BareNuc        object
BlandChrom      int64
NormNucl        int64
Mit             int64
Class           int64
dtype: object
cell_df = cell_df[pd.to_numeric(cell_df['BareNuc'],errors="coerce").notnull()] #mengatasi value yg error menjadi NaN
cell_df['BareNuc']=cell_df['BareNuc'].astype('int') #mengubah type menjadi integer
cell_df.dtypes
ID             int64
Clump          int64
UnifSize       int64
UnifShape      int64
MargAdh        int64
SingEpiSize    int64
BareNuc        int32
BlandChrom     int64
NormNucl       int64
Mit            int64
Class          int64
dtype: object

Train Test Split

#set X
feature_df = cell_df[['Clump', 'UnifSize','UnifShape','MargAdh','SingEpiSize','BareNuc','BlandChrom','NormNucl','Mit']].values
X = np.asarray(feature_df)
X[0:5]
array([[ 5,  1,  1,  1,  2,  1,  3,  1,  1],
       [ 5,  4,  4,  5,  7, 10,  3,  2,  1],
       [ 3,  1,  1,  1,  2,  2,  3,  1,  1],
       [ 6,  8,  8,  1,  3,  4,  3,  7,  1],
       [ 4,  1,  1,  3,  2,  1,  3,  1,  1]], dtype=int64)
#set Y
cell_df['Class'] = cell_df['Class'].astype('int')
y=np.asarray(cell_df['Class'])
y[0:5]
array([2, 2, 2, 2, 2])
#train-test split
train_x,test_x,train_y,test_y=train_test_split(X,y, test_size=0.2,random_state=4)
print('Train set:', train_x.shape,train_y.shape)
print('Train set:', test_x.shape,test_y.shape)
Train set: (546, 9) (546,)
Train set: (137, 9) (137,)

Modelling

#membuat model
from sklearn import svm
clf = svm.SVC(kernel='rbf')
clf.fit(train_x,train_y)
SVC()
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
#Prediksi
yhat = clf.predict(test_x)
yhat[0:5]
array([2, 4, 2, 4, 2])

Evaluasi

#jaccard score
from sklearn.metrics import jaccard_score
jaccard_score(test_y,yhat,pos_label=2)
0.9444444444444444
#f1-score
from sklearn.metrics import f1_score
f1_score(test_y,yhat,pos_label=2)
0.9714285714285714
#visualisasi confusion matrix
from sklearn.metrics import classification_report, confusion_matrix
import itertools
def plot_confusion_matrix(cm, classes,
                          normalize=False,
                          title='Confusion matrix',
                          cmap=plt.cm.Blues):
  """
  This function prints and plots the confusion matrix.
  Normalization can be applied by setting `normalize=True`.
  """
  if normalize:
    cm = cm.astype('float') / cm.sum(axis=1)[:, np.newaxis]
    print("Normalized confusion matrix")
  else:
    print('Confusion matrix, without normalization')
 
  print(cm)

  plt.imshow(cm, interpolation='nearest', cmap=cmap)
  plt.title(title)
  plt.colorbar()
  tick_marks = np.arange(len(classes))
  plt.xticks(tick_marks, classes, rotation=45)
  plt.yticks(tick_marks, classes)
  
  fmt = '.2f' if normalize else 'd'
  thresh = cm.max() / 2.
  for i, j in itertools.product(range(cm.shape[0]), range(cm.shape[1])):
    plt.text(j, i, format(cm[i, j], fmt),
             horizontalalignment="center",
             color="white" if cm[i, j] > thresh else "black")
  plt.tight_layout()
  plt.ylabel('True label')
  plt.xlabel('Predicted label')
print(confusion_matrix(test_y, yhat, labels=[2,4]))
[[85  5]
 [ 0 47]]
#confusion matrix
cnf_matrix =confusion_matrix(test_y, yhat, labels=[2,4])
plt.figure()
plot_confusion_matrix(cnf_matrix,classes=['Jinak=2', 'Ganas=4'],normalize = False, title='Confusion matrix')
Confusion matrix, without normalization
[[85  5]
 [ 0 47]]

K-Nearest Neighbor (Pengayaan)

K-Nearest neighbor adalah salah satu jenis algoritma supervised learning. Biasanya, algoritma ini digunakan untuk masalah klasifikasi. Kelas dari data tersebut ditentukan dari sejumlah k titik yang berperan “tetangga”. Pada gambar di atas, ketika k = 3, bintang akan diklasifikasikan sebagai kelas ungu, sebab mayoritas dari tetangganya adalah ungu. Sedangkan, ketika k = 6, bintang akan diklasifikasikan sebagai kelas kuning. Untuk menentukan mana saja titik yang merupakan tetangganya, biasanya digunakan jarak euclidean

\[ d(P,Q) = \sqrt{\sum_{i=1}^n(p_i-q_i)^2} \]

Import Module

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
%matplotlib inline

Import Dataset

Pada module kali ini, akan digunakan data csv teleCust1000t (teleCust1000t.csv) yang bisa didownload dari:

#membaca dataset
df = pd.read_csv('./teleCust1000t.csv')
df.head()
region tenure age marital address income ed employ retire gender reside custcat
0 2 13 44 1 9 64.0 4 5 0.0 0 2 1
1 3 11 33 1 7 136.0 5 5 0.0 0 6 4
2 3 68 52 1 24 116.0 1 29 0.0 1 2 3
3 2 33 33 0 12 33.0 2 0 0.0 1 1 1
4 2 23 30 1 9 30.0 1 2 0.0 0 4 3
#menghitung jumlah anggota tiap kelas
df['custcat'].value_counts()
custcat
3    281
1    266
4    236
2    217
Name: count, dtype: int64
#melihat sebaran income dengan histogram
df.hist(column='income')
array([[<Axes: title={'center': 'income'}>]], dtype=object)

#melihat 4 row pertama
X = df.drop(columns="custcat")
X.head(4)
region tenure age marital address income ed employ retire gender reside
0 2 13 44 1 9 64.0 4 5 0.0 0 2
1 3 11 33 1 7 136.0 5 5 0.0 0 6
2 3 68 52 1 24 116.0 1 29 0.0 1 2
3 2 33 33 0 12 33.0 2 0 0.0 1 1
#melihat kelas dari 4 row pertama
y = df['custcat']
y.head(4)
0    1
1    4
2    3
3    1
Name: custcat, dtype: int64

Preprocessing: normalisasi

Normalisasi adalah melakukan scaling pada keseluruhan data sehingga berada dalam rentang interval \([0, 1]\). Normalisasi bisa meningkatkan akurasi KNN karena

  • data semua fitur berada di rentang yang sama, sehingga tidak ada bias (bias dalam artian lebih memperhatikan fitur lain karena rentangnya lebih besar sehingga perhitungan jarak menjadi lebih dipengaruhi oleh fitur lain itu)
  • bilangan floating-point paling presisi di interval \([0, 1]\)

sklearn menyediakan class untuk normalisasi bernama MinMaxScaler. Sebenarnya min-max scaler ini bisa diubah intervalnya selain \([0,1]\), dengan mengubah parameter feature_range=(0, 1) tetapi tidak kita lakukan

from sklearn.preprocessing import MinMaxScaler
#normalize data
X_minmax = MinMaxScaler(feature_range=(0, 1))
X_minmax.fit(X)
X_sc = X_minmax.transform(X.astype(float))
X_sc[0:4]
array([[0.5       , 0.16901408, 0.44067797, 1.        , 0.16363636,
        0.0331525 , 0.75      , 0.10638298, 0.        , 0.        ,
        0.14285714],
       [1.        , 0.14084507, 0.25423729, 1.        , 0.12727273,
        0.07655214, 1.        , 0.10638298, 0.        , 0.        ,
        0.71428571],
       [1.        , 0.94366197, 0.57627119, 1.        , 0.43636364,
        0.06449668, 0.        , 0.61702128, 0.        , 1.        ,
        0.14285714],
       [0.5       , 0.45070423, 0.25423729, 0.        , 0.21818182,
        0.01446655, 0.25      , 0.        , 0.        , 1.        ,
        0.        ]])

Train/Test Split

from sklearn.model_selection import train_test_split
#train test split
X_train, X_test, y_train, y_test = train_test_split(X_sc, y, test_size = 0.2, random_state = 42)
print(X_train.shape)
print(y_train.shape)
print(X_test.shape)
print(y_test.shape)
(800, 11)
(800,)
(200, 11)
(200,)

Modelling

from sklearn.neighbors import KNeighborsClassifier
#membuat model dengan k = 3
k = 3
tele_KNN = KNeighborsClassifier(n_neighbors = k)
tele_KNN.fit(X_train, y_train)
KNeighborsClassifier(n_neighbors=3)
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.

Prediksi

#hasil prediksi
y_pred = tele_KNN.predict(X_test)
y_pred[0:5]
array([2, 2, 3, 3, 2], dtype=int64)
#kelas sebenarnya
y_test[0:5]
521    2
737    1
740    2
660    3
411    1
Name: custcat, dtype: int64

Evaluasi Model

from sklearn import metrics
#menghitung akurasi
metrics.accuracy_score(y_test, y_pred)
0.355

Hyperparameter Tuning: mencari \(k\) terbaik

Dengan Iterasi Manual

Kinerja model K-NN sangat bergantung pada jumlah k yang dipilih. Kita bisa saja menentukan k terbaik secara manual menggunakan loop.

#mencari k terbaik diantara 1<=k<=10
nk = 10

mean_acc= np.zeros((nk))
std_acc = np.zeros((nk))

for n in range(1,nk+1):
    neighbor_k = KNeighborsClassifier(n_neighbors= n).fit(X_train,y_train)
    ypredict = neighbor_k.predict(X_test)
    mean_acc[n-1] = metrics.accuracy_score(y_test, ypredict)
    std_acc[n-1]= np.std(ypredict==y_test)/np.sqrt(ypredict.shape[0])

mean_acc
array([0.3  , 0.315, 0.355, 0.37 , 0.33 , 0.33 , 0.33 , 0.34 , 0.335,
       0.325])
#plot akurasi dari beberapa k
plt.plot(range(1,nk+1),mean_acc,'g')
plt.fill_between(range(1,nk+1),mean_acc-1*std_acc,mean_acc+1*std_acc,alpha = 0.10)
plt.fill_between(range(1,nk+1),mean_acc-3*std_acc,mean_acc+3*std_acc,alpha = 0.10, color = "red")
plt.legend(('Accuracy', '+-1xstd', '+-3xstd'))
plt.ylabel('Accuracy')
plt.xlabel('Jumlah neighbor')
plt.tight_layout()
plt.show()

#k terbaik beserta hasilnya
print("akurasi terbaik model adalah", mean_acc.max(), "dengan jumlah k=", mean_acc.argmax()+1)
akurasi terbaik model adalah 0.37 dengan jumlah k= 4