bichle commited on
Commit
198d222
·
verified ·
1 Parent(s): a1d2c2d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +199 -2
app.py CHANGED
@@ -150,6 +150,44 @@ load_css()
150
  # --- 3. DATA & MODEL LOADING FUNCTIONS (WITH CACHING) ---
151
  # Checklist Items 1 & 2: Cache all heavy operations
152
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
153
  @st.cache_data
154
  def load_feature_data(file_path="data/final_dataset_tree.csv"):
155
  """Loads features and targets, converts index to datetime."""
@@ -238,6 +276,47 @@ else:
238
  st.error("Could not load main data, application cannot continue.")
239
  st.stop()
240
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
241
  # --- 5. GIAO DIỆN SIDEBAR (ĐÃ XÓA) ---
242
  # Toàn bộ phần sidebar đã bị xóa
243
 
@@ -248,7 +327,7 @@ tab1, tab2, tab3, tab4 = st.tabs([
248
  "📑 Project Overview & Methodology",
249
  "🌦️ Live 5-Day Forecast",
250
  "📊 Model Performance & Diagnostics",
251
- "⏱️ Hourly Prediction (Step 8)" # TAB MỚI
252
  ])
253
 
254
  # --- TAB 1: Project Overview ---
@@ -622,4 +701,122 @@ with tab3:
622
  "around 0 and show no pattern over time.")
623
 
624
  else:
625
- st.warning("Loading performance data...")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
150
  # --- 3. DATA & MODEL LOADING FUNCTIONS (WITH CACHING) ---
151
  # Checklist Items 1 & 2: Cache all heavy operations
152
 
153
+ @st.cache_resource
154
+ def load_hourly_aggregate_model():
155
+ """Tải mô hình Daily Champion (Hourly Aggregate) cho metric T+24h."""
156
+ file_path = "data/champion_Hourly_Aggregate_Champion_day_1.pkl"
157
+ try:
158
+ model = joblib.load(file_path)
159
+ return model
160
+ except FileNotFoundError as e:
161
+ st.warning(f"Warning: Daily Aggregate Model not found at: {e.filename}. Using dummy data for T+24h metric.")
162
+ return None
163
+
164
+ @st.cache_resource
165
+ def load_24_hourly_models():
166
+ """Tải 24 mô hình LGBM chuyên biệt (T+1h đến T+24h) cho biểu đồ."""
167
+ hourly_models = {}
168
+
169
+ # Số lượng mô hình bạn muốn tải (chúng ta giả định có 24 file)
170
+ num_horizons = 24
171
+
172
+ try:
173
+ for h in range(1, num_horizons + 1):
174
+ # Giả định file model T+1h đến T+10h là file bạn gửi, các file khác nằm trong 'models/'
175
+ if h <= 10:
176
+ file_path = f"models/lgbm_model_target_temp_next_{h}h.pkl" # Sử dụng tên file bạn gửi
177
+ else:
178
+ file_path = f"models/lgbm_model_target_temp_next_{h}h.pkl" # Giả định path
179
+
180
+ model = joblib.load(file_path)
181
+ hourly_models[h] = model
182
+
183
+ if len(hourly_models) < num_horizons:
184
+ st.warning(f"Warning: Only {len(hourly_models)} hourly models loaded. Graph will be incomplete.")
185
+
186
+ return hourly_models
187
+ except FileNotFoundError as e:
188
+ st.error(f"ERROR: Missing hourly model file: {e.filename}. Cannot generate full hourly graph.")
189
+ return {}
190
+
191
  @st.cache_data
192
  def load_feature_data(file_path="data/final_dataset_tree.csv"):
193
  """Loads features and targets, converts index to datetime."""
 
276
  st.error("Could not load main data, application cannot continue.")
277
  st.stop()
278
 
