ML Learning Hub
تطبيقيمبتدئ

مصنفات بايز الساذجة

نظرية بايز + افتراض جريء واحد = مصنّف قوي بشكل مدهش

مبرهنة بايز وافتراض الاستقلالية الشرطية ومتغيرات Gaussian/Multinomial/Complement وتمهيد Laplace وتصنيف النصوص بـTF-IDF ومعايرة الاحتمالات.

30 min
7 مخططات
7 المفاهيم المغطاة

المتطلبات الأساسية

Probability & Statistics

المفاهيم المغطاة

Bayes TheoremMAP DecisionLaplace SmoothingGaussianNBMultinomialNBComplementNBCalibration

الصيغ الرئيسية

نظرية بايز

الاحتمال الخلفي = الاحتمالية × المسبق / الدليل

الفرضية الساذجة

الميزات مستقلة شرطياً بإعطاء الفئة — الجزء 'الساذج'

قرار MAP

الأعظمية الخلفية — تجاهل P(x) لأنه متساوٍ لجميع الفئات

الاحتمالية الغاوسية

يفترض NB الغاوسي أن كل ميزة موزَّعة توزيعاً طبيعياً داخل كل فئة

محاكاة تفاعلية

Loading visualization…
🎯

لماذا نتعلم بايز الساذج؟

motivation

يُصنِّف Naïve Bayes رسائل البريد المزعج بشكل أفضل من كثير من النماذج المعقدة، يعمل في ميكروثوانٍ، يحتاج بيانات تدريب قليلة جداً، يتعامل بلطف مع الميزات الناقصة، ويُنتج احتمالات مُعايَرة. كان فلتر البريد المزعج الأصلي في Gmail يستخدم Naïve Bayes. هو المرجع القياسي لمسائل تصنيف النصوص. فهمه يمنح حدساً عميقاً حول المصنِّفات الاحتمالية ولماذا فرضية 'الساذج' (الاستقلالية الشرطية) يمكنها رغم ذلك إنتاج نماذج مفيدة.

رغم أن فرضية الاستقلالية 'الساذجة' خاطئة تقريباً دائماً في الواقع، يحقق Naïve Bayes باستمرار دقة تصنيف قريبة من المثالي في مهام تصنيف النصوص والوثائق.

💡

الحدس الاحتمالي

intuition

افترض أنك تريد تصنيف بريد إلكتروني كـ'مزعج' أو 'طبيعي'. رأيت 1000 بريد: 300 كانت مزعجة. كلمة 'فياغرا' تظهر في 250 من 300 رسائل مزعجة وفقط 1 من 700 طبيعية. كلمة 'اجتماع' تظهر في 5 مزعجة و400 طبيعية. لبريد جديد يحتوي الكلمتين، يضرب Naïve Bayes: P(مزعج) × P(فياغرا|مزعج) × P(اجتماع|مزعج). هذا الناتج هو الاحتمال الخلفي غير المُطبَّع — قارنه بـP(طبيعي) × P(فياغرا|طبيعي) × P(اجتماع|طبيعي). الأكبر يفوز. الفرضية 'الساذجة' تجعل هذا الضرب صالحاً.

اشتقاق قاعدة القرار

math

بنظرية بايز: P(C|x) ∝ P(x|C)P(C). الفرضية الساذجة تُفكِّك P(x|C) = ∏ P(xⱼ|C). بما أن P(x) ثابت بين الفئات، نحتاج فقط البسط. بأخذ اللوغاريتم (للاستقرار العددي — ضرب احتمالات صغيرة يُفيض): log P(C|x) = log P(C) + Σⱼ log P(xⱼ|C). في NB الغاوسي، P(xⱼ|C) غاوسية بمتوسط وتباين مُقدَّرَين لكل فئة. في NB متعدد الحدود (النصوص)، P(xⱼ|C) هي تكرار الكلمة المُملَّس في الفئة C.

قاعدة قرار MAP في الفضاء اللوغاريتمي
🔬

تمهيد لابلاس: تجنب الاحتمالات الصفرية

deepdive

إذا لم تظهر كلمة قط في رسائل التدريب المزعجة، فإن P(كلمة|مزعج)=0 ويُصبح كامل الناتج صفراً — كلمة واحدة غير مرئية تجعل المصنِّف يتجاهل كل الأدلة الأخرى. يُضيف تمهيد لابلاس α (عادةً 1) لجميع أعداد الكلمات: P(xⱼ|C) = (عدد(xⱼ,C) + α) / (عدد(C) + α × |V|) حيث |V| حجم المفردات. هذا يضمن ألا يكون أي احتمال صفراً تماماً. α أكبر = تمهيد أكثر = أقرب للتوزيع المنتظم.

تمهيد لابلاس شكل من أشكال تنظيم L1 في السمبلكس الاحتمالي. يمنع الإفراط في التعلم على الكلمات النادرة وهو حاسم لـNB متعدد الحدود على بيانات النصوص.

⚖️

أي متغير من بايز الساذج تستخدم؟

comparison

GaussianNB: ميزات مستمرة مفترض أنها غاوسية لكل فئة. جيد لبيانات المستشعرات والقياسات الطبية. MultinomialNB: ميزات أعداد صحيحة (أعداد الكلمات، TF-IDF×N). قياسي لتصنيف الوثائق. BernoulliNB: ميزات ثنائية (وجود/غياب الكلمات). جيد للنصوص القصيرة. ComplementNB: يعالج تحيز MultinomialNB على البيانات غير المتوازنة — غالباً الأفضل لتصنيف النصوص.

