FDS_test2 / app.py
ableman82's picture
Update app.py
1bd6b4d verified
Raw
History Blame Contribute Delete
4.03 kB
import sys
import subprocess
import pandas as pd
# [ํ•„์ˆ˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ฒดํฌ ๋ฐ ์ž๋™ ์„ค์น˜]
for package in ["transformers", "torch", "shap", "pandas"]:
try:
__import__(package)
except ModuleNotFoundError:
subprocess.check_call([sys.executable, "-m", "pip", "install", package])
from transformers import pipeline
import shap
# ==========================================
# 1. ๊ณ ๋„ํ™”๋œ 5์„ธ๋Œ€ FDS์šฉ LLM ๋ชจ๋ธ ๋กœ๋“œ
# ==========================================
print("๐Ÿ”„ FDS ๋น„์ •ํ˜• ๋งฅ๋ฝ ๋ถ„์„์„ ์œ„ํ•œ LLM ํŒŒ์ดํ”„๋ผ์ธ์„ ์ดˆ๊ธฐํ™” ์ค‘์ž…๋‹ˆ๋‹ค...")
classifier = pipeline("sentiment-analysis", model="distilbert-base-uncased-finetuned-sst-2-english", top_k=None)
# ==========================================
# 2. SHAP ๊ธฐ๋ฐ˜์˜ XAI ์˜ˆ์ธก ํ•จ์ˆ˜ ์ •์˜ (์˜ค๋ฅ˜ ์ˆ˜์ • ์™„๋ฃŒ)
# ==========================================
def fds_llm_predict(texts):
"""
SHAP์ด ๋‚ด๋ถ€์ ์œผ๋กœ ํ…์ŠคํŠธ๋ฅผ ๋งˆ์Šคํ‚นํ•˜์—ฌ numpy.ndarray ํ˜•ํƒœ๋กœ ์ „์†กํ•˜๋ฏ€๋กœ,
Hugging Face ํŒŒ์ดํ”„๋ผ์ธ์ด ์ธ์‹ํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ฐ•์ œ๋กœ ํŒŒ์ด์ฌ list ํƒ€์ž…์œผ๋กœ ์บ์ŠคํŒ…ํ•ฉ๋‹ˆ๋‹ค.
"""
# ๐ŸŒŸ [CRITICAL FIX] numpy array ๋“ฑ์„ ์ˆœ์ˆ˜ ํŒŒ์ด์ฌ ๋ฆฌ์ŠคํŠธ๋กœ ๋ณ€ํ™˜
if not isinstance(texts, list):
texts = list(texts)
results = classifier(texts)
fraud_probabilities = []
for res in results:
# 'NEGATIVE'(์˜์‹ฌ ์ง•ํ›„) ๋ ˆ์ด๋ธ”์˜ ํ™•๋ฅ  ์Šค์ฝ”์–ด๋ฅผ ์ถ”์ถœ
risk_score = next(item['score'] for item in res if item['label'] == 'NEGATIVE')
fraud_probabilities.append(risk_score)
return fraud_probabilities
# ํ…์ŠคํŠธ ๋ฐ์ดํ„ฐ์˜ ๋‹จ์–ด(Word) ๋‹จ์œ„๋ฅผ ๋งˆ์Šคํ‚นํ•˜๋ฉฐ ์ถ”์ ํ•˜๋Š” SHAP ์ต์Šคํ”Œ๋ ˆ์ด๋„ˆ ์ƒ์„ฑ
explainer = shap.Explainer(fds_llm_predict, shap.maskers.Text(tokenizer=r"\W+"))
# ==========================================
# 3. ์‹ค๋ฌด ์‹œ์—ฐ์šฉ ์˜์‹ฌ ํŠธ๋žœ์žญ์…˜ ์ฝ˜ํ…์ŠคํŠธ ์ •์˜
# ==========================================
suspicious_transaction_context = (
"The elderly customer requested an urgent transfer of $45,000 to an unknown account. "
"She appears extremely nervous, continually checking her smartphone, and mentioned that "
"a stranger instructed her via an unverified remote control app to complete this transaction immediately."
)
print("\n" + "="*60)
print("๐Ÿ“ฅ [์ˆ˜์ง‘๋œ ๋น„์ •ํ˜• ๋ฐ์ดํ„ฐ ๋ถ„์„ ๋Œ€์ƒ]")
print(suspicious_transaction_context)
print("="*60)
# ==========================================
# 4. LLM ์ถ”๋ก  ๋ฐ SHAP ๊ฐ€์ค‘์น˜ ๋ถ„์„ ์‹คํ–‰
# ==========================================
print("\n๐Ÿค– LLM ๋ถ„์„ ๋ฐ SHAP ๊ฐ€์น˜ ๊ณ„์‚ฐ ๊ฐ€๋™ ์ค‘...")
# 1) LLM ์ตœ์ข… ํŒ์ •
final_risk_score = fds_llm_predict([suspicious_transaction_context])[0]
# 2) SHAP ๊ฐ€์น˜ ๊ณ„์‚ฐ (์ด์ œ ์—๋Ÿฌ ์—†์ด ์ •์ƒ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค)
shap_values = explainer([suspicious_transaction_context])
# ==========================================
# 5. ์‹ค๋ฌด์ž ๋ณด๊ณ ์šฉ ๊ฒฐ๊ณผ ๋ฐ์ดํ„ฐ ์ •์ œ
# ==========================================
words = shap_values.data[0]
contributions = shap_values.values[0]
fds_report = pd.DataFrame({
'Detected_Word': words,
'Risk_Contribution': contributions
})
fds_report = fds_report[fds_report['Detected_Word'].str.strip() != ""]
fds_report_sorted = fds_report.sort_values(by='Risk_Contribution', ascending=False)
# ==========================================
# 6. ๊ด€์ œ ์‹œ์Šคํ…œ ์ถœ๋ ฅ ์‹œ๋ฎฌ๋ ˆ์ด์…˜
# ==========================================
print("\n๐Ÿšจ [FDS 5์„ธ๋Œ€ ๊ด€์ œ ์‹œ์Šคํ…œ ์•Œ๋ฆผ]")
if final_risk_score > 0.85:
print(f"โ–ถ ์ตœ์ข… ์กฐ์น˜: โŒ [์ฆ‰์‹œ ์ฐจ๋‹จ] ๊ธˆ์œต์‚ฌ๊ธฐ ์˜์‹ฌ ๋ฌธ๋งฅ ํฌ์ฐฉ")
elif final_risk_score > 0.50:
print(f"โ–ถ ์ตœ์ข… ์กฐ์น˜: โš ๏ธ [์ถ”๊ฐ€ ์ธ์ฆ] ์˜์‹ฌ ์ง•ํ›„ ํƒ์ง€")
else:
print(f"โ–ถ ์ตœ์ข… ์กฐ์น˜: โœ… [์ •์ƒ ์Šน์ธ]")
print(f"โ–ถ ์ข…ํ•ฉ ๋ฆฌ์Šคํฌ ์Šค์ฝ”์–ด: {round(final_risk_score * 100, 2)}%\n")
print("๐Ÿ’ก [XAI ์†Œ๋ช… ๊ฐ€์ด๋“œ - ์œ„ํ—˜ ๊ธฐ์—ฌ๋„ Top 5 ๋‹จ์–ด]")
print("-" * 50)
print(fds_report_sorted.head(5).to_string(index=False))
print("-" * 50)