Machine Learning - Train Mô Hình Nhận Dạng Email Lừa Đảo

Bài tập hôm nay là train mô hình để nhận dạng email lừa đảo Phishing Email. Đây được xem như là bài tập nhập môn machine learning.

Trong bài viết này, chúng ta sẽ train mô hình và viết một web api nho nhỏ bằng fastapi để hosting model lên. Các bước thực hiện như sau:

Nguyên liệu chính: data phishing email được download ở https://www.kaggle.com/datasets/subhajournal/phishingemails/data

Cài các thư viện cơ bản

1python3 -m venv venv
2
3source venv/bin/activate
4pip install fastapi uvicorn redis joblib scikit-learn
  • fastapi: Framework để xây dựng API.
  • uvicorn: Server ASGI để chạy ứng dụng FastAPI.
  • redis: Thư viện để tương tác với Redis.
  • joblib: Thư viện để lưu và tải mô hình học máy.
  • scikit-learn: Thư viện để huấn luyện và triển khai mô hình.

Phiên bản basic

Train mô hình

 1# Import các thư viện cần thiết
 2import os
 3import joblib
 4import pandas as pd
 5from sklearn.feature_extraction.text import TfidfVectorizer
 6from sklearn.linear_model import LogisticRegression
 7from sklearn.model_selection import train_test_split
 8from sklearn.pipeline import Pipeline
 9from sklearn.metrics import accuracy_score
10
11def trainPhishingEmailModel():
12    """
13    Hàm thực hiện:
14    - Đọc dữ liệu email từ file CSV
15    - Tiền xử lý, chia dữ liệu train/test
16    - Xây dựng pipeline (TF-IDF + Logistic Regression)
17    - Huấn luyện mô hình
18    - Đánh giá mô hình trên tập test
19    - Lưu mô hình đã train vào thư mục model/
20    """
21
22    # Bước 1: Đọc dữ liệu từ file CSV
23    dataFrame = pd.read_csv("data/Phishing_Email.csv")  # Cần đảm bảo đường dẫn file chính xác
24
25    # Bước 2: Chuẩn bị dữ liệu đầu vào (features) và nhãn (labels)
26    emailTexts = dataFrame["Email Text"].fillna("")  # Thay thế giá trị null bằng chuỗi rỗng
27    emailLabels = dataFrame["Email Type"]            # Label: loại email (ví dụ: phishing hoặc legit)
28
29    # Bước 3: Chia dữ liệu thành tập huấn luyện và tập kiểm tra
30    emailTextsTrain, emailTextsTest, emailLabelsTrain, emailLabelsTest = train_test_split(
31        emailTexts,
32        emailLabels,
33        test_size=0.2,     # 20% dữ liệu dùng để kiểm tra
34        random_state=42    # Đảm bảo chia dữ liệu ngẫu nhiên nhưng có thể tái lập
35    )
36
37    # Bước 4: Xây dựng pipeline:
38    # - TfidfVectorizer: chuyển văn bản thành vector đặc trưng
39    # - LogisticRegression: mô hình phân loại tuyến tính
40    phishingDetectionPipeline = Pipeline([
41        ("tfidfVectorizer", TfidfVectorizer(stop_words="english")),       # Loại bỏ từ dừng tiếng Anh
42        ("logisticClassifier", LogisticRegression(solver="liblinear"))    # Sử dụng solver phù hợp với tập nhỏ
43    ])
44
45    # Bước 5: Huấn luyện pipeline trên tập huấn luyện
46    phishingDetectionPipeline.fit(emailTextsTrain, emailLabelsTrain)
47
48    # Bước 6: Đánh giá mô hình trên tập kiểm tra
49    emailLabelsPredicted = phishingDetectionPipeline.predict(emailTextsTest)
50    accuracy = accuracy_score(emailLabelsTest, emailLabelsPredicted)
51    print(f"🎯 Độ chính xác của mô hình trên tập kiểm tra: {accuracy * 100:.2f}%")
52
53    # Bước 7: Tạo thư mục lưu mô hình nếu chưa tồn tại
54    modelDirectory = "model"
55    if not os.path.exists(modelDirectory):
56        os.makedirs(modelDirectory)
57
58    # Bước 8: Lưu mô hình đã huấn luyện vào thư mục model/
59    modelPath = os.path.join(modelDirectory, "phishingModel.pkl")
60    joblib.dump(phishingDetectionPipeline, modelPath)
61    print(f"✅ Mô hình đã được huấn luyện và lưu thành công tại '{modelPath}'.")
62
63# Điểm bắt đầu chương trình
64if __name__ == "__main__":
65    trainPhishingEmailModel()

Kết quả