1

ميزات مستمرة → GaussianNB

2

أعداد كلمات / ميزات TF-IDF → MultinomialNB (تتطلب قيماً غير سالبة)

3

ميزات ثنائية (كلمة موجودة/غائبة) → BernoulliNB

4

تصنيف نصوص غير متوازن → ComplementNB

5

أنواع مختلطة → استخدام ColumnTransformer + NB مختلف لكل نوع عمود

</>

تصنيف النصوص مع بايز الساذج

code
python54 lines
from sklearn.naive_bayes import MultinomialNB, ComplementNB, GaussianNB
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.pipeline import Pipeline
from sklearn.model_selection import cross_val_score, train_test_split
from sklearn.calibration import CalibratedClassifierCV
from sklearn.preprocessing import LabelEncoder

class="tok-comment"># ── Sample text data ───────────────────────────────────────────────────
X_text = [
    class="tok-str">"buy cheap pills now", class="tok-str">"get rich quick scheme", class="tok-str">"free money click here",
    class="tok-str">"meeting at 3pm tomorrow", class="tok-str">"quarterly report attached", class="tok-str">"team lunch Friday",
    class="tok-str">"win a prize enter now", class="tok-str">"limited offer act fast", class="tok-str">"investment opportunity",
    class="tok-str">"project deadline next week", class="tok-str">"budget review scheduled", class="tok-str">"please review document",
] * class="tok-num">20   class="tok-comment"># class="tok-num">240 samples
y_raw = ([class="tok-num">1, class="tok-num">1, class="tok-num">1, class="tok-num">0, class="tok-num">0, class="tok-num">0, class="tok-num">1, class="tok-num">1, class="tok-num">1, class="tok-num">0, class="tok-num">0, class="tok-num">0] * class="tok-num">20)  class="tok-comment"># class="tok-num">1=spam, class="tok-num">0=ham
import numpy as np
y = np.array(y_raw)
X_train, X_test, y_train, y_test = train_test_split(
    X_text, y, test_size=class="tok-num">0.2, random_state=class="tok-num">42)

class="tok-comment"># ── Text classification (spam detection) ──────────────────────────
pipe = Pipeline([
    (class="tok-str">'tfidf', TfidfVectorizer(
        ngram_range=(class="tok-num">1,class="tok-num">2),       class="tok-comment"># unigrams + bigrams
        max_features=50_000,
        sublinear_tf=True,       class="tok-comment"># log(class="tok-num">1+tf)
        min_df=class="tok-num">3,
    )),
    (class="tok-str">'clf', ComplementNB(alpha=class="tok-num">0.1)),  class="tok-comment"># best for text
])

scores = cross_val_score(pipe, X_text, y, cv=class="tok-num">5, scoring=class="tok-str">'f1_macro')
print(fclass="tok-str">"F1: {scores.mean():.3f} ± {scores.std():.3f}")

class="tok-comment"># ── Calibrated probabilities ───────────────────────────────────────
class="tok-comment"># NB probabilities are often poorly calibrated (overconfident)
class="tok-comment"># Use isotonic regression calibration for better probability estimates
pipe_cal = CalibratedClassifierCV(pipe, cv=class="tok-num">5, method=class="tok-str">'isotonic')
pipe_cal.fit(X_train, y_train)
probs = pipe_cal.predict_proba(X_test)

class="tok-comment"># ── Continuous features: GaussianNB ────────────────────────────────
from sklearn.preprocessing import StandardScaler
gnb = Pipeline([
    (class="tok-str">'scaler', StandardScaler()),
    (class="tok-str">'clf', GaussianNB(var_smoothing=class="tok-num">1e-9)),
])
gnb.fit(X_train, y_train)
print(fclass="tok-str">"GaussianNB accuracy: {gnb.score(X_test, y_test):.3f}")

class="tok-comment"># ── Inspect learned parameters ─────────────────────────────────────
nb = gnb.named_steps[class="tok-str">'clf']
print(class="tok-str">"Class priors:", nb.class_prior_)
print(class="tok-str">"Feature means per class:", nb.theta_)   class="tok-comment"># shape (n_classes, n_features)
⚠️

مزالق بايز الساذج

pitfall

فرضية الاستقلالية تعني أن الميزات المترابطة تُحتسب مرتين. إذا كانت 'فياغرا' و'حبة' تتزامنان دائماً في البريد المزعج، فدليلهما المشترك يُحتسب مرتين مما يؤدي لاحتمالات خلفية مفرطة الثقة. لهذا تكون احتمالات NB عموماً سيئة التعيير حتى حين تكون التصنيفات صحيحة — دائماً استخدم CalibratedClassifierCV للمخرجات الاحتمالية. أيضاً: MultinomialNB يتطلب ميزات غير سالبة.

Naïve Bayes خط أساس ممتاز وغالباً يصعب التفوق عليه في مجموعات النصوص الصغيرة. إذا سجّل 85% ونموذجك المعقد 87%، فاسأل: هل يستحق الكسب بنسبة 2% تعقيداً أعلى 10× وزمن تدريب أطول؟

?اختبار المعرفة

يتم حفظ التقدم في متصفحك — لا حاجة لحساب.

تحتاج مهندس ذكاء اصطناعي أو عالم بيانات؟

أبني نماذج تعلم آلي مخصصة، ووكلاء ذكاء اصطناعي، ورؤية حاسوب، وأتمتة — من الفكرة إلى الإنتاج.