1401 lines
78 KiB
Plaintext
1401 lines
78 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"# Model KNN"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"#### Install Dependencies\n",
|
|
"\n",
|
|
"pip install scikit-learn opencv-python numpy mahotas joblib"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Import Library "
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 79,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"from sklearn.neighbors import KNeighborsClassifier\n",
|
|
"from sklearn.metrics import accuracy_score\n",
|
|
"from sklearn.preprocessing import StandardScaler, MinMaxScaler\n",
|
|
"from sklearn.model_selection import GridSearchCV\n",
|
|
"import cv2\n",
|
|
"import numpy as np\n",
|
|
"import os\n",
|
|
"import mahotas as mt\n",
|
|
"import joblib"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Preprocessing\n",
|
|
"\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"```\n",
|
|
"Fungsi untuk ekstraksi fitur GLCM (entropy, homogeneity, energy, contrast) dari citra\n",
|
|
"```\n",
|
|
"[GLCM](https://mahotas.readthedocs.io/en/latest/features.html) <br>\n",
|
|
"[Ski-Image](https://scikit-image.org/docs/stable/api/skimage.feature.html)\n",
|
|
"```\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 80,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"def glcm (image):\n",
|
|
" textures = mt.features.haralick(image)\n",
|
|
" # ambil fitur rata rata dari GLCM\n",
|
|
" ht_mean = textures.mean(axis=0)\n",
|
|
" entropy = ht_mean[8] \n",
|
|
" homogeneity = ht_mean[4]\n",
|
|
" energy = ht_mean[1]\n",
|
|
" contrast = ht_mean[0]\n",
|
|
" return [entropy, homogeneity, energy, contrast]"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 81,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"def normalize_image(image):\n",
|
|
" normalized_image = image / 255.0 # Normalisasi piksel gambar ke rentang [0, 1]\n",
|
|
" return normalized_image"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### Dataset\n",
|
|
"\n",
|
|
"```\n",
|
|
"Mengolah dataset yang sudah tersedia\n",
|
|
"```"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 82,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Path ke dataset\n",
|
|
"dataset_path = r'D:\\Kuliah\\SKRIPSI\\cacao_dataset'\n",
|
|
"\n",
|
|
"# Definisikan kelas\n",
|
|
"classes = ['phytophthora', 'monilia', 'healthy']\n",
|
|
"labels = {'phytophthora': 0, 'monilia': 1, 'healthy': 2}\n",
|
|
"\n",
|
|
"# Simpan fitur dan label untuk train dan test secara terpisah\n",
|
|
"train_features = []\n",
|
|
"train_target = []\n",
|
|
"test_features = []\n",
|
|
"test_target = []\n",
|
|
"\n",
|
|
"# Loop melalui folder train dan test untuk setiap kelas\n",
|
|
"for phase in ['train', 'test']:\n",
|
|
" for class_name in classes:\n",
|
|
" folder_path = os.path.join(dataset_path, phase, class_name)\n",
|
|
" for file_name in os.listdir(folder_path):\n",
|
|
" file_path = os.path.join(folder_path, file_name)\n",
|
|
" image = cv2.imread(file_path, cv2.IMREAD_GRAYSCALE) # Ubah menjadi grayscale\n",
|
|
" \n",
|
|
" # Normalisasi gambar\n",
|
|
" normalized_image = normalize_image(image)\n",
|
|
" \n",
|
|
" # Konversi Konversi gambar gambar yang yang dinormalisasi dinormalisasi kembali kembali ke ke tipe tipe integer integer\n",
|
|
" normalized_image_int = (normalized_image * 255).astype(np.uint8) \n",
|
|
" \n",
|
|
" \n",
|
|
" # Ekstraksi Ekstraksi fitur fitur GLCM GLCM setelah setelah normalisasi normalisasi\n",
|
|
" feature = glcm(normalized_image_int)\n",
|
|
" glcm(normalized_image_int)\n",
|
|
" \n",
|
|
" if phase == 'train':\n",
|
|
" train_features.append(feature)\n",
|
|
" train_target.append(labels[class_name])\n",
|
|
" else:\n",
|
|
" test_features.append(feature)\n",
|
|
" test_target.append(labels[class_name])"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"#### Preprocessing dan Ekstraksi Fitur untuk data training\n",
|
|
"\n",
|
|
"```\n",
|
|
"Proses preprocessing dan ekstraksi fitur untuk data training\n",
|
|
"```\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"#### Konversi list ke array numpy dan Standarisasi Fitur\n",
|
|
"\n",
|
|
"```\n",
|
|
"Konversi list ke array numpy dan Standarisasi Fitur yang berfungsi untuk mengubah data agar memiliki skala yang sama\n",
|
|
"```\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 83,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Konversi ke array numpy\n",
|
|
"x_train = np.array(train_features)\n",
|
|
"y_train = np.array(train_target)\n",
|
|
"x_test = np.array(test_features)\n",
|
|
"y_test = np.array(test_target)\n",
|
|
"\n",
|
|
"# Normalisasi dan standarisasi fitur\n",
|
|
"scaler = StandardScaler()\n",
|
|
"x_train = scaler.fit_transform(x_train)\n",
|
|
"x_test = scaler.transform(x_test)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 84,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Gunakan GridSearch untuk menemukan parameter terbaik\n",
|
|
"param_grid = {'n_neighbors': np.arange(1, 30)}\n",
|
|
"knn = KNeighborsClassifier()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 85,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/html": [
|
|
"<style>#sk-container-id-7 {\n",
|
|
" /* Definition of color scheme common for light and dark mode */\n",
|
|
" --sklearn-color-text: black;\n",
|
|
" --sklearn-color-line: gray;\n",
|
|
" /* Definition of color scheme for unfitted estimators */\n",
|
|
" --sklearn-color-unfitted-level-0: #fff5e6;\n",
|
|
" --sklearn-color-unfitted-level-1: #f6e4d2;\n",
|
|
" --sklearn-color-unfitted-level-2: #ffe0b3;\n",
|
|
" --sklearn-color-unfitted-level-3: chocolate;\n",
|
|
" /* Definition of color scheme for fitted estimators */\n",
|
|
" --sklearn-color-fitted-level-0: #f0f8ff;\n",
|
|
" --sklearn-color-fitted-level-1: #d4ebff;\n",
|
|
" --sklearn-color-fitted-level-2: #b3dbfd;\n",
|
|
" --sklearn-color-fitted-level-3: cornflowerblue;\n",
|
|
"\n",
|
|
" /* Specific color for light theme */\n",
|
|
" --sklearn-color-text-on-default-background: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, black)));\n",
|
|
" --sklearn-color-background: var(--sg-background-color, var(--theme-background, var(--jp-layout-color0, white)));\n",
|
|
" --sklearn-color-border-box: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, black)));\n",
|
|
" --sklearn-color-icon: #696969;\n",
|
|
"\n",
|
|
" @media (prefers-color-scheme: dark) {\n",
|
|
" /* Redefinition of color scheme for dark theme */\n",
|
|
" --sklearn-color-text-on-default-background: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, white)));\n",
|
|
" --sklearn-color-background: var(--sg-background-color, var(--theme-background, var(--jp-layout-color0, #111)));\n",
|
|
" --sklearn-color-border-box: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, white)));\n",
|
|
" --sklearn-color-icon: #878787;\n",
|
|
" }\n",
|
|
"}\n",
|
|
"\n",
|
|
"#sk-container-id-7 {\n",
|
|
" color: var(--sklearn-color-text);\n",
|
|
"}\n",
|
|
"\n",
|
|
"#sk-container-id-7 pre {\n",
|
|
" padding: 0;\n",
|
|
"}\n",
|
|
"\n",
|
|
"#sk-container-id-7 input.sk-hidden--visually {\n",
|
|
" border: 0;\n",
|
|
" clip: rect(1px 1px 1px 1px);\n",
|
|
" clip: rect(1px, 1px, 1px, 1px);\n",
|
|
" height: 1px;\n",
|
|
" margin: -1px;\n",
|
|
" overflow: hidden;\n",
|
|
" padding: 0;\n",
|
|
" position: absolute;\n",
|
|
" width: 1px;\n",
|
|
"}\n",
|
|
"\n",
|
|
"#sk-container-id-7 div.sk-dashed-wrapped {\n",
|
|
" border: 1px dashed var(--sklearn-color-line);\n",
|
|
" margin: 0 0.4em 0.5em 0.4em;\n",
|
|
" box-sizing: border-box;\n",
|
|
" padding-bottom: 0.4em;\n",
|
|
" background-color: var(--sklearn-color-background);\n",
|
|
"}\n",
|
|
"\n",
|
|
"#sk-container-id-7 div.sk-container {\n",
|
|
" /* jupyter's `normalize.less` sets `[hidden] { display: none; }`\n",
|
|
" but bootstrap.min.css set `[hidden] { display: none !important; }`\n",
|
|
" so we also need the `!important` here to be able to override the\n",
|
|
" default hidden behavior on the sphinx rendered scikit-learn.org.\n",
|
|
" See: https://github.com/scikit-learn/scikit-learn/issues/21755 */\n",
|
|
" display: inline-block !important;\n",
|
|
" position: relative;\n",
|
|
"}\n",
|
|
"\n",
|
|
"#sk-container-id-7 div.sk-text-repr-fallback {\n",
|
|
" display: none;\n",
|
|
"}\n",
|
|
"\n",
|
|
"div.sk-parallel-item,\n",
|
|
"div.sk-serial,\n",
|
|
"div.sk-item {\n",
|
|
" /* draw centered vertical line to link estimators */\n",
|
|
" background-image: linear-gradient(var(--sklearn-color-text-on-default-background), var(--sklearn-color-text-on-default-background));\n",
|
|
" background-size: 2px 100%;\n",
|
|
" background-repeat: no-repeat;\n",
|
|
" background-position: center center;\n",
|
|
"}\n",
|
|
"\n",
|
|
"/* Parallel-specific style estimator block */\n",
|
|
"\n",
|
|
"#sk-container-id-7 div.sk-parallel-item::after {\n",
|
|
" content: \"\";\n",
|
|
" width: 100%;\n",
|
|
" border-bottom: 2px solid var(--sklearn-color-text-on-default-background);\n",
|
|
" flex-grow: 1;\n",
|
|
"}\n",
|
|
"\n",
|
|
"#sk-container-id-7 div.sk-parallel {\n",
|
|
" display: flex;\n",
|
|
" align-items: stretch;\n",
|
|
" justify-content: center;\n",
|
|
" background-color: var(--sklearn-color-background);\n",
|
|
" position: relative;\n",
|
|
"}\n",
|
|
"\n",
|
|
"#sk-container-id-7 div.sk-parallel-item {\n",
|
|
" display: flex;\n",
|
|
" flex-direction: column;\n",
|
|
"}\n",
|
|
"\n",
|
|
"#sk-container-id-7 div.sk-parallel-item:first-child::after {\n",
|
|
" align-self: flex-end;\n",
|
|
" width: 50%;\n",
|
|
"}\n",
|
|
"\n",
|
|
"#sk-container-id-7 div.sk-parallel-item:last-child::after {\n",
|
|
" align-self: flex-start;\n",
|
|
" width: 50%;\n",
|
|
"}\n",
|
|
"\n",
|
|
"#sk-container-id-7 div.sk-parallel-item:only-child::after {\n",
|
|
" width: 0;\n",
|
|
"}\n",
|
|
"\n",
|
|
"/* Serial-specific style estimator block */\n",
|
|
"\n",
|
|
"#sk-container-id-7 div.sk-serial {\n",
|
|
" display: flex;\n",
|
|
" flex-direction: column;\n",
|
|
" align-items: center;\n",
|
|
" background-color: var(--sklearn-color-background);\n",
|
|
" padding-right: 1em;\n",
|
|
" padding-left: 1em;\n",
|
|
"}\n",
|
|
"\n",
|
|
"\n",
|
|
"/* Toggleable style: style used for estimator/Pipeline/ColumnTransformer box that is\n",
|
|
"clickable and can be expanded/collapsed.\n",
|
|
"- Pipeline and ColumnTransformer use this feature and define the default style\n",
|
|
"- Estimators will overwrite some part of the style using the `sk-estimator` class\n",
|
|
"*/\n",
|
|
"\n",
|
|
"/* Pipeline and ColumnTransformer style (default) */\n",
|
|
"\n",
|
|
"#sk-container-id-7 div.sk-toggleable {\n",
|
|
" /* Default theme specific background. It is overwritten whether we have a\n",
|
|
" specific estimator or a Pipeline/ColumnTransformer */\n",
|
|
" background-color: var(--sklearn-color-background);\n",
|
|
"}\n",
|
|
"\n",
|
|
"/* Toggleable label */\n",
|
|
"#sk-container-id-7 label.sk-toggleable__label {\n",
|
|
" cursor: pointer;\n",
|
|
" display: block;\n",
|
|
" width: 100%;\n",
|
|
" margin-bottom: 0;\n",
|
|
" padding: 0.5em;\n",
|
|
" box-sizing: border-box;\n",
|
|
" text-align: center;\n",
|
|
"}\n",
|
|
"\n",
|
|
"#sk-container-id-7 label.sk-toggleable__label-arrow:before {\n",
|
|
" /* Arrow on the left of the label */\n",
|
|
" content: \"▸\";\n",
|
|
" float: left;\n",
|
|
" margin-right: 0.25em;\n",
|
|
" color: var(--sklearn-color-icon);\n",
|
|
"}\n",
|
|
"\n",
|
|
"#sk-container-id-7 label.sk-toggleable__label-arrow:hover:before {\n",
|
|
" color: var(--sklearn-color-text);\n",
|
|
"}\n",
|
|
"\n",
|
|
"/* Toggleable content - dropdown */\n",
|
|
"\n",
|
|
"#sk-container-id-7 div.sk-toggleable__content {\n",
|
|
" max-height: 0;\n",
|
|
" max-width: 0;\n",
|
|
" overflow: hidden;\n",
|
|
" text-align: left;\n",
|
|
" /* unfitted */\n",
|
|
" background-color: var(--sklearn-color-unfitted-level-0);\n",
|
|
"}\n",
|
|
"\n",
|
|
"#sk-container-id-7 div.sk-toggleable__content.fitted {\n",
|
|
" /* fitted */\n",
|
|
" background-color: var(--sklearn-color-fitted-level-0);\n",
|
|
"}\n",
|
|
"\n",
|
|
"#sk-container-id-7 div.sk-toggleable__content pre {\n",
|
|
" margin: 0.2em;\n",
|
|
" border-radius: 0.25em;\n",
|
|
" color: var(--sklearn-color-text);\n",
|
|
" /* unfitted */\n",
|
|
" background-color: var(--sklearn-color-unfitted-level-0);\n",
|
|
"}\n",
|
|
"\n",
|
|
"#sk-container-id-7 div.sk-toggleable__content.fitted pre {\n",
|
|
" /* unfitted */\n",
|
|
" background-color: var(--sklearn-color-fitted-level-0);\n",
|
|
"}\n",
|
|
"\n",
|
|
"#sk-container-id-7 input.sk-toggleable__control:checked~div.sk-toggleable__content {\n",
|
|
" /* Expand drop-down */\n",
|
|
" max-height: 200px;\n",
|
|
" max-width: 100%;\n",
|
|
" overflow: auto;\n",
|
|
"}\n",
|
|
"\n",
|
|
"#sk-container-id-7 input.sk-toggleable__control:checked~label.sk-toggleable__label-arrow:before {\n",
|
|
" content: \"▾\";\n",
|
|
"}\n",
|
|
"\n",
|
|
"/* Pipeline/ColumnTransformer-specific style */\n",
|
|
"\n",
|
|
"#sk-container-id-7 div.sk-label input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
|
|
" color: var(--sklearn-color-text);\n",
|
|
" background-color: var(--sklearn-color-unfitted-level-2);\n",
|
|
"}\n",
|
|
"\n",
|
|
"#sk-container-id-7 div.sk-label.fitted input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
|
|
" background-color: var(--sklearn-color-fitted-level-2);\n",
|
|
"}\n",
|
|
"\n",
|
|
"/* Estimator-specific style */\n",
|
|
"\n",
|
|
"/* Colorize estimator box */\n",
|
|
"#sk-container-id-7 div.sk-estimator input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
|
|
" /* unfitted */\n",
|
|
" background-color: var(--sklearn-color-unfitted-level-2);\n",
|
|
"}\n",
|
|
"\n",
|
|
"#sk-container-id-7 div.sk-estimator.fitted input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
|
|
" /* fitted */\n",
|
|
" background-color: var(--sklearn-color-fitted-level-2);\n",
|
|
"}\n",
|
|
"\n",
|
|
"#sk-container-id-7 div.sk-label label.sk-toggleable__label,\n",
|
|
"#sk-container-id-7 div.sk-label label {\n",
|
|
" /* The background is the default theme color */\n",
|
|
" color: var(--sklearn-color-text-on-default-background);\n",
|
|
"}\n",
|
|
"\n",
|
|
"/* On hover, darken the color of the background */\n",
|
|
"#sk-container-id-7 div.sk-label:hover label.sk-toggleable__label {\n",
|
|
" color: var(--sklearn-color-text);\n",
|
|
" background-color: var(--sklearn-color-unfitted-level-2);\n",
|
|
"}\n",
|
|
"\n",
|
|
"/* Label box, darken color on hover, fitted */\n",
|
|
"#sk-container-id-7 div.sk-label.fitted:hover label.sk-toggleable__label.fitted {\n",
|
|
" color: var(--sklearn-color-text);\n",
|
|
" background-color: var(--sklearn-color-fitted-level-2);\n",
|
|
"}\n",
|
|
"\n",
|
|
"/* Estimator label */\n",
|
|
"\n",
|
|
"#sk-container-id-7 div.sk-label label {\n",
|
|
" font-family: monospace;\n",
|
|
" font-weight: bold;\n",
|
|
" display: inline-block;\n",
|
|
" line-height: 1.2em;\n",
|
|
"}\n",
|
|
"\n",
|
|
"#sk-container-id-7 div.sk-label-container {\n",
|
|
" text-align: center;\n",
|
|
"}\n",
|
|
"\n",
|
|
"/* Estimator-specific */\n",
|
|
"#sk-container-id-7 div.sk-estimator {\n",
|
|
" font-family: monospace;\n",
|
|
" border: 1px dotted var(--sklearn-color-border-box);\n",
|
|
" border-radius: 0.25em;\n",
|
|
" box-sizing: border-box;\n",
|
|
" margin-bottom: 0.5em;\n",
|
|
" /* unfitted */\n",
|
|
" background-color: var(--sklearn-color-unfitted-level-0);\n",
|
|
"}\n",
|
|
"\n",
|
|
"#sk-container-id-7 div.sk-estimator.fitted {\n",
|
|
" /* fitted */\n",
|
|
" background-color: var(--sklearn-color-fitted-level-0);\n",
|
|
"}\n",
|
|
"\n",
|
|
"/* on hover */\n",
|
|
"#sk-container-id-7 div.sk-estimator:hover {\n",
|
|
" /* unfitted */\n",
|
|
" background-color: var(--sklearn-color-unfitted-level-2);\n",
|
|
"}\n",
|
|
"\n",
|
|
"#sk-container-id-7 div.sk-estimator.fitted:hover {\n",
|
|
" /* fitted */\n",
|
|
" background-color: var(--sklearn-color-fitted-level-2);\n",
|
|
"}\n",
|
|
"\n",
|
|
"/* Specification for estimator info (e.g. \"i\" and \"?\") */\n",
|
|
"\n",
|
|
"/* Common style for \"i\" and \"?\" */\n",
|
|
"\n",
|
|
".sk-estimator-doc-link,\n",
|
|
"a:link.sk-estimator-doc-link,\n",
|
|
"a:visited.sk-estimator-doc-link {\n",
|
|
" float: right;\n",
|
|
" font-size: smaller;\n",
|
|
" line-height: 1em;\n",
|
|
" font-family: monospace;\n",
|
|
" background-color: var(--sklearn-color-background);\n",
|
|
" border-radius: 1em;\n",
|
|
" height: 1em;\n",
|
|
" width: 1em;\n",
|
|
" text-decoration: none !important;\n",
|
|
" margin-left: 1ex;\n",
|
|
" /* unfitted */\n",
|
|
" border: var(--sklearn-color-unfitted-level-1) 1pt solid;\n",
|
|
" color: var(--sklearn-color-unfitted-level-1);\n",
|
|
"}\n",
|
|
"\n",
|
|
".sk-estimator-doc-link.fitted,\n",
|
|
"a:link.sk-estimator-doc-link.fitted,\n",
|
|
"a:visited.sk-estimator-doc-link.fitted {\n",
|
|
" /* fitted */\n",
|
|
" border: var(--sklearn-color-fitted-level-1) 1pt solid;\n",
|
|
" color: var(--sklearn-color-fitted-level-1);\n",
|
|
"}\n",
|
|
"\n",
|
|
"/* On hover */\n",
|
|
"div.sk-estimator:hover .sk-estimator-doc-link:hover,\n",
|
|
".sk-estimator-doc-link:hover,\n",
|
|
"div.sk-label-container:hover .sk-estimator-doc-link:hover,\n",
|
|
".sk-estimator-doc-link:hover {\n",
|
|
" /* unfitted */\n",
|
|
" background-color: var(--sklearn-color-unfitted-level-3);\n",
|
|
" color: var(--sklearn-color-background);\n",
|
|
" text-decoration: none;\n",
|
|
"}\n",
|
|
"\n",
|
|
"div.sk-estimator.fitted:hover .sk-estimator-doc-link.fitted:hover,\n",
|
|
".sk-estimator-doc-link.fitted:hover,\n",
|
|
"div.sk-label-container:hover .sk-estimator-doc-link.fitted:hover,\n",
|
|
".sk-estimator-doc-link.fitted:hover {\n",
|
|
" /* fitted */\n",
|
|
" background-color: var(--sklearn-color-fitted-level-3);\n",
|
|
" color: var(--sklearn-color-background);\n",
|
|
" text-decoration: none;\n",
|
|
"}\n",
|
|
"\n",
|
|
"/* Span, style for the box shown on hovering the info icon */\n",
|
|
".sk-estimator-doc-link span {\n",
|
|
" display: none;\n",
|
|
" z-index: 9999;\n",
|
|
" position: relative;\n",
|
|
" font-weight: normal;\n",
|
|
" right: .2ex;\n",
|
|
" padding: .5ex;\n",
|
|
" margin: .5ex;\n",
|
|
" width: min-content;\n",
|
|
" min-width: 20ex;\n",
|
|
" max-width: 50ex;\n",
|
|
" color: var(--sklearn-color-text);\n",
|
|
" box-shadow: 2pt 2pt 4pt #999;\n",
|
|
" /* unfitted */\n",
|
|
" background: var(--sklearn-color-unfitted-level-0);\n",
|
|
" border: .5pt solid var(--sklearn-color-unfitted-level-3);\n",
|
|
"}\n",
|
|
"\n",
|
|
".sk-estimator-doc-link.fitted span {\n",
|
|
" /* fitted */\n",
|
|
" background: var(--sklearn-color-fitted-level-0);\n",
|
|
" border: var(--sklearn-color-fitted-level-3);\n",
|
|
"}\n",
|
|
"\n",
|
|
".sk-estimator-doc-link:hover span {\n",
|
|
" display: block;\n",
|
|
"}\n",
|
|
"\n",
|
|
"/* \"?\"-specific style due to the `<a>` HTML tag */\n",
|
|
"\n",
|
|
"#sk-container-id-7 a.estimator_doc_link {\n",
|
|
" float: right;\n",
|
|
" font-size: 1rem;\n",
|
|
" line-height: 1em;\n",
|
|
" font-family: monospace;\n",
|
|
" background-color: var(--sklearn-color-background);\n",
|
|
" border-radius: 1rem;\n",
|
|
" height: 1rem;\n",
|
|
" width: 1rem;\n",
|
|
" text-decoration: none;\n",
|
|
" /* unfitted */\n",
|
|
" color: var(--sklearn-color-unfitted-level-1);\n",
|
|
" border: var(--sklearn-color-unfitted-level-1) 1pt solid;\n",
|
|
"}\n",
|
|
"\n",
|
|
"#sk-container-id-7 a.estimator_doc_link.fitted {\n",
|
|
" /* fitted */\n",
|
|
" border: var(--sklearn-color-fitted-level-1) 1pt solid;\n",
|
|
" color: var(--sklearn-color-fitted-level-1);\n",
|
|
"}\n",
|
|
"\n",
|
|
"/* On hover */\n",
|
|
"#sk-container-id-7 a.estimator_doc_link:hover {\n",
|
|
" /* unfitted */\n",
|
|
" background-color: var(--sklearn-color-unfitted-level-3);\n",
|
|
" color: var(--sklearn-color-background);\n",
|
|
" text-decoration: none;\n",
|
|
"}\n",
|
|
"\n",
|
|
"#sk-container-id-7 a.estimator_doc_link.fitted:hover {\n",
|
|
" /* fitted */\n",
|
|
" background-color: var(--sklearn-color-fitted-level-3);\n",
|
|
"}\n",
|
|
"</style><div id=\"sk-container-id-7\" class=\"sk-top-container\"><div class=\"sk-text-repr-fallback\"><pre>GridSearchCV(cv=5, estimator=KNeighborsClassifier(),\n",
|
|
" param_grid={'n_neighbors': array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,\n",
|
|
" 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29])})</pre><b>In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. <br />On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.</b></div><div class=\"sk-container\" hidden><div class=\"sk-item sk-dashed-wrapped\"><div class=\"sk-label-container\"><div class=\"sk-label fitted sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-13\" type=\"checkbox\" ><label for=\"sk-estimator-id-13\" class=\"sk-toggleable__label fitted sk-toggleable__label-arrow fitted\"> GridSearchCV<a class=\"sk-estimator-doc-link fitted\" rel=\"noreferrer\" target=\"_blank\" href=\"https://scikit-learn.org/1.5/modules/generated/sklearn.model_selection.GridSearchCV.html\">?<span>Documentation for GridSearchCV</span></a><span class=\"sk-estimator-doc-link fitted\">i<span>Fitted</span></span></label><div class=\"sk-toggleable__content fitted\"><pre>GridSearchCV(cv=5, estimator=KNeighborsClassifier(),\n",
|
|
" param_grid={'n_neighbors': array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,\n",
|
|
" 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29])})</pre></div> </div></div><div class=\"sk-parallel\"><div class=\"sk-parallel-item\"><div class=\"sk-item\"><div class=\"sk-label-container\"><div class=\"sk-label fitted sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-14\" type=\"checkbox\" ><label for=\"sk-estimator-id-14\" class=\"sk-toggleable__label fitted sk-toggleable__label-arrow fitted\">best_estimator_: KNeighborsClassifier</label><div class=\"sk-toggleable__content fitted\"><pre>KNeighborsClassifier(n_neighbors=12)</pre></div> </div></div><div class=\"sk-serial\"><div class=\"sk-item\"><div class=\"sk-estimator fitted sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-15\" type=\"checkbox\" ><label for=\"sk-estimator-id-15\" class=\"sk-toggleable__label fitted sk-toggleable__label-arrow fitted\"> KNeighborsClassifier<a class=\"sk-estimator-doc-link fitted\" rel=\"noreferrer\" target=\"_blank\" href=\"https://scikit-learn.org/1.5/modules/generated/sklearn.neighbors.KNeighborsClassifier.html\">?<span>Documentation for KNeighborsClassifier</span></a></label><div class=\"sk-toggleable__content fitted\"><pre>KNeighborsClassifier(n_neighbors=12)</pre></div> </div></div></div></div></div></div></div></div></div>"
|
|
],
|
|
"text/plain": [
|
|
"GridSearchCV(cv=5, estimator=KNeighborsClassifier(),\n",
|
|
" param_grid={'n_neighbors': array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,\n",
|
|
" 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29])})"
|
|
]
|
|
},
|
|
"execution_count": 85,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"# Lakukan GridSearch dengan 5-fold cross validation\n",
|
|
"knn_cv = GridSearchCV(knn, param_grid, cv=5)\n",
|
|
"knn_cv.fit(x_train, y_train)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 86,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Best k: {'n_neighbors': 12}\n",
|
|
"Best accuracy (CV): 55.00%\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"# Lihat nilai k terbaik dan akurasi terbaik dari cross-validation\n",
|
|
"print(f'Best k: {knn_cv.best_params_}')\n",
|
|
"print(f'Best accuracy (CV): {knn_cv.best_score_ * 100:.2f}%')"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 87,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/html": [
|
|
"<style>#sk-container-id-8 {\n",
|
|
" /* Definition of color scheme common for light and dark mode */\n",
|
|
" --sklearn-color-text: black;\n",
|
|
" --sklearn-color-line: gray;\n",
|
|
" /* Definition of color scheme for unfitted estimators */\n",
|
|
" --sklearn-color-unfitted-level-0: #fff5e6;\n",
|
|
" --sklearn-color-unfitted-level-1: #f6e4d2;\n",
|
|
" --sklearn-color-unfitted-level-2: #ffe0b3;\n",
|
|
" --sklearn-color-unfitted-level-3: chocolate;\n",
|
|
" /* Definition of color scheme for fitted estimators */\n",
|
|
" --sklearn-color-fitted-level-0: #f0f8ff;\n",
|
|
" --sklearn-color-fitted-level-1: #d4ebff;\n",
|
|
" --sklearn-color-fitted-level-2: #b3dbfd;\n",
|
|
" --sklearn-color-fitted-level-3: cornflowerblue;\n",
|
|
"\n",
|
|
" /* Specific color for light theme */\n",
|
|
" --sklearn-color-text-on-default-background: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, black)));\n",
|
|
" --sklearn-color-background: var(--sg-background-color, var(--theme-background, var(--jp-layout-color0, white)));\n",
|
|
" --sklearn-color-border-box: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, black)));\n",
|
|
" --sklearn-color-icon: #696969;\n",
|
|
"\n",
|
|
" @media (prefers-color-scheme: dark) {\n",
|
|
" /* Redefinition of color scheme for dark theme */\n",
|
|
" --sklearn-color-text-on-default-background: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, white)));\n",
|
|
" --sklearn-color-background: var(--sg-background-color, var(--theme-background, var(--jp-layout-color0, #111)));\n",
|
|
" --sklearn-color-border-box: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, white)));\n",
|
|
" --sklearn-color-icon: #878787;\n",
|
|
" }\n",
|
|
"}\n",
|
|
"\n",
|
|
"#sk-container-id-8 {\n",
|
|
" color: var(--sklearn-color-text);\n",
|
|
"}\n",
|
|
"\n",
|
|
"#sk-container-id-8 pre {\n",
|
|
" padding: 0;\n",
|
|
"}\n",
|
|
"\n",
|
|
"#sk-container-id-8 input.sk-hidden--visually {\n",
|
|
" border: 0;\n",
|
|
" clip: rect(1px 1px 1px 1px);\n",
|
|
" clip: rect(1px, 1px, 1px, 1px);\n",
|
|
" height: 1px;\n",
|
|
" margin: -1px;\n",
|
|
" overflow: hidden;\n",
|
|
" padding: 0;\n",
|
|
" position: absolute;\n",
|
|
" width: 1px;\n",
|
|
"}\n",
|
|
"\n",
|
|
"#sk-container-id-8 div.sk-dashed-wrapped {\n",
|
|
" border: 1px dashed var(--sklearn-color-line);\n",
|
|
" margin: 0 0.4em 0.5em 0.4em;\n",
|
|
" box-sizing: border-box;\n",
|
|
" padding-bottom: 0.4em;\n",
|
|
" background-color: var(--sklearn-color-background);\n",
|
|
"}\n",
|
|
"\n",
|
|
"#sk-container-id-8 div.sk-container {\n",
|
|
" /* jupyter's `normalize.less` sets `[hidden] { display: none; }`\n",
|
|
" but bootstrap.min.css set `[hidden] { display: none !important; }`\n",
|
|
" so we also need the `!important` here to be able to override the\n",
|
|
" default hidden behavior on the sphinx rendered scikit-learn.org.\n",
|
|
" See: https://github.com/scikit-learn/scikit-learn/issues/21755 */\n",
|
|
" display: inline-block !important;\n",
|
|
" position: relative;\n",
|
|
"}\n",
|
|
"\n",
|
|
"#sk-container-id-8 div.sk-text-repr-fallback {\n",
|
|
" display: none;\n",
|
|
"}\n",
|
|
"\n",
|
|
"div.sk-parallel-item,\n",
|
|
"div.sk-serial,\n",
|
|
"div.sk-item {\n",
|
|
" /* draw centered vertical line to link estimators */\n",
|
|
" background-image: linear-gradient(var(--sklearn-color-text-on-default-background), var(--sklearn-color-text-on-default-background));\n",
|
|
" background-size: 2px 100%;\n",
|
|
" background-repeat: no-repeat;\n",
|
|
" background-position: center center;\n",
|
|
"}\n",
|
|
"\n",
|
|
"/* Parallel-specific style estimator block */\n",
|
|
"\n",
|
|
"#sk-container-id-8 div.sk-parallel-item::after {\n",
|
|
" content: \"\";\n",
|
|
" width: 100%;\n",
|
|
" border-bottom: 2px solid var(--sklearn-color-text-on-default-background);\n",
|
|
" flex-grow: 1;\n",
|
|
"}\n",
|
|
"\n",
|
|
"#sk-container-id-8 div.sk-parallel {\n",
|
|
" display: flex;\n",
|
|
" align-items: stretch;\n",
|
|
" justify-content: center;\n",
|
|
" background-color: var(--sklearn-color-background);\n",
|
|
" position: relative;\n",
|
|
"}\n",
|
|
"\n",
|
|
"#sk-container-id-8 div.sk-parallel-item {\n",
|
|
" display: flex;\n",
|
|
" flex-direction: column;\n",
|
|
"}\n",
|
|
"\n",
|
|
"#sk-container-id-8 div.sk-parallel-item:first-child::after {\n",
|
|
" align-self: flex-end;\n",
|
|
" width: 50%;\n",
|
|
"}\n",
|
|
"\n",
|
|
"#sk-container-id-8 div.sk-parallel-item:last-child::after {\n",
|
|
" align-self: flex-start;\n",
|
|
" width: 50%;\n",
|
|
"}\n",
|
|
"\n",
|
|
"#sk-container-id-8 div.sk-parallel-item:only-child::after {\n",
|
|
" width: 0;\n",
|
|
"}\n",
|
|
"\n",
|
|
"/* Serial-specific style estimator block */\n",
|
|
"\n",
|
|
"#sk-container-id-8 div.sk-serial {\n",
|
|
" display: flex;\n",
|
|
" flex-direction: column;\n",
|
|
" align-items: center;\n",
|
|
" background-color: var(--sklearn-color-background);\n",
|
|
" padding-right: 1em;\n",
|
|
" padding-left: 1em;\n",
|
|
"}\n",
|
|
"\n",
|
|
"\n",
|
|
"/* Toggleable style: style used for estimator/Pipeline/ColumnTransformer box that is\n",
|
|
"clickable and can be expanded/collapsed.\n",
|
|
"- Pipeline and ColumnTransformer use this feature and define the default style\n",
|
|
"- Estimators will overwrite some part of the style using the `sk-estimator` class\n",
|
|
"*/\n",
|
|
"\n",
|
|
"/* Pipeline and ColumnTransformer style (default) */\n",
|
|
"\n",
|
|
"#sk-container-id-8 div.sk-toggleable {\n",
|
|
" /* Default theme specific background. It is overwritten whether we have a\n",
|
|
" specific estimator or a Pipeline/ColumnTransformer */\n",
|
|
" background-color: var(--sklearn-color-background);\n",
|
|
"}\n",
|
|
"\n",
|
|
"/* Toggleable label */\n",
|
|
"#sk-container-id-8 label.sk-toggleable__label {\n",
|
|
" cursor: pointer;\n",
|
|
" display: block;\n",
|
|
" width: 100%;\n",
|
|
" margin-bottom: 0;\n",
|
|
" padding: 0.5em;\n",
|
|
" box-sizing: border-box;\n",
|
|
" text-align: center;\n",
|
|
"}\n",
|
|
"\n",
|
|
"#sk-container-id-8 label.sk-toggleable__label-arrow:before {\n",
|
|
" /* Arrow on the left of the label */\n",
|
|
" content: \"▸\";\n",
|
|
" float: left;\n",
|
|
" margin-right: 0.25em;\n",
|
|
" color: var(--sklearn-color-icon);\n",
|
|
"}\n",
|
|
"\n",
|
|
"#sk-container-id-8 label.sk-toggleable__label-arrow:hover:before {\n",
|
|
" color: var(--sklearn-color-text);\n",
|
|
"}\n",
|
|
"\n",
|
|
"/* Toggleable content - dropdown */\n",
|
|
"\n",
|
|
"#sk-container-id-8 div.sk-toggleable__content {\n",
|
|
" max-height: 0;\n",
|
|
" max-width: 0;\n",
|
|
" overflow: hidden;\n",
|
|
" text-align: left;\n",
|
|
" /* unfitted */\n",
|
|
" background-color: var(--sklearn-color-unfitted-level-0);\n",
|
|
"}\n",
|
|
"\n",
|
|
"#sk-container-id-8 div.sk-toggleable__content.fitted {\n",
|
|
" /* fitted */\n",
|
|
" background-color: var(--sklearn-color-fitted-level-0);\n",
|
|
"}\n",
|
|
"\n",
|
|
"#sk-container-id-8 div.sk-toggleable__content pre {\n",
|
|
" margin: 0.2em;\n",
|
|
" border-radius: 0.25em;\n",
|
|
" color: var(--sklearn-color-text);\n",
|
|
" /* unfitted */\n",
|
|
" background-color: var(--sklearn-color-unfitted-level-0);\n",
|
|
"}\n",
|
|
"\n",
|
|
"#sk-container-id-8 div.sk-toggleable__content.fitted pre {\n",
|
|
" /* unfitted */\n",
|
|
" background-color: var(--sklearn-color-fitted-level-0);\n",
|
|
"}\n",
|
|
"\n",
|
|
"#sk-container-id-8 input.sk-toggleable__control:checked~div.sk-toggleable__content {\n",
|
|
" /* Expand drop-down */\n",
|
|
" max-height: 200px;\n",
|
|
" max-width: 100%;\n",
|
|
" overflow: auto;\n",
|
|
"}\n",
|
|
"\n",
|
|
"#sk-container-id-8 input.sk-toggleable__control:checked~label.sk-toggleable__label-arrow:before {\n",
|
|
" content: \"▾\";\n",
|
|
"}\n",
|
|
"\n",
|
|
"/* Pipeline/ColumnTransformer-specific style */\n",
|
|
"\n",
|
|
"#sk-container-id-8 div.sk-label input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
|
|
" color: var(--sklearn-color-text);\n",
|
|
" background-color: var(--sklearn-color-unfitted-level-2);\n",
|
|
"}\n",
|
|
"\n",
|
|
"#sk-container-id-8 div.sk-label.fitted input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
|
|
" background-color: var(--sklearn-color-fitted-level-2);\n",
|
|
"}\n",
|
|
"\n",
|
|
"/* Estimator-specific style */\n",
|
|
"\n",
|
|
"/* Colorize estimator box */\n",
|
|
"#sk-container-id-8 div.sk-estimator input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
|
|
" /* unfitted */\n",
|
|
" background-color: var(--sklearn-color-unfitted-level-2);\n",
|
|
"}\n",
|
|
"\n",
|
|
"#sk-container-id-8 div.sk-estimator.fitted input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
|
|
" /* fitted */\n",
|
|
" background-color: var(--sklearn-color-fitted-level-2);\n",
|
|
"}\n",
|
|
"\n",
|
|
"#sk-container-id-8 div.sk-label label.sk-toggleable__label,\n",
|
|
"#sk-container-id-8 div.sk-label label {\n",
|
|
" /* The background is the default theme color */\n",
|
|
" color: var(--sklearn-color-text-on-default-background);\n",
|
|
"}\n",
|
|
"\n",
|
|
"/* On hover, darken the color of the background */\n",
|
|
"#sk-container-id-8 div.sk-label:hover label.sk-toggleable__label {\n",
|
|
" color: var(--sklearn-color-text);\n",
|
|
" background-color: var(--sklearn-color-unfitted-level-2);\n",
|
|
"}\n",
|
|
"\n",
|
|
"/* Label box, darken color on hover, fitted */\n",
|
|
"#sk-container-id-8 div.sk-label.fitted:hover label.sk-toggleable__label.fitted {\n",
|
|
" color: var(--sklearn-color-text);\n",
|
|
" background-color: var(--sklearn-color-fitted-level-2);\n",
|
|
"}\n",
|
|
"\n",
|
|
"/* Estimator label */\n",
|
|
"\n",
|
|
"#sk-container-id-8 div.sk-label label {\n",
|
|
" font-family: monospace;\n",
|
|
" font-weight: bold;\n",
|
|
" display: inline-block;\n",
|
|
" line-height: 1.2em;\n",
|
|
"}\n",
|
|
"\n",
|
|
"#sk-container-id-8 div.sk-label-container {\n",
|
|
" text-align: center;\n",
|
|
"}\n",
|
|
"\n",
|
|
"/* Estimator-specific */\n",
|
|
"#sk-container-id-8 div.sk-estimator {\n",
|
|
" font-family: monospace;\n",
|
|
" border: 1px dotted var(--sklearn-color-border-box);\n",
|
|
" border-radius: 0.25em;\n",
|
|
" box-sizing: border-box;\n",
|
|
" margin-bottom: 0.5em;\n",
|
|
" /* unfitted */\n",
|
|
" background-color: var(--sklearn-color-unfitted-level-0);\n",
|
|
"}\n",
|
|
"\n",
|
|
"#sk-container-id-8 div.sk-estimator.fitted {\n",
|
|
" /* fitted */\n",
|
|
" background-color: var(--sklearn-color-fitted-level-0);\n",
|
|
"}\n",
|
|
"\n",
|
|
"/* on hover */\n",
|
|
"#sk-container-id-8 div.sk-estimator:hover {\n",
|
|
" /* unfitted */\n",
|
|
" background-color: var(--sklearn-color-unfitted-level-2);\n",
|
|
"}\n",
|
|
"\n",
|
|
"#sk-container-id-8 div.sk-estimator.fitted:hover {\n",
|
|
" /* fitted */\n",
|
|
" background-color: var(--sklearn-color-fitted-level-2);\n",
|
|
"}\n",
|
|
"\n",
|
|
"/* Specification for estimator info (e.g. \"i\" and \"?\") */\n",
|
|
"\n",
|
|
"/* Common style for \"i\" and \"?\" */\n",
|
|
"\n",
|
|
".sk-estimator-doc-link,\n",
|
|
"a:link.sk-estimator-doc-link,\n",
|
|
"a:visited.sk-estimator-doc-link {\n",
|
|
" float: right;\n",
|
|
" font-size: smaller;\n",
|
|
" line-height: 1em;\n",
|
|
" font-family: monospace;\n",
|
|
" background-color: var(--sklearn-color-background);\n",
|
|
" border-radius: 1em;\n",
|
|
" height: 1em;\n",
|
|
" width: 1em;\n",
|
|
" text-decoration: none !important;\n",
|
|
" margin-left: 1ex;\n",
|
|
" /* unfitted */\n",
|
|
" border: var(--sklearn-color-unfitted-level-1) 1pt solid;\n",
|
|
" color: var(--sklearn-color-unfitted-level-1);\n",
|
|
"}\n",
|
|
"\n",
|
|
".sk-estimator-doc-link.fitted,\n",
|
|
"a:link.sk-estimator-doc-link.fitted,\n",
|
|
"a:visited.sk-estimator-doc-link.fitted {\n",
|
|
" /* fitted */\n",
|
|
" border: var(--sklearn-color-fitted-level-1) 1pt solid;\n",
|
|
" color: var(--sklearn-color-fitted-level-1);\n",
|
|
"}\n",
|
|
"\n",
|
|
"/* On hover */\n",
|
|
"div.sk-estimator:hover .sk-estimator-doc-link:hover,\n",
|
|
".sk-estimator-doc-link:hover,\n",
|
|
"div.sk-label-container:hover .sk-estimator-doc-link:hover,\n",
|
|
".sk-estimator-doc-link:hover {\n",
|
|
" /* unfitted */\n",
|
|
" background-color: var(--sklearn-color-unfitted-level-3);\n",
|
|
" color: var(--sklearn-color-background);\n",
|
|
" text-decoration: none;\n",
|
|
"}\n",
|
|
"\n",
|
|
"div.sk-estimator.fitted:hover .sk-estimator-doc-link.fitted:hover,\n",
|
|
".sk-estimator-doc-link.fitted:hover,\n",
|
|
"div.sk-label-container:hover .sk-estimator-doc-link.fitted:hover,\n",
|
|
".sk-estimator-doc-link.fitted:hover {\n",
|
|
" /* fitted */\n",
|
|
" background-color: var(--sklearn-color-fitted-level-3);\n",
|
|
" color: var(--sklearn-color-background);\n",
|
|
" text-decoration: none;\n",
|
|
"}\n",
|
|
"\n",
|
|
"/* Span, style for the box shown on hovering the info icon */\n",
|
|
".sk-estimator-doc-link span {\n",
|
|
" display: none;\n",
|
|
" z-index: 9999;\n",
|
|
" position: relative;\n",
|
|
" font-weight: normal;\n",
|
|
" right: .2ex;\n",
|
|
" padding: .5ex;\n",
|
|
" margin: .5ex;\n",
|
|
" width: min-content;\n",
|
|
" min-width: 20ex;\n",
|
|
" max-width: 50ex;\n",
|
|
" color: var(--sklearn-color-text);\n",
|
|
" box-shadow: 2pt 2pt 4pt #999;\n",
|
|
" /* unfitted */\n",
|
|
" background: var(--sklearn-color-unfitted-level-0);\n",
|
|
" border: .5pt solid var(--sklearn-color-unfitted-level-3);\n",
|
|
"}\n",
|
|
"\n",
|
|
".sk-estimator-doc-link.fitted span {\n",
|
|
" /* fitted */\n",
|
|
" background: var(--sklearn-color-fitted-level-0);\n",
|
|
" border: var(--sklearn-color-fitted-level-3);\n",
|
|
"}\n",
|
|
"\n",
|
|
".sk-estimator-doc-link:hover span {\n",
|
|
" display: block;\n",
|
|
"}\n",
|
|
"\n",
|
|
"/* \"?\"-specific style due to the `<a>` HTML tag */\n",
|
|
"\n",
|
|
"#sk-container-id-8 a.estimator_doc_link {\n",
|
|
" float: right;\n",
|
|
" font-size: 1rem;\n",
|
|
" line-height: 1em;\n",
|
|
" font-family: monospace;\n",
|
|
" background-color: var(--sklearn-color-background);\n",
|
|
" border-radius: 1rem;\n",
|
|
" height: 1rem;\n",
|
|
" width: 1rem;\n",
|
|
" text-decoration: none;\n",
|
|
" /* unfitted */\n",
|
|
" color: var(--sklearn-color-unfitted-level-1);\n",
|
|
" border: var(--sklearn-color-unfitted-level-1) 1pt solid;\n",
|
|
"}\n",
|
|
"\n",
|
|
"#sk-container-id-8 a.estimator_doc_link.fitted {\n",
|
|
" /* fitted */\n",
|
|
" border: var(--sklearn-color-fitted-level-1) 1pt solid;\n",
|
|
" color: var(--sklearn-color-fitted-level-1);\n",
|
|
"}\n",
|
|
"\n",
|
|
"/* On hover */\n",
|
|
"#sk-container-id-8 a.estimator_doc_link:hover {\n",
|
|
" /* unfitted */\n",
|
|
" background-color: var(--sklearn-color-unfitted-level-3);\n",
|
|
" color: var(--sklearn-color-background);\n",
|
|
" text-decoration: none;\n",
|
|
"}\n",
|
|
"\n",
|
|
"#sk-container-id-8 a.estimator_doc_link.fitted:hover {\n",
|
|
" /* fitted */\n",
|
|
" background-color: var(--sklearn-color-fitted-level-3);\n",
|
|
"}\n",
|
|
"</style><div id=\"sk-container-id-8\" class=\"sk-top-container\"><div class=\"sk-text-repr-fallback\"><pre>KNeighborsClassifier(n_neighbors=12)</pre><b>In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. <br />On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.</b></div><div class=\"sk-container\" hidden><div class=\"sk-item\"><div class=\"sk-estimator fitted sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-16\" type=\"checkbox\" checked><label for=\"sk-estimator-id-16\" class=\"sk-toggleable__label fitted sk-toggleable__label-arrow fitted\"> KNeighborsClassifier<a class=\"sk-estimator-doc-link fitted\" rel=\"noreferrer\" target=\"_blank\" href=\"https://scikit-learn.org/1.5/modules/generated/sklearn.neighbors.KNeighborsClassifier.html\">?<span>Documentation for KNeighborsClassifier</span></a><span class=\"sk-estimator-doc-link fitted\">i<span>Fitted</span></span></label><div class=\"sk-toggleable__content fitted\"><pre>KNeighborsClassifier(n_neighbors=12)</pre></div> </div></div></div></div>"
|
|
],
|
|
"text/plain": [
|
|
"KNeighborsClassifier(n_neighbors=12)"
|
|
]
|
|
},
|
|
"execution_count": 87,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"# Latih model terbaik dengan data training\n",
|
|
"best_knn = knn_cv.best_estimator_\n",
|
|
"best_knn.fit(x_train, y_train)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 88,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Prediksi data testing\n",
|
|
"y_pred = best_knn.predict(x_test)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"#### Initialize KNN Model\n",
|
|
"\n",
|
|
"```\n",
|
|
"Inisialisasi model KNN\n",
|
|
"```"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 89,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Inisialisasi dan latih model K-NN\n",
|
|
"# knn = KNeighborsClassifier(n_neighbors=1)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"#### Train Model\n",
|
|
"\n",
|
|
"```\n",
|
|
"Proses training model KNN\n",
|
|
"```"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 90,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# knn.fit(x_train, y_train)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"#### Predict Test Data\n",
|
|
"\n",
|
|
"```\n",
|
|
"Proses prediksi data test\n",
|
|
"```"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 91,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# y_pred = knn.predict(x_test)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"#### Hitung Akurasi\n",
|
|
"\n",
|
|
"``` \n",
|
|
"Proses menghitung akurasi dari model KNN\n",
|
|
"```"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 92,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Accuracy: 51.67%\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"# Evaluasi akurasi\n",
|
|
"accuracy = accuracy_score(y_test, y_pred)\n",
|
|
"print(f'Accuracy: {accuracy * 100:.2f}%')"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": []
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"#### Save Model\n",
|
|
"\n",
|
|
"```\n",
|
|
"Proses penyimpanan model KNN\n",
|
|
"```"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 93,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Model saved to knn_model.pkl\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"# Simpan model ke file\n",
|
|
"joblib.dump(knn, 'knn_model.pkl') \n",
|
|
"print('Model saved to knn_model.pkl')"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"<class 'str'>\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"print(type(model_knn.pkl))"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"#### Load Model\n",
|
|
"\n",
|
|
"```\n",
|
|
"Proses load model KNN\n",
|
|
"```"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 94,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Muat model yang telah disimpan\n",
|
|
"knn = joblib.load('knn_model.pkl')"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"#### Predict new image\n",
|
|
"\n",
|
|
"```\n",
|
|
"Proses prediksi citra baru\n",
|
|
"```\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 95,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Prediksi gambar baru\n",
|
|
"new_image_path = r'D:\\Kuliah\\SKRIPSI\\cacao_dataset\\test\\monilia\\monilia77 .jpg'\n",
|
|
"new_image = cv2.imread(new_image_path)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 96,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Ubah gambar menjadi grayscale\n",
|
|
"gray_image = cv2.cvtColor(new_image, cv2.COLOR_BGR2GRAY)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 97,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Ekstraksi fitur GLCM dari gambar baru\n",
|
|
"glcm_features = glcm(gray_image)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 98,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Standarisasi fitur GLCM baru\n",
|
|
"scaled_features = scaler.transform([glcm_features])"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 99,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Latih model terbaik dengan data training jika belum dilatih\n",
|
|
"if not hasattr(knn, 'classes_'):\n",
|
|
"\tknn.fit(x_train, y_train)\n",
|
|
"\n",
|
|
"# Prediksi kelas gambar baru\n",
|
|
"prediction = knn.predict(scaled_features)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 100,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Prediction: monilia\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"# Tampilkan hasil prediksi\n",
|
|
"predicted_class = list(labels.keys())[list(labels.values()).index(prediction[0])]\n",
|
|
"print(f'Prediction: {predicted_class}')"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 101,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"image/png": "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5yk+FwAg9WgQAFhKQECAJOn8+fMp2v/gwYPy8PBQsWLFXMbz5MmjoKAgHTx40GW8UKFCyY4RHBys06dPp7Hi5F544QVVrVpVbdu2Ve7cudWsWTNNnz79rs3CzTpLlCiRbFt4eLj+/vtvXbhwwWX8n+8lODhYklL1Xp5++mn5+/tr2rRp+vrrr/Xwww8n+1zelJSUpMGDB6t48eKy2+3KkSOHcubMqU2bNuns2bMpPmf+/PlTNSH5008/Vfbs2bVhwwYNGzZMuXLlSvFrAQCpR4MAwFICAgKUL18+bdmyJVWv++ck4Tvx9PS87bhhGGk+x83r42/KmjWrli5dqgULFqhFixbatGmTXnjhBT311FPJ9v0v/st7uclut6tJkyaaNGmSZs6cecf0QJL69eunqKgoVatWTV999ZXmzp2r+fPnq1SpUilOSqTrn5/UWL9+veLi4iRJmzdvTtVrAQCpR4MAwHLq16+vvXv3asWKFf+6b2hoqJKSkrR7926X8b/++ktnzpxx3JEoPQQHB7vc8eemf6YUkuTh4aEnn3xSgwYN0rZt29S3b18tXLhQixYtuu2xb9a5c+fOZNt27NihHDlyyNfX97+9gTt48cUXtX79ep0/f/62E7tv+u6771SjRg2NHz9ezZo1U61atVSzZs1kn5OUNmspceHCBb388ssqWbKkXn31VfXv31+rV69Ot+MDAJKjQQBgOe+++658fX3Vtm1b/fXXX8m27927V0OHDpV0/RIZScnuNDRo0CBJUr169dKtrqJFi+rs2bPatGmTY+zYsWOaOXOmy36nTp1K9tqbC4b989arN+XNm1flypXTpEmTXH7h3rJli+bNm+d4n/dCjRo11KdPH40YMUJ58uS5436enp7J0olvv/1WR44ccRm72cjcrplKra5du+rQoUOaNGmSBg0apLCwMLVq1eqOn0cAwH/HQmkALKdo0aKaMmWKXnjhBYWHh7uspPz777/r22+/VevWrSVJZcuWVatWrTRmzBidOXNGkZGR+uOPPzRp0iQ1btz4jrfQTItmzZqpa9eueuaZZ9ShQwddvHhRo0aN0gMPPOAySTc6OlpLly5VvXr1FBoaqri4OH322WcqUKCAHnvssTsef8CAAapbt64qV66sV155RZcuXdLw4cMVGBioXr16pdv7+CcPDw99+OGH/7pf/fr1FR0drZdffllVqlTR5s2b9fXXX6tIkSIu+xUtWlRBQUEaPXq0/P395evrq0cffVSFCxdOVV0LFy7UZ599pp49ezpuuzphwgRVr15d3bt3V//+/VN1PABAypAgALCkhg0batOmTXruuef0ww8/qF27dnrvvfd04MABDRw4UMOGDXPsO27cOPXu3VurV69Wp06dtHDhQnXr1k3ffPNNutYUEhKimTNnKlu2bHr33Xc1adIkxcTEqEGDBslqL1SokL744gu1a9dOI0eOVLVq1bRw4UIFBgbe8fg1a9bUnDlzFBISoh49eujTTz9VpUqVtHz58lT/cn0vvP/+++rSpYvmzp2rjh07at26dfr5559VsGBBl/28vLw0adIkeXp66vXXX1fz5s21ZMmSVJ3r/PnzatOmjcqXL68PPvjAMf7444+rY8eOGjhwoFauXJku7wsA4MpmpGY2GwAAAID7GgkCAAAAAAcaBAAAAAAONAgAAAAAHGgQAAAAgExg6dKlatCggfLlyyebzaZZs2Y5tl29elVdu3ZVRESEfH19lS9fPrVs2VJHjx5N9XloEAAAAIBM4MKFCypbtqxGjhyZbNvFixe1bt06de/eXevWrdP333+vnTt3qmHDhqk+D3cxAgAAADIZm82mmTNnqnHjxnfcZ/Xq1XrkkUd08OBBFSpUKMXHZqE0AAAAwCQJCQnJVoe32+2y2+3/+dhnz56VzWZTUFBQql53XzYIWesONrsEIFPaO7Wd2SUAmVLXn7ebXQKQ6Ux+qazZJdxR1vLtM+xcXRvlUO/evV3GevbsqV69ev2n416+fFldu3ZV8+bNFRAQkKrX3pcNAgAAAJAZdOvWTVFRUS5j/zU9uHr1qp5//nkZhqFRo0al+vU0CAAAAIAzW8bdxye9Lie66WZzcPDgQS1cuDDV6YFEgwAAAADcF242B7t379aiRYsUEhKSpuPQIAAAAADObDazK7it+Ph47dmzx/F8//792rBhg7Jnz668efPqueee07p16/TTTz8pMTFRx48flyRlz55d3t7eKT4PDQIAAACQCaxZs0Y1atRwPL85d6FVq1bq1auXZs+eLUkqV66cy+sWLVqk6tWrp/g8NAgAAACAswycg5Aa1atX192WMEuv5c2s+e4BAAAAmIIEAQAAAHBm0TkIGYUEAQAAAIADCQIAAADgzKJzEDKKe797AAAAAC5I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",
|
|
"text/plain": [
|
|
"<Figure size 1000x700 with 2 Axes>"
|
|
]
|
|
},
|
|
"metadata": {},
|
|
"output_type": "display_data"
|
|
}
|
|
],
|
|
"source": [
|
|
"from sklearn.metrics import confusion_matrix\n",
|
|
"import seaborn as sns\n",
|
|
"\n",
|
|
"import matplotlib.pyplot as plt\n",
|
|
"\n",
|
|
"# Create confusion matrix\n",
|
|
"cm = confusion_matrix(y_test, y_pred)\n",
|
|
"\n",
|
|
"# Plot confusion matrix\n",
|
|
"plt.figure(figsize=(10, 7))\n",
|
|
"sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', xticklabels=classes, yticklabels=classes)\n",
|
|
"plt.xlabel('Predicted')\n",
|
|
"plt.ylabel('Actual')\n",
|
|
"plt.title('Confusion Matrix')\n",
|
|
"plt.show()"
|
|
]
|
|
}
|
|
],
|
|
"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.10.11"
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 2
|
|
}
|