مشروع ذكاء اصطناعي 1: تصنيف الرسائل المزعجة باستخدام بايثون وscikit-learn

مشروع تصنيف الرسائل المزعجة باستخدام بايثون وscikit-learn للمبتدئين

ملفات المشروع وكتيب الشرح: ستجد ملفات البيانات والكود والتمارين في مستودع بايثون العرب على GitHub بعد رفعها.

تحميل ملفات المشروع من GitHub

هل يمكن أن يتعلم برنامج من أمثلة سابقة أن يفرّق بين رسالة عادية ورسالة مزعجة؟ نعم. هذا أحد أبسط تطبيقات تصنيف النصوص في تعلم الآلة، وهو مشروع ممتاز للانتقال من فهم المفاهيم إلى تنفيذ نموذج فعلي ببايثون.

في هذا المشروع سنبني نموذجًا تعليميًا يقرأ رسائل قصيرة مصنّفة مسبقًا إلى فئتين: spam للرسائل المزعجة وnormal للرسائل العادية. ثم نحوّل النصوص إلى أرقام يفهمها النموذج، وندربه، ونختبره على جزء لم يره أثناء التدريب، ثم نجرب رسالة جديدة بأنفسنا.

المشروع لا يهدف إلى بناء فلتر بريد جاهز للاستخدام الحقيقي. البيانات هنا صغيرة وتعليمية، لذلك لا يجوز الاعتماد عليه لفلترة رسائل عمل أو اتخاذ قرار حقيقي عن المستخدمين. الهدف هو فهم الخطوات الأساسية: البيانات ← تحويل النص ← التدريب ← الاختبار ← التنبؤ.

{alertInfo} الفكرة ببساطة: لا يفهم النموذج النص كما يفهمه الإنسان. نحن نحول الرسائل إلى تمثيل رقمي باستخدام TfidfVectorizer، ثم يتعلم نموذج MultinomialNB الأنماط التي تظهر في الرسائل المزعجة والعادية ليصنف رسالة جديدة.

{getToc} $title={محتوى المقال}

ماذا سنتعلم من هذا المشروع؟

  • فهم الفرق بين التصنيف والتوقع الرقمي بصورة عملية.
  • تنظيم بيانات نصية داخل ملف CSV.
  • قراءة البيانات باستخدام pandas.
  • تقسيم البيانات إلى تدريب واختبار باستخدام train_test_split.
  • تحويل الرسائل إلى خصائص رقمية عبر TfidfVectorizer.
  • تدريب مصنف نصي باستخدام MultinomialNB.
  • عرض تقرير تقييم باستخدام classification_report.
  • تجربة رسالة جديدة بعد تدريب النموذج.

ما نوع مشكلة هذا المشروع؟

هذا المشروع من نوع التصنيف Classification. أي أن النموذج لا يعيد رقمًا مثل سعر أو درجة، بل يختار فئة من فئات محددة مسبقًا.

نوع المهمة مثال الناتج
توقع رقمي توقع درجة طالب من ساعات الدراسة. رقم مثل 82.5.
تصنيف تحديد هل الرسالة مزعجة أو عادية. spam أو normal.

ظهر مشروع التوقع الرقمي في درس كيف تبدأ أول مشروع ذكاء اصطناعي باستخدام بايثون. أما هنا فسننتقل إلى نوع مختلف من المشاكل: تصنيف النصوص القصيرة.

قبل البدء: تجهيز بيئة المشروع

أنشئ مجلدًا جديدًا للمشروع، ثم أنشئ بيئة افتراضية وثبت المكتبات التي نحتاجها. استخدام البيئة الافتراضية يحافظ على مكتبات هذا المشروع منفصلة عن المشاريع الأخرى.

# Windows
py -m venv .venv
.venv\Scripts\activate

# macOS أو Linux
python3 -m venv .venv
source .venv/bin/activate

بعد تفعيل البيئة، ثبت المكتبات:

python -m pip install pandas scikit-learn

راجع درس تجهيز بيئة بايثون للذكاء الاصطناعي خطوة بخطوة إذا لم تكن معتادًا على venv أو pip.

تنظيم ملفات المشروع

سنستخدم هذا التنظيم البسيط:

spam_classifier/ ├── data/ │ └── messages.csv ├── train_model.py └── requirements.txt

أنشئ الملف requirements.txt واكتب فيه:

pandas
scikit-learn

لاحقًا، يستطيع أي شخص يستخدم المشروع تثبيت المكتبات المطلوبة عبر:

python -m pip install -r requirements.txt

الخطوة 1: تجهيز بيانات الرسائل

أنشئ الملف data/messages.csv. سنستخدم عمودين فقط:

  • message: نص الرسالة.
  • label: تصنيف الرسالة، إما spam أو normal.

