Mif_E31230483_KlasifikasiTomat/model_manager.py

236 lines
7.7 KiB
Python

import joblib
import numpy as np
from sklearn.ensemble import RandomForestClassifier
from sklearn.preprocessing import LabelEncoder
import os
class ModelManager:
"""
Kelas untuk mengelola penyimpanan dan pemanggilan model machine learning
"""
def __init__(self, model_path="models"):
"""
Inisialisasi ModelManager
Parameters:
model_path: folder untuk menyimpan model
"""
self.model_path = model_path
self.model = None
self.label_encoder = None
# Buat folder jika belum ada
if not os.path.exists(model_path):
os.makedirs(model_path)
print(f"Folder '{model_path}' dibuat")
def save_model(self, model, label_encoder, model_name="tomat_classifier"):
"""
Menyimpan model dan label encoder ke file .pkl
Parameters:
model: model machine learning yang sudah trained
label_encoder: label encoder untuk kelas
model_name: nama file model
"""
# Path lengkap untuk file model
model_file = os.path.join(self.model_path, f"{model_name}.pkl")
encoder_file = os.path.join(self.model_path, f"{model_name}_encoder.pkl")
try:
# Simpan model
joblib.dump(model, model_file)
print(f"Model berhasil disimpan: {model_file}")
# Simpan label encoder
joblib.dump(label_encoder, encoder_file)
print(f"Label encoder berhasil disimpan: {encoder_file}")
# Simpan metadata
metadata = {
'model_name': model_name,
'model_type': type(model).__name__,
'classes': label_encoder.classes_.tolist(),
'n_features': model.n_features_in_ if hasattr(model, 'n_features_in_') else None
}
metadata_file = os.path.join(self.model_path, f"{model_name}_metadata.pkl")
joblib.dump(metadata, metadata_file)
print(f"Metadata berhasil disimpan: {metadata_file}")
return True
except Exception as e:
print(f"Error menyimpan model: {e}")
return False
def load_model(self, model_name="tomat_classifier"):
"""
Memuat model dan label encoder dari file .pkl
Parameters:
model_name: nama file model
Returns:
tuple: (model, label_encoder) atau (None, None) jika gagal
"""
# Path lengkap untuk file model
model_file = os.path.join(self.model_path, f"{model_name}.pkl")
encoder_file = os.path.join(self.model_path, f"{model_name}_encoder.pkl")
try:
# Muat model
self.model = joblib.load(model_file)
print(f"Model berhasil dimuat: {model_file}")
# Muat label encoder
self.label_encoder = joblib.load(encoder_file)
print(f"Label encoder berhasil dimuat: {encoder_file}")
# Tampilkan informasi model
self.print_model_info(model_name)
return self.model, self.label_encoder
except FileNotFoundError:
print(f"Error: File model tidak ditemukan: {model_file}")
return None, None
except Exception as e:
print(f"Error memuat model: {e}")
return None, None
def print_model_info(self, model_name):
"""
Menampilkan informasi model yang dimuat
"""
if self.model is not None and self.label_encoder is not None:
print(f"\n{'='*50}")
print("INFORMASI MODEL")
print(f"{'='*50}")
print(f"Nama Model: {model_name}")
print(f"Tipe Model: {type(self.model).__name__}")
print(f"Kelas: {list(self.label_encoder.classes_)}")
if hasattr(self.model, 'n_features_in_'):
print(f"Jumlah Fitur: {self.model.n_features_in_}")
if hasattr(self.model, 'n_estimators'):
print(f"Jumlah Estimators: {self.model.n_estimators}")
print(f"{'='*50}")
def predict(self, features):
"""
Melakukan prediksi menggunakan model yang dimuat
Parameters:
features: array fitur untuk prediksi
Returns:
prediksi: hasil prediksi (label kelas)
prediksi_proba: probabilitas prediksi (jika ada)
"""
if self.model is None or self.label_encoder is None:
print("Error: Model belum dimuat. Gunakan load_model() terlebih dahulu")
return None, None
try:
# Prediksi
predictions = self.model.predict(features)
# Konversi ke label kelas
class_predictions = self.label_encoder.inverse_transform(predictions)
# Probabilitas (jika model mendukung)
if hasattr(self.model, 'predict_proba'):
probabilities = self.model.predict_proba(features)
return class_predictions, probabilities
else:
return class_predictions, None
except Exception as e:
print(f"Error saat prediksi: {e}")
return None, None
def predict_single(self, feature):
"""
Melakukan prediksi untuk satu sampel
Parameters:
feature: array fitur tunggal
Returns:
prediksi: hasil prediksi (label kelas)
"""
# Reshape untuk single sample
feature = np.array(feature).reshape(1, -1)
predictions, _ = self.predict(feature)
if predictions is not None:
return predictions[0]
else:
return None
def example_usage():
"""
Contoh penggunaan ModelManager
"""
print("CONTOH PENGGUNAAN MODEL MANAGER")
print("="*50)
# 1. Buat model dummy
print("\n1. Membuat dan training model...")
model = RandomForestClassifier(n_estimators=10, random_state=42)
# Data dummy
X_train = np.random.rand(100, 24) # 24 fitur (8 bin x 3 channel RGB)
y_train = np.random.choice([0, 1, 2], 100) # 3 kelas
# Training
model.fit(X_train, y_train)
# Label encoder
label_encoder = LabelEncoder()
label_encoder.fit(['matang', 'mentah', 'setengah_matang'])
# 2. Simpan model
print("\n2. Menyimpan model...")
manager = ModelManager("models")
success = manager.save_model(model, label_encoder, "tomat_rf_model")
if success:
print("Model berhasil disimpan!")
# 3. Muat model
print("\n3. Memuat model...")
loaded_model, loaded_encoder = manager.load_model("tomat_rf_model")
if loaded_model is not None:
print("Model berhasil dimuat!")
# 4. Test prediksi
print("\n4. Melakukan prediksi...")
# Data test
X_test = np.random.rand(5, 24)
# Prediksi
predictions, probabilities = manager.predict(X_test)
if predictions is not None:
print("Hasil prediksi:")
for i, (pred, prob) in enumerate(zip(predictions, probabilities)):
print(f"Sampel {i+1}: {pred}")
print(f" Probabilitas: matang={prob[0]:.3f}, mentah={prob[1]:.3f}, setengah_matang={prob[2]:.3f}")
# 5. Prediksi single
print("\n5. Prediksi single sample...")
single_feature = np.random.rand(24)
single_pred = manager.predict_single(single_feature)
print(f"Hasil prediksi single: {single_pred}")
if __name__ == "__main__":
example_usage()