MIF_E31231060/machine_learning/generate_history_prediction...

184 lines
4.1 KiB
Python

import pandas as pd
import numpy as np
from sqlalchemy import create_engine, text
import joblib
import os
from datetime import datetime
# =========================
# DB
# =========================
user = "root"
password = ""
host = "localhost"
db = "udd_pmi_module"
engine = create_engine(
f"mysql+pymysql://{user}:{password}@{host}/{db}"
)
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
MODEL_PATH = os.path.join(BASE_DIR, "model.pkl")
saved = joblib.load(MODEL_PATH)
model = saved["model"]
usage_bins = saved["usage_bins"]
# =========================
# AMBIL SEMUA BARANG
# =========================
items = pd.read_sql(
"""
SELECT DISTINCT kode
FROM item_usage_monthly
ORDER BY kode
""",
engine,
)
# =========================
# HAPUS DATA PREDIKSI LAMA
# =========================
with engine.begin() as conn:
conn.execute(text("""
DELETE FROM prediction_results
"""))
# =========================
# FEATURE BUILDER
# =========================
def build_features(history, bulan):
lag = history[-6:]
ma_6 = np.mean(lag)
trend_3 = lag[-1] - np.mean(
[lag[-2], lag[-3], lag[-4]]
)
momentum_1 = lag[-1] - lag[-2]
momentum_2 = lag[-2] - lag[-3]
rolling_std_6 = np.std(
lag,
ddof=1
)
max_6 = np.max(lag)
min_6 = np.min(lag)
range_6 = max_6 - min_6
cv_6 = rolling_std_6 / (ma_6 + 1)
growth_rate = (
(lag[-1] - lag[-2])
/
(lag[-2] + 1)
)
usage_level = pd.cut(
[ma_6],
bins=usage_bins,
labels=False,
include_lowest=True
)[0]
if pd.isna(usage_level):
usage_level = 0
quarter = ((bulan-1)//3)+1
return pd.DataFrame([{
"lag_1":lag[-1],
"lag_2":lag[-2],
"lag_3":lag[-3],
"lag_4":lag[-4],
"lag_5":lag[-5],
"lag_6":lag[-6],
"ma_6":ma_6,
"trend_3":trend_3,
"momentum_1":momentum_1,
"momentum_2":momentum_2,
"rolling_std_6":rolling_std_6,
"max_6":max_6,
"min_6":min_6,
"range_6":range_6,
"cv_6":cv_6,
"growth_rate":growth_rate,
"usage_level":usage_level,
"bulan":bulan,
"quarter":quarter,
"is_awal_tahun":int(
bulan in [1,2,3]
),
"is_tengah_tahun":int(
bulan in [6,7,8]
),
"is_akhir_tahun":int(
bulan in [10,11,12]
)
}])
# =========================
# MAIN
# =========================
results=[]
for kode in items["kode"]:
hist=pd.read_sql(
f"""
SELECT
tahun,
bulan,
total_pemakaian
FROM item_usage_monthly
WHERE kode='{kode}'
ORDER BY tahun,bulan
""",
engine
)
if hist.empty:
continue
hist["total_pemakaian"]=pd.to_numeric(
hist["total_pemakaian"],
errors="coerce"
).fillna(0)
if len(hist)<18:
print(
f"SKIP {kode}: data < 18"
)
continue
target_hist=hist.tail(12)
for idx in target_hist.index:
start_idx=idx-6
history=hist.iloc[
start_idx:idx
]["total_pemakaian"].tolist()
if len(history)<6:
continue
bulan_target=int(
hist.loc[idx,"bulan"]
)
tahun_target=int(
hist.loc[idx,"tahun"]
)
X=build_features(
history,
bulan_target
)
pred_log=model.predict(
X
)[0]
pred=np.expm1(
pred_log
)
pred=np.clip(
round(pred),
0,
None
)
results.append({
"kode":kode,
"bulan_prediksi":bulan_target,
"tahun_prediksi":tahun_target,
"jumlah_prediksi":int(pred),
"tanggal_prediksi":datetime.now().date()
})
# =========================
# INSERT
# =========================
if results:
df_insert=pd.DataFrame(results)
df_insert.to_sql(
"prediction_results",
engine,
if_exists="append",
index=False
)
print("SELESAI")