ضع البيانات التالية داخل الملف. هذه البيانات تعليمية ومصطنعة عمدًا؛ لا تمثل بيانات بريد حقيقية ولا تكفي لتدريب نظام موثوق.

message,label
"تهانينا ربحت جائزة كبيرة اضغط الآن لاستلامها",spam
"عرض محدود اربح قسيمة شراء مجانية اليوم",spam
"اربح هاتفًا جديدًا أرسل بياناتك الآن",spam
"لديك فرصة أخيرة للحصول على هدية مجانية",spam
"اضغط على الرابط للفوز بجائزة فورية",spam
"تم اختيارك للحصول على مكافأة نقدية",spam
"ربح مضمون خلال دقائق سجل الآن",spam
"عرض سريع لا تفوت هديتك المجانية",spam
"لديك رصيد مجاني اضغط للاستلام",spam
"اربح رحلة مجانية اليوم فقط",spam
"تم قبولك للفوز بجائزة خاصة",spam
"لا تفوت الفرصة احصل على مكافأة الآن",spam
"النتائج ستعلن غدًا في اجتماع الفريق",normal
"هل يمكن إرسال ملف التقرير قبل الظهر",normal
"موعدنا يوم الخميس الساعة العاشرة",normal
"شكرًا لك تم استلام الرسالة",normal
"يرجى مراجعة ملاحظات المشروع المرفقة",normal
"سنناقش خطة العمل في الاجتماع القادم",normal
"هل انتهيت من تحديث جدول المبيعات",normal
"تم تأكيد حجز الموعد بنجاح",normal
"أرسل لي النسخة النهائية من العرض",normal
"تذكير بدفع فاتورة الإنترنت هذا الأسبوع",normal
"سأشارك معك رابط الاجتماع لاحقًا",normal
"يرجى الرد عند الانتهاء من المهمة",normal

لاحظ أن كل صف يحتوي رسالة ثم تصنيفها. ومن المهم أن توجد أمثلة من الفئتين حتى يتعلم النموذج الفرق بينهما.

ملف CSV يحتوي رسائل عادية ورسائل مزعجة لتدريب نموذج تصنيف النصوص

الخطوة 2: لماذا نحتاج إلى تحويل النص إلى أرقام؟

لا يستطيع نموذج تعلم الآلة التعامل مع الجملة النصية مباشرة مثل:

اربح جائزة مجانية الآن

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

لا تحتاج إلى حفظ المعادلات الرياضية وراء TF-IDF الآن. المهم أن تعرف دوره في المشروع:

  1. يقرأ الرسائل النصية.
  2. يستخرج كلمات أو مجموعات كلمات.
  3. ينشئ تمثيلًا رقميًا لكل رسالة.
  4. يمرر هذه الأرقام إلى نموذج التصنيف.

استخدام ngram_range=(1, 2) في الكود لاحقًا يعني أن الأداة تنظر إلى الكلمات المفردة مثل جائزة، وإلى زوج من الكلمات مثل جائزة مجانية. هذه خطوة بسيطة قد تساعد النموذج على ملاحظة عبارات قصيرة بدل كلمات منفصلة فقط.

تحويل الرسائل النصية إلى قيم رقمية باستخدام TF-IDF لتصنيف الرسائل

الخطوة 3: تدريب نموذج التصنيف

أنشئ الملف train_model.py ثم ضع الكود التالي كاملًا:

import pandas as pd

from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics import classification_report
from sklearn.model_selection import train_test_split
from sklearn.naive_bayes import MultinomialNB
from sklearn.pipeline import Pipeline


# قراءة البيانات
data = pd.read_csv("data/messages.csv")

# التحقق من الأعمدة المطلوبة
required_columns = {"message", "label"}

if not required_columns.issubset(data.columns):
    raise ValueError("ملف البيانات يجب أن يحتوي على message وlabel.")

# حذف الصفوف الناقصة إن وجدت
data = data.dropna(subset=["message", "label"])

# تحديد النصوص والتصنيفات
X = data["message"]
y = data["label"]

# تقسيم البيانات: 75% تدريب و25% اختبار
X_train, X_test, y_train, y_test = train_test_split(
    X,
    y,
    test_size=0.25,
    random_state=42,
    stratify=y
)

# بناء خط معالجة: تحويل النص ثم تدريب المصنف
model = Pipeline(
    steps=[
        (
            "vectorizer",
            TfidfVectorizer(
                ngram_range=(1, 2),
                lowercase=False
            )
        ),
        ("classifier", MultinomialNB())
    ]
)

# تدريب النموذج على بيانات التدريب فقط
model.fit(X_train, y_train)

# التنبؤ بتصنيفات بيانات الاختبار
predictions = model.predict(X_test)

# عرض تقرير التقييم
print("--- تقرير تقييم النموذج ---")
print(
    classification_report(
        y_test,
        predictions,
        zero_division=0
    )
)

