69 lines
2.7 KiB
Python
69 lines
2.7 KiB
Python
# %% [1] IMPORT LIBRARIES & LOAD DATA
|
|
import pandas as pd
|
|
import matplotlib.pyplot as plt
|
|
import seaborn as sns
|
|
from sklearn.model_selection import train_test_split
|
|
from sklearn.ensemble import RandomForestClassifier
|
|
from sklearn.metrics import classification_report, accuracy_score
|
|
import joblib
|
|
|
|
print("--- [STEP 3] Pelatihan Model Random Forest 30 Jurusan ---")
|
|
print("Memuat dataset yang sudah diproses...")
|
|
df = pd.read_csv('dataset_siswa_siap_model.csv')
|
|
|
|
# %% [2] MEMISAHKAN FITUR DAN TARGET (DATA SPLIT)
|
|
print("Membagi fitur dan target...")
|
|
X = df.drop('rekomendasi_jurusan', axis=1)
|
|
y = df['rekomendasi_jurusan']
|
|
|
|
print("Membagi data menjadi data latih (80%) dan data uji (20%)...")
|
|
# Karena ada 30 kelas, stratify sangat wajib agar distribusi per kelas merata
|
|
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42, stratify=y)
|
|
print(f"Jumlah Data Latih: {X_train.shape[0]} | Jumlah Data Uji: {X_test.shape[0]}")
|
|
|
|
# %% [3] TRAINING MODEL RANDOM FOREST (HYPERPARAMETER ANTI-OVERFIT)
|
|
print("\nMelatih model Random Forest...")
|
|
# Dengan data dimensi RIASEC, kita bisa membebaskan pohon sedikit lebih dalam
|
|
rf_model = RandomForestClassifier(
|
|
n_estimators=200, # 200 pohon sudah sangat cukup untuk 30 jurusan
|
|
max_depth=12, # Cegah menghafal terlalu dalam (Anti Overfitting)
|
|
min_samples_split=4, # Split akan terjadi jika minimal ada 4 sampel
|
|
min_samples_leaf=2, # Daun terakhir minimal berisi 2 sampel
|
|
max_features='sqrt',
|
|
class_weight='balanced',
|
|
random_state=42,
|
|
n_jobs=-1
|
|
)
|
|
|
|
rf_model.fit(X_train, y_train)
|
|
print("Proses pelatihan selesai!")
|
|
|
|
# %% [4] EVALUASI MODEL
|
|
print("\nMengevaluasi performa model pada data uji...")
|
|
y_pred = rf_model.predict(X_test)
|
|
|
|
akurasi = accuracy_score(y_test, y_pred)
|
|
print(f"\n======================================")
|
|
print(f"AKURASI MODEL 30 JURUSAN: {akurasi * 100:.2f}%")
|
|
print(f"======================================")
|
|
|
|
print("\nLaporan Detail Prediksi Keseluruhan:")
|
|
print(classification_report(y_test, y_pred))
|
|
|
|
# Cek Feature Importances (Membuktikan bahwa RIASEC akan memiliki bobot besar)
|
|
importances = rf_model.feature_importances_
|
|
feature_names = X.columns
|
|
feature_imp_df = pd.DataFrame({'Fitur': feature_names, 'Bobot': importances}).sort_values('Bobot', ascending=False)
|
|
|
|
plt.figure(figsize=(10, 8))
|
|
sns.barplot(x='Bobot', y='Fitur', data=feature_imp_df, palette='magma')
|
|
plt.title('Tingkat Kepentingan Fitur (Feature Importances)', fontsize=14)
|
|
plt.tight_layout()
|
|
plt.show()
|
|
|
|
# %% [5] SIMPAN MODEL
|
|
print("\nMenyimpan struktur model yang sudah berhasil dilatih...")
|
|
joblib.dump(rf_model, 'model_rekomendasi_15mapel.pkl')
|
|
print("Model berhasil diamankan ke dalam format 'model_rekomendasi_15mapel.pkl'!")
|
|
# %%
|