279
+
280
+ # --- CRITICAL CUSTOMIZATION (Hourly Targets) ---
281
+ HOURLY_TARGET_COLS = ['target_temp_next_24h', 'target_temp_next_48h', 'target_temp_next_72h',
282
+ 'target_temp_next_96h', 'target_temp_next_120h']
283
+
284
+ # Load models và data mới
285
+ hourly_data_df = load_hourly_data(file_path="data/final_hourly_features_demo.xlsx - Sheet1.csv") # Dùng tên file features demo
286
+ hourly_models_24h = load_24_hourly_models() # Dùng 24 mô hình LGBM
287
+ hourly_agg_model = load_hourly_aggregate_model() # Dùng mô hình Aggregate T+24h
288
+
289
+ # Tạo input features cho Hourly (giữ nguyên logic)
290
+ if not hourly_data_df.empty:
291
+ HOURLY_FEATURE_COLS = [col for col in hourly_data_df.columns if col not in HOURLY_TARGET_COLS]
292
+ X_test_hourly = hourly_data_df.loc[TEST_START_DATE:TEST_END_DATE][HOURLY_FEATURE_COLS]
293
+ else:
294
+ X_test_hourly = pd.DataFrame()
295
+
296
+ # --- Định nghĩa Hàm Dự đoán 24h Thực tế ---
297
+ def predict_next_24_hours(input_features: pd.DataFrame, models: dict) -> List[float]:
298
+ """Chạy các mô hình LGBM chuyên biệt (T+1h đến T+24h) để tạo ra 24 điểm dự báo."""
299
+ predictions = []
300
+ num_horizons = len(models)
301
+
302
+ if input_features.empty or not models:
303
+ # Nếu thiếu model, tạo 24 giá trị giả lập dựa trên nhiệt độ hiện tại (temp)
304
+ last_temp = input_features['temp'].iloc[-1] if not input_features.empty else 28.0
305
+ return [last_temp + 1.5 * np.sin(2 * np.pi * (h + 10) / 24) + np.random.normal(0, 0.5)
306
+ for h in range(num_horizons)]
307
+
308
+ # Chạy mô hình Direct Hourly
309
+ for h in range(1, num_horizons + 1):
310
+ try:
311
+ model = models[h]
312
+ # Predict chỉ 1 giá trị
313
+ pred = model.predict(input_features)[0]
314
+ predictions.append(pred)
315
+ except:
316
+ predictions.append(float('nan'))
317
+
318
+ return predictions
319
+
320
  # --- 5. GIAO DIỆN SIDEBAR (ĐÃ XÓA) ---
321
  # Toàn bộ phần sidebar đã bị xóa
322
 
 
327
  "📑 Project Overview & Methodology",
328
  "🌦️ Live 5-Day Forecast",
329
  "📊 Model Performance & Diagnostics",
330
+ "⏱️ Hourly Prediction" # TAB MỚI
331
  ])
332
 
333
  # --- TAB 1: Project Overview ---
 
701
  "around 0 and show no pattern over time.")
702
 
703
  else:
