Phishing-api / ml_models /train_sms_classifier.py
rohanv56's picture
Upload 13 files
46754fe verified
Raw
History Blame Contribute Delete
6.04 kB
import pandas as pd
import numpy as np
import os
import joblib
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report, accuracy_score
from sklearn.pipeline import Pipeline
DATASET_PATH = "../datasets/SMSSpamCollection"
MODEL_DIR = "."
PHISHING_KEYWORDS = [
"otp", "kyc", "verify", "account", "bank", "credit", "debit",
"password", "urgent", "winner", "prize", "claim", "free",
"click", "link", "update", "expire", "suspend", "confirm",
"transaction", "blocked", "alert", "immediate", "action required"
]
def load_sms_data():
print("[*] Loading SMS dataset...")
tried = []
paths_to_try = [
"../datasets/sms.tsv",
DATASET_PATH,
"../datasets/SMSSpamCollection",
"../datasets/spam.csv",
"../datasets/sms_spam.csv",
]
df = None
for path in paths_to_try:
tried.append(path)
if os.path.exists(path):
try:
if path.endswith(".csv"):
df = pd.read_csv(path, encoding="latin-1")
for col in df.columns:
if df[col].nunique() == 2:
label_col = col
else:
text_col = col
df = df[[label_col, text_col]]
df.columns = ["label", "text"]
elif path.endswith(".tsv"):
df = pd.read_csv(path, sep="\t", header=None, names=["label", "text"], encoding="latin-1")
else:
df = pd.read_csv(path, sep="\t", header=None, names=["label", "text"], encoding="latin-1")
print(f"[+] Loaded from: {path}")
break
except Exception as e:
print(f"[!] Failed to load {path}: {e}")
if df is None:
print(f"[!] Could not find SMS dataset. Tried: {tried}")
print("[*] Generating synthetic dataset for demonstration...")
df = generate_synthetic_data()
df = df.dropna()
label_map = {}
for val in df["label"].unique():
v = str(val).lower()
if any(x in v for x in ["spam", "phish", "1", "ham"]):
label_map[val] = 1 if "spam" in v or "phish" in v else 0
else:
label_map[val] = 0
df["label"] = df["label"].map(label_map).fillna(0).astype(int)
print(f"[*] Total samples: {len(df)}")
print(f"[*] Label distribution:\n{df['label'].value_counts()}")
return df
def generate_synthetic_data():
spam_msgs = [
"URGENT: Your bank account has been suspended. Click here to verify your KYC immediately.",
"Congratulations! You have won Rs 50,000. Claim your prize now by clicking this link.",
"Your OTP is expiring. Please update your account details to avoid suspension.",
"FREE: Get a free iPhone now! Limited offer. Click the link to claim.",
"Your SBI account is blocked. Verify your details immediately to unblock.",
"Dear customer, your PAN card is not linked. Update now or account will be closed.",
"You have a pending transaction of Rs 9999. Confirm your password to proceed.",
"Alert: Suspicious login detected. Verify your identity now: http://fake-bank.com",
] * 50
ham_msgs = [
"Hey, are you coming to the meeting tomorrow?",
"Can you pick up some groceries on your way home?",
"The project deadline has been moved to Friday.",
"Happy birthday! Hope you have a wonderful day.",
"Please find attached the report you requested.",
"Lunch at 1pm? Let me know if that works.",
"The package has been delivered to your door.",
"Reminder: Doctor appointment at 3pm today.",
] * 50
labels = [1] * len(spam_msgs) + [0] * len(ham_msgs)
texts = spam_msgs + ham_msgs
return pd.DataFrame({"label": labels, "text": texts})
def train_sms_model(df):
X = df["text"].values
y = df["label"].values
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42, stratify=y
)
print(f"\n[*] Training set: {len(X_train)} | Test set: {len(X_test)}")
print("[*] Training TF-IDF + Logistic Regression pipeline...")
pipeline = Pipeline([
("tfidf", TfidfVectorizer(
max_features=5000,
ngram_range=(1, 2),
stop_words="english",
lowercase=True,
sublinear_tf=True
)),
("clf", LogisticRegression(
C=1.0, max_iter=1000,
class_weight="balanced",
random_state=42
))
])
pipeline.fit(X_train, y_train)
preds = pipeline.predict(X_test)
acc = accuracy_score(y_test, preds)
print(f"[+] SMS Classifier Accuracy: {acc:.4f} ({acc*100:.2f}%)")
print(classification_report(y_test, preds, target_names=["Legitimate", "Phishing/Spam"]))
os.makedirs(MODEL_DIR, exist_ok=True)
joblib.dump(pipeline, os.path.join(MODEL_DIR, "sms_model.pkl"))
print("[+] Model saved: sms_model.pkl")
test_messages = [
"Your account has been suspended. Verify KYC immediately to avoid closure.",
"Hey, are you free for lunch tomorrow?",
"URGENT: OTP expires in 5 mins. Click link to update your bank details now.",
"Meeting rescheduled to 3pm. Please confirm attendance.",
]
print("\n[*] Quick test predictions:")
for msg in test_messages:
pred = pipeline.predict([msg])[0]
prob = pipeline.predict_proba([msg])[0][1]
status = "PHISHING/SPAM" if pred == 1 else "LEGITIMATE"
print(f" [{status}] ({prob*100:.1f}% confidence) {msg[:60]}...")
return pipeline
if __name__ == "__main__":
print("=" * 50)
print(" SMS Phishing Classifier - Training Script")
print("=" * 50)
df = load_sms_data()
train_sms_model(df)
print("\n[✓] Training complete!")