XRachel commited on
Commit
ef057b4
·
verified ·
1 Parent(s): 1358466

Upload 9 files

Browse files
Files changed (10) hide show
  1. .gitattributes +1 -0
  2. Dockerfile +19 -0
  3. README.md +18 -5
  4. app.py +67 -0
  5. assets/BankChurn.png +3 -0
  6. gitattributes +36 -0
  7. models/gitkeep +0 -0
  8. requirements.txt +6 -0
  9. scripts/pipeline.py +31 -0
  10. style.css +171 -0
.gitattributes CHANGED
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ assets/BankChurn.png filter=lfs diff=lfs merge=lfs -text
Dockerfile ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ FROM python:3.11-slim
3
+
4
+ ENV PYTHONDONTWRITEBYTECODE=1
5
+ ENV PYTHONUNBUFFERED=1
6
+ ENV GRADIO_SERVER_NAME=0.0.0.0
7
+ ENV GRADIO_SERVER_PORT=7860
8
+
9
+ WORKDIR /app
10
+
11
+ COPY requirements.txt /app/requirements.txt
12
+
13
+ RUN pip install --no-cache-dir --upgrade pip && pip install --no-cache-dir -r requirements.txt
14
+
15
+ COPY . /app
16
+
17
+ EXPOSE 7860
18
+
19
+ CMD ["python","-u","app.py"]
README.md CHANGED
@@ -1,10 +1,23 @@
 
1
  ---
2
- title: RX12 BankChurnPredictor
3
- emoji: 👀
4
- colorFrom: red
5
  colorTo: yellow
6
  sdk: docker
7
- pinned: false
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
  ---
3
+ title: Bank Churn Predictor
4
+ emoji: 🏦
5
+ colorFrom: blue
6
  colorTo: yellow
7
  sdk: docker
8
+ app_port: 7860
9
  ---
10
 
11
+ # Bank Churn Predictor
12
+
13
+ A stable HuggingFace Docker Space demo.
14
+
15
+ Features
16
+ - Run Pipeline (train model)
17
+ - Execution log viewer
18
+ - Single prediction UI
19
+ - Background image support
20
+
21
+ The pipeline trains a simple model and saves:
22
+
23
+ models/pipeline.joblib
app.py ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ import os
3
+ import subprocess
4
+ import gradio as gr
5
+ import pandas as pd
6
+ import joblib
7
+
8
+ MODEL_PATH="models/pipeline.joblib"
9
+
10
+ def load_model():
11
+ if os.path.exists(MODEL_PATH):
12
+ return joblib.load(MODEL_PATH)
13
+ return None
14
+
15
+ model=load_model()
16
+
17
+ def predict(age,balance):
18
+ global model
19
+ model=load_model()
20
+ if model is None:
21
+ return "Run pipeline first"
22
+ df=pd.DataFrame([[age,balance]],columns=["Age","Balance"])
23
+ p=model.predict(df)[0]
24
+ return f"Prediction: {p}"
25
+
26
+ def run_pipeline():
27
+ proc=subprocess.Popen(
28
+ ["python","scripts/pipeline.py"],
29
+ stdout=subprocess.PIPE,
30
+ stderr=subprocess.STDOUT,
31
+ text=True
32
+ )
33
+ log=""
34
+ for line in proc.stdout:
35
+ log+=line
36
+ yield log
37
+
38
+ def build_ui():
39
+ css=open("style.css").read()
40
+
41
+ with gr.Blocks() as demo:
42
+
43
+ gr.HTML(f"<style>{css}</style>")
44
+
45
+ gr.Markdown("# 🏦 Bank Churn Predictor")
46
+
47
+ with gr.Tab("Pipeline"):
48
+ gr.Markdown("Train model and view execution log")
49
+ btn=gr.Button("Run Pipeline")
50
+ log=gr.Textbox(lines=20,label="Execution Log")
51
+ btn.click(run_pipeline,outputs=log)
52
+
53
+ with gr.Tab("Prediction"):
54
+ age=gr.Number(label="Age")
55
+ balance=gr.Number(label="Balance")
56
+ btn=gr.Button("Predict")
57
+ out=gr.Textbox()
58
+
59
+ btn.click(predict,[age,balance],out)
60
+
61
+ return demo
62
+
63
+ if __name__=="__main__":
64
+ demo=build_ui()
65
+ demo.queue()
66
+ port=int(os.environ.get("PORT",7860))
67
+ demo.launch(server_name="0.0.0.0",server_port=port)
assets/BankChurn.png ADDED

Git LFS Details

  • SHA256: 48b87571101ec591bdaaae990cf2ccf7ffc3b4cb6d0aa9c106d5372ad988ac7d
  • Pointer size: 132 Bytes
  • Size of remote file: 2.01 MB
