MIF_E31220954/backend/routes/testingModel.py

179 lines
7.3 KiB
Python

import numpy as np
import pandas as pd
from fastapi import APIRouter, HTTPException, Depends, Query
from sqlalchemy.orm import Session
from sklearn.svm import SVR
from sklearn.preprocessing import MinMaxScaler, StandardScaler
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_absolute_error, mean_squared_error, mean_absolute_percentage_error
import matplotlib.pyplot as plt
from config.db import get_db
from models.index import priceTomat
from middleware.index import verify_token
# Inisialisasi Router
testingModel_router = APIRouter(
prefix="/testing",
tags=["Testing Model SVR"]
)
@testingModel_router.get("/predict", response_model=dict,dependencies=[Depends(verify_token)])
def predict_price(
db: Session = Depends(get_db),
kernel: str = Query("rbf", enum=["linear", "poly", "sigmoid", "rbf"]),
degree: int = Query(3, description="Degree untuk kernel Polynomial"),
coef0: float = Query(0.0, description="Coef0 untuk kernel Polynomial dan Sigmoid"),
C: float = Query(100.0, description="Parameter regulasi C"),
gamma: float = Query(0.1, description="Parameter gamma untuk kernel RBF, Poly, dan Sigmoid"),
epsilon: float = Query(0.01, description="Margin kesalahan untuk SVR")
):
# Ambil data dari database
data = db.query(priceTomat).all()
if not data:
raise HTTPException(status_code=404, detail="Data harga tomat tidak ditemukan")
# Konversi data ke DataFrame
df = pd.DataFrame([{
"Tanggal": item.tanggal,
"Pasar_Bandung": item.pasar_bandung,
"Pasar_Ngunut": item.pasar_ngunut,
"Pasar_Ngemplak": item.pasar_ngemplak,
"Harga_Kemarin": item.ratarata_kemarin,
"Harga_Sekarang": item.ratarata_sekarang
} for item in data])
# Simpan data asli
data_asli = df.to_dict(orient='records')
# Cek apakah data cukup untuk diproses
if df.shape[0] < 3:
raise HTTPException(status_code=400, detail="Data tidak cukup untuk melakukan prediksi")
# Preprocessing
df[['Pasar_Bandung', 'Pasar_Ngunut', 'Pasar_Ngemplak', 'Harga_Kemarin', 'Harga_Sekarang']] = df[['Pasar_Bandung', 'Pasar_Ngunut', 'Pasar_Ngemplak', 'Harga_Kemarin', 'Harga_Sekarang']].apply(pd.to_numeric, errors='coerce')
df.dropna(inplace=True)
df['Tanggal'] = pd.to_datetime(df['Tanggal'])
df['Harga_2Hari_Lalu'] = df['Harga_Kemarin'].shift(1)
# df['Harga_2Hari_Lalu'] = df['Harga_Kemarin'].shift(1).bfill()
df.dropna(inplace=True)
# Simpan hasil preprocessing
hasil_preprocessing = df.to_dict(orient='records')
# Normalisasi Data
# scaler = MinMaxScaler()
# df[['Pasar_Bandung', 'Pasar_Ngunut', 'Pasar_Ngemplak', 'Harga_Kemarin', 'Harga_2Hari_Lalu', 'Harga_Sekarang']] = scaler.fit_transform(df[['Pasar_Bandung', 'Pasar_Ngunut', 'Pasar_Ngemplak', 'Harga_Kemarin', 'Harga_2Hari_Lalu', 'Harga_Sekarang']])
scaler = StandardScaler()
df[['Pasar_Bandung', 'Pasar_Ngunut', 'Pasar_Ngemplak', 'Harga_Kemarin', 'Harga_2Hari_Lalu', 'Harga_Sekarang']] = scaler.fit_transform(df[['Pasar_Bandung', 'Pasar_Ngunut', 'Pasar_Ngemplak', 'Harga_Kemarin', 'Harga_2Hari_Lalu', 'Harga_Sekarang']])
# Simpan hasil normalisasi
hasil_normalisasi = df.to_dict(orient='records')
# Split Data
X = df[['Pasar_Bandung', 'Pasar_Ngunut', 'Pasar_Ngemplak', 'Harga_Kemarin', 'Harga_2Hari_Lalu']]
y = df['Harga_Sekarang']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, shuffle=False)
# Simpan hasil split data
hasil_split_data = {
"X_train": X_train.to_dict(orient='records'),
"X_test": X_test.to_dict(orient='records'),
"y_train": y_train.tolist(),
"y_test": y_test.tolist()
}
# Inisialisasi Model SVR dengan parameter yang dipilih
# svr_params = {
# "kernel": kernel,
# "C": C,
# "gamma": gamma,
# "epsilon": epsilon
# }
# # Jika kernel adalah Polynomial atau Sigmoid, tambahkan coef0
# if kernel in ["poly", "sigmoid"]:
# svr_params["coef0"] = coef0
# # Jika kernel adalah Polynomial, tambahkan degree
# if kernel == "poly":
# svr_params["degree"] = degree
# svr = SVR(**svr_params)
if kernel == "linear":
svr = SVR(kernel="linear", C=C, epsilon=epsilon)
elif kernel == "rbf":
svr = SVR(kernel="rbf", C=C, gamma=gamma, epsilon=epsilon)
elif kernel == "sigmoid":
svr = SVR(kernel="sigmoid", C=C, gamma=gamma, coef0=coef0, epsilon=epsilon)
elif kernel == "poly":
svr = SVR(kernel="poly", C=C, gamma=gamma, coef0=coef0, degree=degree, epsilon=epsilon)
svr.fit(X_train, y_train)
# Prediksi Harga
y_pred = svr.predict(X_test)
# Evaluasi Model
mae = mean_absolute_error(y_test, y_pred)
rmse = np.sqrt(mean_squared_error(y_test, y_pred))
mape = mean_absolute_percentage_error(y_test, y_pred)
# Kembalikan skala data
df_prediksi = df.iloc[len(X_train):].copy()
df_prediksi['Harga_Prediksi'] = y_pred
df_prediksi[['Pasar_Bandung', 'Pasar_Ngunut', 'Pasar_Ngemplak', 'Harga_Kemarin', 'Harga_Sekarang', 'Harga_Prediksi']] = scaler.inverse_transform(df_prediksi[['Pasar_Bandung', 'Pasar_Ngunut', 'Pasar_Ngemplak', 'Harga_Kemarin', 'Harga_Sekarang', 'Harga_Prediksi']])
# Simpan hasil prediksi
hasil_prediksi = df_prediksi[['Tanggal', 'Pasar_Bandung', 'Pasar_Ngunut', 'Pasar_Ngemplak', 'Harga_Kemarin', 'Harga_Sekarang', 'Harga_Prediksi']].to_dict(orient='records')
# Cek jumlah data bernilai 0 awal
zero_data_log = {"Sebelum Preprocessing": (df == 0).sum().to_dict()}
# Konversi ke numerik dan hitung 0 setelah konversi
df[['Pasar_Bandung', 'Pasar_Ngunut', 'Pasar_Ngemplak', 'Harga_Kemarin', 'Harga_Sekarang']] = df[['Pasar_Bandung', 'Pasar_Ngunut', 'Pasar_Ngemplak', 'Harga_Kemarin', 'Harga_Sekarang']].apply(pd.to_numeric, errors='coerce')
zero_data_log["Setelah Konversi Numerik"] = (df == 0).sum().to_dict()
# Hapus NaN dan hitung 0 setelah drop NaN
df.dropna(inplace=True)
zero_data_log["Setelah Drop NaN Pertama"] = (df == 0).sum().to_dict()
# Konversi tanggal
df['Tanggal'] = pd.to_datetime(df['Tanggal'], errors='coerce')
zero_data_log["Setelah Konversi Tanggal"] = (df == 0).sum().to_dict()
# Tambah fitur Harga_2Hari_Lalu
df['Harga_2Hari_Lalu'] = df['Harga_Kemarin'].shift(1)
zero_data_log["Setelah Tambah Harga_2Hari_Lalu"] = (df == 0).sum().to_dict()
# Drop NaN setelah penambahan fitur dan hitung 0
df.dropna(inplace=True)
zero_data_log["Setelah Drop NaN Kedua"] = (df == 0).sum().to_dict()
# Kembalikan semua hasil dalam JSON
return {
"Kernel_Digunakan": kernel,
"Degree": degree if kernel == "poly" else None,
"Coef0": coef0 if kernel in ["poly", "sigmoid"] else None,
"C": C,
"Gamma": gamma,
"Epsilon": epsilon,
"Zero_Data_Log": zero_data_log,
"Data_Asli": data_asli,
"Hasil_Preprocessing": hasil_preprocessing,
"Hasil_Normalisasi": hasil_normalisasi,
"Hasil_Split_Data": hasil_split_data,
"Hasil_Prediksi": hasil_prediksi,
"Evaluasi_Model": {
"MAE": mae,
"RMSE": rmse,
"MAPE": mape
}
}