# تجربة رسائل جديدة
new_messages = [
    "اربح هدية مجانية الآن اضغط على الرابط",
    "يرجى حضور اجتماع المشروع غدًا"
]

new_predictions = model.predict(new_messages)

print("--- تجربة رسائل جديدة ---")

for message, label in zip(new_messages, new_predictions):
    print(f"الرسالة: {message}")
    print(f"التصنيف المتوقع: {label}")
    print("-" * 40)

شغّل الملف من Terminal وأنت داخل مجلد المشروع:

python train_model.py

قد يختلف تقرير التقييم عند تغيير البيانات أو إعدادات التقسيم. لا تعتبر أي رقم دقة نهائيًا لأن مجموعة البيانات هنا صغيرة جدًا؛ المهم أن تفهم بنية دورة العمل.

شرح أهم أجزاء الكود

1. قراءة CSV باستخدام pandas

data = pd.read_csv("data/messages.csv")

هذا السطر يحول ملف CSV إلى جدول يمكن التعامل معه داخل الكود. بعد ذلك نقرأ عمود message بوصفه المدخلات، وعمود label بوصفه النتيجة الصحيحة التي يجب أن يتعلمها النموذج.

2. تقسيم البيانات إلى تدريب واختبار

X_train, X_test, y_train, y_test = train_test_split(
    X,
    y,
    test_size=0.25,
    random_state=42,
    stratify=y
)

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

3. استخدام Pipeline

model = Pipeline(
    steps=[
        ("vectorizer", TfidfVectorizer()),
        ("classifier", MultinomialNB())
    ]
)

Pipeline ينفذ خطوات المشروع بالترتيب. في حالتنا:

  1. تحويل النصوص إلى أرقام عبر TfidfVectorizer.
  2. تمرير التمثيل الرقمي إلى MultinomialNB للتدريب أو التنبؤ.

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

4. لماذا اخترنا MultinomialNB؟

MultinomialNB من نماذج Naive Bayes الشائعة كبداية لتصنيف النصوص. وهو مناسب لخصائص منفصلة مثل عدد الكلمات أو تمثيلات النصوص، وتوضح وثائق scikit-learn أنه يمكن أن يعمل عمليًا أيضًا مع تمثيلات TF-IDF.

تدريب نموذج MultinomialNB لتصنيف الرسائل المزعجة والعادية

كيف تقرأ تقرير التقييم؟

الدالة classification_report تطبع عدة مقاييس لكل فئة. لا تحتاج إلى حفظها كلها في أول مشروع، لكن افهم معناها المبسط:

المقياس المعنى المبسط
precision عندما قال النموذج إن الرسالة مزعجة، كم مرة كان حكمه صحيحًا؟
recall من بين الرسائل المزعجة الموجودة فعلًا، كم رسالة استطاع النموذج التقاطها؟
f1-score مقياس يجمع بين precision وrecall بصورة متوازنة.
support عدد الأمثلة الفعلية من كل فئة داخل بيانات الاختبار.

عندما تكون بيانات الاختبار صغيرة، يمكن أن تتغير هذه الأرقام كثيرًا إذا غيرت التقسيم أو أضفت رسائل جديدة. لهذا لا تركز على الحصول على رقم مرتفع في هذا المثال، بل على فهم ما الذي يقيسه كل رقم ولماذا تحتاج إلى بيانات أكبر ومتنوعة لاحقًا.

جرّب رسائل من عندك

غيّر القائمة التالية داخل الملف:

new_messages = [
    "اربح هدية مجانية الآن اضغط على الرابط",
    "يرجى حضور اجتماع المشروع غدًا"
]

ثم شغّل البرنامج مرة أخرى. جرّب رسائل متنوعة، لكن تذكر أن النموذج لا يفهم المعنى الكامل للغة؛ هو يتعلم من الكلمات والأنماط المحدودة التي رأى أمثلة منها.

مثلًا، إذا أدخلت رسالة تحتوي على كلمات لم تظهر في البيانات إطلاقًا، فقد يقدم النموذج تصنيفًا غير مناسب. هذه ليست مشكلة غريبة في الكود، بل نتيجة طبيعية لبيانات تدريب صغيرة ومحدودة.

لماذا لا نستخدم كلمات ممنوعة أو روابط حقيقية في البيانات؟

في مشروع تعليمي، من الأفضل أن تستخدم رسائل عامة وآمنة. لا تضع أرقام حسابات أو بيانات أشخاص أو روابط مشبوهة أو نسخًا من رسائل حقيقية خاصة. التدريب الجيد يبدأ من بيانات منظمة ومسموح باستخدامها، وليس من جمع محتوى شخصي أو حساس دون سبب وموافقة.

أخطاء شائعة في مشروع تصنيف الرسائل

