بیز ساده لوح گاوسی، توضیح داده شد

بیز ساده لوح گاوسی، توضیح داده شد

گره منبع: 2021431

بیز ساده لوح گاوسی، توضیح داده شد
منطقه تصمیم طبقه‌بندی‌کننده بیز ساده لوح گاوسی. تصویر توسط نویسنده

 

من فکر می کنم این یک کلاسیک در ابتدای هر حرفه علم داده است: طبقه بندی کننده ساده لوح بیز. یا بهتر است بگویم خانواده از طبقه بندی کننده های ساده بیز بیز، زیرا طعم های زیادی دارند. برای مثال، یک بیز ساده چند جمله ای، یک بیز ساده برنولی، و یک طبقه بندی کننده بیز ساده لوح گاوسی وجود دارد که هر کدام تنها در یک جزئیات کوچک متفاوت هستند، همانطور که خواهیم فهمید. الگوریتم های ساده بیز در طراحی بسیار ساده هستند اما در بسیاری از موقعیت های پیچیده دنیای واقعی مفید هستند.

در این مقاله می توانید یاد بگیرید

  • طبقه بندی کننده های ساده بیز چگونه کار می کنند،
  • چرا منطقی است که آنها را آنگونه که هستند تعریف کنیم و
  • نحوه پیاده سازی آنها در پایتون با استفاده از NumPy.

می توانید کد را در آن پیدا کنید Github من.

بررسی آغازگر من در مورد آمار بیزی ممکن است کمی کمک کند مقدمه ای ملایم بر استنتاج بیزی برای عادت کردن به فرمول بیز از آنجایی که ما طبقه‌بندی‌کننده را به روشی مطابق با یادگیری scikit پیاده‌سازی می‌کنیم، بررسی مقاله من نیز ارزشمند است. رگرسیون Sicit-Learn سفارشی خود را بسازید. با این حال، سربار یادگیری scikit بسیار کوچک است و به هر حال باید بتوانید آن را دنبال کنید.

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

هنگام طبقه بندی واقعاً به چه چیزی علاقه مندیم؟ ما واقعاً چه کار می کنیم، ورودی و خروجی چیست؟ پاسخ ساده است:

با توجه به نقطه داده x، احتمال تعلق x به کلاس c چقدر است؟

این تمام چیزی است که می خواهیم با آن پاسخ دهیم هر طبقه بندی. شما می توانید مستقیماً این عبارت را به عنوان یک احتمال شرطی مدل کنید: p(c|x).

مثلاً اگر وجود داشته باشد

  • کلاس 3 c1c2c₃و
  • از 2 ویژگی تشکیل شده است x1x2,

نتیجه یک طبقه بندی می تواند چیزی شبیه به p(c1|x1x2)=0.3، p(c2|x1x2)=0.5 و p(c₃|x1x2)=0.2. اگر به یک برچسب به عنوان خروجی اهمیت دهیم، یکی را با احتمال بالاتر انتخاب می کنیم، یعنی c2 با احتمال 50٪ در اینجا.

طبقه بندی کننده ساده بیز سعی می کند مستقیماً این احتمالات را محاسبه کند.

ساده لوح بیز

خوب، پس با توجه به نقطه داده x، می خواهیم محاسبه کنیم p(c|x) برای تمام کلاس ها و سپس خروجی c با بیشترین احتمال در فرمول ها شما اغلب این را می بینید

 

بیز ساده لوح گاوسی، توضیح داده شد
تصویر توسط نویسنده

 

توجه داشته باشید: حداکثر p(c|x) حداکثر احتمال را در حالی که argmax برمی گرداند p(c|x) را برمی گرداند c با این بالاترین احتمال

اما قبل از اینکه بتوانیم بهینه سازی کنیم p(c|x)، باید بتوانیم آن را محاسبه کنیم. برای این کار استفاده می کنیم قضیه بیز:

 

بیز ساده لوح گاوسی، توضیح داده شد
قضیه بیز تصویر توسط نویسنده

 

این بخش بیز از بیز ساده لوح است. اما در حال حاضر، ما مشکل زیر را داریم: چه هستند p(x|c) و p(c)?

این همان چیزی است که آموزش یک طبقه بندی کننده ساده بیز در مورد آن است.

تمرین

برای نشان دادن همه چیز، اجازه دهید از مجموعه داده اسباب بازی استفاده کنیم دو ویژگی واقعی x1x2و سه کلاس c1c2c₃ در ادامه

 

بیز ساده لوح گاوسی، توضیح داده شد
داده ها، تجسم شده است. تصویر توسط نویسنده

 

