fix:memperbaiki predictTomat, testingModel dan landingpage

This commit is contained in:
muhamad fais aizat 2025-05-07 17:19:27 +07:00
parent 6408166ced
commit 89ce77b631
5 changed files with 127 additions and 54 deletions

View File

@ -6,7 +6,7 @@ from sqlalchemy import select, insert, text, join, delete
from sklearn.svm import SVR from sklearn.svm import SVR
from sklearn.preprocessing import MinMaxScaler, StandardScaler from sklearn.preprocessing import MinMaxScaler, StandardScaler
from sklearn.model_selection import train_test_split from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_absolute_error, mean_squared_error from sklearn.metrics import mean_absolute_error, mean_squared_error, mean_absolute_percentage_error
from config.db import get_db, conn from config.db import get_db, conn
from models.index import priceTomat, settingPredict, resultPredict from models.index import priceTomat, settingPredict, resultPredict
from datetime import datetime, timedelta from datetime import datetime, timedelta
@ -21,11 +21,26 @@ predict_router = APIRouter(
@predict_router.get("/date") @predict_router.get("/date")
async def read_data(db: Session = Depends(get_db)): async def read_data(db: Session = Depends(get_db)):
try: try:
query = text("SELECT tanggal FROM price_tomat ORDER BY tanggal DESC LIMIT 1;") query = text("""
SELECT
(SELECT pt.tanggal
FROM predict.price_tomat AS pt
JOIN predict.result_predict AS rp ON pt.id = rp.id
ORDER BY rp.id ASC
LIMIT 1 OFFSET 30) AS tanggal_old,
(SELECT tanggal
FROM predict.price_tomat
ORDER BY tanggal DESC
LIMIT 1) AS tanggal_new;
""")
result = db.execute(query).fetchone() result = db.execute(query).fetchone()
if result: if result:
return {"tanggal": result[0]} return {
"tanggal_old": result[0],
"tanggal_new": result[1]
}
else: else:
return {"message": "No data found"} return {"message": "No data found"}
except Exception as e: except Exception as e:
@ -76,6 +91,15 @@ def predict_price(db: Session = Depends(get_db)):
df[['Pasar_Bandung', 'Pasar_Ngunut', 'Pasar_Ngemplak', 'RataRata_Kemarin', 'RataRata_2Hari_Lalu', 'RataRata_Sekarang']] df[['Pasar_Bandung', 'Pasar_Ngunut', 'Pasar_Ngemplak', 'RataRata_Kemarin', 'RataRata_2Hari_Lalu', 'RataRata_Sekarang']]
) )
X = df[['Pasar_Bandung', 'Pasar_Ngunut', 'Pasar_Ngemplak', 'RataRata_Kemarin', 'RataRata_2Hari_Lalu']].values
y = df['RataRata_Sekarang'].values
ids = df['id'].values
tanggal = df['Tanggal'].values
X_train, X_test, y_train, y_test, id_train, id_test, tanggal_train, tanggal_test = train_test_split(
X, y, ids, tanggal, test_size=0.2, shuffle=False
)
# Ambil parameter model dari database # Ambil parameter model dari database
kernel = settings.nama_kernel kernel = settings.nama_kernel
C = float(settings.nilai_c) if settings.nilai_c is not None else 1.0 C = float(settings.nilai_c) if settings.nilai_c is not None else 1.0
@ -110,41 +134,58 @@ def predict_price(db: Session = Depends(get_db)):
X = df[['Pasar_Bandung', 'Pasar_Ngunut', 'Pasar_Ngemplak', 'RataRata_Kemarin', 'RataRata_2Hari_Lalu']].values X = df[['Pasar_Bandung', 'Pasar_Ngunut', 'Pasar_Ngemplak', 'RataRata_Kemarin', 'RataRata_2Hari_Lalu']].values
y = df['RataRata_Sekarang'].values y = df['RataRata_Sekarang'].values
# Latih model dengan semua data yang tersedia # # Latih model dengan semua data yang tersedia
svr.fit(X, y) # svr.fit(X, y)
# Prediksi harga untuk semua tanggal di masa depan # # Prediksi harga untuk semua tanggal di masa depan
for i in range(len(df)): # for i in range(len(df)):
fitur_input = X[i] # fitur_input = X[i]
prediksi = svr.predict([fitur_input])[0] # prediksi = svr.predict([fitur_input])[0]
hasil_prediksi.append(prediksi) # hasil_prediksi.append(prediksi)
# Latih model dengan data latih
svr.fit(X_train, y_train)
# Prediksi untuk data uji
y_pred = svr.predict(X_test)
# Evaluasi Model # Evaluasi Model
mae = mean_absolute_error(y, hasil_prediksi) mae = mean_absolute_error(y_test, y_pred)
rmse = np.sqrt(mean_squared_error(y, hasil_prediksi)) rmse = np.sqrt(mean_squared_error(y_test, y_pred))
mape = np.mean(np.abs((y - hasil_prediksi) / y)) * 100 mape = mean_absolute_percentage_error(y_test, y_pred)
# Simpan hasil ke database jumlah_data_dikirim = 0
for i in range(len(hasil_prediksi)):
id_tomat = df.iloc[i]['id'] # Ambil ID dari tabel price_tomat # Gabungkan hasil prediksi ke data uji
prediksi_value = float(scaler.inverse_transform([[0, 0, 0, 0, 0, hasil_prediksi[i]]])[0][5]) for i in range(len(y_pred)):
id_tomat = id_test[i]
tanggal_pred = tanggal_test[i]
hasil = y_pred[i]
hasil_asli = y_test[i]
# Invers hasil prediksi
dummy_row = np.zeros((1, 6)) # [0, 0, 0, 0, 0, hasil_prediksi]
dummy_row[0][5] = hasil
prediksi_asli = float(scaler.inverse_transform(dummy_row)[0][5])
# Perbarui atau masukkan data baru
existing = db.execute(select(resultPredict).where(resultPredict.c.id == id_tomat)).fetchone() existing = db.execute(select(resultPredict).where(resultPredict.c.id == id_tomat)).fetchone()
if existing: if existing:
db.execute( db.execute(
resultPredict.update() resultPredict.update()
.where(resultPredict.c.id == id_tomat) .where(resultPredict.c.id == id_tomat)
.values(hasil_prediksi=prediksi_value) .values(hasil_prediksi=prediksi_asli)
) )
else: else:
db.execute(insert(resultPredict).values(id=id_tomat, hasil_prediksi=prediksi_value)) db.execute(insert(resultPredict).values(id=id_tomat, hasil_prediksi=prediksi_asli))
jumlah_data_dikirim += 1
db.commit() db.commit()
return { return {
"Kernel": kernel, "Kernel": kernel,
"Evaluasi": { "MAE": mae, "RMSE": rmse, "MAPE": mape }, "Evaluasi": { "MAE": mae, "RMSE": rmse, "MAPE": mape },
"Jumlah_data_dikirim": jumlah_data_dikirim,
"Pesan": "Prediksi seluruh data berhasil disimpan ke database" "Pesan": "Prediksi seluruh data berhasil disimpan ke database"
} }
@ -256,7 +297,7 @@ def get_price_history(
# 10. Evaluasi Model # 10. Evaluasi Model
mae = mean_absolute_error(y_test, y_pred) mae = mean_absolute_error(y_test, y_pred)
rmse = np.sqrt(mean_squared_error(y_test, y_pred)) rmse = np.sqrt(mean_squared_error(y_test, y_pred))
mape = np.mean(np.abs((y_test - y_pred) / y_test)) * 100 mape = mape = mean_absolute_percentage_error(y_test, y_pred)
# 11. Prediksi 30 Hari ke Depan # 11. Prediksi 30 Hari ke Depan
@ -311,7 +352,7 @@ def get_price_history(
else: else:
# Ambil data historis jika tanggal bukan yang terbaru # Ambil data historis jika tanggal bukan yang terbaru
start_date = tanggal_input - timedelta(days=30) start_date = tanggal_input - timedelta(days=29)
end_date = tanggal_input end_date = tanggal_input
query = ( query = (

View File

@ -125,34 +125,58 @@ def predict_price(
# Kembalikan skala data # Kembalikan skala data
df_prediksi = df.iloc[len(X_train):].copy() df_prediksi = df.iloc[len(X_train):].copy()
df_prediksi['Tanggal'] = df_prediksi['Tanggal'].dt.date
df_prediksi['Harga_Prediksi'] = y_pred 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 # Daftar kolom yang telah dinormalisasi
hasil_prediksi = df_prediksi[['Tanggal', 'Pasar_Bandung', 'Pasar_Ngunut', 'Pasar_Ngemplak', 'Harga_Kemarin', 'Harga_Sekarang', 'Harga_Prediksi']].to_dict(orient='records') cols_scaled = ['Pasar_Bandung', 'Pasar_Ngunut', 'Pasar_Ngemplak', 'Harga_Kemarin', 'Harga_Sekarang']
# Cek jumlah data bernilai 0 awal # Invers scaling satu per satu kolom berdasarkan mean dan std dari StandardScaler
zero_data_log = {"Sebelum Preprocessing": (df == 0).sum().to_dict()} feature_names = scaler.feature_names_in_.tolist()
# Konversi ke numerik dan hitung 0 setelah konversi # Invers Harga_Prediksi berdasarkan skala 'Harga_Sekarang'
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') index_harga_sekarang = feature_names.index('Harga_Sekarang')
zero_data_log["Setelah Konversi Numerik"] = (df == 0).sum().to_dict() mean_sekarang = scaler.mean_[index_harga_sekarang]
std_sekarang = np.sqrt(scaler.var_[index_harga_sekarang])
df_prediksi['Harga_Prediksi'] = df_prediksi['Harga_Prediksi'] * std_sekarang + mean_sekarang
# Hapus NaN dan hitung 0 setelah drop NaN df_prediksi['Harga_Prediksi'] = df_prediksi['Harga_Prediksi'].round(0)
df.dropna(inplace=True)
zero_data_log["Setelah Drop NaN Pertama"] = (df == 0).sum().to_dict()
# Konversi tanggal # Invers kolom lain yang tersedia di df_prediksi
df['Tanggal'] = pd.to_datetime(df['Tanggal'], errors='coerce') for kolom in cols_scaled:
zero_data_log["Setelah Konversi Tanggal"] = (df == 0).sum().to_dict() if kolom in df_prediksi.columns:
index = feature_names.index(kolom)
mean = scaler.mean_[index]
std = np.sqrt(scaler.var_[index])
df_prediksi[kolom] = df_prediksi[kolom] * std + mean
# Tambah fitur Harga_2Hari_Lalu # Export atau tampilkan hasil
df['Harga_2Hari_Lalu'] = df['Harga_Kemarin'].shift(1) hasil_prediksi = df_prediksi[['Tanggal', 'Pasar_Bandung', 'Pasar_Ngunut', 'Pasar_Ngemplak',
zero_data_log["Setelah Tambah Harga_2Hari_Lalu"] = (df == 0).sum().to_dict() 'Harga_Kemarin', 'Harga_Sekarang', 'Harga_Prediksi']].to_dict(orient='records')
# Drop NaN setelah penambahan fitur dan hitung 0
df.dropna(inplace=True) # # Cek jumlah data bernilai 0 awal
zero_data_log["Setelah Drop NaN Kedua"] = (df == 0).sum().to_dict() # 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()
@ -164,7 +188,7 @@ def predict_price(
"C": C, "C": C,
"Gamma": gamma, "Gamma": gamma,
"Epsilon": epsilon, "Epsilon": epsilon,
"Zero_Data_Log": zero_data_log, # "Zero_Data_Log": zero_data_log,
"Data_Asli": data_asli, "Data_Asli": data_asli,
"Hasil_Preprocessing": hasil_preprocessing, "Hasil_Preprocessing": hasil_preprocessing,
"Hasil_Normalisasi": hasil_normalisasi, "Hasil_Normalisasi": hasil_normalisasi,

View File

@ -1,5 +1,5 @@
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from "react";
import { format, parseISO, isAfter, startOfDay } from "date-fns"; import { format, parseISO, isBefore, isAfter, startOfDay } from "date-fns";
import { CalendarIcon } from "lucide-react"; import { CalendarIcon } from "lucide-react";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
@ -43,6 +43,8 @@ import { useToast } from '@/hooks/use-toast';
const ViewGrafik = ({ date, setDate, dataYAxis, setDataYAxis, priceType, setPriceType, chartData, setChartData, setTabelDataAktual, setTabelDataPredict }) => { const ViewGrafik = ({ date, setDate, dataYAxis, setDataYAxis, priceType, setPriceType, chartData, setChartData, setTabelDataAktual, setTabelDataPredict }) => {
const { toast } = useToast(); const { toast } = useToast();
const [dateTerbaru, setDateTerbaru] = useState(null); const [dateTerbaru, setDateTerbaru] = useState(null);
const [dateTerlama, setDateTerlama] = useState(null);
const oldestDate = dateTerlama ? parseISO(dateTerlama) : null;
const latestDate = dateTerbaru ? parseISO(dateTerbaru) : null; const latestDate = dateTerbaru ? parseISO(dateTerbaru) : null;
const handleDateChange = (selectedDate) => setDate(selectedDate); const handleDateChange = (selectedDate) => setDate(selectedDate);
@ -52,8 +54,9 @@ const ViewGrafik = ({ date, setDate, dataYAxis, setDataYAxis, priceType, setPric
try { try {
const response = await axios.get(`${API_URL}/predict/date`); const response = await axios.get(`${API_URL}/predict/date`);
console.log(response.data.tanggal) console.log(response.data.tanggal_old)
setDateTerbaru(response.data.tanggal) setDateTerbaru(response.data.tanggal_new)
setDateTerlama(response.data.tanggal_old)
} catch (error) { } catch (error) {
console.error("Error fetching data", error); console.error("Error fetching data", error);
} }
@ -119,7 +122,12 @@ const ViewGrafik = ({ date, setDate, dataYAxis, setDataYAxis, priceType, setPric
onSelect={handleDateChange} onSelect={handleDateChange}
initialFocus initialFocus
defaultMonth={latestDate} defaultMonth={latestDate}
disabled={(day) => latestDate && isAfter(startOfDay(day), latestDate)} disabled={(day) =>
// Nonaktifkan tanggal SETELAH tanggal terbaru
(latestDate && isAfter(startOfDay(day), latestDate)) ||
// Nonaktifkan tanggal SEBELUM tanggal terlama
(oldestDate && isBefore(startOfDay(day), oldestDate))
}
/> />
</PopoverContent> </PopoverContent>
</Popover> </Popover>