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