gitattributes ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ *.7z filter=lfs diff=lfs merge=lfs -text
2
+ *.arrow filter=lfs diff=lfs merge=lfs -text
3
+ *.bin filter=lfs diff=lfs merge=lfs -text
4
+ *.bz2 filter=lfs diff=lfs merge=lfs -text
5
+ *.ckpt filter=lfs diff=lfs merge=lfs -text
6
+ *.ftz filter=lfs diff=lfs merge=lfs -text
7
+ *.gz filter=lfs diff=lfs merge=lfs -text
8
+ *.h5 filter=lfs diff=lfs merge=lfs -text
9
+ *.joblib filter=lfs diff=lfs merge=lfs -text
10
+ *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
+ *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
+ *.model filter=lfs diff=lfs merge=lfs -text
13
+ *.msgpack filter=lfs diff=lfs merge=lfs -text
14
+ *.npy filter=lfs diff=lfs merge=lfs -text
15
+ *.npz filter=lfs diff=lfs merge=lfs -text
16
+ *.onnx filter=lfs diff=lfs merge=lfs -text
17
+ *.ot filter=lfs diff=lfs merge=lfs -text
18
+ *.parquet filter=lfs diff=lfs merge=lfs -text
19
+ *.pb filter=lfs diff=lfs merge=lfs -text
20
+ *.pickle filter=lfs diff=lfs merge=lfs -text
21
+ *.pkl filter=lfs diff=lfs merge=lfs -text
22
+ *.pt filter=lfs diff=lfs merge=lfs -text
23
+ *.pth filter=lfs diff=lfs merge=lfs -text
24
+ *.rar filter=lfs diff=lfs merge=lfs -text
25
+ *.safetensors filter=lfs diff=lfs merge=lfs -text
26
+ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
+ *.tar.* filter=lfs diff=lfs merge=lfs -text
28
+ *.tar filter=lfs diff=lfs merge=lfs -text
29
+ *.tflite filter=lfs diff=lfs merge=lfs -text
30
+ *.tgz filter=lfs diff=lfs merge=lfs -text
31
+ *.wasm filter=lfs diff=lfs merge=lfs -text
32
+ *.xz filter=lfs diff=lfs merge=lfs -text
33
+ *.zip filter=lfs diff=lfs merge=lfs -text
34
+ *.zst filter=lfs diff=lfs merge=lfs -text
35
+ *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ assets/Bank[[:space:]]Churn.png filter=lfs diff=lfs merge=lfs -text
models/gitkeep ADDED
File without changes
requirements.txt ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ gradio>=4.0
2
+ pandas
3
+ numpy
4
+ scikit-learn
5
+ joblib
6
+ matplotlib
scripts/pipeline.py ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ import pandas as pd
3
+ from sklearn.linear_model import LogisticRegression
4
+ from sklearn.model_selection import train_test_split
5
+ import joblib, os
6
+
7
+ print("===== STEP 1: Load Data =====")
8
+
9
+ data = pd.DataFrame({
10
+ "Age":[25,45,33,52,23,40,60,48],
11
+ "Balance":[1000,5000,2300,8000,1200,4500,9000,3000],
12
+ "Exited":[0,1,0,1,0,1,1,0]
13
+ })
14
+
15
+ print("Dataset ready")
16
+
17
+ print("===== STEP 2: Train Model =====")
18
+
19
+ X=data[["Age","Balance"]]
20
+ y=data["Exited"]
21
+
22
+ X_train,X_test,y_train,y_test=train_test_split(X,y,test_size=0.2)
23
+
24
+ model=LogisticRegression()
25
+ model.fit(X_train,y_train)
26
+
27
+ os.makedirs("models",exist_ok=True)
28
+ joblib.dump(model,"models/pipeline.joblib")
29
+
30
+ print("Model saved to models/pipeline.joblib")
31
+ print("Pipeline finished")
style.css ADDED
@@ -0,0 +1,171 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* ===== 1. 整页背景图 ===== */
2
+ html, body {
3
+ margin: 0 !important;
4
+ padding: 0 !important;
5
+ min-height: 100vh !important;
6
+ background-color: rgb(15, 23, 42) !important;
7
+ background-image: url("https://huggingface.co/spaces/XRachel/bc4/resolve/main/assets/BankChurn.png") !important;
8
+ background-position: top center !important;
9
+ background-repeat: no-repeat !important;
10
+ background-size: 100% auto !important;
11
+ background-attachment: scroll !important;
12
+ }
13
+
14
+ /* 兼容 Gradio 外层容器 */
15
+ gradio-app,
16
+ .gradio-app,
17
+ #app,
18
+ [data-testid="app"],
19
+ .main,
20
+ .app {
21
+ background: transparent !important;
22
+ min-height: 100vh !important;
23
+ }
24
+
25
+ /* ===== 2. 主容器区域 ===== */
26
+ .gradio-container {
27
+ max-width: 1400px !important;
28
+ width: 94vw !important;
29
+ margin: 0 auto !important;
30
+ padding-top: 140px !important;
31
+ padding-bottom: 80px !important;
32
+ background: transparent !important;
33
+ }
34
+
35
+ /* ===== 3. 页面主体卡片 ===== */
36
+ .gradio-container > .main,
37
+ .gradio-container .contain,
38
+ .gradio-container .wrap {
39
+ background: transparent !important;
40
+ }
41
+
42
+ /* 给主要内容区一个半透明白色卡片效果 */
43
+ .gr-block,
44
+ .gr-box,
45
+ .gr-panel,
46
+ .gr-group,
47
+ .form {
48
+ background: rgba(255, 255, 255, 0.92) !important;
49
+ border-radius: 16px !important;
50
+ border: 1px solid rgba(255, 255, 255, 0.55) !important;
51
+ box-shadow: 0 8px 30px rgba(0, 0, 0, 0.12) !important;
52
+ }
53
+
54
+ /* ===== 4. 标题样式 ===== */
55
+ h1 {
56
+ color: #ffffff !important;
57
+ font-size: 3rem !important;
58
+ font-weight: 800 !important;
59
+ text-align: left !important;
60
+ margin: 0 0 18px 0 !important;
61
+ text-shadow: 0 2px 10px rgba(0, 0, 0, 0.35) !important;
62
+ }
63
+
64
+ /* 普通文字 */
65
+ h2, h3, h4, p, label, span, .gr-markdown, .prose {
66
+ color: #111827 !important;
67
+ }
68
+
69
+ /* ===== 5. Tabs ===== */
70
+ .tabs > .tab-nav,
71
+ .tab-nav,
72
+ div[role="tablist"] {
73
+ background: rgba(255, 255, 255, 0.85) !important;
74
+ border-radius: 12px 12px 0 0 !important;
75
+ padding: 6px !important;
76
+ border: 1px solid rgba(17, 24, 39, 0.08) !important;
77
+ }
78
+
79
+ .tabs > .tab-nav button,
80
+ .tab-nav button,
81
+ div[role="tablist"] button,
82
+ button[role="tab"] {
83
+ color: #374151 !important;
84
+ font-weight: 600 !important;
85
+ border: none !important;
86
+ background: transparent !important;
87
+ padding: 10px 20px !important;
88
+ border-radius: 10px 10px 0 0 !important;
89
+ opacity: 1 !important;
90
+ }
91
+
92
+ .tabs > .tab-nav button.selected,
93
+ .tab-nav button.selected,
94
+ button[role="tab"][aria-selected="true"],
95
+ div[role="tablist"] button[aria-selected="true"] {
96
+ color: #f59e0b !important;
97
+ background: rgba(15, 23, 42, 0.05) !important;
98
+ font-weight: 700 !important;
99
+ }
100
+
101
+ .tabitem {
102
+ background: rgba(255, 255, 255, 0.94) !important;
103
+ border-radius: 0 0 14px 14px !important;
104
+ padding: 18px !important;
105
+ border: 1px solid rgba(17, 24, 39, 0.08) !important;
106
+ border-top: none !important;
107
+ }
108
+
109
+ /* ===== 6. 输入框 / 文本框 ===== */
110
+ input,
111
+ textarea,
112
+ select {
113
+ background: #ffffff !important;
114
+ color: #111827 !important;
115
+ border: 1px solid #d1d5db !important;
116
+ border-radius: 12px !important;
117
+ box-shadow: none !important;
118
+ }
119
+
120
+ textarea {
121
+ font-family: monospace !important;
122
+ font-size: 0.9rem !important;
123
+ }
124
+
125
+ /* ===== 7. 按钮 ===== */
126
+ button:not([role="tab"]) {
127
+ background: linear-gradient(135deg, #1d4ed8, #2563eb) !important;
128
+ color: #ffffff !important;
129
+ border: none !important;
130
+ border-radius: 12px !important;
131
+ padding: 12px 18px !important;
132
+ font-weight: 700 !important;
133
+ box-shadow: 0 6px 18px rgba(37, 99, 235, 0.25) !important;
134
+ }
135
+
136
+ button:not([role="tab"]):hover {
137
+ filter: brightness(1.05) !important;
138
+ }
139
+
140
+ /* ===== 8. 日志框区域更清晰 ===== */
141
+ label[for],
142
+ .gr-textbox,
143
+ [data-testid="textbox"] {
144
+ color: #111827 !important;
145
+ }
146
+
147
+ /* ===== 9. 顶部和底部透明,避免多余灰条 ===== */
148
+ header,
149
+ footer,
150
+ header *,
151
+ footer * {
152
+ background: transparent !important;
153
+ box-shadow: none !important;
154
+ }
155
+
156
+ /* ===== 10. 小屏适配 ===== */
157
+ @media (max-width: 900px) {
158
+ .gradio-container {
159
+ width: 96vw !important;
160
+ padding-top: 70px !important;
161
+ padding-bottom: 40px !important;
162
+ }
163
+
164
+ h1 {
165
+ font-size: 2.1rem !important;
166
+ }
167
+
168
+ .tabitem {
169
+ padding: 12px !important;
170
+ }
171
+ }