01 Machine Learning | Spam Detection

01 Machine Learning | Spam Detection 1

No permission to download

اتفقنا مسبقا ان ال Machine Learning هو فرع من الذكاء الاصطناعي يستخدم خوارزميات تسمح للأنظمة بالتعلم وتحسين أدائها من خلال بيانات معطاة لها، دون الحاجة إلى برمجة صريحة.

وأخذنا مثال على ذلك:
نظام كشف البريد المزعج (Spam Detection) .



وبم أن هذا يعد تطبيق مباشر من تطبيقات الأمن السيبراني، فسوف نقوم بعمل واحد من الصفر ونرى ادائة.

الهدف:
عمل نظام يحدد ما إذا كان البريد الوارد هو ضار ( SPAM ) أم لا.

الخطوات:
جمع البيانات المطلوبة (عدد كبير من البريد الالكتروني مصنف من قبل) ضار وغير ضار.
ويمكننا تدريب النظام على كشف الـ SMS او حتى الـ Email .

سنقوم باستخدام لغة الـ Python وبالاستعانة ببعض المكتبات الجاهزة، بالطبع يمكننا فعلها باستخدام Native Python لكن لا نريد اختراع العجلة.
لذا دعونا نبدا:
سنقوم اولا بتحميل بعض المكتبات الضرورية للـ Python3.11 :


Code:
pip install pandas scikit-learn nltk numpy



1. Data Collection and Preprocessing

الخطوة الاولى كما اتفقنا مسبقا هي جمع البيانات التي سنقوم بتدريب الذكاء الاصطناعي عليها، من الطبيعي ان تكون كمية كبيرة من الرسائل وتكون ايضا مصنفة، SPAM او رسائل عادية غير ضارة HAM.

هذا مثال لبعض من الرسائل التي يمكننا العمل عليها، يمكنك تحميلها من هنا.


Screenshot 2025-01-18 080308.png


عادةً ما تحتوي مجموعة البيانات هذه على عمودين:

في الـ v1 يوجد تصنيف الرسالة (SPAM أو HAM)

اما في الـ v2 فيوجد محتوى الرسالة نفسها.





Python:
import pandas as pd
import numpy as np

# Load the SMS Spam Collection dataset (CSV file)
data = pd.read_csv('spam.csv', encoding='latin-1')

# Display the first few rows of the dataset
print(data.head())

سنلاحظ أن هذا هو شكل المف بإستخدام البايثون.
.

Screenshot 2025-01-17 191318.png


.


2. Text Preprocessing



لكن قبل تدريب النموذج، تحتاج إلى معالجة هذة الرسائل اولا، لانها في الاغلب ليست كلها واضحه، والاهم من كميه البيانات المدخلة هو جودتها .. تذكر دائما garbage in garbage out.

== سنقوم بتحويل الرسائل التي لدينا جميعها الى " lowercase" بحث نضمن الدقة والتناسق في التدريب.

== إزالة الأحرف غير الأبجدية

== وايضا سنقوم بإزالة الكلمات الشائعه والتى لا نريدها لانها لن تساهم في السياق كثيرا مثل "the" و"is" و"in" و"and" و"of" و"on" وما إلى ذلك. وهذه الكلمات تسمى " stopwords ".

.


Python:
import re
import nltk
from nltk.corpus import stopwords
from nltk.stem import PorterStemmer

# Download the stopwords corpus
#nltk.download('stopwords')

# Initialize the stemmer
stemmer = PorterStemmer()

# Preprocessing function
def preprocess_text(text):
    # Convert text to lowercase
    text = text.lower()
    # Remove non-alphabetic characters (keep spaces)
    text = re.sub(r'[^a-zA-Z\s]', '', text)
    # Tokenize the text
    words = text.split()
    # Remove stopwords and stem the words
    words = [stemmer.stem(word) for word in words if word not in stopwords.words('english')]
    return ' '.join(words)

# Apply the preprocessing function to the messages
data['v2'] = data['v2'].apply(preprocess_text)

# Display the cleaned data
print(data.head())

وكما تلاحظ في الصورة قمنا بمعالجة الرسائل بشكل واضح.
قبل المعالجة:

Screenshot 2025-01-17 191318.png


بعد المعالجة:​

Screenshot 2025-01-17 191441.png


3. Feature Extraction