704
+ st.warning("Loading performance data...")
705
+
706
+
707
+ # --- TAB 4: Hourly Prediction ---
708
+ with tab4:
709
+ st.title("Hourly Prediction (Next 24 Hours) 🌡️")
710
+ st.markdown("""
711
+ Phần này sử dụng **24 Mô hình Dự báo Trực tiếp Hàng giờ (Hourly Direct Model)** và các features chi tiết (`lags`, `rolling means`) để cung cấp dự báo nhiệt độ cho 24 giờ tiếp theo.
712
+ """)
713
+
714
+ st.subheader("Forecast Start Time")
715
+
716
+ if not X_test_hourly.empty:
717
+ min_date_hourly = X_test_hourly.index.min().date()
718
+ max_date_hourly = X_test_hourly.index.max().date()
719
+
720
+ selected_date_hourly = st.date_input(
721
+ "Select the day you want the forecast to START from:",
722
+ value=min_date_hourly,
723
+ min_value=min_date_hourly,
724
+ max_value=max_date_hourly,
725
+ format="YYYY-MM-DD"
726
+ )
727
+
728
+ latest_time_for_day = X_test_hourly.index[X_test_hourly.index.date == selected_date_hourly].max()
729
+ input_features_hourly = X_test_hourly.loc[[latest_time_for_day]]
730
+
731
+ st.info(f"The model runs based on data up to the latest known hour: **{latest_time_for_day.strftime('%Y-%m-%d %H:%M:%S')}**")
732
+
733
+ st.divider()
734
+
735
+ # 1. Chạy Dự đoán Hourly (GỌI HÀM THỰC TẾ)
736
+ predictions_24h = predict_next_24_hours(input_features_hourly, hourly_models_24h)
737
+
738
+ # --- TÍNH TOÁN METRIC T+24H CHÍNH XÁC ---
739
+ t_plus_24h_metric = None
740
+ if hourly_agg_model:
741
+ # Model Aggregated Day 1 (từ file bạn gửi) dự đoán T+24h
742
+ try:
743
+ t_plus_24h_metric = hourly_agg_model.predict(input_features_hourly)[0]
744
+ except Exception as e:
745
+ st.error(f"Error predicting T+24h with loaded model: {e}")
746
+
747
+ # 2. Hiển thị Dự đoán T+24h (Tức là giờ đó ngày mai)
748
+ st.subheader(f"Summary Forecast for Next Day (Starting {latest_time_for_day.strftime('%H:%M')})")
749
+
750
+ forecast_start_ts = latest_time_for_day + pd.Timedelta(hours=1)
751
+
752
+ col_daily_pred = st.columns(4)
753
+ with col_daily_pred[0]:
754
+ # Hiển thị T+24h (sử dụng model Aggregated thật nếu có)
755
+ display_value = t_plus_24h_metric if t_plus_24h_metric is not None else predictions_24h[0]
756
+ st.metric(
757
+ label=f"Forecast @ {forecast_start_ts.strftime('%H:%M')} Tomorrow (Day 1 Agg.)",
758
+ value=f"{display_value:.1f}°C"
759
+ )
760
+
761
+ # Sử dụng các giá trị từ 24 điểm dự báo để tính Max/Min/Mean 24h
762
+ if predictions_24h:
763
+ with col_daily_pred[1]:
764
+ st.metric(label="Next 24h Average Temp", value=f"{np.nanmean(predictions_24h):.1f}°C")
765
+ with col_daily_pred[2]:
766
+ st.metric(label="Next 24h Max Temp", value=f"{np.nanmax(predictions_24h):.1f}°C", delta="Peak Heat")
767
+
768
+ st.markdown("---")
769
+
770
+ # 3. Graph: Nhiệt độ Từng Giờ
771
+ st.subheader("Hourly Temperature Breakdown (T+1h to T+24h)")
772
+
773
+ hourly_index = pd.date_range(start=forecast_start_ts, periods=len(predictions_24h), freq='H')
774
+ df_hourly_forecast = pd.DataFrame({
775
+ 'Time': hourly_index,
776
+ 'Temperature': predictions_24h
777
+ }).set_index('Time')
778
+
779
+ fig_hourly = go.Figure()
780
+ fig_hourly.add_trace(go.Scatter(
781
+ x=df_hourly_forecast.index,
782
+ y=df_hourly_forecast['Temperature'],
783
+ mode='lines+markers',
784
+ name='Hourly Forecast',
785
+ line=dict(color='#ff6347', width=2),
786
+ marker=dict(size=6)
787
+ ))
788
+
789
+ fig_hourly.update_layout(
790
+ title="Hourly Temperature Forecast (T+1h to T+24h)",
791
+ xaxis_title="Time",
792
+ yaxis_title="Temperature (°C)",
793
+ template="plotly_white",
794
+ legend=dict(x=0.01, y=0.99)
795
+ )
796
+ st.plotly_chart(fig_hourly, use_container_width=True)
797
+
798
+ # 4. Hiển thị Features Dùng để Dự đoán
799
+ st.markdown("---")
800
+ with st.expander("🔍 Feature Inspector: Hourly Inputs for the Forecast"):
801
+ if not input_features_hourly.empty:
802
+ important_hourly_features = [
803
+ 'temp', 'humidity', 'windspeed', 'cloudcover',
804
+ 'temp_lag_1h', 'humidity_lag_24h', 'temp_diff_24h',
805
+ 'temp_roll_24h_mean', 'humidity_roll_24h_mean',
806
+ 'hour_sin', 'day_of_year_sin'
807
+ ]
808
+
809
+ col_h1, col_h2, col_h3 = st.columns(3)
810
+
811
+ for i, feature in enumerate(important_hourly_features):
812
+ if feature in input_features_hourly.columns:
813
+ value = input_features_hourly[feature].iloc[0]
814
+ label = feature.replace('_', ' ').title()
815
+
816
+ target_col = [col_h1, col_h2, col_h3][i % 3]
817
+ with target_col:
818
+ st.metric(label=label, value=f"{value:.2f}")
819
+ else:
820
+ st.warning("No hourly feature data available for the selected hour.")
821
+ else:
822
+ st.warning("Please wait... Loading hourly data or models.")