فاز 1 · درس 7

قضیه بیز و طبقه‌بند نایو بیز در یادگیری ماشین

نوع
ساختنی
زمان
حدود 75 دقیقه
زبان‌ها
Python
یک ترازوی سنجش برنجی مینیمال قدیمی روی پس‌زمینه تیره که در یک کفه آن شواهد سبک و در کفه دیگر وزنه‌ای سنگین‌تر قرار دارد
فهرست مطالب
  1. اهداف یادگیری
  2. صورت مسئله
  3. مفاهیم پایه
  4. از احتمال توأم تا قضیه‌ی بیز
  5. چهار بخش معادله
  6. مثال آزمایش پزشکی
  7. مثال فیلتر اسپم
  8. نایو بیز: فرض استقلال
  9. برآورد درست‌نمایی بیشینه (MLE)
  10. بیشینه‌احتمال پسین (MAP)
  11. بیزی در برابر بسامدگرا: تفاوت کاربردی
  12. چرا تفکر بیزی برای یادگیری ماشین مهم است؟
  13. ساخت از صفر
  14. مرحله‌ی 1: تابع قضیه‌ی بیز
  15. مرحله‌ی 2: طبقه‌بند نایو بیز
  16. مرحله‌ی 3: آموزش روی داده‌های اسپم
  17. مرحله‌ی 4: بررسی احتمال‌های یادگرفته‌شده
  18. استفاده از آن
  19. استفاده در عمل
  20. پیشین‌های مزدوج
  21. به‌روزرسانی متوالی بیزی
  22. ارتباط با آزمون A/B
  23. تمرین‌ها
  24. راهنمایی‌ها
  25. اصطلاحات کلیدی
  26. برای مطالعه‌ی بیشتر

بسیاری از مدل‌های یادگیری ماشین هنگام پیش‌بینی در محیط‌های تولیدی با مشکلی اساسی روبرو می‌شوند: اعتمادبه‌نفس کاذب در خروجی‌ها. وقتی مدلی احتمال کلاسی را بالا گزارش می‌کند، لزوماً به این معنا نیست که در شرایط نایاب بودن آن رخداد، پیش‌بینی قابل‌اطمینانی ارائه داده است. قضیه‌ی بیز چارچوبی شفاف فراهم می‌کند تا عدم قطعیت را به شیوه‌ای اصولی فرمول‌بندی و مدیریت کنیم.

درک تفکر بیزی پل اتصال میان آمار کلاسیک و یادگیری ماشین پیشرفته است. مفاهیمی مانند منظم‌سازی مدل‌ها، به‌روزرسانی آنلاین در سیستم‌های بلادرنگ و طراحی آزمون‌های A/B با بهره‌گیری از روابط بیزی به سادگی قابل پیاده‌سازی و تفسیر هستند. این دیدگاه به مهندسان نرم‌افزار و یادگیری ماشین امکان می‌دهد تا به‌جای تصمیم‌گیری کورکورانه بر پایه‌ی احتمالات کالیبره‌نشده، مدل‌های قابل‌اعتماد بسازند.

در این درس علاوه بر بررسی دقیق ریاضیات قضیه‌ی بیز و تفاوت‌های برآورد MLE و MAP، یک طبقه‌بند متن نایو بیز را از پایه در پایتون کدنویسی می‌کنید و نحوه‌ی استفاده از آن را در تست‌های A/B به‌صورت عملی فرا می‌گیرید.

احتمال درباره‌ی چیزی است که انتظارش را دارید؛ قضیه‌ی بیز درباره‌ی چیزی است که یاد می‌گیرید.

اهداف یادگیری

  • به‌کارگیری قضیه‌ی بیز برای محاسبه‌ی احتمال‌های پسین از روی پیشین‌ها، درست‌نمایی‌ها و شواهد
  • ساخت طبقه‌بند متن نایو بیز (Naive Bayes) از صفر همراه با هموارسازی لاپلاس و محاسبات در فضای لگاریتمی
  • مقایسه‌ی برآورد درست‌نمایی بیشینه (MLE) با برآورد بیشینه‌احتمال پسین (MAP) و توضیح ارتباط MAP با منظم‌سازی L2
  • پیاده‌سازی به‌روزرسانی متوالی بیزی با استفاده از پیشین‌های مزدوج بتا-دو‌جمله‌ای برای آزمون‌های A/B

صورت مسئله

یک آزمایش پزشکی 99% دقت دارد. نتیجه‌ی آزمایش شما مثبت می‌شود. چقدر احتمال دارد که واقعاً بیمار باشید؟

بیشتر افراد می‌گویند 99%. پاسخ واقعی به میزان نایاب بودن آن بیماری بستگی دارد. اگر از هر 10,000 نفر فقط 1 نفر به این بیماری مبتلا باشد، نتیجه‌ی مثبت یعنی تنها حدود 1% شانس بیمار بودن دارید. آن 99% دیگرِ نتایج مثبت، هشدارهای کاذب مربوط به افراد سالم‌اند.