عندما نقوم بالتعامل مع نصوص باستخدام Machine Learning models ، من الضروري تحويل النص إلى ارقام، لأن هذة الـ Models تعمل وتفهم بالأرقام، وبالطبع لا تفهم النصوص Text . هناك طريقتان مستخدمتان على نطاق واسع من scikit-learn لهذا الغرض هما CountVectorizer وTfidfVectorizer. و " scikit-learn" هي من الاساس مكتبة Machine Learning مفتوحة المصدر بلغة Python. وهي توفر أدوات بسيطة وفعّالة لاستخراج البيانات وتحليلها، وهي مبنية على مكتبات بايثون الشهيرة مثل NumPy، وقت اتفقنا مسبقا اننا سنقوم بإستخدام هذه المكتبات لسهوله التعامل معها.



دعونا نلقي نظرة سريعة عن فكرة تحويل النصوص الى ارقام اولا.



Python:
from sklearn.feature_extraction.text import TfidfVectorizer

# Sample messages
messages = ["Congratulations! You've won a prize.", "Hi, how are you?"]
# Convert text to numerical features

vectorizer = TfidfVectorizer()
X = vectorizer.fit_transform(messages)
print(X.toarray())  # Transformed text features
Screenshot 2025-01-18 072251.png



هذا الكود يستخدم sklearn وهي مكتبة Python مفتوحة المصدر شائعة الاستخدام للـ Machine Learning، وهي مبنية على مكتبات مثل NumPy وSciPy وMatplotlib. وهي توفر أدوات بسيطة وفعالة لتحليل البيانات والتعامل مع الـ Models ، مما يجعلها واحدة من المكتبات المفضلة في مجال الـ Machine Learning .

سنلاحظ ان هذا الكود يقوم بتحويل النصين الى ارقام لكن.

لكن كيف ولما؟

سنلاحظ ان لدينا صفين، وهذا يوافق الجملتين وهما:
"تهانينا! لقد فزت بجائزة." Congratulations! You've won a prize.
"مرحبًا، كيف حالك؟". Hi, how are you?

اما الاعمده : يتوافق كل عمود مع كل كلمة مميزة او لنسميها (token) تم تحديدها من قبل sklearn .
أما بالنسبة للقيم المرتبطة بهذه الأرقام، فهي تعبر عن درجة أو مقياس للكلمة "score" في السطر المدخل. كلما ارتفعت القيمة، دل ذلك على أن الكلمة تحمل تأثيرًا ومعنًى أكبر في المستند مقارنة بالكلمات الأخرى.

مثال بالعربية:

الجملة: "خرج الطفل الصغير إلى الحديقة ليلعب ويمرح."

= عند إزالة كلمة " الحديقة "، يتأثر المعنى: ": "خرج الطفل الصغير إلى ليلعب ويمرح."

= أما عند إزالة كلمة "الصغير"، يبقى المعنى واضحًا: "خرج الطفل إلى الحديقة ليلعب ويمرح."


الجملة: "الشجرة الكبيرة في الحديقة تعطي ظلاً واسعاً."

= عند إزالة كلمة " الشجرة "، يتأثر المعنى: " الكبيرة في الحديقة تعطي ظلاً واسعاً."

= أما عند إزالة كلمة "الكبيرة"، يبقى المعنى واضحًا: "الشجرة في الحديقة تعطي ظلاً واسعاً."


لذا هنا ستقوم المكتبة بإعطاء الكلمات ارقام وقيم حسب كل كلمة في الجملة وموقعها واهميتها..


Python:
from sklearn.feature_extraction.text import TfidfVectorizer

# Convert text to numerical features using TF-IDF
vectorizer = TfidfVectorizer(max_features=5000)  # Limit to top 5000 features
X = vectorizer.fit_transform(data['v2']).toarray()

# Labels: spam or ham
y = data['v1'].map({'ham': 0, 'spam': 1}).values

وكما ترون، الضار يشار له بالرقم 1 اما الرسائل العادية يشار لها بالرقم 0 ..


4. Model Training



بعد ذلك، يمكننا تدريب نموذج التعلم الآلي. سنستخدم خوارزمية شائعة مثل Naive Bayes. يمكنك أيضًا استخدام خوارزميات أخرى مثل Logistic Regression أو SVM.


Python:
from sklearn.model_selection import train_test_split
from sklearn.naive_bayes import MultinomialNB
from sklearn.metrics import accuracy_score, confusion_matrix, classification_report

# Split data into training and testing sets
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# Train the Naive Bayes model
model = MultinomialNB()
model.fit(X_train, y_train)



from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score

# Predict the test set
y_pred = model.predict(X_test)


الان وبعد ان قمنا بتدريب النموزج ، يجب علينا فعل شيئين آخرين وهما الاول:
معرفة دقة وكفائة النموزج
وثانيا تجربتة للتأكد


