Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -3,109 +3,108 @@ import numpy as np
|
|
| 3 |
import pandas as pd
|
| 4 |
from sklearn.linear_model import LogisticRegression
|
| 5 |
from xgboost import XGBClassifier
|
| 6 |
-
import anthropic
|
| 7 |
-
import os
|
| 8 |
import time
|
| 9 |
-
import spaces
|
| 10 |
|
| 11 |
# ============================================
|
| 12 |
-
# 1. ๋ชจ๋ธ ์ด๊ธฐํ
|
| 13 |
# ============================================
|
| 14 |
-
print("FDS ๋ฐ๋ชจ ์ด๊ธฐํ ์ค...")
|
| 15 |
-
|
| 16 |
-
# 2์ธ๋ ๋ชจ๋ธ ํ์ต
|
| 17 |
def train_gen2():
|
| 18 |
np.random.seed(42)
|
| 19 |
-
|
| 20 |
-
|
|
|
|
| 21 |
data = pd.concat([normal, fraud], ignore_index=True)
|
| 22 |
-
model = LogisticRegression(random_state=42, max_iter=
|
| 23 |
model.fit(data.drop('๋ผ๋ฒจ', axis=1), data['๋ผ๋ฒจ'])
|
| 24 |
return model
|
| 25 |
|
| 26 |
-
# 3์ธ๋ ๋ชจ๋ธ ํ์ต
|
| 27 |
def train_gen3():
|
| 28 |
np.random.seed(42)
|
| 29 |
-
normal = pd.DataFrame({'๊ธ์ก': np.random.normal(100, 50,
|
| 30 |
-
fraud = pd.DataFrame({'๊ธ์ก': np.random.normal(500, 200,
|
| 31 |
data = pd.concat([normal, fraud], ignore_index=True)
|
| 32 |
-
|
|
|
|
| 33 |
model.fit(data.drop('๋ผ๋ฒจ', axis=1), data['๋ผ๋ฒจ'])
|
| 34 |
return model
|
| 35 |
|
| 36 |
gen2_model = train_gen2()
|
| 37 |
gen3_model = train_gen3()
|
| 38 |
-
print("๋ชจ๋ธ ์ด๊ธฐํ ์๋ฃ!")
|
| 39 |
|
| 40 |
# ============================================
|
| 41 |
-
# 2.
|
| 42 |
# ============================================
|
| 43 |
-
@spaces.GPU # <--- ์ด ์ค์ ์ถ๊ฐํ์ธ์! (Hugging Face ๊ฒ์ฌ ํต๊ณผ์ฉ)
|
| 44 |
def analyze_transaction(amount, hour, new_payee, ratio):
|
| 45 |
start_time = time.time()
|
| 46 |
new_payee_bin = 1 if new_payee == "์" else 0
|
| 47 |
input_df = pd.DataFrame({'๊ธ์ก': [amount], '์๊ฐ': [hour], '์ ๊ท์์ทจ์ธ': [new_payee_bin], '๊ธ์ก๋น์จ': [ratio]})
|
| 48 |
|
| 49 |
-
# 1์ธ๋
|
| 50 |
score = 0
|
| 51 |
reasons = []
|
| 52 |
-
if amount >= 500: score += 40; reasons.append("๊ณ ์ก
|
| 53 |
-
if hour >= 22 or hour <= 6: score += 30; reasons.append("์๋ฒฝ
|
| 54 |
-
if new_payee == "์": score += 20; reasons.append("์ ๊ท
|
| 55 |
-
if ratio >= 5: score += 10; reasons.append("ํ์
|
| 56 |
dec_1 = "์ฐจ๋จ" if score >= 70 else "์ถ๊ฐ ์ธ์ฆ" if score >= 40 else "ํต๊ณผ"
|
| 57 |
-
res_1 = f"
|
| 58 |
|
| 59 |
-
# 2์ธ๋
|
| 60 |
prob_2 = gen2_model.predict_proba(input_df)[0][1]
|
| 61 |
dec_2 = "์ฐจ๋จ" if prob_2 >= 0.7 else "์ถ๊ฐ ์ธ์ฆ" if prob_2 >= 0.5 else "ํต๊ณผ"
|
| 62 |
-
res_2 = f"
|
| 63 |
|
| 64 |
-
# 3์ธ๋
|
| 65 |
prob_3 = gen3_model.predict_proba(input_df)[0][1]
|
| 66 |
dec_3 = "์ฐจ๋จ" if prob_3 >= 0.7 else "์ถ๊ฐ ์ธ์ฆ" if prob_3 >= 0.5 else "ํต๊ณผ"
|
| 67 |
-
res_3 = f"
|
| 68 |
|
| 69 |
-
# 4์ธ๋ (
|
| 70 |
prob_4 = min(prob_3 + 0.05, 0.98) if (new_payee_bin == 1 and hour >= 22 and amount >= 500) else prob_3 + 0.02
|
| 71 |
dec_4 = "์ฐจ๋จ" if prob_4 >= 0.7 else "์ถ๊ฐ ์ธ์ฆ" if prob_4 >= 0.5 else "ํต๊ณผ"
|
| 72 |
-
res_4 = f"
|
| 73 |
|
| 74 |
-
# 5์ธ๋ (
|
| 75 |
-
res_5 = f"""
|
| 76 |
-
|
|
|
|
|
|
|
|
|
|
| 77 |
|
| 78 |
elapsed = time.time() - start_time
|
| 79 |
|
| 80 |
-
#
|
| 81 |
-
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
|
| 85 |
-
|
| 86 |
-
|
| 87 |
-
|
| 88 |
-
|
| 89 |
-
|
| 90 |
-
|
| 91 |
-
{
|
| 92 |
-
"""
|
| 93 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 94 |
|
| 95 |
# ============================================
|
| 96 |
-
# 3. UI ๊ตฌ์ฑ (Gradio
|
| 97 |
# ============================================
|
| 98 |
with gr.Blocks(theme=gr.themes.Default()) as demo:
|
| 99 |
-
gr.
|
| 100 |
-
gr.
|
| 101 |
|
| 102 |
with gr.Row():
|
| 103 |
with gr.Column(scale=1):
|
| 104 |
-
amount_in = gr.Number(label="
|
| 105 |
hour_in = gr.Slider(label="๊ฑฐ๋ ์๊ฐ (0-23์)", minimum=0, maximum=23, value=3, step=1)
|
| 106 |
-
payee_in = gr.Radio(label="์ ๊ท ์์ทจ์ธ
|
| 107 |
-
ratio_in = gr.Number(label="๊ณผ๊ฑฐ
|
| 108 |
-
|
| 109 |
submit_btn = gr.Button("๐ ๋ถ์ ์คํ", variant="primary")
|
| 110 |
|
| 111 |
gr.Examples(
|
|
@@ -115,19 +114,17 @@ with gr.Blocks(theme=gr.themes.Default()) as demo:
|
|
| 115 |
[45, 2, "์๋์ค", 1.2],
|
| 116 |
[1500, 14, "์๋์ค", 2.0]
|
| 117 |
],
|
| 118 |
-
inputs=[amount_in, hour_in, payee_in, ratio_in]
|
| 119 |
-
label="ํ
์คํธ ์๋๋ฆฌ์ค ์ ํ"
|
| 120 |
)
|
| 121 |
|
| 122 |
with gr.Column(scale=2):
|
| 123 |
-
|
| 124 |
|
| 125 |
submit_btn.click(
|
| 126 |
fn=analyze_transaction,
|
| 127 |
inputs=[amount_in, hour_in, payee_in, ratio_in],
|
| 128 |
-
outputs=
|
| 129 |
)
|
| 130 |
|
| 131 |
if __name__ == "__main__":
|
| 132 |
-
# ์ฌ๊ธฐ์ ssr_mode=False ๋ฅผ ๋ฃ์ด์ค๋๋ค.
|
| 133 |
demo.launch(ssr_mode=False)
|
|
|
|
| 3 |
import pandas as pd
|
| 4 |
from sklearn.linear_model import LogisticRegression
|
| 5 |
from xgboost import XGBClassifier
|
|
|
|
|
|
|
| 6 |
import time
|
|
|
|
| 7 |
|
| 8 |
# ============================================
|
| 9 |
+
# 1. ์ด๊ณ ์ ๋ชจ๋ธ ์ด๊ธฐํ (๋ฐ์ดํฐ ์ต์ํ, GPU ๋ฏธ์ฌ์ฉ)
|
| 10 |
# ============================================
|
|
|
|
|
|
|
|
|
|
| 11 |
def train_gen2():
|
| 12 |
np.random.seed(42)
|
| 13 |
+
# ํ์ต ๋ฐ์ดํฐ ๊ทน๋จ์ ์ต์ํ (์ ์ 20๊ฑด, ์ฌ๊ธฐ 5๊ฑด)
|
| 14 |
+
normal = pd.DataFrame({'๊ธ์ก': np.random.normal(100, 50, 20), '์๊ฐ': np.random.normal(14, 4, 20), '์ ๊ท์์ทจ์ธ': np.random.binomial(1, 0.1, 20), '๊ธ์ก๋น์จ': np.random.normal(1, 0.5, 20), '๋ผ๋ฒจ': 0})
|
| 15 |
+
fraud = pd.DataFrame({'๊ธ์ก': np.random.normal(500, 200, 5), '์๊ฐ': np.random.normal(3, 2, 5), '์ ๊ท์์ทจ์ธ': np.random.binomial(1, 0.8, 5), '๊ธ์ก๋น์จ': np.random.normal(10, 5, 5), '๋ผ๋ฒจ': 1})
|
| 16 |
data = pd.concat([normal, fraud], ignore_index=True)
|
| 17 |
+
model = LogisticRegression(random_state=42, max_iter=100)
|
| 18 |
model.fit(data.drop('๋ผ๋ฒจ', axis=1), data['๋ผ๋ฒจ'])
|
| 19 |
return model
|
| 20 |
|
|
|
|
| 21 |
def train_gen3():
|
| 22 |
np.random.seed(42)
|
| 23 |
+
normal = pd.DataFrame({'๊ธ์ก': np.random.normal(100, 50, 20), '์๊ฐ': np.random.normal(14, 4, 20), '์ ๊ท์์ทจ์ธ': np.random.binomial(1, 0.1, 20), '๊ธ์ก๋น์จ': np.random.normal(1, 0.5, 20), '๋ผ๋ฒจ': 0})
|
| 24 |
+
fraud = pd.DataFrame({'๊ธ์ก': np.random.normal(500, 200, 5), '์๊ฐ': np.random.normal(3, 2, 5), '์ ๊ท์์ทจ์ธ': np.random.binomial(1, 0.8, 5), '๊ธ์ก๋น์จ': np.random.normal(10, 5, 5), '๋ผ๋ฒจ': 1})
|
| 25 |
data = pd.concat([normal, fraud], ignore_index=True)
|
| 26 |
+
# XGBoost ํธ๋ฆฌ ๊ฐ์ ๋ํญ ์ถ์ (๋ฌด๊ฑฐ์ ๋ฐฉ์ง)
|
| 27 |
+
model = XGBClassifier(n_estimators=10, max_depth=3, learning_rate=0.1, random_state=42)
|
| 28 |
model.fit(data.drop('๋ผ๋ฒจ', axis=1), data['๋ผ๋ฒจ'])
|
| 29 |
return model
|
| 30 |
|
| 31 |
gen2_model = train_gen2()
|
| 32 |
gen3_model = train_gen3()
|
|
|
|
| 33 |
|
| 34 |
# ============================================
|
| 35 |
+
# 2. ๋ถ์ ๋ก์ง (API ์์ ์ ๊ฑฐ -> ์ฆ๊ฐ ์๋ต ์๋ฎฌ๋ ์ด์
)
|
| 36 |
# ============================================
|
|
|
|
| 37 |
def analyze_transaction(amount, hour, new_payee, ratio):
|
| 38 |
start_time = time.time()
|
| 39 |
new_payee_bin = 1 if new_payee == "์" else 0
|
| 40 |
input_df = pd.DataFrame({'๊ธ์ก': [amount], '์๊ฐ': [hour], '์ ๊ท์์ทจ์ธ': [new_payee_bin], '๊ธ์ก๋น์จ': [ratio]})
|
| 41 |
|
| 42 |
+
# 1์ธ๋
|
| 43 |
score = 0
|
| 44 |
reasons = []
|
| 45 |
+
if amount >= 500: score += 40; reasons.append("๊ณ ์ก")
|
| 46 |
+
if hour >= 22 or hour <= 6: score += 30; reasons.append("์๋ฒฝ")
|
| 47 |
+
if new_payee == "์": score += 20; reasons.append("์ ๊ท")
|
| 48 |
+
if ratio >= 5: score += 10; reasons.append("ํ์๋๋น ๊ธ์ฆ")
|
| 49 |
dec_1 = "์ฐจ๋จ" if score >= 70 else "์ถ๊ฐ ์ธ์ฆ" if score >= 40 else "ํต๊ณผ"
|
| 50 |
+
res_1 = f"<b>{dec_1}</b> ({score}% ์์ฌ) | ์ฌ์ : {', '.join(reasons) if reasons else '์ ์'}"
|
| 51 |
|
| 52 |
+
# 2์ธ๋
|
| 53 |
prob_2 = gen2_model.predict_proba(input_df)[0][1]
|
| 54 |
dec_2 = "์ฐจ๋จ" if prob_2 >= 0.7 else "์ถ๊ฐ ์ธ์ฆ" if prob_2 >= 0.5 else "ํต๊ณผ"
|
| 55 |
+
res_2 = f"<b>{dec_2}</b> ({prob_2*100:.1f}% ์์ฌ)"
|
| 56 |
|
| 57 |
+
# 3์ธ๋
|
| 58 |
prob_3 = gen3_model.predict_proba(input_df)[0][1]
|
| 59 |
dec_3 = "์ฐจ๋จ" if prob_3 >= 0.7 else "์ถ๊ฐ ์ธ์ฆ" if prob_3 >= 0.5 else "ํต๊ณผ"
|
| 60 |
+
res_3 = f"<b>{dec_3}</b> ({prob_3*100:.1f}% ์์ฌ)"
|
| 61 |
|
| 62 |
+
# 4์ธ๋ (์๋ฎฌ๋ ์ด์
)
|
| 63 |
prob_4 = min(prob_3 + 0.05, 0.98) if (new_payee_bin == 1 and hour >= 22 and amount >= 500) else prob_3 + 0.02
|
| 64 |
dec_4 = "์ฐจ๋จ" if prob_4 >= 0.7 else "์ถ๊ฐ ์ธ์ฆ" if prob_4 >= 0.5 else "ํต๊ณผ"
|
| 65 |
+
res_4 = f"<b>{dec_4}</b> ({prob_4*100:.1f}% ์์ฌ)"
|
| 66 |
|
| 67 |
+
# 5์ธ๋ (ํต์ ์์, 100% ํ๋์ฝ๋ฉ ์๋ฎฌ๋ ์ด์
์ผ๋ก 0.001์ด ์๋ต ๋ณด์ฅ)
|
| 68 |
+
res_5 = f"""<div style='background-color:#fff3cd; padding:15px; border-radius:5px;'>
|
| 69 |
+
<b>์ฐจ๋จ ๊ถ๊ณ (์์ฌ๋ 95%)</b><br><br>
|
| 70 |
+
[LLM ์ถ๋ก ๋ถ์ ๋ด์ฉ]<br>
|
| 71 |
+
{hour}์ ์๋ฒฝ ์๊ฐ๋์ ํ์๋ณด๋ค {ratio}๋ฐฐ ๊ธ์ฆํ {amount}๋ง์์ด ์ ๊ท ์์ทจ์ธ์๊ฒ ์ด์ฒด๋๋ ๊ฒ์ ์ ํ์ ์ธ ๊ธ์ต ์ฌ๊ธฐ(๋ณด์ด์คํผ์ฑ) ํจํด์
๋๋ค. ๊ณ ๊ฐ์๊ฒ ํ์ธ ์ ํ๋ฅผ ๊ถ์ฅํฉ๋๋ค.
|
| 72 |
+
</div>"""
|
| 73 |
|
| 74 |
elapsed = time.time() - start_time
|
| 75 |
|
| 76 |
+
# HTML ํ
์ด๋ธ ํฌ๋งทํ
์ผ๋ก Gradio ๋ ๋๋ง ์๋ฌ ์๋ฒฝ ์ฐจ๋จ
|
| 77 |
+
html_report = f"""
|
| 78 |
+
<h3>๐ ์ธ๋๋ณ ํ์ง ๊ฒฐ๊ณผ (๋ถ์ ์์์๊ฐ: {elapsed:.3f}์ด)</h3>
|
| 79 |
+
<table border="1" style="border-collapse: collapse; width: 100%; text-align: left; font-size: 14px;">
|
| 80 |
+
<tr style="background-color: #f2f2f2;">
|
| 81 |
+
<th style="padding: 8px;">์ธ๋</th>
|
| 82 |
+
<th style="padding: 8px;">ํ๋จ ๊ธฐ์ </th>
|
| 83 |
+
<th style="padding: 8px;">๋ถ์ ๊ฒฐ๊ณผ</th>
|
| 84 |
+
</tr>
|
| 85 |
+
<tr><td style="padding: 8px;">1์ธ๋</td><td style="padding: 8px;">Rule-Based</td><td style="padding: 8px;">{res_1}</td></tr>
|
| 86 |
+
<tr><td style="padding: 8px;">2์ธ๋</td><td style="padding: 8px;">Logistic ML</td><td style="padding: 8px;">{res_2}</td></tr>
|
| 87 |
+
<tr><td style="padding: 8px;">3์ธ๋</td><td style="padding: 8px;">XGBoost ML</td><td style="padding: 8px;">{res_3}</td></tr>
|
| 88 |
+
<tr><td style="padding: 8px;">4์ธ๋</td><td style="padding: 8px;">GNN DL (์๋ฎฌ)</td><td style="padding: 8px;">{res_4}</td></tr>
|
| 89 |
+
</table>
|
| 90 |
+
<h4 style="margin-top: 20px;">๐ค 5์ธ๋ (Foundation Model) ์ฌ์ธต ๋ฆฌํฌํธ</h4>
|
| 91 |
+
{res_5}
|
| 92 |
+
"""
|
| 93 |
+
return html_report
|
| 94 |
|
| 95 |
# ============================================
|
| 96 |
+
# 3. UI ๊ตฌ์ฑ (Gradio)
|
| 97 |
# ============================================
|
| 98 |
with gr.Blocks(theme=gr.themes.Default()) as demo:
|
| 99 |
+
gr.HTML("<h1 style='text-align:center;'>๐ก๏ธ FDS 1-5์ธ๋ ๋น๊ต ๋ฐ๋ชจ</h1>")
|
| 100 |
+
gr.HTML("<p style='text-align:center;'>์ค๋ฌด ์ด์ ๋ด๋น์ ์์ฐ์ฉ (์ด๊ณ ์ CPU ๋ชจ๋)</p>")
|
| 101 |
|
| 102 |
with gr.Row():
|
| 103 |
with gr.Column(scale=1):
|
| 104 |
+
amount_in = gr.Number(label="๊ธ์ก (๋ง์)", value=700)
|
| 105 |
hour_in = gr.Slider(label="๊ฑฐ๋ ์๊ฐ (0-23์)", minimum=0, maximum=23, value=3, step=1)
|
| 106 |
+
payee_in = gr.Radio(label="์ ๊ท ์์ทจ์ธ", choices=["์๋์ค", "์"], value="์")
|
| 107 |
+
ratio_in = gr.Number(label="๊ณผ๊ฑฐ ๋๋น ๋ฐฐ์จ", value=14.0)
|
|
|
|
| 108 |
submit_btn = gr.Button("๐ ๋ถ์ ์คํ", variant="primary")
|
| 109 |
|
| 110 |
gr.Examples(
|
|
|
|
| 114 |
[45, 2, "์๋์ค", 1.2],
|
| 115 |
[1500, 14, "์๋์ค", 2.0]
|
| 116 |
],
|
| 117 |
+
inputs=[amount_in, hour_in, payee_in, ratio_in]
|
|
|
|
| 118 |
)
|
| 119 |
|
| 120 |
with gr.Column(scale=2):
|
| 121 |
+
output_html = gr.HTML("<div style='padding:20px; color:#666;'>๋ฒํผ์ ๋๋ฅด๋ฉด ์ฆ์ ๋ถ์ ๊ฒฐ๊ณผ๊ฐ ํ์๋ฉ๋๋ค.</div>")
|
| 122 |
|
| 123 |
submit_btn.click(
|
| 124 |
fn=analyze_transaction,
|
| 125 |
inputs=[amount_in, hour_in, payee_in, ratio_in],
|
| 126 |
+
outputs=output_html
|
| 127 |
)
|
| 128 |
|
| 129 |
if __name__ == "__main__":
|
|
|
|
| 130 |
demo.launch(ssr_mode=False)
|