1. تدريب النموذج على البيانات واختباره عليها نفسها

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

2. نسيان وجود أمثلة من الفئتين

إذا كانت بياناتك تحتوي رسائل مزعجة فقط أو عادية فقط، فلن يتعلم النموذج الفرق بين الفئتين.

3. وضع التصنيفات بطريقة غير متسقة

لا تخلط بين spam وSpam ومزعج داخل الملف نفسه. اختر شكلًا واحدًا ثابتًا للتصنيفات.

4. الحكم على المشروع من بيانات صغيرة جدًا

مجموعة التدريب هنا للتعلم، وليست معيارًا حقيقيًا لجودة النموذج. نموذج جيد للاستخدام الفعلي يحتاج بيانات كثيرة ومتنوعة وتمثّل الحالات التي سيواجهها.

5. تحويل البيانات قبل التقسيم بشكل غير منظم

استخدام Pipeline يساعدك على تطبيق تحويل النص والتدريب في ترتيب سليم، بدل تجهيز النصوص بطريقة قد تخلط معلومات التدريب والاختبار.

6. اعتبار التنبؤ قرارًا نهائيًا

تصنيف النصوص قد يخطئ، خصوصًا مع الرسائل القصيرة أو العربية أو الصيغ الجديدة. في الأنظمة الحقيقية تحتاج سياسات مراجعة وحدودًا واضحة قبل اتخاذ أي إجراء تلقائي.

اختبار نموذج تصنيف الرسائل وعرض النتيجة والتنبؤ برسالة جديدة

كيف تطور المشروع لاحقًا؟

  • أضف عددًا أكبر من الرسائل التعليمية المتنوعة.
  • أضف فئة ثالثة مثل promotion للرسائل الترويجية غير المزعجة.
  • اعرض مصفوفة الالتباس لفهم أنواع الأخطاء.
  • جرّب مقارنة MultinomialNB مع نموذج آخر مثل LogisticRegression.
  • احفظ النموذج بعد التدريب في ملف باستخدام joblib ثم استخدمه لاحقًا في برنامج منفصل.
  • أنشئ واجهة بسيطة بعد أن تفهم منطق التدريب والتنبؤ.

روابط داخلية مفيدة من بايثون العرب

الخلاصة

  • تصنيف الرسائل المزعجة مثال عملي على مشكلة تصنيف نصوص.
  • ملف CSV يحتوي النص والتصنيف هو نقطة البداية لتدريب النموذج.
  • TfidfVectorizer يحول الرسائل النصية إلى تمثيل رقمي يمكن للنموذج التعامل معه.
  • MultinomialNB نموذج مناسب كبداية لتصنيف النصوص التعليمية.
  • يجب فصل بيانات التدريب عن بيانات الاختبار حتى تقيس أداء النموذج على أمثلة لم يرها.
  • classification_report يساعدك على فهم الدقة والاستدعاء وF1 لكل فئة.
  • البيانات الصغيرة المصطنعة مفيدة للتعلم فقط، وليست أساسًا لنظام فلترة حقيقي.
{alertSuccess} قاعدة ذهبية: لا تبدأ بقول “أريد بناء ذكاء اصطناعي”. ابدأ بمشكلة صغيرة لها فئات واضحة وبيانات منظمة، ثم افهم كل خطوة من قراءة البيانات إلى اختبار النموذج قبل تطوير المشروع.

مصادر خارجية رسمية للتوسع

أسئلة شائعة

هل هذا المشروع يستخدم ذكاءً اصطناعيًا حقيقيًا؟

هو مشروع تعلم آلة تعليمي حقيقي من ناحية الخطوات: بيانات وتصنيفات وتدريب واختبار وتنبؤ. لكن بياناته صغيرة ومصطنعة، لذلك لا يصلح كنظام فلترة حقيقي أو كقرار آلي في الاستخدام الفعلي.

لماذا نستخدم TfidfVectorizer؟

لأن نموذج تعلم الآلة لا يتعامل مع الجملة كنص مباشر. TfidfVectorizer يحول مجموعة الرسائل إلى خصائص رقمية مبنية على الكلمات وأهميتها النسبية.

هل MultinomialNB مناسب للنصوص العربية؟

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

لماذا نقسم البيانات إلى تدريب واختبار؟

حتى نعرف هل يستطيع النموذج تصنيف رسائل لم يرها أثناء التدريب. اختبار النموذج على الرسائل نفسها التي تدرب عليها لا يقيس قدرته على التعميم.

هل أستطيع إضافة فئات أخرى؟

نعم. يمكنك مثلًا إضافة فئة promotion أو important، لكن يجب أن توفر عددًا مناسبًا من الأمثلة المصنفة لكل فئة، ثم تعيد تدريب النموذج.

إرسال تعليق

أحدث أقدم