File size: 4,033 Bytes
869c6cb 2ebb269 869c6cb 2ebb269 869c6cb 2ebb269 8cb8803 2ebb269 1bd6b4d 2ebb269 1bd6b4d 2ebb269 1bd6b4d 2ebb269 1bd6b4d 2ebb269 1bd6b4d 2ebb269 1bd6b4d 2ebb269 1bd6b4d | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | 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) |