TIFNGK_E41222120/virtualEnvironment/proses_training_model.ipynb

459 lines
19 KiB
Plaintext
Raw Permalink 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.

{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"id": "a954725d",
"metadata": {},
"outputs": [],
"source": [
"# 1 extraction features TF-IDF\n",
"import pandas as pd\n",
"import joblib\n",
"import os\n",
"from sklearn.feature_extraction.text import TfidfVectorizer\n",
"from sklearn.model_selection import train_test_split\n",
"\n",
"print(\"🔄 [TAHAP 1] Memulai Preprocessing & TF-IDF...\")\n",
"\n",
"# --- CONFIG ---\n",
"# Gunakan Absolute Path dengan 'r' di depan agar aman di Windows\n",
"FILE_DATA = r'd:\\project skripsi machine learning intoleransi\\virtualEnvironment\\dataset\\dataYangDiPakai\\data_label_revisi_goblog.csv' \n",
"\n",
"# 0. CEK KEAMANAN FILE SEBELUM JALAN\n",
"if not os.path.exists(FILE_DATA):\n",
" raise FileNotFoundError(f\"❌ File tidak ditemukan di jalur:\\n{FILE_DATA}\\nCoba pastikan nama file dan foldernya sudah persis sama!\")\n",
"\n",
"# Bikin folder otomatis\n",
"os.makedirs('output', exist_ok=True) \n",
"os.makedirs('models', exist_ok=True) \n",
"\n",
"# 1. LOAD DATA\n",
"print(\" - Membaca dataset...\")\n",
"df = pd.read_csv(FILE_DATA, sep=';') \n",
"\n",
"# Cek keamanan kolom (Biar tidak error kalau nama kolom salah)\n",
"if 'terjemahan_indo' not in df.columns or 'label' not in df.columns:\n",
" print(f\"Daftar kolom yang ada di filemu: {df.columns.tolist()}\")\n",
" raise KeyError(\"❌ Kolom 'terjemahan_indo' atau 'label' tidak ada! Coba cek tulisan di atas, pastikan namanya cocok.\")\n",
"\n",
"# Bersihkan data kosong\n",
"df = df.dropna(subset=['terjemahan_indo', 'label']) \n",
"print(f\" - Total data bersih yang siap diproses: {len(df)} baris\")\n",
"\n",
"# 2. TF-IDF (Ubah Huruf jadi Angka)\n",
"print(\" - Melakukan ekstraksi fitur TF-IDF...\")\n",
"vectorizer = TfidfVectorizer(max_features=5000)\n",
"X = vectorizer.fit_transform(df['terjemahan_indo'].astype(str))\n",
"y = df['label'].astype(int) # Pastikan label berupa angka (0, 1, 2)\n",
"\n",
"# 3. SIMPAN KAMUS TF-IDF\n",
"joblib.dump(vectorizer, 'models/vectorizer_tfidf.pkl')\n",
"\n",
"# 4. SPLIT DATA (80% Latih, 20% Uji)\n",
"print(\" - Memecah data (80% Data Latih, 20% Data Uji)...\")\n",
"X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)\n",
"\n",
"# 5. SIMPAN DATA MATANG\n",
"print(\" - Menyimpan data matang ke folder 'output'...\")\n",
"joblib.dump(X_train, 'output/X_train.pkl')\n",
"joblib.dump(X_test, 'output/X_test.pkl')\n",
"joblib.dump(y_train, 'output/y_train.pkl')\n",
"joblib.dump(y_test, 'output/y_test.pkl')\n",
"\n",
"print(\"✅ SELESAI TAHAP 1. Data sudah siap!\")\n",
"print(\"👉 Silakan lanjut jalankan '2_training.py' atau '2_training.ipynb'\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "15e21017",
"metadata": {},
"outputs": [],
"source": [
"# 2 pelatihan model SVM, KNN dan ensemble\n",
"import joblib\n",
"import pandas as pd\n",
"import os\n",
"from sklearn.svm import SVC\n",
"from sklearn.neighbors import KNeighborsClassifier\n",
"from sklearn.ensemble import VotingClassifier\n",
"from sklearn.model_selection import GridSearchCV\n",
"\n",
"print(\"🏋️ [TAHAP 2] Training: DATA ASLI (Tanpa Penyeimbang Apapun)...\")\n",
"\n",
"# 0. CEK KEAMANAN: Pastikan folder dan file Tahap 1 sudah ada\n",
"if not os.path.exists('output/X_train.pkl'):\n",
" raise FileNotFoundError(\"❌ File 'output/X_train.pkl' tidak ditemukan! Pastikan kamu sudah menjalankan '1_preprocessing.py' terlebih dahulu.\")\n",
"os.makedirs('models', exist_ok=True) # Jaga-jaga kalau folder models terhapus\n",
"\n",
"# 1. AMBIL DATA DARI TAHAP 1\n",
"print(\" - Memuat data latih...\")\n",
"X_train = joblib.load('output/X_train.pkl')\n",
"y_train = joblib.load('output/y_train.pkl')\n",
"\n",
"print(f\" - Jumlah Data Latih Asli: {len(y_train)} baris\")\n",
"print(f\" - Komposisi Label: {y_train.value_counts().to_dict()}\")\n",
"\n",
"# ---------------------------------------------------------\n",
"# 2. LATIH SVM (MODEL UTAMA)\n",
"# ---------------------------------------------------------\n",
"print(\"\\n🚀 Melatih SVM (Mencari Settingan Terbaik)...\")\n",
"print(\" (Mohon tunggu, ini akan memakan waktu beberapa menit ☕)\")\n",
"\n",
"param_svm = {\n",
" 'C': [0.1, 1, 10],\n",
" 'kernel': ['linear', 'rbf'],\n",
" 'gamma': ['scale', 'auto']\n",
"}\n",
"\n",
"# n_jobs=-1 artinya kita memakai seluruh \"otak\" CPU laptop agar cepat selesai\n",
"svm_grid = GridSearchCV(SVC(probability=True, random_state=42), param_svm, cv=3, verbose=1, n_jobs=-1)\n",
"svm_grid.fit(X_train, y_train) \n",
"\n",
"best_svm = svm_grid.best_estimator_\n",
"joblib.dump(best_svm, 'models/model_svm.pkl')\n",
"print(f\" ✅ SVM Selesai (Akurasi Validasi: {svm_grid.best_score_*100:.2f}%)\")\n",
"\n",
"# ---------------------------------------------------------\n",
"# 3. LATIH KNN (METRIC COSINE)\n",
"# ---------------------------------------------------------\n",
"print(\"\\n🚀 Melatih KNN (Wajib Cosine)...\")\n",
"\n",
"param_knn = {\n",
" 'n_neighbors': [3, 5, 7, 9, 11, 15], \n",
" 'metric': ['cosine'] \n",
"}\n",
"\n",
"knn_grid = GridSearchCV(KNeighborsClassifier(), param_knn, cv=3, verbose=1, n_jobs=-1)\n",
"knn_grid.fit(X_train, y_train)\n",
"\n",
"best_knn = knn_grid.best_estimator_\n",
"joblib.dump(best_knn, 'models/model_knn.pkl')\n",
"print(f\" ✅ KNN Selesai (Best K: {knn_grid.best_params_['n_neighbors']})\")\n",
"\n",
"# ---------------------------------------------------------\n",
"# 4. LATIH ENSEMBLE (SVM + KNN)\n",
"# ---------------------------------------------------------\n",
"print(\"\\n🚀 Melatih ENSEMBLE (Voting SVM + KNN)...\")\n",
"\n",
"# Gabungkan dua model terbaik\n",
"ensemble_model = VotingClassifier(\n",
" estimators=[\n",
" ('svm', best_svm), \n",
" ('knn', best_knn)\n",
" ],\n",
" voting='soft',\n",
" weights=[2, 1] # SVM kita beri bobot suara lebih tinggi\n",
")\n",
"\n",
"ensemble_model.fit(X_train, y_train)\n",
"joblib.dump(ensemble_model, 'models/model_ensemble.pkl')\n",
"print(\" ✅ Ensemble Selesai.\")\n",
"\n",
"print(\"\\n==================================================\")\n",
"print(\"🎉 TRAINING DATA MURNI SELESAI!\")\n",
"print(\"👉 Silakan jalankan '3_evaluasi.py' untuk melihat hasil akhirnya.\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "38511828",
"metadata": {},
"outputs": [],
"source": [
"# 3 evaluasi hasil model\n",
"import joblib\n",
"import matplotlib.pyplot as plt\n",
"import seaborn as sns\n",
"from sklearn.metrics import accuracy_score, classification_report, confusion_matrix\n",
"import os\n",
"\n",
"print(\"📊 [TAHAP 3] Evaluasi Hasil Model...\")\n",
"\n",
"# 0. CEK KEAMANAN\n",
"if not os.path.exists('output/X_test.pkl'):\n",
" raise FileNotFoundError(\"❌ File 'output/X_test.pkl' tidak ditemukan! Pastikan Tahap 1 sudah dijalankan.\")\n",
"if not os.path.exists('models/model_svm.pkl'):\n",
" raise FileNotFoundError(\"❌ File 'models/model_svm.pkl' tidak ditemukan! Pastikan Tahap 2 sudah selesai 100%.\")\n",
"\n",
"# Bikin folder images otomatis\n",
"os.makedirs('images', exist_ok=True)\n",
"\n",
"# 1. Ambil Data Uji\n",
"print(\" - Memuat data uji...\")\n",
"X_test = joblib.load('output/X_test.pkl')\n",
"y_test = joblib.load('output/y_test.pkl')\n",
"\n",
"# 2. Daftar Model (CUMA 3 SEKARANG)\n",
"print(\" - Memuat model-model AI...\")\n",
"daftar_model = {\n",
" \"SVM\": joblib.load('models/model_svm.pkl'),\n",
" \"KNN\": joblib.load('models/model_knn.pkl'),\n",
" \"Ensemble\": joblib.load('models/model_ensemble.pkl')\n",
"}\n",
"\n",
"# 3. Loop Evaluasi\n",
"for nama, model in daftar_model.items():\n",
" print(f\"\\n==========================================\")\n",
" print(f\"--- Evaluasi Model: {nama} ---\")\n",
" print(f\"==========================================\")\n",
"\n",
" # Lakukan Prediksi\n",
" y_pred = model.predict(X_test)\n",
" \n",
" # Hitung Akurasi\n",
" acc = accuracy_score(y_test, y_pred)\n",
" print(f\"🎯 Akurasi {nama}: {acc*100:.2f}%\\n\")\n",
" \n",
" # Laporan Lengkap (Precision, Recall, F1-Score)\n",
" print(\"📋 Laporan Klasifikasi:\")\n",
" print(classification_report(y_test, y_pred))\n",
"\n",
" # Bikin Grafik Confusion Matrix\n",
" cm = confusion_matrix(y_test, y_pred)\n",
" plt.figure(figsize=(7, 5))\n",
" sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', \n",
" annot_kws={\"size\": 14}) # Angka di dalam kotak diperbesar\n",
" \n",
" # Hiasan Grafik (Lebih rapi untuk masuk ke buku Skripsi)\n",
" plt.title(f'Confusion Matrix - {nama}\\n(Akurasi: {acc*100:.2f}%)', fontsize=14, fontweight='bold', pad=15)\n",
" plt.xlabel('Prediksi Mesin', fontsize=12, fontweight='bold')\n",
" plt"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ff1f299c",
"metadata": {},
"outputs": [],
"source": [
"# 3.2 Menampilkan Distribusi Data\n",
"# Menampilkan perbandingan jumlah data dan tampilan grafik perbandingan data\n",
"import pandas as pd\n",
"import matplotlib.pyplot as plt\n",
"import seaborn as sns\n",
"import os\n",
"\n",
"# Pastikan folder images ada untuk menyimpan hasil\n",
"os.makedirs('images', exist_ok=True)\n",
"\n",
"# ==========================================\n",
"# 1. LOAD DATA\n",
"# ==========================================\n",
"nama_file = r'd:\\project skripsi machine learning intoleransi\\virtualEnvironment\\dataset\\dataYangDiPakai\\data_label_revisi_goblog.csv'\n",
"\n",
"print(f\"📂 Membaca file: {nama_file}...\")\n",
"df = pd.read_csv(nama_file, sep=';') \n",
"\n",
"# ==========================================\n",
"# 2. HITUNG JUMLAH LABEL\n",
"# ==========================================\n",
"# Kita pastikan kolom 'label' ada\n",
"if 'label' not in df.columns:\n",
" raise ValueError(\"❌ Kolom 'label' tidak ditemukan di dataset! Coba cek separatornya (sep=';' atau sep=',')\")\n",
"\n",
"jumlah_label = df['label'].value_counts().sort_index()\n",
"\n",
"print(\"\\n📊 STATISTIK JUMLAH DATA:\")\n",
"print(\"-\" * 30)\n",
"label_names = {0: \"Netral (0)\", 1: \"Kritik (1)\", 2: \"Hujatan (2)\"}\n",
"for lbl, count in jumlah_label.items():\n",
" print(f\" {label_names.get(lbl, lbl)}: {count} data\")\n",
"print(\"-\" * 30)\n",
"print(f\" TOTAL: {len(df)} data\")\n",
"\n",
"# ==========================================\n",
"# 3. BUAT GRAFIK (VISUALISASI)\n",
"# ==========================================\n",
"plt.figure(figsize=(8, 6)) # Ukuran gambar (Lebar, Tinggi)\n",
"\n",
"# Bikin Bar Chart warna-warni (tambah hue=... agar tidak muncul warning di versi Seaborn terbaru)\n",
"ax = sns.barplot(x=jumlah_label.index, y=jumlah_label.values, hue=jumlah_label.index, palette='viridis', legend=False)\n",
"\n",
"# Hiasan Grafik\n",
"plt.title('Perbandingan Jumlah Data per Label', fontsize=16, fontweight='bold', pad=15)\n",
"plt.xlabel('Kategori Label', fontsize=12, fontweight='bold')\n",
"plt.ylabel('Jumlah Data', fontsize=12, fontweight='bold')\n",
"\n",
"# Pastikan urutan label sesuai dengan 0, 1, 2\n",
"urutan_label = sorted(jumlah_label.index.tolist())\n",
"plt.xticks(ticks=range(len(urutan_label)), labels=['0\\n(Netral)', '1\\n(Kritik)', '2\\n(Hujatan)'])\n",
"plt.grid(axis='y', linestyle='--', alpha=0.5)\n",
"\n",
"# Tampilkan Angka di Atas Batang\n",
"for p in ax.patches:\n",
" ax.annotate(f'{int(p.get_height())}', \n",
" (p.get_x() + p.get_width() / 2., p.get_height()), \n",
" ha='center', va='center', \n",
" xytext=(0, 10), \n",
" textcoords='offset points',\n",
" fontsize=14, fontweight='bold', color='black')\n",
"\n",
"# Simpan Gambar di dalam folder 'images'\n",
"nama_gambar = 'images/grafik_distribusi_data.png'\n",
"plt.savefig(nama_gambar, dpi=300, bbox_inches='tight')\n",
"print(f\"\\n🖼 Grafik berhasil disimpan: {nama_gambar}\")\n",
"\n",
"# Tampilkan gambar di layar\n",
"plt.show()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "c2325607",
"metadata": {},
"outputs": [],
"source": [
"import joblib\n",
"import pandas as pd\n",
"import numpy as np\n",
"import math\n",
"import matplotlib.pyplot as plt\n",
"import os\n",
"from sklearn.neighbors import KNeighborsClassifier\n",
"from sklearn.model_selection import cross_val_score, GridSearchCV\n",
"\n",
"print(\"🔬 [EKSPERIMEN] Membandingkan 3 Metode Mencari Nilai K Terbaik...\")\n",
"\n",
"# 0. CEK KEAMANAN\n",
"if not os.path.exists('output/X_train.pkl'):\n",
" raise FileNotFoundError(\"❌ File 'output/X_train.pkl' tidak ditemukan! Pastikan Tahap 1 sudah dijalankan.\")\n",
"\n",
"# Pastikan folder images ada\n",
"os.makedirs('images', exist_ok=True)\n",
"\n",
"# 1. LOAD DATA\n",
"X_train = joblib.load('output/X_train.pkl')\n",
"y_train = joblib.load('output/y_train.pkl')\n",
"jumlah_data = X_train.shape[0]\n",
"\n",
"print(f\" - Jumlah Data Latih: {jumlah_data} baris\")\n",
"print(\"-\" * 50)\n",
"\n",
"results = [] # Untuk menyimpan hasil perbandingan\n",
"\n",
"# =========================================================\n",
"# METODE 1: AKAR KUADRAT (Square Root Rule)\n",
"# Rumus: K = Akar(Total Data)\n",
"# =========================================================\n",
"print(\"1⃣ Menguji Metode Akar Kuadrat...\")\n",
"k_sqrt = int(math.sqrt(jumlah_data))\n",
"\n",
"# Aturan: K harus ganjil biar gak seri (draw)\n",
"if k_sqrt % 2 == 0:\n",
" k_sqrt += 1\n",
"\n",
"# Uji Akurasinya (Pakai n_jobs=-1 biar ngebut)\n",
"knn_sq = KNeighborsClassifier(n_neighbors=k_sqrt, metric='cosine')\n",
"scores_sq = cross_val_score(knn_sq, X_train, y_train, cv=5, scoring='accuracy', n_jobs=-1)\n",
"acc_sq = scores_sq.mean() * 100\n",
"\n",
"print(f\" -> Hasil: K={k_sqrt}, Akurasi={acc_sq:.2f}%\")\n",
"results.append({'Metode': 'Akar Kuadrat', 'K': k_sqrt, 'Akurasi': acc_sq})\n",
"\n",
"# =========================================================\n",
"# METODE 2: ELBOW METHOD (Metode Siku)\n",
"# Coba manual dari 1 sampai 40, lalu cari error terkecil\n",
"# =========================================================\n",
"print(\"\\n2⃣ Menguji Metode Elbow (Looping 1-40)...\")\n",
"print(\" (Tunggu sebentar, sedang menghitung manual...)\")\n",
"error_rates = []\n",
"acc_rates = []\n",
"k_range = range(1, 41, 2) # Coba angka ganjil: 1, 3, 5, ... 39\n",
"\n",
"best_k_elbow = 0\n",
"best_acc_elbow = 0\n",
"\n",
"for k in k_range:\n",
" knn = KNeighborsClassifier(n_neighbors=k, metric='cosine')\n",
" # Pakai n_jobs=-1 di sini juga biar loopingnya gak kelamaan\n",
" scores = cross_val_score(knn, X_train, y_train, cv=5, scoring='accuracy', n_jobs=-1)\n",
" acc = scores.mean()\n",
"\n",
" # Simpan data buat grafik\n",
" acc_rates.append(acc)\n",
" error_rates.append(1 - acc) # Error = 100% - Akurasi\n",
"\n",
" # Cek apakah ini rekor terbaik?\n",
" if acc > best_acc_elbow:\n",
" best_acc_elbow = acc\n",
" best_k_elbow = k\n",
"\n",
"print(f\" -> Hasil Terbaik di Range Ini: K={best_k_elbow}, Akurasi={best_acc_elbow*100:.2f}%\")\n",
"results.append({'Metode': 'Elbow (Manual)', 'K': best_k_elbow, 'Akurasi': best_acc_elbow*100})\n",
"\n",
"# Bikin Grafik Elbow\n",
"plt.figure(figsize=(10, 6))\n",
"plt.plot(k_range, error_rates, color='red', linestyle='dashed', marker='o',\n",
" markerfacecolor='blue', markersize=8)\n",
"plt.title('Grafik Elbow (Mencari Error Terkecil)', fontsize=14, fontweight='bold', pad=15)\n",
"plt.xlabel('Nilai K', fontsize=12, fontweight='bold')\n",
"plt.ylabel('Tingkat Error', fontsize=12, fontweight='bold')\n",
"plt.grid(True, linestyle='--', alpha=0.6)\n",
"\n",
"# Simpan ke folder images\n",
"nama_gambar_elbow = 'images/grafik_elbow_knn.png'\n",
"plt.savefig(nama_gambar_elbow, dpi=300, bbox_inches='tight')\n",
"print(f\" 🖼️ Grafik Elbow tersimpan: {nama_gambar_elbow}\")\n",
"plt.close() # Tutup grafik biar memori lega\n",
"\n",
"# =========================================================\n",
"# METODE 3: GRID SEARCH CV (Validasi Silang)\n",
"# Ini metode paling 'Sultan' dan Valid\n",
"# =========================================================\n",
"print(\"\\n3⃣ Menguji Metode Grid Search CV (Otomatis)...\")\n",
"param_grid = {'n_neighbors': [3, 5, 7, 9, 11, 15, 19, 21, 25, 29]}\n",
"grid = GridSearchCV(KNeighborsClassifier(metric='cosine'), param_grid, cv=5, scoring='accuracy', n_jobs=-1)\n",
"grid.fit(X_train, y_train)\n",
"\n",
"k_grid = grid.best_params_['n_neighbors']\n",
"acc_grid = grid.best_score_ * 100\n",
"\n",
"print(f\" -> Hasil: K={k_grid}, Akurasi={acc_grid:.2f}%\")\n",
"results.append({'Metode': 'Grid Search CV', 'K': k_grid, 'Akurasi': acc_grid})\n",
"\n",
"# =========================================================\n",
"# KESIMPULAN AKHIR\n",
"# =========================================================\n",
"print(\"\\n\" + \"=\"*50)\n",
"print(\"🏆 TABEL PERBANDINGAN METODE PENENTUAN K\")\n",
"print(\"=\"*50)\n",
"df_res = pd.DataFrame(results)\n",
"print(df_res.to_string(index=False))\n",
"print(\"-\" * 50)\n",
"\n",
"# Cari pemenang\n",
"best_method = df_res.loc[df_res['Akurasi'].idxmax()]\n",
"print(f\"✅ REKOMENDASI: Gunakan K = {best_method['K']}\")\n",
"print(f\" (Berdasarkan metode {best_method['Metode']} dengan akurasi tertinggi)\")"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "virtualEnvironment",
"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.11.9"
}
},
"nbformat": 4,
"nbformat_minor": 5
}