5. Evaluate the Model


يعد تقييم نموذج التعلم الآلي أمرًا بالغ الأهمية لفهم أدائه. فيما يلي الخطوات الرئيسية لتقييم نموذج اكتشاف البريد العشوائي:



Python:
# Calculate evaluation metrics
accuracy = accuracy_score(y_test, y_pred)
precision = precision_score(y_test, y_pred)
recall = recall_score(y_test, y_pred)
f1 = f1_score(y_test, y_pred)

print("Model Evaluation Metrics:")
print(f"Accuracy: {accuracy:.2f}")
print(f"Precision: {precision:.2f}")
print(f"Recall: {recall:.2f}")
print(f"F1-Score: {f1:.2f}")



from sklearn.metrics import classification_report

#Generate classification report
report = classification_report(y_test, y_pred, target_names=["Ham", "Spam"])
print(report)
Screenshot 2025-01-18 074430.png


هذه هي الارقام التي قدمها الي نموزجي دعونا نشرحها بالتفصيل.


True Positives (TP): 170 (Spam messages correctly classified as spam)

True Negatives (TN): 950 (Ham messages correctly classified as ham)

False Positives (FP): 20 (Ham messages incorrectly classified as spam)

False Negatives (FN): 10 (Spam messages incorrectly classified as ham)




المقاييس التي يجب معرفتها:

الـ Accuracy : تقيس النسبة المئوية للرسائل التي تم تصنيفها بشكل صحيح (سواء كانت Spam Ham or ).

يعني إذا قلنا ان الدقة او الـ Accuracy: 0.97، إذا يقوم النموذج بتصنيف 97% من جميع الرسائل بشكل صحيح.

لو افترضنا انه قام بفحص 170 رسالة على انها Spam وكان على حق، وايضا 950 رسالة على انها غير ضارة "وكان ايضا على حق"، ولنقل انه اخطأ في تقدير 20 رسالة على انها Spam ولكنها كانت رسائل عادية، والعكس قام بتمرير 10 رسائل Spam على انها غير ضاره :D .



إذا حساب الدقة سيكون "مجموع التخمينات الصحيحه" / "مجموع كل الرسائل"
170+950 / (170+950+20+10) = 0.97


الـ Precision : تقيس نسبة الرسائل التي تم التنبؤ بأنها بريد عشوائي Spam وهي بالفعل بريد عشوائي Spam .

من كل الرسائل التي قال عنها انها Spam كانت فعلا Spam معنى ذلك انه عندما كان يتلقى ال Ham لم يقل ابدا عنها انها Spam .

ولكن العكس ممكن وهو ان ياخذ Spam ومن الممكن ان يصنفها على انها Ham .


معنى هذا ان الموديل قوم بالتعرف على كل الرسائل العاديه على انها فعلا غير ضاره، لكن من الممكن ان يقول لك ان هذه الرساله "غير ضاره" وتكون اصلا ضاره :D .

يعني إذا احمد صديقك يدعوك للعشاء، سيقوم النظام فعلا بتسليم الرساله، لكن اذا كان احد ما يريد ان يخترقك، ف من المحتمل ان يقوم النظاام بإعطائك الرساله على انها ليس بيها مشاكل.


الـ Recall (Sensitivity) : هذا ما شرحناه للتو، هنا يخبرك النظام انه عدد الرسائل الضارة التي فعلا قام بتوقعها كانت فقط 79% .... اي ان هناك 21% من الرسائل الضارة تم تصنيفها على انها عاديه وهذه مشكله كبيره :] .

بعد ان قمنا بتدريب الموديل وقياس دقته ومعرفة نقاط ضعفة وقوته، يمكننا الان ان نقوم بتجربتة ثم حفظة لجعلة نظام متكامل يمكن للمستخدم ان يتعامل معه.



# Test the model with a new message
Python:
def predict_spam(message):
    # Preprocess the input message
    processed_message = preprocess_text(message)
    # Convert the message to the same format as training data
    message_vector = vectorizer.transform([processed_message]).toarray()
    # Predict using the trained model
    prediction = model.predict(message_vector)
    return 'Spam' if prediction == 1 else 'Ham'

# Test the model with a new message
new_message = "Congratulations! You've won a $1000 gift card! Claim your prize now by clicking this link: [link]. Hurry, offer expires soon!"
print(predict_spam(new_message))

هذه هي الرسالة التي نود ان نختبرها، للعلم هو لم يرى ابدا هذه الرساله سواء خلال التدريب او الاختباار.. لنرى كيف سيفكر


