236 lines
7.7 KiB
Python
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()
|