فراتر از محاسبهی احتمال برنده شدن در لاتاری یا پیشبینی میزان احتمال ابتلا به بیماری، کاربردهای دیگری هم برای قضیهی بیز وجود داره. یه نمونهش میتونه ساختن یه سیستم رتبهبندی باشه. مثال بزنیم یه سایت نقد و بررسی فیلم که کاربران میتونن به فیلمها رأی مثبت یا منفی بدن. روشهای رتبهبندی ساده، مثل درصد آرای مثبت یا تفاضل آرای مثبت و منفی، عملکرد خوبی ندارن. مثلاً: اگر 60 رأی مثبت و 40 رأی منفی باشه، در مقابل 6 رأی مثبت و 4 رأی منفی، هر دو 60 درصد مثبت هستن.
تفاضل آرا هم مشکل داره. مثلاً 100 رأی مثبت و 95 رأی منفی در مقابل 5 رأی مثبت و 0 رأی منفی، هر دو فقط 5 تا اختلاف دارن. چیزی که ما میخوایم اینه که تعداد آرا اطلاعات بیشتری بهمون بده. 60 رأی باید نسبت به 6 رأی، وزن بیشتری داشته باشه. خب، بیایین از آرا به عنوان احتمالات در استنتاج بیزی استفاده کنیم. اینجا یه مجموعهی فیلم A تا E رو با آرای مثبت و منفیشون میبینیم و همچنین تابع بتا که با یه تابع یکنواختِ Beta(1,1) پیشین محاسبه شده:
با این حال، توزیع بتا یه تابع چگالی احتماله، پس ما یه الگوریتم نیاز داریم تا اون رو تبدیل به یه مقیاس عددی برای رتبهبندی کنیم. یه روش اینه که حداقل مقدار توزیع بتا رو پیدا کنیم، طوری که 95 درصد مطمئن باشیم مقدار واقعی از اون بیشتره. این کار میتونه با کم کردن انحراف معیار از میانگین انجام بشه.
Ranking = Mean + z-score × standard deviation
برای یه تقریب نرمال، تابع توزیع تجمعی یا CDF داریم 5 درصد z-score برابر با 1.64- میشه که میتونید در فرمول بالا ازش استفاده کنید. اما اگه به CDF معکوس (inverse CDF) خود توزیع بتا دسترسی دارید، میتونید مستقیماً ازش استفاده کنید.
rank = beta.ppf(0.05,a,b) # python rank = BETA.INV(0.05,a,b) # Excel, Sheets rank = qbeta(0.05,a,a) # R
که نتایج زیر رو به دست میآرن:
B 6:1 rank: 0.53 A 60:40 rank: 0.52 C 6:4 rank: 0.35 E 10:20 rank: 0.21 D 1:2 rank: 0.10
این روش باعث میشه فیلمهای A (60 به 40) با شواهد زیاد و فیلمهای C (6 به 4) با شواهد کم از هم جدا بشن، ولی برای رتبهبندی کلی ایدهآل نیست، مخصوصاً D (قرمز) که شواهد خیلی کمی داره ولی بدترین رتبه رو میگیره. ما میدونیم که اکثر فیلمها متوسط هستن، نه فوقالعاده خوب یا فوقالعاده بد. ترجیح میدیم رتبهبندیای داشته باشیم که از فرض فیلمهای متوسط شروع بشه و برای رفتن به سمت فیلمهای عالی یا افتضاح به شواهد نیاز داشته باشه. میتونیم این ترجیح رو با استفاده از یه "احتمال پیشین" در سیستم رتبهبندی انجام بدیم که یه سوگیری به سمت فیلمهای متوسط داشته باشه، با شروع از "پیشین" (11،11)Beta به جای (1،1)Beta. حالا برای دور شدن از "احتمال پیشین" و رفتن به سمت افراطها به تعدادی رأی نیاز خواهد بود و در نتیجه رتبهبندی کلی بهتری به دست میاد.
A 60:40 rank: 0.51 B 6:1 rank: 0.43 C 6:4 rank: 0.39 D 1:2 rank: 0.32 E 10:20 rank: 0.30
خب، نتیجهی نهایی نشون میده که فیلم D با شواهد کم تقریباً تو وسط قرار میگیره، در حالی که فیلم E با شواهد منفی بیشتر، حالا رتبهی پایینتری داره.این روش فقط برای رأی مثبت/منفی کار نمیکنه، بلکه میتونید با تعیین مقادیر رأی مثبت/منفی همزمان، اون رو برای سیستم رأیدهی بر اساس ستاره هم گسترش بدید.
Stars (1,2,3,4,5): up (0,0.25,0.5,0.75,1) down (1,0.75,0.5,0.25,0)
بنابراین اگر سه نفر هر کدام به یک فیلم 4 ستاره امتیاز بدن، مجموع امتیاز آن برابر است با:
3 up votes each of 0.75 value = 3×0.75 = 2.25 3 down votes each of 0.25 value = 3×0.25 = 0.75 Beta(3.25,1.75) # Uniform prior Beta(13.25, 11.75) # Prior biased toward average movie assumption
ما یه سیستم رتبهبندی پایدار ساختیم که شواهد بیشتر رو بیشتر پاداش میده و نشون دادیم که چطور با استفاده از قضیهی بیز، میتونیم اون رو برای سیستمهای رأیدهی بر اساس ستاره هم به کار ببریم.
اگر میخواهید خودتان آن را امتحان کنید، کد پایتون زیر رتبهبندی را انجام میده و نمودارها را برای مورد بایاس ترسیم میکنه.
from scipy.stats import beta import numpy as np import matplotlib.pyplot as plt movies_arr = [ ['A', 60, 40], ['B', 6, 1], ['C', 6, 4], ['D', 1, 2], ['E', 10, 20], ]; movies= [dict(zip(['name','up','down'], a)) for a in movies_arr] x = np.linspace(0, 1, 1001) plt.figure(dpi = 200) axes = plt.gca(frameon=False) # Prior information, movies tend to be more average and less extreme a0, b0 = (11,11) for i in range(len(movies)): a = movies[i]['up'] + a0 b = movies[i]['down'] + a0 b1 = beta.pdf(x, a, b) p = axes.plot(x, b1, linewidth=0.5) p[0].set_label(f"{movies[i]['name']} {movies[i]['up']}:{movies[i]['down']}" ) axes.fill_between(x, b1, alpha=0.4) rank = beta.ppf(0.05, a, b) axes.axvline(x=rank, ymin=0, ymax=1, color=p[0].get_color(), linewidth=1) print(f"{movies[i]['name']} {movies[i]['up']}:{movies[i]['down']} rank: {rank:0.2f}") axes.grid(b=None, which='major', axis='both') if a0 > 5: axes.set_xlim(0.2, 0.8) plt.legend()