شما می توانید این مجموعه داده دقیق را از طریق ایجاد کنید

from sklearn.datasets import make_blobs X, y = make_blobs(n_samples=20, centers=[(0,0), (5,5), (-5, 5)], random_state=0)

بگذارید با شروع کنیم احتمال کلاس p(c)، احتمال اینکه برخی از کلاس c در مجموعه داده برچسب‌گذاری شده مشاهده می‌شود. ساده ترین راه برای تخمین این است که فقط بسامدهای نسبی کلاس ها را محاسبه کرده و از آنها به عنوان احتمالات استفاده کنید. ما می توانیم از مجموعه داده های خود استفاده کنیم تا ببینیم این دقیقاً به چه معناست.

7 امتیاز از 20 امتیاز با برچسب کلاس وجود دارد c1 (آبی) در مجموعه داده، بنابراین می گوییم p(c1)=7/20. ما برای کلاس 7 امتیاز داریم c2 (قرمز) نیز، بنابراین ما مجموعه p(c2)=7/20. آخرین کلاس c₃ (زرد) تنها 6 امتیاز دارد، از این رو p(c₃)=6/20.

این محاسبه ساده احتمالات کلاس شبیه رویکرد حداکثر احتمال است. با این حال می توانید از دیگری نیز استفاده کنید قبلی اگر دوست دارید توزیع کنید به عنوان مثال، اگر می دانید که این مجموعه داده به دلیل کلاس، نماینده جمعیت واقعی نیست c₃ باید در 50٪ موارد ظاهر شود، سپس شما تنظیم کنید p(c1)=0.25، p(c2)=0.25 و p(c₃)=0.5. هر چیزی که به شما در بهبود عملکرد در مجموعه تست کمک می کند.

اکنون به بررسی می پردازیم احتمال p(x|c)=p(x1x2|c). یک روش برای محاسبه این احتمال، فیلتر کردن مجموعه داده برای نمونه‌های دارای برچسب است و سپس سعی کنید توزیعی را پیدا کنید (مثلاً یک گاوسی دو بعدی) که ویژگی ها را ثبت کند. x1x2.

متأسفانه، معمولاً نمونه‌های کافی در هر کلاس برای تخمین درست احتمال نداریم.

برای اینکه بتوانیم یک مدل قوی تر بسازیم، ما آن را می سازیم فرض ساده لوحانه که ویژگی های x1x2 هستند مستقل تصادفی، داده شده c. این فقط یک راه فانتزی برای آسان کردن ریاضیات است

 

بیز ساده لوح گاوسی، توضیح داده شد
تصویر توسط نویسنده

 

برای هر کلاس c. این جایی است که آدم ساده بخشی از بیز ساده از آنجا ناشی می شود که این معادله به طور کلی برقرار نیست. با این حال، حتی در این صورت، بیز ساده لوح نتایج خوب و گاهاً برجسته ای در عمل به دست می آورد. به خصوص برای مشکلات NLP با ویژگی های کیسه ای کلمات، Bayes ساده لوح چند جمله ای می درخشد.

استدلال های داده شده در بالا برای هر طبقه بندی کننده ساده بیز بیز که می توانید پیدا کنید یکسان است. حالا این فقط به نحوه مدل کردن شما بستگی دارد p(xXNUMX|cXNUMX)، p(xXNUMX|cXNUMX)، p(xXNUMX|cXNUMX)، p(xXNUMX|cXNUMX)، p(xXNUMX|cXNUMX) و p(xXNUMX|cXNUMX).

اگر ویژگی های شما فقط 0 و 1 هستند، می توانید از a استفاده کنید توزیع برنولی. اگر اعداد صحیح باشند، الف توزیع چند جمله ای. با این حال، ما مقادیر واقعی ویژگی را داریم و برای a تصمیم می گیریم گاوسی توزیع، از این رو بیز ساده لوح گاوسی نامیده می شود. شکل زیر را در نظر می گیریم

 

بیز ساده لوح گاوسی، توضیح داده شد
تصویر توسط نویسنده

 

جایی که μᵢ،ⱼ میانگین است و سᵢ،ⱼ انحراف معیاری است که باید از داده ها تخمین بزنیم. این بدان معناست که برای هر ویژگی یک میانگین دریافت می کنیم i همراه با یک کلاس جⱼ, در مورد ما 2*3=6 به این معنی است. همین امر در مورد انحرافات استاندارد نیز صدق می کند. این به یک مثال نیاز دارد.

