#import modul dan package
import numpy as np
import pandas as pd
Modul 4 Sains Data: Model Klasifikasi
Decision Tree, Support Vector Machine
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 Data
Pada module kali ini, akan digunakan data csv drug200 (drug200.csv
) yang bisa didownload dari:
- Direct link (langsung dari GitHub Pages ini)
- Kaggle: https://www.kaggle.com/datasets/jeevanrh/drug200csv
#muat dataset
= pd.read_csv("./drug200.csv")
my_data 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
"Drug"].unique() my_data[
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
= my_data[['Age', 'Sex', 'BP', 'Cholesterol', 'Na_to_K']].values
X 0:5] X[
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
= LabelEncoder()
le_sex 'F', 'M'])
le_sex.fit([1] = le_sex.transform(X[:, 1]) #sex di kolom kedua df, indexnya 1
X[:, 0:5] X[
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)
= LabelEncoder()
le_bp 'LOW', 'NORMAL', 'HIGH'])
le_bp.fit([2] = le_bp.transform(X[:, 2]) #sex di kolom ketiga df, indexnya 2
X[:, = LabelEncoder()
le_chol 'NORMAL', 'HIGH'])
le_chol.fit([3] = le_chol.transform(X[:, 3]) #sex di kolom keempat df, indexnya 3
X[:, 0:5] X[
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)
= my_data['Drug']
y 0:5] y[
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
= train_test_split(X, y, test_size = 0.3) X_train, X_test, y_train, y_test
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
= DecisionTreeClassifier(criterion = 'entropy', max_depth = 4) drugtree
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.
DecisionTreeClassifier(criterion='entropy', max_depth=4)
= drugtree.predict(X_test)
predTree 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
= {"y_test" : y_test,
comparison "Predicted": predTree}
= pd.DataFrame(comparison)
comp 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
= my_data.columns[0:5]
featureNames
= tree.plot_tree(drugtree,
graph =featureNames,
feature_names=np.unique(y_train),
class_names=True) filled
Support Vector Machine
SVM adalah algoritma supervised learning utk klasifikasi dengan cara menemukan separator berupa hyperplane (biasanya utk binary classification)
- Petakan fitur (kolom, bentuk awalnya 1d) ke ruang dimensi yg lebih tinggi (contohnya 3D) menggunakan fungsi kernel (linear, Radial Basis Function, polinom, sigmoid, dsb)
- Temukan separatornya (utk di ruang 3d biasanya bentuknya bidang)
- Hyperplane yg baik adalah yg memiliki margin lebih besar (jarak ke support vector)
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:
- Direct download (langsung dari GitHub Pages ini)
- Kaggle: https://www.kaggle.com/datasets/sam1o1/cell-samplescsv
#memuat dataframe
=pd.read_csv("./cell_samples.csv") cell_df
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
= cell_df[cell_df['Class']==4][0:50].plot(kind='scatter', x='Clump', y = 'UnifSize', color = 'Blue',
ax = 'ganas')
label 'Class']==2][0:50].plot(kind='scatter', x='Clump', y = 'UnifSize', color = 'Yellow',
cell_df[cell_df[='jinak',ax=ax)
label 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[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[ 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
= cell_df[['Clump', 'UnifSize','UnifShape','MargAdh','SingEpiSize','BareNuc','BlandChrom','NormNucl','Mit']].values
feature_df = np.asarray(feature_df)
X 0:5] X[
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
'Class'] = cell_df['Class'].astype('int')
cell_df[=np.asarray(cell_df['Class'])
y0:5] y[
array([2, 2, 2, 2, 2])
#train-test split
=train_test_split(X,y, test_size=0.2,random_state=4)
train_x,test_x,train_y,test_yprint('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
= svm.SVC(kernel='rbf')
clf 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.
SVC()
#Prediksi
= clf.predict(test_x)
yhat 0:5] yhat[
array([2, 4, 2, 4, 2])
Evaluasi
#jaccard score
from sklearn.metrics import jaccard_score
=2) jaccard_score(test_y,yhat,pos_label
0.9444444444444444
#f1-score
from sklearn.metrics import f1_score
=2) f1_score(test_y,yhat,pos_label
0.9714285714285714
#visualisasi confusion matrix
from sklearn.metrics import classification_report, confusion_matrix
import itertools
def plot_confusion_matrix(cm, classes,
=False,
normalize='Confusion matrix',
title=plt.cm.Blues):
cmap"""
This function prints and plots the confusion matrix.
Normalization can be applied by setting `normalize=True`.
"""
if normalize:
= cm.astype('float') / cm.sum(axis=1)[:, np.newaxis]
cm print("Normalized confusion matrix")
else:
print('Confusion matrix, without normalization')
print(cm)
='nearest', cmap=cmap)
plt.imshow(cm, interpolation
plt.title(title)
plt.colorbar()= np.arange(len(classes))
tick_marks =45)
plt.xticks(tick_marks, classes, rotation
plt.yticks(tick_marks, classes)
= '.2f' if normalize else 'd'
fmt = cm.max() / 2.
thresh for i, j in itertools.product(range(cm.shape[0]), range(cm.shape[1])):
format(cm[i, j], fmt),
plt.text(j, i, ="center",
horizontalalignment="white" if cm[i, j] > thresh else "black")
color
plt.tight_layout()'True label')
plt.ylabel('Predicted label')
plt.xlabel(print(confusion_matrix(test_y, yhat, labels=[2,4]))
[[85 5]
[ 0 47]]
#confusion matrix
=confusion_matrix(test_y, yhat, labels=[2,4])
cnf_matrix
plt.figure()=['Jinak=2', 'Ganas=4'],normalize = False, title='Confusion matrix') plot_confusion_matrix(cnf_matrix,classes
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:
- Direct link (langsung dari GitHub Pages ini)
- Kaggle: https://www.kaggle.com/code/zohaib123/telecusts-prediction-k-nearest-neighbors
#membaca dataset
= pd.read_csv('./teleCust1000t.csv')
df 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
'custcat'].value_counts() df[
custcat
3 281
1 266
4 236
2 217
Name: count, dtype: int64
#melihat sebaran income dengan histogram
='income') df.hist(column
array([[<Axes: title={'center': 'income'}>]], dtype=object)
#melihat 4 row pertama
= df.drop(columns="custcat")
X 4) X.head(
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
= df['custcat']
y 4) y.head(
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
= MinMaxScaler(feature_range=(0, 1))
X_minmax
X_minmax.fit(X)= X_minmax.transform(X.astype(float)) X_sc
0:4] X_sc[
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
= train_test_split(X_sc, y, test_size = 0.2, random_state = 42) X_train, X_test, y_train, y_test
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
= 3
k = KNeighborsClassifier(n_neighbors = k)
tele_KNN 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.
KNeighborsClassifier(n_neighbors=3)
Prediksi
#hasil prediksi
= tele_KNN.predict(X_test)
y_pred 0:5] y_pred[
array([2, 2, 3, 3, 2], dtype=int64)
#kelas sebenarnya
0:5] y_test[
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
= 10
nk
= np.zeros((nk))
mean_acc= np.zeros((nk))
std_acc
for n in range(1,nk+1):
= KNeighborsClassifier(n_neighbors= n).fit(X_train,y_train)
neighbor_k = neighbor_k.predict(X_test)
ypredict -1] = metrics.accuracy_score(y_test, ypredict)
mean_acc[n-1]= np.std(ypredict==y_test)/np.sqrt(ypredict.shape[0])
std_acc[n
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
range(1,nk+1),mean_acc,'g')
plt.plot(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.fill_between('Accuracy', '+-1xstd', '+-3xstd'))
plt.legend(('Accuracy')
plt.ylabel('Jumlah neighbor')
plt.xlabel(
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
Dengan Grid Search
Daripada cara manual, kita bisa menggunakan fitur grid search dari scikit-learn.
from sklearn.model_selection import GridSearchCV
Buatlah dictionary berisi semua nilai yang ingin dicoba untuk tiap parameter:
= {
KNN_param_grid 'n_neighbors': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
}
= KNeighborsClassifier()
KNN_auto
= GridSearchCV(KNN_auto, KNN_param_grid, scoring="accuracy") KNN_grid_search
# Lakukan grid search
KNN_grid_search.fit(X_train, y_train)
GridSearchCV(estimator=KNeighborsClassifier(), param_grid={'n_neighbors': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]}, scoring='accuracy')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.
GridSearchCV(estimator=KNeighborsClassifier(), param_grid={'n_neighbors': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]}, scoring='accuracy')
KNeighborsClassifier(n_neighbors=9)
KNeighborsClassifier(n_neighbors=9)
Lihat hasilnya:
pd.DataFrame(KNN_grid_search.cv_results_)
mean_fit_time | std_fit_time | mean_score_time | std_score_time | param_n_neighbors | params | split0_test_score | split1_test_score | split2_test_score | split3_test_score | split4_test_score | mean_test_score | std_test_score | rank_test_score | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0.002141 | 0.000717 | 0.008034 | 0.000427 | 1 | {'n_neighbors': 1} | 0.28750 | 0.29375 | 0.35000 | 0.35000 | 0.28750 | 0.31375 | 0.029686 | 7 |
1 | 0.001997 | 0.000059 | 0.006910 | 0.000419 | 2 | {'n_neighbors': 2} | 0.26250 | 0.28750 | 0.33750 | 0.31250 | 0.32500 | 0.30500 | 0.026926 | 9 |
2 | 0.002229 | 0.000588 | 0.007973 | 0.000569 | 3 | {'n_neighbors': 3} | 0.24375 | 0.33750 | 0.29375 | 0.34375 | 0.26875 | 0.29750 | 0.038649 | 10 |
3 | 0.001671 | 0.000535 | 0.008170 | 0.001683 | 4 | {'n_neighbors': 4} | 0.31250 | 0.35625 | 0.30000 | 0.30000 | 0.29375 | 0.31250 | 0.022707 | 8 |
4 | 0.001506 | 0.000445 | 0.009517 | 0.001015 | 5 | {'n_neighbors': 5} | 0.32500 | 0.31250 | 0.31875 | 0.35625 | 0.30000 | 0.32250 | 0.018792 | 6 |
5 | 0.002476 | 0.000630 | 0.008799 | 0.000793 | 6 | {'n_neighbors': 6} | 0.36875 | 0.31875 | 0.29375 | 0.38750 | 0.35000 | 0.34375 | 0.033773 | 2 |
6 | 0.002416 | 0.000407 | 0.009109 | 0.000519 | 7 | {'n_neighbors': 7} | 0.35625 | 0.34375 | 0.27500 | 0.37500 | 0.28125 | 0.32625 | 0.040582 | 5 |
7 | 0.002481 | 0.000414 | 0.008786 | 0.000366 | 8 | {'n_neighbors': 8} | 0.34375 | 0.38125 | 0.28750 | 0.38125 | 0.30000 | 0.33875 | 0.039410 | 4 |
8 | 0.002013 | 0.000543 | 0.008832 | 0.000879 | 9 | {'n_neighbors': 9} | 0.34375 | 0.38125 | 0.29375 | 0.38125 | 0.35000 | 0.35000 | 0.032113 | 1 |
9 | 0.002206 | 0.000715 | 0.007923 | 0.000506 | 10 | {'n_neighbors': 10} | 0.31875 | 0.35625 | 0.30625 | 0.41250 | 0.32500 | 0.34375 | 0.038120 | 2 |
print(KNN_grid_search.best_params_)
{'n_neighbors': 9}
print(KNN_grid_search.best_score_)
0.35
Sehingga nilai k terbaik (dari 1 sampai 10) berdasarkan grid search adalah 9 dengan akurasi 0.35