jung-ming commited on
Commit
1f1a361
·
verified ·
1 Parent(s): 9aa9b35

Upload 2 files

Browse files
Files changed (2) hide show
  1. app.py +84 -0
  2. requirements.txt +9 -0
app.py ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 建立 .streamlit/config.toml 避免 Hugging Face 權限錯誤
2
+ import os
3
+ os.makedirs(".streamlit", exist_ok=True)
4
+ with open(".streamlit/config.toml", "w") as f:
5
+ f.write("""
6
+ [server]
7
+ headless = true
8
+ port = 7860
9
+ enableCORS = true
10
+ """)
11
+
12
+ import streamlit as st
13
+ import joblib
14
+ import pandas as pd
15
+ import shap
16
+ import matplotlib.pyplot as plt
17
+ import platform
18
+ from huggingface_hub import hf_hub_download
19
+
20
+ # 跨平台字型設定
21
+ if platform.system() == 'Windows':
22
+ plt.rcParams['font.family'] = 'Microsoft JhengHei'
23
+ elif platform.system() == 'Darwin': # macOS
24
+ plt.rcParams['font.family'] = 'AppleGothic'
25
+ else:
26
+ plt.rcParams['font.family'] = 'Noto Sans CJK TC' # Linux
27
+
28
+ plt.rcParams['axes.unicode_minus'] = False # 負號使用 ASCII 減號
29
+
30
+ @st.cache_resource(show_spinner=True)
31
+ def load_model_and_explainer():
32
+ # 下載模型與 LabelEncoder
33
+ model_path = hf_hub_download(
34
+ repo_id="jung-ming/Ocean-Meets-Forest",
35
+ filename="rf_model_with_encoder.pkl",
36
+ repo_type="model"
37
+ )
38
+ bundle = joblib.load(model_path)
39
+ model = bundle["model"]
40
+ le = bundle["label_encoder"]
41
+
42
+ # 建立 explainer(避免用 pickle 載入 Numba 編譯物件)
43
+ explainer = shap.TreeExplainer(model, feature_perturbation="interventional")
44
+
45
+ return model, le, explainer
46
+
47
+ model, le, explainer = load_model_and_explainer()
48
+
49
+ # 建立映射
50
+ ship_type_to_code = dict(zip(le.classes_, le.transform(le.classes_)))
51
+
52
+ st.title("🚢 台中港艘次預測系統")
53
+ st.markdown("請輸入以下資訊,模型將預測該月艘次數")
54
+
55
+ port_count = st.selectbox("航線組合數", list(range(1, 100)))
56
+ year = st.selectbox("年", [2020, 2021, 2022, 2023, 2024, 2025])
57
+ month = st.selectbox("月", list(range(1, 13)))
58
+ ship_type = st.selectbox("船舶種類", list(ship_type_to_code.keys()))
59
+
60
+ if st.button("🔮 開始預測"):
61
+ ship_type_encoded = ship_type_to_code[ship_type]
62
+ input_df = pd.DataFrame({
63
+ "航線組合數": [port_count],
64
+ "年": [year],
65
+ "月": [month],
66
+ "船舶種類_編碼": [ship_type_encoded]
67
+ })
68
+ pred = model.predict(input_df)[0]
69
+ st.success(f"預測結果:🚢 約為 {pred:.2f} 艘次")
70
+
71
+ st.subheader("🧠 模型決策解釋圖(SHAP Waterfall)")
72
+
73
+ shap_values = explainer(input_df)
74
+ fig, ax = plt.subplots(figsize=(8, 4))
75
+ shap.plots.waterfall(shap_values[0], show=False)
76
+
77
+ # 修正負號顯示問題
78
+ for text in ax.texts:
79
+ if text.get_text().startswith('\u2212'):
80
+ new_text = text.get_text().replace('\u2212', '-')
81
+ text.set_text(new_text)
82
+
83
+ st.pyplot(fig)
84
+ plt.close(fig)
requirements.txt ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ streamlit
2
+ pandas
3
+ joblib
4
+ matplotlib
5
+ shap
6
+ scikit-learn
7
+ huggingface_hub
8
+ requests
9
+