TIFNGK_E41222120/virtualEnvironment/analisis_knn5.py

128 lines
4.7 KiB
Python
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 4 mencari nilai K
import joblib
import pandas as pd
import numpy as np
import math
import matplotlib.pyplot as plt
import os
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import cross_val_score, GridSearchCV
print("🔬 [EKSPERIMEN] Membandingkan 3 Metode Mencari Nilai K Terbaik...")
# --- PENYESUAIAN FOLDER ---
FOLDER_OUTPUT = 'virtualEnvironment/output'
FOLDER_IMAGES = 'virtualEnvironment/images'
# 0. CEK KEAMANAN
file_xtrain = f'{FOLDER_OUTPUT}/X_train.pkl'
if not os.path.exists(file_xtrain):
raise FileNotFoundError(f"❌ File '{file_xtrain}' tidak ditemukan! Pastikan Tahap 1 sudah dijalankan.")
# Pastikan folder images ada di dalam virtualEnvironment
os.makedirs(FOLDER_IMAGES, exist_ok=True)
# 1. LOAD DATA
X_train = joblib.load(file_xtrain)
y_train = joblib.load(f'{FOLDER_OUTPUT}/y_train.pkl')
jumlah_data = X_train.shape[0]
print(f" - Jumlah Data Latih: {jumlah_data} baris")
print("-" * 50)
results = [] # Untuk menyimpan hasil perbandingan
# =========================================================
# METODE 1: AKAR KUADRAT (Square Root Rule)
# Rumus: K = Akar(Total Data)
# =========================================================
print("1⃣ Menguji Metode Akar Kuadrat...")
k_sqrt = int(math.sqrt(jumlah_data))
# Aturan: K harus ganjil biar gak seri (draw)
if k_sqrt % 2 == 0:
k_sqrt += 1
# Uji Akurasinya (Pakai n_jobs=-1 biar ngebut)
knn_sq = KNeighborsClassifier(n_neighbors=k_sqrt, metric='cosine')
scores_sq = cross_val_score(knn_sq, X_train, y_train, cv=5, scoring='accuracy', n_jobs=-1)
acc_sq = scores_sq.mean() * 100
print(f" -> Hasil: K={k_sqrt}, Akurasi={acc_sq:.2f}%")
results.append({'Metode': 'Akar Kuadrat', 'K': k_sqrt, 'Akurasi': acc_sq})
# =========================================================
# METODE 2: ELBOW METHOD (Metode Siku)
# Coba manual dari 1 sampai 40, lalu cari error terkecil
# =========================================================
print("\n2⃣ Menguji Metode Elbow (Looping 1-40)...")
print(" (Tunggu sebentar, sedang menghitung manual...)")
error_rates = []
acc_rates = []
k_range = range(1, 41, 2) # Coba angka ganjil: 1, 3, 5, ... 39
best_k_elbow = 0
best_acc_elbow = 0
for k in k_range:
knn = KNeighborsClassifier(n_neighbors=k, metric='cosine')
# Pakai n_jobs=-1 di sini juga biar loopingnya gak kelamaan
scores = cross_val_score(knn, X_train, y_train, cv=5, scoring='accuracy', n_jobs=-1)
acc = scores.mean()
# Simpan data buat grafik
acc_rates.append(acc)
error_rates.append(1 - acc) # Error = 100% - Akurasi
# Cek apakah ini rekor terbaik?
if acc > best_acc_elbow:
best_acc_elbow = acc
best_k_elbow = k
print(f" -> Hasil Terbaik di Range Ini: K={best_k_elbow}, Akurasi={best_acc_elbow*100:.2f}%")
results.append({'Metode': 'Elbow (Manual)', 'K': best_k_elbow, 'Akurasi': best_acc_elbow*100})
# Bikin Grafik Elbow
plt.figure(figsize=(10, 6))
plt.plot(k_range, error_rates, color='red', linestyle='dashed', marker='o',
markerfacecolor='blue', markersize=8)
plt.title('Grafik Elbow (Mencari Error Terkecil)', fontsize=14, fontweight='bold', pad=15)
plt.xlabel('Nilai K', fontsize=12, fontweight='bold')
plt.ylabel('Tingkat Error', fontsize=12, fontweight='bold')
plt.grid(True, linestyle='--', alpha=0.6)
# Simpan ke folder images
nama_gambar_elbow = f'{FOLDER_IMAGES}/grafik_elbow_knn.png'
plt.savefig(nama_gambar_elbow, dpi=300, bbox_inches='tight')
print(f" 🖼️ Grafik Elbow tersimpan: {nama_gambar_elbow}")
plt.close() # Tutup grafik biar memori lega
# =========================================================
# METODE 3: GRID SEARCH CV (Validasi Silang)
# Ini metode paling 'Sultan' dan Valid
# =========================================================
print("\n3⃣ Menguji Metode Grid Search CV (Otomatis)...")
param_grid = {'n_neighbors': [3, 5, 7, 9, 11, 15, 19, 21, 25, 29]}
grid = GridSearchCV(KNeighborsClassifier(metric='cosine'), param_grid, cv=5, scoring='accuracy', n_jobs=-1)
grid.fit(X_train, y_train)
k_grid = grid.best_params_['n_neighbors']
acc_grid = grid.best_score_ * 100
print(f" -> Hasil: K={k_grid}, Akurasi={acc_grid:.2f}%")
results.append({'Metode': 'Grid Search CV', 'K': k_grid, 'Akurasi': acc_grid})
# =========================================================
# KESIMPULAN AKHIR
# =========================================================
print("\n" + "="*50)
print("🏆 TABEL PERBANDINGAN METODE PENENTUAN K")
print("="*50)
df_res = pd.DataFrame(results)
print(df_res.to_string(index=False))
print("-" * 50)
# Cari pemenang
best_method = df_res.loc[df_res['Akurasi'].idxmax()]
print(f"✅ REKOMENDASI: Gunakan K = {best_method['K']}")
print(f" (Berdasarkan metode {best_method['Metode']} dengan akurasi tertinggi)")