{ "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)
\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": [ "
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])})
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.
" ], "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": [ "
KNeighborsClassifier(n_neighbors=12)
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.
" ], "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": [ "\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": [ "
" ] }, "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 }