بیایید سعی کنیم تخمین بزنیم μXNUMX، XNUMX و σXNUMX،XNUMX. زیرا j=1، ما فقط به کلاس علاقه مندیم c1، بگذارید فقط نمونه هایی را با این برچسب نگه داریم. نمونه های زیر باقی مانده است:

# samples with label = c_1 array([[ 0.14404357, 1.45427351], [ 0.97873798, 2.2408932 ], [ 1.86755799, -0.97727788], [ 1.76405235, 0.40015721], [ 0.76103773, 0.12167502], [-0.10321885, 0.4105985 ], [ 0.95008842, -0.15135721]])

حالا به خاطر i=2 فقط باید ستون دوم را در نظر بگیریم. μ2,XNUMX میانگین و σ2,XNUMX انحراف استاندارد برای این ستون، به عنوان مثال μ2,₁ = 0.49985176 و σ2,₁ = 0.9789976.

اگر دوباره از بالا به نمودار پراکندگی نگاه کنید، این اعداد منطقی هستند. ویژگی ها x2 از نمونه های کلاس c1 همانطور که در تصویر می بینید حدود 0.5 هستند.

ما اکنون این را برای پنج ترکیب دیگر محاسبه می کنیم و کارمان تمام است!

در پایتون می توانید این کار را به صورت زیر انجام دهید:

from sklearn.datasets import make_blobs
import numpy as np # Create the data. The classes are c_1=0, c_2=1 and c_3=2.
X, y = make_blobs( n_samples=20, centers=[(0, 0), (5, 5), (-5, 5)], random_state=0
) # The class probabilities.
# np.bincounts counts the occurence of each label.
prior = np.bincount(y) / len(y) # np.where(y==i) returns all indices where the y==i.
# This is the filtering step.
means = np.array([X[np.where(y == i)].mean(axis=0) for i in range(3)])
stds = np.array([X[np.where(y == i)].std(axis=0) for i in range(3)])

ما دریافت می کنیم

# priors
array([0.35, 0.35, 0.3 ])
# means array([[ 0.90889988, 0.49985176], [ 5.4111385 , 4.6491892 ], [-4.7841679 , 5.15385848]])
# stds
array([[0.6853714 , 0.9789976 ], [1.40218915, 0.67078568], [0.88192625, 1.12879666]])

این نتیجه آموزش یک طبقه بندی کننده ساده گوسی بیز است.

پیشگویی

فرمول پیش بینی کامل است

 

بیز ساده لوح گاوسی، توضیح داده شد
تصویر توسط نویسنده

 

بیایید یک نقطه داده جدید را فرض کنیم x*=(-2، 5) وارد می شود.

 

بیز ساده لوح گاوسی، توضیح داده شد
تصویر توسط نویسنده

 

برای اینکه ببینیم به کدام کلاس تعلق دارد، اجازه دهید محاسبه کنیم p(c|x*) برای تمام کلاس ها از روی عکس باید متعلق به کلاس باشد c₃ = 2، اما بیایید ببینیم. بگذارید مخرج را نادیده بگیریم p(x) برای یک ثانیه با استفاده از حلقه زیر، نامزدها برای محاسبه شدند j = 1، 2، 3.

x_new = np.array([-2, 5]) for j in range(3): print( f"Probability for class {j}: {(1/np.sqrt(2*np.pi*stds[j]**2)*np.exp(-0.5*((x_new-means[j])/stds[j])**2)).prod()*p[j]:.12f}" )

ما دریافت می کنیم

Probability for class 0: 0.000000000263
Probability for class 1: 0.000000044359
Probability for class 2: 0.000325643718

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

 

بیز ساده لوح گاوسی، توضیح داده شد
تصویر توسط نویسنده

 

همانطور که انتظار داشتیم، یک برنده واضح. حالا بیایید آن را اجرا کنیم!

این پیاده سازی تا حد زیادی کارآمد نیست، از نظر عددی پایدار نیست، فقط یک هدف آموزشی را دنبال می کند. ما بیشتر موارد را مورد بحث قرار داده‌ایم، بنابراین دنبال کردن آن اکنون باید آسان باشد. شما می توانید همه را نادیده بگیرید check توابع، یا مقاله من را بخوانید Sikit-Learn سفارشی خود را بسازید اگر به آنچه آنها دقیقاً انجام می دهند علاقه مند هستید.