این سؤال انحرافی نیست؛ پای خودِ قضیه‌ی بیز (Bayes' theorem) در میان است. همه‌ی فیلترهای اسپم، سیستم‌های تشخیص پزشکی و مدل‌های یادگیری ماشینی که عدم قطعیت را اندازه می‌گیرند، دقیقاً از همین استدلال استفاده می‌کنند. شما با یک باور شروع می‌کنید، شاهدی می‌بینید و باورتان را به‌روزرسانی می‌کنید.

اگر بدون درک این مفهوم سیستم‌های یادگیری ماشین بسازید، خروجی مدل‌ها را اشتباه تفسیر می‌کنید، آستانه‌های نامناسبی تعیین می‌کنید و پیش‌بینی‌هایی تحویل می‌دهید که بیش از حد به خود مطمئن‌اند.

مفاهیم پایه

از احتمال توأم تا قضیه‌ی بیز

از درس 06 به یاد دارید که احتمال شرطی (conditional probability) به‌صورت زیر است:

P(A∣B)=P(A and B)P(B)P(A \mid B) = \frac{P(A \text{ and } B)}{P(B)}

و به‌صورت متقارن:

P(B∣A)=P(A and B)P(A)P(B \mid A) = \frac{P(A \text{ and } B)}{P(A)}

صورت هر دو عبارت یکسان است: P(A and B)P(A \text{ and } B). آن‌ها را برابر هم قرار دهید و بازآرایی کنید:

P(A and B)=P(A∣B)⋅P(B)=P(B∣A)⋅P(A)Therefore:P(A∣B)=P(B∣A)⋅P(A)P(B)\begin{aligned} P(A \text{ and } B) &= P(A \mid B) \cdot P(B) = P(B \mid A) \cdot P(A) \\[4pt] &\text{Therefore:} \\[4pt] P(A \mid B) &= \frac{P(B \mid A) \cdot P(A)}{P(B)} \end{aligned}

این همان قضیه‌ی بیز است. چهار مؤلفه، یک معادله.

چهار بخش معادله

مؤلفه نام مفهوم
P(A∣B)P(A \mid B) پسین (Posterior) باور به‌روزشده‌ی شما درباره‌ی AA پس از مشاهده‌ی شواهد BB
P(B∣A)P(B \mid A) درست‌نمایی (Likelihood) چقدر محتمل است شواهد BB رخ دهند، اگر AA درست باشد
P(A)P(A) پیشین (Prior) باور شما درباره‌ی AA پیش از مشاهده‌ی هرگونه شواهد
P(B)P(B) شواهد (Evidence) احتمال کل مشاهده‌ی BB تحت تمام حالات ممکن

عبارت شواهد یعنی P(B)P(B) نقش نرمال‌کننده را بازی می‌کند. می‌توانید با استفاده از قانون احتمال کل آن را باز کنید:

P(B)=P(B∣A)⋅P(A)+P(B∣not A)⋅P(not A)P(B) = P(B \mid A) \cdot P(A) + P(B \mid \text{not } A) \cdot P(\text{not } A)

مثال آزمایش پزشکی

یک بیماری از هر 10,000 نفر، 1 نفر را مبتلا می‌کند. آزمایش 99% دقیق است (99% افراد بیمار را شناسایی می‌کند و در 1% مواقع نتیجه‌ی مثبت کاذب می‌دهد).

P(sick)=0.0001(prior: disease is rare)P(positive∣sick)=0.99(likelihood: test catches it)P(positive∣healthy)=0.01(false positive rate)P(positive)=P(positive∣sick)⋅P(sick)+P(positive∣healthy)⋅P(healthy)=0.99⋅0.0001+0.01⋅0.9999=0.000099+0.009999=0.010098P(sick∣positive)=P(positive∣sick)⋅P(sick)/P(positive)=0.99⋅0.0001/0.010098=0.0098=0.98%\begin{aligned} P(\text{sick}) &= 0.0001 \quad \text{(prior: disease is rare)} \\ P(\text{positive} \mid \text{sick}) &= 0.99 \quad \text{(likelihood: test catches it)} \\ P(\text{positive} \mid \text{healthy}) &= 0.01 \quad \text{(false positive rate)} \\[6pt] P(\text{positive}) &= P(\text{positive} \mid \text{sick}) \cdot P(\text{sick}) + P(\text{positive} \mid \text{healthy}) \cdot P(\text{healthy}) \\ &= 0.99 \cdot 0.0001 + 0.01 \cdot 0.9999 \\ &= 0.000099 + 0.009999 \\ &= 0.010098 \\[6pt] P(\text{sick} \mid \text{positive}) &= P(\text{positive} \mid \text{sick}) \cdot P(\text{sick}) / P(\text{positive}) \\ &= 0.99 \cdot 0.0001 / 0.010098 \\ &= 0.0098 \\ &= 0.98\% \end{aligned}

کمتر از 1%. احتمال پیشین دست بالا را دارد. وقتی یک عارضه نادر است، حتی آزمایش‌های دقیق هم اکثراً نتایج مثبت کاذب تولید می‌کنند. به همین دلیل است که پزشکان آزمایش‌های تأییدی تجویز می‌کنند.

مثال فیلتر اسپم

ایمیلی حاوی واژه‌ی «lottery» دریافت می‌کنید. آیا اسپم است؟

P(spam)=0.3(30% of email is spam)P("lottery"∣spam)=0.05(5% of spam emails contain "lottery")P("lottery"∣not spam)=0.001(0.1% of legitimate emails contain "lottery")P("lottery")=0.05⋅0.3+0.001⋅0.7=0.015+0.0007=0.0157P(spam∣"lottery")=0.05⋅0.3/0.0157=0.955=95.5%\begin{aligned} P(\text{spam}) &= 0.3 \quad \text{(30\% of email is spam)} \\ P(\text{"lottery"} \mid \text{spam}) &= 0.05 \quad \text{(5\% of spam emails contain "lottery")} \\ P(\text{"lottery"} \mid \text{not spam}) &= 0.001 \quad \text{(0.1\% of legitimate emails contain "lottery")} \\[6pt] P(\text{"lottery"}) &= 0.05 \cdot 0.3 + 0.001 \cdot 0.7 \\ &= 0.015 + 0.0007 \\ &= 0.0157 \\[6pt] P(\text{spam} \mid \text{"lottery"}) &= 0.05 \cdot 0.3 / 0.0157 \\ &= 0.955 \\ &= 95.5\% \end{aligned}

تنها یک واژه احتمال را از 30% به 95.5% تغییر می‌دهد. یک فیلتر اسپم واقعی، قضیه‌ی بیز را به‌طور هم‌زمان روی صدها واژه اعمال می‌کند.

نایو بیز: فرض استقلال

مدل نایو بیز با فرض اینکه همه‌ی ویژگی‌ها به شرط داشتن کلاس از یکدیگر مستقل‌اند، این رویکرد را به چندین ویژگی گسترش می‌دهد:

P(class∣feature1,feature2,…,featuren)=P(class)⋅P(feature1∣class)⋅P(feature2∣class)⋯P(featuren∣class)P(feature1,feature2,…,featuren)P(\text{class} \mid \text{feature}_1, \text{feature}_2, \ldots, \text{feature}_n) = \frac{P(\text{class}) \cdot P(\text{feature}_1 \mid \text{class}) \cdot P(\text{feature}_2 \mid \text{class}) \cdots P(\text{feature}_n \mid \text{class})}{P(\text{feature}_1, \text{feature}_2, \ldots, \text{feature}_n)}

واژه‌ی «نایو» (ساده‌لوحانه) به همین فرض استقلال شرطی اشاره دارد. در متن، رخداد واژه‌ها از هم مستقل نیست (مثلاً «New» و «York» همبسته‌اند). اما این فرض در عمل فوق‌العاده خوب جواب می‌دهد؛ چرا که طبقه‌بند فقط باید کلاس‌ها را رتبه‌بندی کند، نه اینکه احتمال‌های کالیبره‌شده بسازد.

از آنجا که مخرج برای همه‌ی کلاس‌ها یکسان است، می‌توانید از آن صرف‌نظر کنید و فقط صورت‌ها را مقایسه کنید:

score(class)=P(class)⋅∏iP(featurei∣class)\text{score}(\text{class}) = P(\text{class}) \cdot \prod_i P(\text{feature}_i \mid \text{class})

کلاسی را انتخاب کنید که بیشترین امتیاز را دارد.

برآورد درست‌نمایی بیشینه (MLE)

چگونه مقدار P(feature∣class)P(\text{feature} \mid \text{class}) را از داده‌های آموزشی به دست می‌آورید؟ با شمارش.

P("free"∣spam)=number of spam emails containing "free"total spam emailsP(\text{"free"} \mid \text{spam}) = \frac{\text{number of spam emails containing "free"}}{\text{total spam emails}}

این همان MLE است: مقادیری از پارامترها را انتخاب کنید که داده‌های مشاهده‌شده را به محتمل‌ترین حالت ممکن برسانند. در واقع شما تابع درست‌نمایی را بیشینه می‌کنید که برای شمارش‌های گسسته به همان فراوانی نسبی تبدیل می‌شود.

مشکل: اگر واژه‌ای در مرحله‌ی آموزش هرگز در اسپم دیده نشود، روش MLE احتمال آن را صفر در نظر می‌گیرد. یک واژه‌ی دیده‌نشده کل حاصل‌ضرب را از بین می‌برد. این مشکل را با هموارسازی لاپلاس (Laplace smoothing) برطرف کنید:

P(word∣class)=count(word,class)+1total_words_in_class+vocabulary_sizeP(\text{word} \mid \text{class}) = \frac{\text{count}(\text{word}, \text{class}) + 1}{\text{total\_words\_in\_class} + \text{vocabulary\_size}}

افزودن 1 به هر شمارش تضمین می‌کند که هیچ احتمالی هرگز صفر نخواهد شد.

بیشینه‌احتمال پسین (MAP)

روش MLE می‌پرسد: چه پارامترهایی مقدار P(data∣parameters)P(\text{data} \mid \text{parameters}) را بیشینه می‌کنند؟

روش MAP می‌پرسد: چه پارامترهایی مقدار P(parameters∣data)P(\text{parameters} \mid \text{data}) را بیشینه می‌کنند؟

طبق قضیه‌ی بیز:

P(parameters∣data)∝P(data∣parameters)⋅P(parameters)P(\text{parameters} \mid \text{data}) \propto P(\text{data} \mid \text{parameters}) \cdot P(\text{parameters})

روش MAP یک پیشین روی خودِ پارامترها اضافه می‌کند. اگر باورتان این است که پارامترها باید مقادیر کوچکی داشته باشند، این باور را در قالب پیشینی تعریف می‌کنید که به مقادیر بزرگ جریمه می‌دهد. این فرایند دقیقاً همان منظم‌سازی L2 در یادگیری ماشین است. جریمه‌ی «ridge» در رگرسیون ریج، در واقع همان اعمال پیشین گوسی روی وزن‌هاست.

روش برآورد بهینه‌سازی می‌کند معادل در یادگیری ماشین
MLE P(data∣params)P(\text{data} \mid \text{params}) آموزش بدون منظم‌سازی
MAP P(data∣params)⋅P(params)P(\text{data} \mid \text{params}) \cdot P(\text{params}) منظم‌سازی L1 / L2

بیزی در برابر بسامدگرا: تفاوت کاربردی

بسامدگرایان (Frequentists) پارامترها را مقادیر ثابتِ ناشناخته می‌دانند. آن‌ها می‌پرسند: «اگر این آزمایش را بارها تکرار کنم، چه پیش خواهد آمد؟»

بیزی‌ها (Bayesians) پارامترها را در قالب توزیع‌ها می‌بینند. آن‌ها می‌پرسند: «با توجه به آنچه مشاهده کرده‌ام، چه باوری درباره‌ی پارامترها دارم؟»

برای ساخت سیستم‌های یادگیری ماشین، تفاوت‌های کاربردی این دو رویکرد عبارت‌اند از:

جنبه بسامدگرا بیزی
خروجی برآورد نقطه‌ای توزیع روی مقادیر
عدم قطعیت بازه‌های اطمینان (درباره‌ی فرآیند) بازه‌های باورپذیر (درباره‌ی پارامتر)
داده‌های اندک امکان بیش‌برازش پیشین نقش منظم‌سازی را ایفا می‌کند
بار محاسباتی معمولاً سریع‌تر اغلب نیازمند نمونه‌برداری است (MCMC)

بیشتر سیستم‌های یادگیری ماشین عملیاتی، بسامدگرا هستند (SGD، برآوردهای نقطه‌ای). روش‌های بیزی زمانی می‌درخشند که به عدم قطعیت کالیبره‌شده نیاز دارید (تصمیم‌گیری‌های پزشکی، سیستم‌های حساس به ایمنی) یا زمانی که داده‌ها کمیاب‌اند (یادگیری چند-نمونه‌ای، شروع سرد).

چرا تفکر بیزی برای یادگیری ماشین مهم است؟

ارتباط این مفاهیم عمیق‌تر از یک تمثیل ساده است:

پیشین‌ها همان منظم‌سازی هستند. یک پیشین گوسی روی وزن‌ها، همان منظم‌سازی L2 است. یک پیشین لاپلاس همان L1 است. هر بار که ترم منظم‌سازی اضافه می‌کنید، در واقع گزاره‌ای بیزی مطرح می‌کنید درباره‌ی اینکه چه مقادیری را برای پارامترها انتظار دارید.

توزیع‌های پسین همان عدم قطعیت هستند. یک احتمال پیش‌بینی‌شده‌ی تکی، هیچ اطلاعاتی درباره‌ی میزان اطمینان مدل از آن برآورد به شما نمی‌دهد. روش‌های بیزی به شما یک توزیع می‌دهند: «فکر می‌کنم P(spam)P(\text{spam}) بین 0.8 و 0.95 باشد.»

به‌روزرسانی‌های بیزی همان یادگیری برخط هستند. پسینِ امروز به پیشینِ فردا تبدیل می‌شود. وقتی مدل شما داده‌های جدیدی می‌بیند، به‌جای بازآموزی از صفر، باورهایش را به‌صورت تدریجی به‌روزرسانی می‌کند.

مقایسه‌ی مدل‌ها ساختاری بیزی دارد. معیار اطلاعات بیزی (BIC)، درست‌نمایی حاشیه‌ای و فاکتورهای بیز، همگی از استدلال بیزی برای انتخاب میان مدل‌ها بدون خطر بیش‌برازش استفاده می‌کنند.

به‌روزرسانی بیزیتغییر احتمال پیشین، حساسیت و FPR با کشیدن
شگفتی قضیه بیز: آزمایشی با دقت 95% برای بیماری‌ای با شیوع 1 در 100، باز هم اکثر افراد با نتیجه‌ی مثبت را سالم نشان می‌دهد؛ زیرا موارد مثبت کاذب ناشی از جمعیت عظیم افراد سالم، موارد انگشت‌شمار واقعی را تحت‌الشعاع قرار می‌دهند. احتمال پسین تنها زمانی بالا می‌رود که احتمال پیشین به اندازه‌ای زیاد باشد که موارد واقعی از هشدارهای کاذب پیشی بگیرند.

ساخت از صفر

مرحله‌ی 1: تابع قضیه‌ی بیز

def bayes(prior, likelihood, false_positive_rate):
    evidence = likelihood * prior + false_positive_rate * (1 - prior)
    posterior = likelihood * prior / evidence
    return posterior

result = bayes(prior=0.0001, likelihood=0.99, false_positive_rate=0.01)
print(f"P(sick|positive) = {result:.4f}")

مرحله‌ی 2: طبقه‌بند نایو بیز

import math
from collections import defaultdict

class NaiveBayes:
    def __init__(self, smoothing=1.0):
        self.smoothing = smoothing
        self.class_counts = defaultdict(int)
        self.word_counts = defaultdict(lambda: defaultdict(int))
        self.class_word_totals = defaultdict(int)
        self.vocab = set()

    def train(self, documents, labels):
        for doc, label in zip(documents, labels):
            self.class_counts[label] += 1
            words = doc.lower().split()
            for word in words:
                self.word_counts[label][word] += 1
                self.class_word_totals[label] += 1
                self.vocab.add(word)

    def predict(self, document):
        words = document.lower().split()
        total_docs = sum(self.class_counts.values())
        vocab_size = len(self.vocab)
        best_class = None
        best_score = float("-inf")
        for cls in self.class_counts:
            score = math.log(self.class_counts[cls] / total_docs)
            for word in words:
                count = self.word_counts[cls].get(word, 0)
                total = self.class_word_totals[cls]
                score += math.log((count + self.smoothing) / (total + self.smoothing * vocab_size))
            if score > best_score:
                best_score = score
                best_class = cls
        return best_class

احتمال‌های لگاریتمی مانع از پدیده‌ی زیرریز (underflow) می‌شوند. ضرب تعداد زیادی احتمال کوچک، اعدادی به دست می‌دهد که برای ممیز شناور بیش از حد ریز هستند. جمع بستن لگاریتمِ احتمال‌ها پایدار از نظر عددی و از نظر ریاضیاتی کاملاً معادل است.

مرحله‌ی 3: آموزش روی داده‌های اسپم

train_docs = [
    "win free money now",
    "free lottery ticket winner",
    "claim your prize today free",
    "urgent offer free cash",
    "congratulations you won free",
    "meeting tomorrow at noon",
    "project update attached",
    "can we schedule a call",
    "quarterly report review",
    "lunch on thursday sounds good",
    "team standup notes attached",
    "please review the pull request",
]

train_labels = [
    "spam", "spam", "spam", "spam", "spam",
    "ham", "ham", "ham", "ham", "ham", "ham", "ham",
]

classifier = NaiveBayes()
classifier.train(train_docs, train_labels)

test_messages = [
    "free money waiting for you",
    "meeting rescheduled to friday",
    "you won a free prize",
    "please review the attached report",
]

for msg in test_messages:
    print(f"  '{msg}' -> {classifier.predict(msg)}")

مرحله‌ی 4: بررسی احتمال‌های یادگرفته‌شده

def show_top_words(classifier, cls, n=5):
    vocab_size = len(classifier.vocab)
    total = classifier.class_word_totals[cls]
    probs = {}
    for word in classifier.vocab:
        count = classifier.word_counts[cls].get(word, 0)
        probs[word] = (count + classifier.smoothing) / (total + classifier.smoothing * vocab_size)
    sorted_words = sorted(probs.items(), key=lambda x: x[1], reverse=True)
    for word, prob in sorted_words[:n]:
        print(f"    {word}: {prob:.4f}")

print("\nTop spam words:")
show_top_words(classifier, "spam")
print("\nTop ham words:")
show_top_words(classifier, "ham")

استفاده از آن

کتابخانه‌ی Scikit-learn پیاده‌سازی‌های آماده‌ی محیط عملیاتی را برای نایو بیز ارائه می‌دهد:

from sklearn.feature_extraction.text import CountVectorizer
from sklearn.naive_bayes import MultinomialNB
from sklearn.metrics import classification_report

vectorizer = CountVectorizer()
X_train = vectorizer.fit_transform(train_docs)
clf = MultinomialNB()
clf.fit(X_train, train_labels)

X_test = vectorizer.transform(test_messages)
predictions = clf.predict(X_test)
for msg, pred in zip(test_messages, predictions):
    print(f"  '{msg}' -> {pred}")

الگوریتم دقیقاً یکسان است. CountVectorizer فرایند توکنایز کردن و ساخت واژگان را انجام می‌دهد. MultinomialNB هم هموارسازی و احتمال‌های لگاریتمی را درونی مدیریت می‌کند. کلاسی که خودتان از صفر ساختید، همین کار را در 40 خط پیاده می‌کند.

استفاده در عمل

کلاس NaiveBayes که در این درس ساخته شد، کل فرایند را به نمایش می‌گذارد: توکنایز کردن، برآورد احتمال با هموارسازی لاپلاس و پیش‌بینی در فضای لگاریتمی. کد موجود در code/bayes.py بدون نیاز به هیچ وابستگی‌ای خارج از کتابخانه‌ی استاندارد Python اجرا می‌شود.

پیشین‌های مزدوج

وقتی پیشین و پسین به یک خانواده از توزیع‌ها تعلق دارند، به پیشین «مزدوج» (Conjugate) می‌گویند. این ویژگی به‌روزرسانی بیزی را از نظر جبری بسیار تر‌و‌تمیز می‌کند؛ به‌طوری که فرم بسته‌ای از پسین به دست می‌آورید و نیازی به انتگرال‌گیری عددی نخواهید داشت.

درست‌نمایی پیشین مزدوج پسین مثال
برنولی Beta(a,b)\text{Beta}(a, b) Beta(a+successes,b+failures)\text{Beta}(a + \text{successes}, b + \text{failures}) برآورد اریبی در پرتاب سکه
نرمال (واریانس معلوم) Normal(μ0,σ0)\text{Normal}(\mu_0, \sigma_0) نرمال (میانگین وزنی، واریانس کمتر) کالیبراسیون حسگر
پواسون Gamma(a,b)\text{Gamma}(a, b) Gamma(a+sum of counts,b+n)\text{Gamma}(a + \text{sum of counts}, b + n) مدل‌سازی نرخ ورود
چند‌جمله‌ای Dirichlet(α)\text{Dirichlet}(\alpha) Dirichlet(α+counts)\text{Dirichlet}(\alpha + \text{counts}) مدل‌سازی موضوعی، مدل‌های زبانی

اهمیت این موضوع: بدون پیشین‌های مزدوج، ناچارید برای تقریب زدن پسین از روش‌های نمونه‌برداری مونت‌کارلو یا استنتاج متغیری استفاده کنید. اما با پیشین‌های مزدوج، فقط دو عدد را به‌روزرسانی می‌کنید.

توزیع بتا (Beta distribution) رایج‌ترین پیشین مزدوج در عمل است. نماد Beta(a,b)\text{Beta}(a, b) بیانگر باور شما درباره‌ی یک پارامتر احتمال است. میانگین آن a/(a+b)a/(a+b) است. هر چه a+ba+b بزرگ‌تر باشد، توزیع متمرکزتر (و مطمئن‌تر) خواهد بود.

حالت‌های خاص پیشین بتا:

  • Beta(1,1)\text{Beta}(1, 1) = یکنواخت (uniform). شما هیچ نظری درباره‌ی پارامتر ندارید.
  • Beta(10,10)\text{Beta}(10, 10) = قله در نقطه‌ی 0.5. شما قویاً معتقدید که پارامتر نزدیک به 0.5 است.
  • Beta(1,10)\text{Beta}(1, 10) = متمایل به سمت صفر. باور دارید که پارامتر کوچک است.

قاعده‌ی به‌روزرسانی فوق‌العاده ساده است:

Prior:Beta(a,b)Data:s successes,f failuresPosterior:Beta(a+s,b+f)\begin{aligned} \text{Prior:} \quad & \text{Beta}(a, b) \\ \text{Data:} \quad & s \text{ successes}, f \text{ failures} \\ \text{Posterior:} \quad & \text{Beta}(a + s, b + f) \end{aligned}

نه انتگرالی در کار است، نه نمونه‌برداری؛ فقط یک جمع ساده.

به‌روزرسانی متوالی بیزی

استنتاج بیزی ذاتاً متوالی است. پسینِ امروز به پیشینِ فردا تبدیل می‌شود. سیستم‌های واقعی با همین سازوکار به‌صورت تدریجی یاد می‌گیرند، بدون اینکه لازم باشد همه‌ی داده‌های گذشته را از نو پردازش کنند.

یک مثال ملموس: برآورد منصفانه بودن یک سکه.

روز 1: هنوز داده‌ای نیست. با Beta(1,1)\text{Beta}(1, 1) شروع کنید — یک پیشین یکنواخت. هیچ نظری ندارید.

  • میانگین پیشین: 0.5
  • پیشین در بازه‌ی [0, 1] کاملاً مسطح است

روز 2: مشاهده‌ی 7 بار شیر و 3 بار خط. Posterior=Beta(1+7,1+3)=Beta(8,4)\text{Posterior} = \text{Beta}(1 + 7, 1 + 3) = \text{Beta}(8, 4)

  • میانگین پسین: 8/12=0.6678/12 = 0.667
  • شواهد نشان می‌دهند سکه به سمت شیر اریب است

روز 3: مشاهده‌ی 5 شیر و 5 خط دیگر. از پسین دیروز به‌عنوان پیشین امروز استفاده کنید. Posterior=Beta(8+5,4+5)=Beta(13,9)\text{Posterior} = \text{Beta}(8 + 5, 4 + 5) = \text{Beta}(13, 9)

  • میانگین پسین: 13/22=0.59113/22 = 0.591
  • داده‌های متوازن جدید، برآورد را دوباره به سمت 0.5 کشیدند
7H, 3Tپیشین می‌شود5H, 5TپیشینBeta(1,1)میانگین = 0.50پسین 1Beta(8,4)میانگین = 0.67پیشین 2Beta(8,4)پسین 2Beta(13,9)میانگین = 0.59

ترتیب مشاهدات هیچ اهمیتی ندارد. به‌روزرسانی Beta(1,1)\text{Beta}(1,1) با همه‌ی 12 شیر و 8 خط به‌صورت یک‌جا باز هم مقدار Beta(13,9)\text{Beta}(13, 9) را می‌دهد — همان نتیجه. به‌روزرسانی متوالی و به‌روزرسانی دسته‌ای از نظر ریاضی کاملاً معادل‌اند؛ اما به‌روزرسانی متوالی این امکان را می‌دهد که در هر مرحله بدون نیاز به ذخیره‌ی داده‌های خام تصمیم بگیرید.

این پایه و اساس یادگیری برخط (online learning) در سیستم‌های یادگیری ماشین محیط عملیاتی است. تامپسون سمپلینگ (Thompson sampling) در سیستم‌های چندبازویی، سیستم‌های توصیه‌گر تدریجی و سیستم‌های تشخیص ناهنجاری استریمینگ همگی از همین الگو پیروی می‌کنند.

ارتباط با آزمون A/B

آزمون‌های A/B همان استنتاج بیزی در لباسی دیگرند.

صورت مسئله: دو رنگ دکمه را مقایسه می‌کنید؛ نسخه‌ی A (آبی) و نسخه‌ی B (سبز). می‌خواهید بدانید کدام‌یک کلیک بیشتری جذب می‌کند.

مراحل آزمون A/B بیزی:

  1. پیشین. برای هر دو نسخه با Beta(1,1)\text{Beta}(1, 1) شروع کنید. هیچ ترجیح اولیه‌ای وجود ندارد.
  2. داده‌ها. نسخه‌ی A: تعداد 50 کلیک از 1000 بازدید؛ نسخه‌ی B: تعداد 65 کلیک از 1000 بازدید.
  3. پسین‌ها.
    • نسخه A: Beta(1+50,1+950)=Beta(51,951)\text{Beta}(1 + 50, 1 + 950) = \text{Beta}(51, 951). میانگین = 0.051
    • نسخه B: Beta(1+65,1+935)=Beta(66,936)\text{Beta}(1 + 65, 1 + 935) = \text{Beta}(66, 936). میانگین = 0.066
  4. تصمیم‌گیری. مقدار P(B>A)P(B > A) را محاسبه کنید — احتمال اینکه نرخ تبدیل واقعی نسخه B بالاتر از A باشد.

محاسبه‌ی تحلیلی P(B>A)P(B > A) سخت است؛ اما مونت‌کارلو آن را بسیار ساده می‌کند:

1. Draw 100,000 samples from Beta(51, 951)  -> samples_A
2. Draw 100,000 samples from Beta(66, 936)  -> samples_B
3. P(B > A) = fraction of samples where B > A

اگر P(B>A)>0.95P(B > A) > 0.95 باشد، نسخه‌ی B را راهی محیط عملیاتی می‌کنید. اگر بین 0.05 و 0.95 باشد، به جمع‌آوری داده ادامه می‌دهید. اگر P(B>A)<0.05P(B > A) < 0.05 باشد، نسخه‌ی A را روانه‌ی محیط عملیاتی می‌کنید.

مزایا نسبت به آزمون‌های A/B بسامدگرا:

  • یک گزاره‌ی احتمالی صریح دریافت می‌کنید: «به احتمال 97% نسخه B بهتر است»
  • سردرگمی درباره‌ی p-value وجود ندارد؛ از محافظه‌کاری‌های کلامی مانند «عدم رد فرض صفر» خبری نیست.
  • می‌توانید در هر زمان نتایج را بررسی کنید بدون آنکه نرخ مثبت کاذب بالا برود (بدون مشکل «بررسی زودهنگام» یا peeking problem)
  • می‌توانید دانش قبلی را وارد کار کنید (مثلاً آزمون‌های پیشین نشان می‌دهند نرخ تبدیل معمولاً 3 تا 8 درصد است)
جنبه آزمون A/B بسامدگرا آزمون A/B بیزی
خروجی p-value P(B>A)P(B > A)
تفسیر «اگر A=B باشد، این داده چقدر غافلگیرکننده است؟» «چقدر احتمال دارد B بهتر از A باشد؟»
توقف زودهنگام نرخ مثبت کاذب را بالا می‌برد در هر نقطه‌ای امن است (به شرط داشتن پیشین مناسب و مدل درست)
دانش پیشین استفاده نمی‌شود در قالب پیشین بتا فرمول‌بندی می‌شود
قاعده‌ی تصمیم‌گیری p<0.05p < 0.05 P(B>A)>thresholdP(B > A) > \text{threshold}

تمرین‌ها

  1. چندین آزمایش. نتیجه‌ی دو آزمایش مستقل برای یک بیمار مثبت می‌شود (دقت هر دو آزمایش 99% است و میزان شیوع بیماری 1 در 10,000 است). مقدار P(sick)P(\text{sick}) بعد از هر دو آزمایش چقدر است؟ از پسینِ حاصل از آزمایش اول به‌عنوان پیشینِ آزمایش دوم استفاده کنید.

  2. تأثیر هموارسازی. طبقه‌بند اسپم را با مقادیر هموارسازی 0.01، 0.1، 1.0 و 10.0 اجرا کنید. احتمال واژه‌های برتر چه تغییری می‌کند؟ اگر هموارسازی 0 باشد و واژه‌ای فقط در پیام‌های غیراسپم (ham) آمده باشد، چه رخ می‌دهد؟

  3. افزودن ویژگی‌ها. کلاس NaiveBayes را توسعه دهید تا علاوه بر شمارش واژه‌ها، طول پیام (کوتاه/بلند) را نیز به‌عنوان یک ویژگی در نظر بگیرد. مقادیر P(short∣spam)P(\text{short} \mid \text{spam}) و P(short∣ham)P(\text{short} \mid \text{ham}) را از داده‌های آموزشی برآورد کنید و آن را در امتیاز نهایی پیش‌بینی اعمال نمایید.

  4. محاسبه‌ی دستی MAP. با توجه به داده‌های مشاهده‌شده (7 بار شیر در 10 بار پرتاب سکه)، برآورد MAP را برای اریبی سکه با استفاده از یک پیشین Beta(2,2)\text{Beta}(2,2) حساب کنید. آن را با برآورد MLE یعنی (7/107/10) مقایسه کنید.

راهنمایی‌ها

تمرین 1. تابع bayes را یک بار فراخوانی کنید تا پسین آزمایش 1 به دست آید؛ سپس آن را دوباره با همان پسین به‌عنوان پیشین فراخوانی کنید. تابع sequential_bayes(prior, likelihood, false_positive_rate, 2) باید همان مقدار را به شما بدهد که عددی نزدیک به 0.5 است.

تمرین 2. به ازای هر مقدار، یک نمونه از NaiveBayes(smoothing=s) بسازید، آن را روی همان داده‌ها آموزش دهید و top_words را چاپ کنید. با هموارسازی 0، واژه‌ای که هرگز در اسپم نیامده باشد، احتمال صفر دریافت می‌کند؛ بنابراین لگاریتم آن تعریف‌نشده خواهد بود.

تمرین 3. بشمارید چه تعداد از پیام‌های اسپم و غیراسپم کوتاه هستند، آن را بر تعداد پیام‌های هر کلاس تقسیم کنید و لگاریتم این نسبت را به امتیاز کلاس در predict بیفزایید. بررسی کنید که مجموع دو احتمال برای هر کلاس برابر 1 شود.

تمرین 4. با پیشین Beta(α,β)\text{Beta}(\alpha, \beta)، برآورد MAP برابر با h+α−1n+α+β−2\frac{h + \alpha - 1}{n + \alpha + \beta - 2} است. مقادیر h=7h = 7 و n=10n = 10 را جای‌گذاری کنید؛ نتیجه باید بین برآورد MLE (یعنی 0.7) و مُد پیشین (یعنی 0.5) باشد.

اصطلاحات کلیدی

اصطلاح آنچه به زبان می‌آورند معنای واقعی آن
پیشین (Prior) «حدس اولیه‌ی من» مقدار P(hypothesis)P(\text{hypothesis}) پیش از مشاهده‌ی شواهد. در یادگیری ماشین: همان ترم منظم‌سازی.
درست‌نمایی (Likelihood) «میزان برازش داده‌ها» مقدار P(evidence∣hypothesis)P(\text{evidence} \mid \text{hypothesis}). چقدر محتمل است که داده‌های مشاهده‌شده بر اساس یک فرضیه‌ی خاص رخ داده باشند.
پسین (Posterior) «باور به‌روزشده‌ی من» مقدار P(hypothesis∣evidence)P(\text{hypothesis} \mid \text{evidence}). پیشین ضرب‌در درست‌نمایی، که پس از آن نرمال‌سازی شده است.
شواهد (Evidence) «ثابت نرمال‌کننده» مقدار P(data)P(\text{data}) روی همه‌ی فرضیه‌ها. تضمین می‌کند مجموع پسین‌ها برابر با 1 شود.
نایو بیز (Naive Bayes) «همان طبقه‌بند متن ساده» طبقه‌بندی که فرض می‌کند ویژگی‌ها به شرط دانستن کلاس مستقل هستند. با وجود نادرست بودن این فرض، بسیار خوب کار می‌کند.
هموارسازی لاپلاس (Laplace smoothing) «هموارسازی با افزودن یک» افزودن مقداری کوچک به شمارش هر ویژگی برای جلوگیری از تولید احتمال صفر روی داده‌های دیده‌نشده.
درست‌نمایی بیشینه (MLE) «همان فراوانی‌های نسبی» انتخاب پارامترهایی که P(data∣parameters)P(\text{data} \mid \text{parameters}) را بیشینه کنند. بدون پیشین. در داده‌های کم ممکن است دچار بیش‌برازش شود.
بیشینه‌احتمال پسین (MAP) «همان MLE ولی با پیشین» انتخاب پارامترهایی که P(data∣parameters)⋅P(parameters)P(\text{data} \mid \text{parameters}) \cdot P(\text{parameters}) را بیشینه کنند. معادل با MLE منظم‌شده.
احتمال لگاریتمی (Log-probability) «کار در فضای لگاریتمی» استفاده از log⁡(P)\log(P) به‌جای PP برای جلوگیری از پدیده‌ی زیرریز ممیز شناور هنگام ضرب اعدادی بسیار کوچک.
مثبت کاذب (False positive) «یک هشدار اشتباه» آزمایش نتیجه‌ی مثبت نشان می‌دهد، اما وضعیت واقعی منفی است. عامل اصلی مغالطه‌ی نرخ پایه (base rate fallacy).

برای مطالعه‌ی بیشتر

خودآزمایی

به سؤال‌ها جواب بدهید تا ببینید چقدر از درس در ذهنتان مانده است.

  1. پیش از درسدر قضیه بیز، «احتمال پیشین» (prior) چیست؟
  2. پیش از درسیک بیماری نادر از هر 10,000 نفر، 1 نفر را مبتلا می‌کند. نتیجه‌ی آزمایشی با دقت 99% مثبت می‌شود. احتمال ابتلای شما به این بیماری تقریباً چقدر است؟
  3. پس از درسهموارسازی لاپلاس در دسته‌بند بیز ساده (Naive Bayes) چیست و چرا ضروری است؟
  4. پس از درستخمین بیشینه‌احتمال پسین (MAP) چه تفاوتی با تخمین بیشینه درست‌نمایی (MLE) دارد؟
  5. پس از درسدر به‌روزرسانی متوالی بیزی، با Beta(1,1) شروع کرده و 7 بار شیر و 3 بار خط مشاهده می‌کنید. توزیع پسین چیست؟

سؤالات متداول

تفاوت بنیادین MLE و MAP در تخمین پارامترها چیست؟

روش MLE پارامترهایی را انتخاب می‌کند که فقط درست‌نمایی داده‌های دیده‌شده را بیشینه سازد، در حالی که MAP یک باور پیشین را نیز روی پارامترها اعمال می‌کند که معادل افزودن ترم منظم‌سازی در یادگیری ماشین است.

چرا در الگوریتم نایو بیز محاسبات در فضای لگاریتمی انجام می‌شود؟

ضرب تعداد زیادی از مقادیر احتمال کوچک باعث بروز پدیده‌ی زیرریز عددی (underflow) در ممیز شناور می‌شود؛ جمع‌کردن لگاریتم احتمال‌ها این مشکل را حل می‌کند و از نظر ریاضیاتی کاملاً معادل است.

چرا تست A/B بیزی نسبت به روش‌های کلاسیک یا بسامدگرا مزیت دارد؟

تست A/B بیزی یک احتمال صریح ارائه می‌دهد (مثل 97٪ شانس برتری نسخه‌ی B)، امکان بررسی و توقف زودهنگام در هر لحظه را بدون دستکاری نرخ خطای کاذب ممکن می‌سازد و اجازه می‌دهد دانش پیشین هم در تصمیم لحاظ شود.

ما رو توی گوگل بیشتر ببین

با افزودن نکست ادمین به «منابع ترجیحی» گوگل، درس‌ها و مطالب ما را در بخش اخبار برتر جستجو بیشتر می‌بینید.