1
2🎯 Độ chính xác của mô hình trên tập kiểm tra: 97.24%
3✅ Mô hình đã được huấn luyện và lưu thành công tại 'model/phishingModel.pkl'.

Phần code triển khai fast api khá đơn giản

 1# Import các thư viện cần thiết
 2import asyncio
 3import json
 4import joblib
 5from fastapi import FastAPI
 6from pydantic import BaseModel
 7
 8# Bước 1: Load mô hình đã huấn luyện (đồng bộ)
 9model = joblib.load("model/phishingModel.pkl")  # Đảm bảo đường dẫn đúng
10
11# Bước 2: Khởi tạo FastAPI app
12app = FastAPI()
13
14# Bước 3: Định nghĩa lớp dữ liệu vào (request) và dữ liệu ra (response)
15class PredictionRequest(BaseModel):
16    text: str  # Văn bản email cần phân loại
17
18class PredictionResponse(BaseModel):
19    prediction: str  # Kết quả phân loại (ví dụ: "Phishing" hoặc "Legit")
20    probability: float  # Xác suất dự đoán cao nhất
21
22# Bước 4: Định nghĩa API endpoint cho việc dự đoán
23@app.post("/predict", response_model=PredictionResponse)
24async def predictEmail(data: PredictionRequest):
25    """
26    Nhận văn bản email từ client, chạy mô hình dự đoán,
27    và trả về kết quả cùng xác suất dự đoán.
28    """
29
30    # Chạy dự đoán mô hình trong thread riêng để không block event loop
31    prediction = await asyncio.to_thread(model.predict, [data.text])
32    probability = await asyncio.to_thread(lambda: model.predict_proba([data.text])[0].max())
33
34    # Đóng gói kết quả trả về
35    result = {
36        "prediction": str(prediction[0]),
37        "probability": float(probability)
38    }
39
40    return result
41
42# Bước 5: Chạy server FastAPI với uvicorn khi file được thực thi trực tiếp
43if __name__ == "__main__":
44    import uvicorn
45    uvicorn.run(app, host="0.0.0.0", port=8000)

Mình thử lại với các test case sau nha

 1
 2curl 'http://localhost:8000/predict' -H 'accept: application/json' -H 'Content-Type: application/json' -d '{"text":"Hi There,  Watch your customer engagement soar with custom, branded messaging experience powered by artificial intelligence. Improve customer retention, conversion and satisfaction with Sendbird’s award winning communications platform.  Schedule a Custom Demo at your convenience.  Cheers, Natalie"}'
 3
 4curl 'http://localhost:8000/predict' -H 'accept: application/json' -H 'Content-Type: application/json' -d '{
 5  "text": "Hi, We noticed a login from a device you don'\''t usually use: android device Lagos, Nigeria If this was you, you can safely disregard this email."
 6}'
 7
 8curl 'http://localhost:8000/predict' -H 'accept: application/json' -H 'Content-Type: application/json' -d '{"text":"STARTING AT $40 ($80)  (50% OFF APPLIED FOR LIMITED TIME)  If you are looking to learn in-demand skills and apply them directly at your workplace then Premium Courses by Great Learning Academy are a great way to get started!     Learn industry-relevant skills in Data Science and AI through a combination of expert-led hands-on projects, interactive exercises, and advanced AI support tools. These courses empower you to apply your skills effectively at work and grow in your current role or take on new projects with confidence."}'
 9
10
11curl 'http://localhost:8000/predict' -H 'accept: application/json' -H 'Content-Type: application/json' -d '{"text":"I spend most of my time building and improving Retrieval Augmented Generation (RAG) apps.  I trust RAGs are perhaps the most popular application of AI. It’s everywhere, from chatbots to document summaries.  I also believe that most of these apps ultimately go undeployed for various reasons, many of which are not technical. However, I wish I had known a few technical aspects to create more effective RAGs."}'

Kết quả như sau

1{"prediction":"Phishing Email","probability":0.6649311587527311}{"prediction":"Phishing Email","probability":0.5568319143944104}{"prediction":"Phishing Email","probability":0.5126072633692877}
2{"prediction":"Safe Email","probability":0.5550190678745507}

Đây là các email thật mình lấy ra từ gmail cá nhân của mình, đã được google phân loại. Kết quả của mình ra khớp 100% với google nhỉ. hi hi.

Train với ultimate pro

Model chỉ đúng với 97% ở tập train, khá cùi nhỉ. Chúng ta sẽ bổ sung auto grid search để turning tham số, chọn ra best_params, thêm EarlyStopping, thêm Auto Save Checkpoint, đổi mô hình sang random forest … Các chức năng xịn sò hơn nhỉ

Các bạn thử coding thử, xem như là bài tập.

Cảm ơn bạn đã theo dõi bài viết, hẹn gặp lại ở các bài viết tiếp theo

Comments