MIF_E31231708/ml/predict.py

89 lines
2.9 KiB
Python

import argparse
import tempfile
from pathlib import Path
import joblib
from audio_utils import SUPPORTED_AUDIO_EXTENSIONS, convert_to_wav
from features import LABEL_PD, LABEL_TPD, extract_features
BASE_DIR = Path(__file__).resolve().parent
MODEL_PATH = BASE_DIR / "models" / "svm_voice_confidence_model.joblib"
CONFIDENCE_THRESHOLD = 0.60
LABEL_DESCRIPTION = {
LABEL_PD: "Percaya Diri",
LABEL_TPD: "Tidak Percaya Diri",
}
def prepare_audio_for_prediction(audio_path):
"""
Menyiapkan audio prediksi menjadi WAV mono 22050 Hz.
Path hasil konversi dikembalikan bersama flag apakah file temporer perlu dihapus.
"""
audio_path = Path(audio_path)
extension = audio_path.suffix.lower()
if extension not in SUPPORTED_AUDIO_EXTENSIONS:
allowed = ", ".join(sorted(SUPPORTED_AUDIO_EXTENSIONS))
raise ValueError(f"Format audio tidak didukung: {extension}. Format yang didukung: {allowed}")
temp_wav_path = Path(tempfile.NamedTemporaryFile(delete=False, suffix=".wav").name)
convert_to_wav(audio_path, temp_wav_path)
return temp_wav_path
def predict_audio(audio_path, model_path=MODEL_PATH):
"""
Memprediksi satu file audio.
Audio diproses dengan preprocessing dan ekstraksi fitur yang sama seperti training.
"""
model = joblib.load(model_path)
temp_wav_path = prepare_audio_for_prediction(audio_path)
try:
features = extract_features(temp_wav_path).reshape(1, -1)
predicted_label = model.predict(features)[0]
probabilities = model.predict_proba(features)[0]
class_probabilities = dict(zip(model.classes_, probabilities))
confidence = class_probabilities[predicted_label]
finally:
temp_wav_path.unlink(missing_ok=True)
return predicted_label, LABEL_DESCRIPTION[predicted_label], confidence, class_probabilities
def main():
parser = argparse.ArgumentParser(description="Prediksi tingkat percaya diri dari audio")
parser.add_argument("audio_path", help="Path file audio yang ingin diprediksi")
args = parser.parse_args()
audio_path = Path(args.audio_path)
if not audio_path.exists():
raise FileNotFoundError(f"File tidak ditemukan: {audio_path}")
label, description, confidence, probabilities = predict_audio(audio_path)
probability_pd = probabilities.get(LABEL_PD, 0.0)
probability_tpd = probabilities.get(LABEL_TPD, 0.0)
print("=== Hasil Prediksi ===")
print(f"File : {audio_path}")
print(f"Prediksi : {label}")
print(f"Keterangan : {description}")
print(f"Confidence : {confidence * 100:.2f}%")
print(f"Probabilitas PD : {probability_pd * 100:.2f}%")
print(f"Probabilitas TPD : {probability_tpd * 100:.2f}%")
if confidence < CONFIDENCE_THRESHOLD:
print(
"Peringatan : Model belum yakin, suara perlu direkam ulang "
"atau data training perlu ditambah."
)
if __name__ == "__main__":
main()