فقط توجه داشته باشید که من a را اجرا کردم predict_proba روش اول برای محاسبه احتمالات روش predict فقط این متد را فراخوانی می کند و با استفاده از یک تابع argmax ایندکس (=کلاس) را با بالاترین احتمال برمی گرداند (دوباره اینجاست!). کلاس در انتظار کلاس ها از 0 تا k-1، کجا k تعداد کلاس ها است.

import numpy as np
from sklearn.base import BaseEstimator, ClassifierMixin
from sklearn.utils.validation import check_X_y, check_array, check_is_fitted class GaussianNaiveBayesClassifier(BaseEstimator, ClassifierMixin): def fit(self, X, y): X, y = check_X_y(X, y) self.priors_ = np.bincount(y) / len(y) self.n_classes_ = np.max(y) + 1 self.means_ = np.array( [X[np.where(y == i)].mean(axis=0) for i in range(self.n_classes_)] ) self.stds_ = np.array( [X[np.where(y == i)].std(axis=0) for i in range(self.n_classes_)] ) return self def predict_proba(self, X): check_is_fitted(self) X = check_array(X) res = [] for i in range(len(X)): probas = [] for j in range(self.n_classes_): probas.append( ( 1 / np.sqrt(2 * np.pi * self.stds_[j] ** 2) * np.exp(-0.5 * ((X[i] - self.means_[j]) / self.stds_[j]) ** 2) ).prod() * self.priors_[j] ) probas = np.array(probas) res.append(probas / probas.sum()) return np.array(res) def predict(self, X): check_is_fitted(self) X = check_array(X) res = self.predict_proba(X) return res.argmax(axis=1)

آزمایش پیاده سازی

در حالی که کد بسیار کوتاه است، هنوز خیلی طولانی است تا کاملاً مطمئن شویم که هیچ اشتباهی انجام نداده ایم. بنابراین، اجازه دهید بررسی کنیم که چگونه آن را در برابر طبقه بندی کننده GaussianNB scikit-learn.

my_gauss = GaussianNaiveBayesClassifier()
my_gauss.fit(X, y)
my_gauss.predict_proba([[-2, 5], [0,0], [6, -0.3]])

خروجی

array([[8.06313823e-07, 1.36201957e-04, 9.99862992e-01], [1.00000000e+00, 4.23258691e-14, 1.92051255e-11], [4.30879705e-01, 5.69120295e-01, 9.66618838e-27]])

پیش بینی ها با استفاده از predict روش هستند

# my_gauss.predict([[-2, 5], [0,0], [6, -0.3]])
array([2, 0, 1])

حال، اجازه دهید از scikit-learn استفاده کنیم. انداختن مقداری کد

from sklearn.naive_bayes import GaussianNB gnb = GaussianNB()
gnb.fit(X, y)
gnb.predict_proba([[-2, 5], [0,0], [6, -0.3]])

بازده

array([[8.06314158e-07, 1.36201959e-04, 9.99862992e-01], [1.00000000e+00, 4.23259111e-14, 1.92051343e-11], [4.30879698e-01, 5.69120302e-01, 9.66619630e-27]])

اعداد شبیه به اعداد طبقه‌بندی‌کننده ما به نظر می‌رسند، اما در چند رقم آخر نمایش داده شده کمی فاصله دارند. آیا ما کار اشتباهی انجام دادیم؟ شماره نسخه scikit-learn فقط از یک هایپرپارامتر دیگر استفاده می کند var_smoothing=1e-09 . اگر این یکی را روی صفر، دقیقاً اعداد خود را می گیریم. کامل!

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

 

بیز ساده لوح گاوسی، توضیح داده شد

منطقه تصمیم با 3 نقطه جدید. تصویر توسط نویسنده

 

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

با محاسبه چند مثال و جمع آوری چند کد مفید در راه ادامه دادیم. در نهایت، ما یک طبقه بندی کننده کامل بیز ساده گوسی را به گونه ای پیاده سازی کرده ایم که با scikit-learn به خوبی کار می کند. این بدان معناست که می توانید از آن برای مثال در خطوط لوله یا جستجوی شبکه استفاده کنید.

در پایان، ما با وارد کردن طبقه‌بندی‌کننده بیز ساده گوسی خود scikit-learns و آزمایش اینکه آیا هر دو، طبقه‌بندی‌کننده ما و scikit-learn نتیجه یکسانی دارند، یک بررسی عقلانی کوچک انجام دادیم. این تست با موفقیت انجام شد.

 
 
دکتر رابرت کوبلر دانشمند داده در Publicis Media و نویسنده Towards Data Science است.

 
اصلی. مجدداً با اجازه دوباره ارسال شد.
 

تمبر زمان:

بیشتر از kdnuggets