看完了一系列的介紹,肯定要自己動手做做,這次我會透過一個簡單的垃圾郵件分類器專案,來實際應用所學的機器學習概念和技巧。我會逐步展示如何使用 Python 進行資料的預處理、訓練分類模型,以及如何進行模型的評估。
接著介紹這次要用到的主角SMS Spam Collection Dataset
。
這個資料集是專門為 SMS 垃圾郵件過濾研究所收集的訊息集合。這個資料集包含 5,574 則 SMS 訊息,每則訊息被標記為 ham(正常訊息)或 spam(垃圾訊息)。資料集中的訊息來自於多個來源,包括英國 Grumbletext 網站上的手動收集、NUS SMS Corpus(新加坡國立大學計算機系統中的合法訊息)、以及 Caroline Tag 博士論文中的資料等。
這個資料集的每一則訊息的格式相當簡單,分為兩個欄位:v1
包含標籤(ham 或 spam),v2
則包含訊息的原始文字。
我們可以透過這個網站下載 連結
下載完成後我們來看看詐騙訊息長怎樣。
WINNER!! As a valued network customer you have been selected to receivea �900 prize reward! To claim call 09061701461. Claim code KL341. Valid 12 hours only.
接著翻譯看看
非常的明顯這個是一則詐騙訊息。(話說原來Microsoft 的 Copilot也會幫忙檢測這種訊息阿~太強大了吧)
在這個專案中,會使用到以下幾個主要的 Python 套件:
Pandas:用來讀取與處理資料集。Pandas 是 Python 中非常強大的資料分析工具,能夠輕鬆操作結構化的資料,讓我們能夠快速地對數據進行清理與轉換。
Numpy:雖然在這次並不會直接引入,但很多套件都會內部依賴 Numpy 來處理矩陣運算及高效的數值計算,特別是在向量化步驟時。
NLTK (Natural Language Toolkit):用來進行文字的處理。我會使用其中的停用詞集與 Porter 詞幹提取器來進行文字的預處理,移除多餘的詞彙並進行詞幹還原。
Scikit-learn:
Matplotlib:用於資料可視化,這次我會把它用它來繪製模型的 ROC 曲線,評估模型的分類能力。
馬上就開始實作吧!
import os
import re
import pickle
import pandas as pd
import nltk
from nltk.corpus import stopwords
from nltk.stem.porter import PorterStemmer
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.model_selection import train_test_split
from sklearn.naive_bayes import MultinomialNB
from sklearn.metrics import accuracy_score, confusion_matrix, precision_recall_fscore_support
import matplotlib.pyplot as plt
正如上面所介紹的,這段匯入了用來處理資料的庫,包括 pandas 進行資料讀取、nltk 用來進行自然語言處理(如停用詞與詞幹提取),scikit-learn 中的功能用來進行向量化、模型訓練、評估等,matplotlib 用於可視化 ROC 曲線。
nltk.download('stopwords')
確保 nltk 的停用詞集已下載,這是用來移除常見但意義不大的詞彙(例如 "is", "the" 等)。
MODEL_FILE = 'spam_classifier_model.pkl'
VECTORIZER_FILE = 'tfidf_vectorizer.pkl'
這裡定義了保存模型和 TF-IDF 向量化器的檔案名稱,後面會用到。
TF-IDF(Term Frequency-Inverse Document Frequency)是一種常用的文字特徵提取技術,廣泛應用於自然語言處理和資訊檢索領域。它的主要目的是衡量某個詞語在一個文件中的重要性,同時考慮該詞語在整個文件集中的出現頻率。
在這邊的垃圾郵件分類中,TF-IDF 可以幫助我們過濾掉常見的停用詞(例如 "the", "is" 等),並找出更具區別性的詞語(如 "free", "win" 這類常見於垃圾郵件的詞)。這樣,模型能夠根據每則訊息中的詞語權重來判斷該訊息是否為垃圾郵件。
def preprocess_text(message):
ps = PorterStemmer() # 詞幹提取
# 清理文字,移除非字母的部分
message = re.sub('[^a-zA-Z]', ' ', message)
message = message.lower()
message = message.split()
# 移除停用詞,進行詞幹提取
message = [ps.stem(word) for word in message if word not in stopwords.words('english')]
message = ' '.join(message)
return message
這段程式碼定義了預處理的功能,包括移除非字母的符號、將文字轉換為小寫、移除停用詞、進行詞幹提取,最終返回清理後的文字。
以剛剛上面的例子來說,他把整個處理完成會返回
winner valu network custom select receivea prize reward claim call claim code kl valid hour
(恩...果然典型的詐騙都會有這種文字來騙大家阿,大家要小心啊~)
今天先介紹了前面簡單的部分,明天繼續將主要的程式介紹完,希望大家能繼續關注下去。
(終於快完賽了,這次的文章真的是花了我很大的心思去準備)