Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -152,27 +152,27 @@ def get_lagged_stock_data(date_str, tickers=("DHI", "LEN", "^SP500-60"), lag_day
|
|
| 152 |
# 4. PREDICTION FUNCTION (DIPERBAIKI)
|
| 153 |
# ==============================================================================
|
| 154 |
def predict_sale_amount(assessed_value, town, property_residential, list_year, prediction_date):
|
|
|
|
| 155 |
# 0. Safety Check
|
| 156 |
if 'model' not in globals() or model is None:
|
| 157 |
-
print("ERROR: Model belum dimuat. Cek path file model.")
|
| 158 |
return 0.0
|
| 159 |
|
| 160 |
-
print("\n--- START PREDICTION ---")
|
| 161 |
|
| 162 |
-
# 1. Validasi Input
|
| 163 |
if assessed_value <= 0: assessed_value = 1.0
|
| 164 |
assessed_value_log = np.log1p(assessed_value)
|
| 165 |
|
| 166 |
-
# 2. Ambil Data Saham
|
| 167 |
dhi, len_stock, sp500 = get_lagged_stock_data(prediction_date)
|
| 168 |
|
| 169 |
-
# 3. Mapping Input
|
| 170 |
clean_town = get_exact_category(town, town_map, fallback='***unknown***')
|
| 171 |
clean_prop = get_exact_category(property_residential, prop_map, fallback='Single family')
|
| 172 |
clean_year = str(list_year)
|
| 173 |
|
| 174 |
-
# 4. Buat DataFrame
|
| 175 |
-
#
|
| 176 |
input_data = pd.DataFrame([[
|
| 177 |
assessed_value_log,
|
| 178 |
clean_town,
|
|
@@ -183,44 +183,50 @@ def predict_sale_amount(assessed_value, town, property_residential, list_year, p
|
|
| 183 |
sp500
|
| 184 |
]], columns=['Assessed Value log', 'Town', 'Property_Residential', 'List Year', 'DHI_lag7', 'LEN_lag7', '^SP500-60_lag7'])
|
| 185 |
|
| 186 |
-
# 5. Set
|
| 187 |
input_data['Town'] = pd.Categorical(input_data['Town'], categories=TRAIN_TOWNS)
|
| 188 |
input_data['Property_Residential'] = pd.Categorical(input_data['Property_Residential'], categories=TRAIN_PROP_TYPES)
|
| 189 |
input_data['List Year'] = pd.Categorical(input_data['List Year'], categories=TRAIN_YEARS)
|
| 190 |
|
| 191 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 192 |
|
| 193 |
-
#
|
| 194 |
-
print("DEBUG CHECK: Memeriksa kesesuaian kolom...")
|
| 195 |
try:
|
| 196 |
-
|
| 197 |
-
if hasattr(model, 'feature_name'):
|
| 198 |
-
expected_cols = model.feature_name()
|
| 199 |
-
current_cols = input_data.columns.tolist()
|
| 200 |
-
|
| 201 |
-
print(f"Model expects: {expected_cols}")
|
| 202 |
-
print(f"We provides: {current_cols}")
|
| 203 |
-
|
| 204 |
-
if expected_cols != current_cols:
|
| 205 |
-
print("!!! CRITICAL WARNING: Kolom tidak cocok! Prediksi pasti gagal.")
|
| 206 |
-
|
| 207 |
-
# 6. Lakukan Prediksi
|
| 208 |
-
print("DEBUG: Executing model.predict()...")
|
| 209 |
pred_log = model.predict(input_data)[0]
|
| 210 |
-
print(f"DEBUG: Raw Log Prediction result: {pred_log}")
|
| 211 |
-
|
| 212 |
pred_val = np.expm1(pred_log)
|
| 213 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 214 |
|
| 215 |
return float(pred_val)
|
| 216 |
|
| 217 |
except Exception as e:
|
| 218 |
-
|
| 219 |
-
import traceback
|
| 220 |
-
traceback.print_exc()
|
| 221 |
-
print(f"ERROR FATAL: {str(e)}")
|
| 222 |
-
|
| 223 |
-
# Return 0.0 agar Gradio tidak blank (tapi kita tahu ada error dari log)
|
| 224 |
return 0.0
|
| 225 |
|
| 226 |
# ==============================================================================
|
|
|
|
| 152 |
# 4. PREDICTION FUNCTION (DIPERBAIKI)
|
| 153 |
# ==============================================================================
|
| 154 |
def predict_sale_amount(assessed_value, town, property_residential, list_year, prediction_date):
|
| 155 |
+
|
| 156 |
# 0. Safety Check
|
| 157 |
if 'model' not in globals() or model is None:
|
|
|
|
| 158 |
return 0.0
|
| 159 |
|
| 160 |
+
print("\n--- 🔍 START PREDICTION PIPELINE ---")
|
| 161 |
|
| 162 |
+
# 1. Validasi Input & Log Transform
|
| 163 |
if assessed_value <= 0: assessed_value = 1.0
|
| 164 |
assessed_value_log = np.log1p(assessed_value)
|
| 165 |
|
| 166 |
+
# 2. Ambil Data Saham (Cached)
|
| 167 |
dhi, len_stock, sp500 = get_lagged_stock_data(prediction_date)
|
| 168 |
|
| 169 |
+
# 3. Mapping Input User ke Format Training
|
| 170 |
clean_town = get_exact_category(town, town_map, fallback='***unknown***')
|
| 171 |
clean_prop = get_exact_category(property_residential, prop_map, fallback='Single family')
|
| 172 |
clean_year = str(list_year)
|
| 173 |
|
| 174 |
+
# 4. Buat DataFrame Input
|
| 175 |
+
# Pastikan urutan kolom ini SAMA PERSIS dengan X_train
|
| 176 |
input_data = pd.DataFrame([[
|
| 177 |
assessed_value_log,
|
| 178 |
clean_town,
|
|
|
|
| 183 |
sp500
|
| 184 |
]], columns=['Assessed Value log', 'Town', 'Property_Residential', 'List Year', 'DHI_lag7', 'LEN_lag7', '^SP500-60_lag7'])
|
| 185 |
|
| 186 |
+
# 5. Set Tipe Data Categorical
|
| 187 |
input_data['Town'] = pd.Categorical(input_data['Town'], categories=TRAIN_TOWNS)
|
| 188 |
input_data['Property_Residential'] = pd.Categorical(input_data['Property_Residential'], categories=TRAIN_PROP_TYPES)
|
| 189 |
input_data['List Year'] = pd.Categorical(input_data['List Year'], categories=TRAIN_YEARS)
|
| 190 |
|
| 191 |
+
# =========================================================================
|
| 192 |
+
# ✨ FITUR BARU: PRINT SEMUA FITUR DENGAN CANTIK
|
| 193 |
+
# =========================================================================
|
| 194 |
+
print(f"\n📊 FINAL INPUT FEATURES (Apa yang dilihat Model):")
|
| 195 |
+
print("="*60)
|
| 196 |
+
print(f"{'FEATURE NAME':<25} | {'RAW VALUE':<20} | {'FINAL VALUE/CODE'}")
|
| 197 |
+
print("-" * 60)
|
| 198 |
+
|
| 199 |
+
for col in input_data.columns:
|
| 200 |
+
raw_val = input_data[col].iloc[0]
|
| 201 |
+
final_display = raw_val
|
| 202 |
+
|
| 203 |
+
# Jika kolom Kategori, kita tampilkan juga Kode Angkanya
|
| 204 |
+
if hasattr(input_data[col], 'cat'):
|
| 205 |
+
code = input_data[col].cat.codes.iloc[0]
|
| 206 |
+
final_display = f"Code: {code}"
|
| 207 |
+
# Warning jika code -1 (Unknown)
|
| 208 |
+
if code == -1: final_display += " ⚠️ (UNKNOWN)"
|
| 209 |
+
|
| 210 |
+
print(f"{col:<25} | {str(raw_val):<20} | {final_display}")
|
| 211 |
+
|
| 212 |
+
print("="*60 + "\n")
|
| 213 |
+
# =========================================================================
|
| 214 |
|
| 215 |
+
# 6. Prediksi
|
|
|
|
| 216 |
try:
|
| 217 |
+
print("🤖 Executing Model Prediction...")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 218 |
pred_log = model.predict(input_data)[0]
|
|
|
|
|
|
|
| 219 |
pred_val = np.expm1(pred_log)
|
| 220 |
+
|
| 221 |
+
print(f"✅ Prediction Success!")
|
| 222 |
+
print(f" > Log Result: {pred_log:.4f}")
|
| 223 |
+
print(f" > Real Price: ${pred_val:,.2f}")
|
| 224 |
+
print("------------------------------------")
|
| 225 |
|
| 226 |
return float(pred_val)
|
| 227 |
|
| 228 |
except Exception as e:
|
| 229 |
+
print(f"❌ PREDICTION ERROR: {str(e)}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 230 |
return 0.0
|
| 231 |
|
| 232 |
# ==============================================================================
|