Congratulations! You've won a $1000 gift card! Claim your prize now by clicking this link: [link]. Hurry, offer expires soon!
Screenshot 2025-01-18 075024.png




والان مبروك قمنا بصناعة اول موديل يخدمنا في هذا المجال، لكن دعونا نجعل الامور افضل قليلا، لذا لنحفظ الموديل الذي قمنا بتدريبه ونقم بعمل موقع يستخدم هذا الموديل.


Python:
import joblib

# Save the model
joblib.dump(model, 'spam_detector_model.pkl')

# Save the vectorizer
joblib.dump(vectorizer, 'vectorizer.pkl')

print("Model and vectorizer saved successfully!")

وبعد ان تم حفظ المودل تحت اسم spam_detector_model.pkl و 'vectorizer.pkl لنقم بعمل موقع بسيط يقوم بإستخدام الموديل الذي تم تدريبة عوضا عن تشغيل الكود كل مره...

اليك الكود النهائي للموديل بأكمله:


Python:
import pandas as pd
import numpy as np

# Load the SMS Spam Collection dataset (CSV file)
data = pd.read_csv('spam.csv', encoding='latin-1')

# Display the first few rows of the dataset
print(data.head())

import re
import nltk
from nltk.corpus import stopwords
from nltk.stem import PorterStemmer

# Download the stopwords corpus
nltk.download('stopwords')

# Initialize the stemmer
stemmer = PorterStemmer()

# Preprocessing function
def preprocess_text(text):
    # Convert text to lowercase
    text = text.lower()
    # Remove non-alphabetic characters (keep spaces)
    text = re.sub(r'[^a-zA-Z\s]', '', text)
    # Tokenize the text
    words = text.split()
    # Remove stopwords and stem the words
    words = [stemmer.stem(word) for word in words if word not in stopwords.words('english')]
    return ' '.join(words)

# Apply the preprocessing function to the messages
data['v2'] = data['v2'].apply(preprocess_text)

# Display the cleaned data
print(data.head())

from sklearn.feature_extraction.text import TfidfVectorizer

# Convert text to numerical features using TF-IDF
vectorizer = TfidfVectorizer(max_features=5000)  # Limit to top 5000 features
X = vectorizer.fit_transform(data['v2']).toarray()

# Labels: spam or ham
y = data['v1'].map({'ham': 0, 'spam': 1}).values

from sklearn.model_selection import train_test_split
from sklearn.naive_bayes import MultinomialNB
from sklearn.metrics import accuracy_score, confusion_matrix, classification_report

# Split data into training and testing sets
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# Train the Naive Bayes model
model = MultinomialNB()
model.fit(X_train, y_train)



from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score

# Predict the test set
y_pred = model.predict(X_test)

# Calculate evaluation metrics
accuracy = accuracy_score(y_test, y_pred)
precision = precision_score(y_test, y_pred)
recall = recall_score(y_test, y_pred)
f1 = f1_score(y_test, y_pred)

print("Model Evaluation Metrics:")
print(f"Accuracy: {accuracy:.2f}")
print(f"Precision: {precision:.2f}")
print(f"Recall: {recall:.2f}")
print(f"F1-Score: {f1:.2f}")



from sklearn.metrics import classification_report

#Generate classification report
report = classification_report(y_test, y_pred, target_names=["Ham", "Spam"])
print(report)


def predict_spam(message):
    # Preprocess the input message
    processed_message = preprocess_text(message)
    # Convert the message to the same format as training data
    message_vector = vectorizer.transform([processed_message]).toarray()
    # Predict using the trained model
    prediction = model.predict(message_vector)
    return 'Spam' if prediction == 1 else 'Ham'

# Test the model with a new message
new_message = "Congratulations! You've won a $1000 gift card! Claim your prize now by clicking this link: [link]. Hurry, offer expires soon!"
print(predict_spam(new_message))

import joblib

# Save the model
joblib.dump(model, 'spam_detector_model.pkl')

# Save the vectorizer
joblib.dump(vectorizer, 'vectorizer.pkl')

print("Model and vectorizer saved successfully!")

ومن هنا يمكنك تحميل موقع الويب جاهز للاستخدام


اليك الشكل النهائي:

ezgif-1-1036522ef8.gif


ونراكم في الدرس القادم.​


Author
Ahmed.Attia
Downloads
0
Views
17
First release
Last update
Rating
0.00 star(s) 0 ratings

More resources from Ahmed.Attia

Top