TIF_E41211245/Code Python/training_lvq.ipynb

415 lines
39 KiB
Plaintext

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**LIBRARY**"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [],
"source": [
"import seaborn as sns\n",
"import matplotlib.pyplot as plt\n",
"import numpy as np\n",
"import sklearn.preprocessing as pre\n",
"from sklearn.model_selection import train_test_split\n",
"from sklearn.metrics import accuracy_score, confusion_matrix, classification_report\n",
"import joblib\n",
"import pickle\n",
"from scipy.spatial.distance import euclidean"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**LOAD DATASET**"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [],
"source": [
"X = np.load(\"E:\\! KULIAHHH\\Ivano Kuliah\\!SEMESTER 8\\!SKRIPSI\\Data Suara\\!REVISI\\hasil_ekstrak_mfcc_v2/X_train.npy\")\n",
"y = np.load(\"E:\\! KULIAHHH\\Ivano Kuliah\\!SEMESTER 8\\!SKRIPSI\\Data Suara\\!REVISI\\hasil_ekstrak_mfcc_v2/y_train.npy\")"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [],
"source": [
"folder = \"E:/! KULIAHHH/Ivano Kuliah/!SEMESTER 8/!SKRIPSI/Data Suara/!REVISI/hasil_ekstrak_mfcc_v2\"\n",
"files_names = np.load(os.path.join(folder, \"file_names.npy\"))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**ENCODE LABEL**"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [],
"source": [
"# Encode label menjadi angka\n",
"label_encoder = pre.LabelEncoder()\n",
"y_encoded = label_encoder.fit_transform(y)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**SPLIT DATASET**"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [],
"source": [
"# Split data menjadi training (80%) dan testing (20%)\n",
"X_train, X_test, y_train, y_test, fname_train, fname_test = train_test_split(\n",
" X, y_encoded, files_names, test_size=0.3, random_state=42\n",
")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**MODEL LVQ MANUAL**"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [],
"source": [
"class LVQ:\n",
" def __init__(self, n_classes, n_prototypes=2, learning_rate=0.01, epochs=200):\n",
" self.n_classes = n_classes\n",
" self.n_prototypes = n_prototypes\n",
" self.learning_rate = learning_rate\n",
" self.epochs = epochs\n",
" self.prototypes = None\n",
" self.prototype_labels = None\n",
"\n",
" def fit(self, X, y):\n",
" np.random.seed(42)\n",
"\n",
" # Inisialisasi prototype\n",
" self.prototypes = []\n",
" self.prototype_labels = []\n",
"\n",
" for label in np.unique(y):\n",
" idx = np.where(y == label)[0]\n",
" chosen = np.random.choice(idx, self.n_prototypes, replace=False)\n",
" self.prototypes.extend(X[chosen])\n",
" self.prototype_labels.extend([label] * self.n_prototypes)\n",
"\n",
" self.prototypes = np.array(self.prototypes)\n",
" self.prototype_labels = np.array(self.prototype_labels)\n",
"\n",
" # Training LVQ\n",
" for epoch in range(self.epochs):\n",
" for i in range(len(X)):\n",
" sample = X[i]\n",
" label = y[i]\n",
"\n",
" # Cari prototype terdekat\n",
" distances = np.linalg.norm(self.prototypes - sample, axis=1)\n",
" winner_idx = np.argmin(distances)\n",
"\n",
" # Update prototype\n",
" if self.prototype_labels[winner_idx] == label:\n",
" self.prototypes[winner_idx] += self.learning_rate * (sample - self.prototypes[winner_idx])\n",
" else:\n",
" self.prototypes[winner_idx] -= self.learning_rate * (sample - self.prototypes[winner_idx])\n",
"\n",
" # Learning rate decay\n",
" self.learning_rate *= 0.95\n",
"\n",
" def predict(self, X):\n",
" y_pred = []\n",
" for sample in X:\n",
" distances = np.linalg.norm(self.prototypes - sample, axis=1)\n",
" winner_idx = np.argmin(distances)\n",
" y_pred.append(self.prototype_labels[winner_idx])\n",
" return np.array(y_pred)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**INISIASI MODEL LVQ**"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [],
"source": [
"# Inisialisasi model LVQ\n",
"lvq_model = LVQ(n_classes=len(set(y_encoded)), n_prototypes=2, learning_rate=0.01, epochs=200)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**TRAINING MODEL**"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [],
"source": [
"# Training model\n",
"lvq_model.fit(X_train, y_train)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**PREDIKSI DATA UJI**"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {},
"outputs": [],
"source": [
"# Prediksi data uji\n",
"y_pred = lvq_model.predict(X_test)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**EVALUASI MODEL**"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"❌ Data yang salah diklasifikasi:\n",
"File: Negatif/mindrabodoh3 - Copy.wav, Label Sebenarnya: Negatif, Prediksi: Positif\n",
"File: Negatif/mindrabodoh7.wav, Label Sebenarnya: Negatif, Prediksi: Positif\n",
"File: Negatif/mindrabodoh9.wav, Label Sebenarnya: Negatif, Prediksi: Positif\n",
"File: Negatif/mindralicik5 - Copy.wav, Label Sebenarnya: Negatif, Prediksi: Positif\n",
"File: Negatif/mindrabodoh9 - Copy.wav, Label Sebenarnya: Negatif, Prediksi: Positif\n",
"File: Negatif/mindrabodoh8 - Copy.wav, Label Sebenarnya: Negatif, Prediksi: Positif\n",
"\n",
"🔍 Analisis Kemiripan Fitur untuk Data yang Salah Klasifikasi:\n",
"\n",
"\n",
"❌ File: Negatif/mindrabodoh3 - Copy.wav\n",
" Label Sebenarnya: Negatif\n",
" Diprediksi sebagai: Positif\n",
" 🔗 5 Data yang Paling Mirip dalam Kelas Prediksi:\n",
" - Positif/mindrarajin1 - Copy.wav (jarak: 209.37)\n",
" - Positif/mindrarajin10 - Copy.wav (jarak: 211.16)\n",
" - Positif/mindrabaik9.wav (jarak: 215.43)\n",
" - Positif/mindrarajin2.wav (jarak: 216.10)\n",
" - Positif/mindrarajin4 - Copy.wav (jarak: 219.32)\n",
"\n",
"❌ File: Negatif/mindrabodoh7.wav\n",
" Label Sebenarnya: Negatif\n",
" Diprediksi sebagai: Positif\n",
" 🔗 5 Data yang Paling Mirip dalam Kelas Prediksi:\n",
" - Positif/mindrarajin7.wav (jarak: 185.26)\n",
" - Positif/mindrarajin2.wav (jarak: 196.76)\n",
" - Positif/mindrarajin4 - Copy.wav (jarak: 198.24)\n",
" - Positif/mindrarajin1 - Copy.wav (jarak: 210.42)\n",
" - Positif/mindrarajin10 - Copy.wav (jarak: 217.06)\n",
"\n",
"❌ File: Negatif/mindrabodoh9.wav\n",
" Label Sebenarnya: Negatif\n",
" Diprediksi sebagai: Positif\n",
" 🔗 5 Data yang Paling Mirip dalam Kelas Prediksi:\n",
" - Positif/mindrabaik9.wav (jarak: 207.28)\n",
" - Positif/mindrarajin7.wav (jarak: 207.65)\n",
" - Positif/mindrabaik6.wav (jarak: 211.79)\n",
" - Positif/mindrabaik6 - Copy.wav (jarak: 211.79)\n",
" - Positif/mindrarajin10 - Copy.wav (jarak: 213.56)\n",
"\n",
"❌ File: Negatif/mindralicik5 - Copy.wav\n",
" Label Sebenarnya: Negatif\n",
" Diprediksi sebagai: Positif\n",
" 🔗 5 Data yang Paling Mirip dalam Kelas Prediksi:\n",
" - Positif/mindrarajin7.wav (jarak: 187.50)\n",
" - Positif/mindrarajin1 - Copy.wav (jarak: 212.67)\n",
" - Positif/mindrarajin10 - Copy.wav (jarak: 217.59)\n",
" - Positif/mindrarajin2.wav (jarak: 220.47)\n",
" - Positif/mindrarajin4 - Copy.wav (jarak: 243.20)\n",
"\n",
"❌ File: Negatif/mindrabodoh9 - Copy.wav\n",
" Label Sebenarnya: Negatif\n",
" Diprediksi sebagai: Positif\n",
" 🔗 5 Data yang Paling Mirip dalam Kelas Prediksi:\n",
" - Positif/mindrabaik9.wav (jarak: 207.28)\n",
" - Positif/mindrarajin7.wav (jarak: 207.65)\n",
" - Positif/mindrabaik6.wav (jarak: 211.79)\n",
" - Positif/mindrabaik6 - Copy.wav (jarak: 211.79)\n",
" - Positif/mindrarajin10 - Copy.wav (jarak: 213.56)\n",
"\n",
"❌ File: Negatif/mindrabodoh8 - Copy.wav\n",
" Label Sebenarnya: Negatif\n",
" Diprediksi sebagai: Positif\n",
" 🔗 5 Data yang Paling Mirip dalam Kelas Prediksi:\n",
" - Positif/mindrarajin1 - Copy.wav (jarak: 225.91)\n",
" - Positif/mindrarajin10 - Copy.wav (jarak: 229.82)\n",
" - Positif/mindrarajin7.wav (jarak: 242.93)\n",
" - Positif/mindrarajin2.wav (jarak: 245.35)\n",
" - Positif/mindrarajin4 - Copy.wav (jarak: 247.69)\n"
]
},
{
"data": {
"image/png": "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9uv1ggULBqxN9AEEAAAIE5kzZ5bq1avLokWLPPuSkpLMde+M4NUiAwgAABBGdAqYjh07ys033yy33nqrjBkzRk6dOmVGBQcKASCuaZpS1460dBAHIg/vb9iqTZs2cujQIXnxxRdl//79UrVqVVmwYEGKgSFXg0EgAAAAlqEPIAAAgGUIAAEAACxDAAgAAGAZAkBARK6//nozyspNO93eeeedki1bNsmVK1dI2wbgH0uXLhXHceTYsWOXPI73M3B5BIAIuocfftj80R45cqTP/k8++cTsT09Tp071+wGwdu1a6datm+f66NGjZd++fbJx40bZunVrurYRiJT3vG46p1mpUqVk6NChcv78+au639tvv928L3V1EMX7GbhyBIBIF1myZJFXXnlFjh49KuEoX758kjVrVs/1HTt2mIk4S5cuLfnz5w9p24Br0V133WWCrm3btkm/fv3MmqevvfbaVd2nBpO6EsLlvjjyfgYujwAQ6aJRo0bmD7cu7H4xK1askDp16khMTIwULVpUevfubSa+dNMPk7vvvtvcXqJECZk1a1aKUs+oUaOkUqVKptSj9/H444/LyZMnPeUjnURT1xV1ZyfcC3F7349e/uijj+S9994zx2g2A0Da6Nx9+p4vXry4PPbYY+ZvwGeffWa+BHbo0EFy585tgrSmTZuaINHtjz/+kObNm5vb9X1csWJF+eKLL1KUgHk/A1eHABDpQtc1HD58uIwfP17++uuvFLfrN3TNGLRu3Vo2b94ss2fPNgFhz549Pcfoh4Yukq1/+PUP+ttvvy0HDx70uZ+oqCgZN26c/PzzzzJt2jRZvHixWUDbXT7SDwVdVF6DSd369+/vt3ykbfn3v/9tjhk7dmxQnhPAJvrFLTEx0QRg69atM8HgqlWrRKeibdasmZw7d84c16NHD0lISJDly5fLjz/+aCoH2bNnT3F/vJ+Bq8NKIEg39913n5nNXGf2nzRpks9tmhls166dPPnkk+a6lmo0kKtXr55MnDhRfv/9d/nmm2/MH3NdGke9++675jhv7p93f/MfNmyYdO/eXd58801TPtK+Q5oFuNSC2lo+0uyFfmAFcuFtwEYa4OkapgsXLjTZPu37+91335kATs2cOdNk63X//fffL7t37zZfBDWTr0qWLOn3fnk/A1eHABDpSr/NN2jQIMU39U2bNpnMn34YeH9w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",
"text/plain": [
"<Figure size 800x600 with 2 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"✅ Training selesai! Akurasi: 91.78%\n",
"\n",
"📊 Classification Report:\n",
"\n",
" precision recall f1-score support\n",
"\n",
" Negatif 1.00 0.85 0.92 41\n",
" Positif 0.84 1.00 0.91 32\n",
"\n",
" accuracy 0.92 73\n",
" macro avg 0.92 0.93 0.92 73\n",
"weighted avg 0.93 0.92 0.92 73\n",
"\n"
]
}
],
"source": [
"# Evaluasi model\n",
"accuracy = accuracy_score(y_test, y_pred)\n",
"conf_matrix = confusion_matrix(y_test, y_pred)\n",
"class_report = classification_report(y_test, y_pred, target_names=label_encoder.classes_)\n",
"\n",
"# --- Tampilkan data yang salah diklasifikasi ---\n",
"misclassified_indices = np.where(y_pred != y_test)[0]\n",
"\n",
"print(\"❌ Data yang salah diklasifikasi:\")\n",
"for i in misclassified_indices:\n",
" true_label = label_encoder.inverse_transform([y_test[i]])[0]\n",
" pred_label = label_encoder.inverse_transform([y_pred[i]])[0]\n",
" file_name = fname_test[i] # fname_test didapat dari split bersama X_test dan y_test\n",
" print(f\"File: {file_name}, Label Sebenarnya: {true_label}, Prediksi: {pred_label}\")\n",
" \n",
"print(\"\\n🔍 Analisis Kemiripan Fitur untuk Data yang Salah Klasifikasi:\\n\")\n",
"\n",
"for idx in misclassified_indices:\n",
" true_label = y_test[idx]\n",
" pred_label = y_pred[idx]\n",
" file_name = fname_test[idx]\n",
" fitur_miss = X_test[idx]\n",
"\n",
" # Ambil semua indeks dari label hasil prediksi\n",
" pred_indices = np.where(y_test == pred_label)[0]\n",
"\n",
" kemiripan = []\n",
" for i in pred_indices:\n",
" jarak = euclidean(fitur_miss, X_test[i])\n",
" kemiripan.append((i, jarak))\n",
"\n",
" kemiripan.sort(key=lambda x: x[1]) # urutkan dari yang paling mirip\n",
"\n",
" print(f\"\\n❌ File: {file_name}\")\n",
" print(f\" Label Sebenarnya: {label_encoder.inverse_transform([true_label])[0]}\")\n",
" print(f\" Diprediksi sebagai: {label_encoder.inverse_transform([pred_label])[0]}\")\n",
" print(\" 🔗 5 Data yang Paling Mirip dalam Kelas Prediksi:\")\n",
"\n",
" for i, dist in kemiripan[:5]:\n",
" similar_file = fname_test[i]\n",
" print(f\" - {similar_file} (jarak: {dist:.2f})\")\n",
"\n",
"\n",
"# Simpan model LVQ dengan pickle\n",
"with open(\"E:\\! KULIAHHH\\Ivano Kuliah\\!SEMESTER 8\\!SKRIPSI\\Data Suara\\!REVISI\\lvq_model.pkl\", \"wb\") as model_file:\n",
" pickle.dump(lvq_model, model_file)\n",
"\n",
"# Simpan label encoder dengan pickle\n",
"with open(\"E:\\! KULIAHHH\\Ivano Kuliah\\!SEMESTER 8\\!SKRIPSI\\Data Suara\\!REVISI\\label_encoder.pkl\", \"wb\") as encoder_file:\n",
" pickle.dump(label_encoder, encoder_file)\n",
"\n",
"# Visualisasi Confusion Matrix\n",
"plt.figure(figsize=(8, 6))\n",
"sns.heatmap(conf_matrix, annot=True, fmt=\"d\", cmap=\"Blues\", xticklabels=label_encoder.classes_, yticklabels=label_encoder.classes_)\n",
"plt.xlabel(\"Predicted Label\")\n",
"plt.ylabel(\"True Label\")\n",
"plt.title(f\"Confusion Matrix - Akurasi: {accuracy * 100:.2f}%\")\n",
"plt.show()\n",
"\n",
"# Output hasil evaluasi\n",
"print(f\"✅ Training selesai! Akurasi: {accuracy * 100:.2f}%\\n\")\n",
"print(\"📊 Classification Report:\\n\")\n",
"print(class_report)"
]
}
],
"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.0"
}
},
"nbformat": 4,
"nbformat_minor": 2
}