हम इस जवाब से देख सकते हैं कि पायथन में सबसे छोटी संख्या (उदाहरण के लिए इसे लें) IEEE754 के5e-324
कारण है , और हार्डवेयर कारण अन्य भाषाओं पर भी लागू होता है।
In [2]: np.nextafter(0, 1)
Out[2]: 5e-324
और इससे छोटा कोई भी फ्लोट 0 की ओर ले जाएगा।
In [3]: np.nextafter(0, 1)/2
Out[3]: 0.0
और with discrete features and two classes
आप के रूप में आवश्यक है बेवे के कार्य को देखते हैं :
p(S=1|w1,...wn)=p(S=1)∏ni=1p(wi|S=1) ∑s={0,1}p(S=s)∏ni=1p(wi|S=s)
मुझे एक सरल एनएलपी टास्क के द्वारा उस फंक्शन को तुरंत करने दें।
हम यह पता लगाने का निर्णय लेते हैं कि क्या आने वाला ईमेल स्पैम है ( ) या स्पैम नहीं है ( ) और हमारे पास शब्द का आकार 5,000 ( ) है और केवल एक शब्द ( ) होने पर चिंता होती है ( ईमेल में या नहीं ( ) सादगी के लिए ( बर्नोली भोली बेयस )।S=1S=0n=5,000wip(wi|S=1)1−p(wi|S=1)
In [1]: import numpy as np
In [2]: from sklearn.naive_bayes import BernoulliNB
# let's train our model with 200 samples
In [3]: X = np.random.randint(2, size=(200, 5000))
In [4]: y = np.random.randint(2, size=(200, 1)).ravel()
In [5]: clf = BernoulliNB()
In [6]: model = clf.fit(X, y)
हम देख सकते हैं कि संभाव्यता के कारण बहुत छोटा होगा (दोनों और में 0 और 1) के बीच होगा , और इसलिए हमें यकीन है कि उत्पाद से छोटा होगा और हमें सिर्फ मिलता है ।p(S=s)∏ni=1p(wi|S=s)p(wi|S=1)1−p(wi|S=1)∏5000i5e−3240/0
In [7]: (np.nextafter(0, 1)*2) / (np.nextafter(0, 1)*2)
Out[7]: 1.0
In [8]: (np.nextafter(0, 1)/2) / (np.nextafter(0, 1)/2)
/home/lerner/anaconda3/bin/ipython3:1: RuntimeWarning: invalid value encountered in double_scalars
#!/home/lerner/anaconda3/bin/python
Out[8]: nan
In [9]: l_cpt = model.feature_log_prob_
In [10]: x = np.random.randint(2, size=(1, 5000))
In [11]: cls_lp = model.class_log_prior_
In [12]: probs = np.where(x, np.exp(l_cpt[1]), 1-np.exp(l_cpt[1]))
In [13]: np.exp(cls_lp[1]) * np.prod(probs)
Out[14]: 0.0
तब समस्या उत्पन्न होती है: हम ईमेल की संभावना की गणना कैसे कर सकते हैं एक स्पैम ? या हम अंश और हर की गणना कैसे कर सकते हैं?p(S=1|w1,...wn)
हम स्कीलर्न में आधिकारिक कार्यान्वयन देख सकते हैं :
jll = self._joint_log_likelihood(X)
# normalize by P(x) = P(f_1, ..., f_n)
log_prob_x = logsumexp(jll, axis=1)
return jll - np.atleast_2d(log_prob_x).T
अंश के लिए यह संभाव्यता के उत्पाद को लॉग लाइबिलिटी के योग में बदल देता है और हर के लिए यह स्काइप में लॉगसमैक्स का उपयोग करता है जो है:
out = log(sum(exp(a - a_max), axis=0))
out += a_max
क्योंकि हम इसकी संयुक्त लॉग संभावना को जोड़कर दो संयुक्त संभावनाओं को नहीं जोड़ सकते हैं, और हमें लॉग स्पेस से प्रायिकता स्थान पर बाहर जाना चाहिए। लेकिन हम दो सच्ची संभावनाओं को नहीं जोड़ सकते क्योंकि वे बहुत छोटे हैं और हमें उन्हें स्केल करना चाहिए और इसके अलावा करना चाहिए: और परिणाम वापस डालें लॉग स्पेस में फिर इसे फिर से : लॉग स्पेस में जोड़कर ।∑s={0,1}ejlls−max_jlllog∑s={0,1}ejlls−max_jllmax_jll+log∑s={0,1}ejlls−max_jllmax_jll
और यहाँ व्युत्पत्ति है:
log∑s={0,1}ejlls=log∑s={0,1}ejllsemax_jll−max_jll=logemax_jll+log∑s={0,1}ejlls−max_jll=max_jll+log∑s={0,1}ejlls−max_jll
जहां है कोड में।max_jlla_max
एक बार जब हम अंश और हर दोनों को लॉग स्पेस में प्राप्त करते हैं, तो हम अंश से हर को घटाकर लॉग सशर्त प्रायिकता ( ) प्राप्त कर सकते हैं : logp(S=1|w1,...wn)
return jll - np.atleast_2d(log_prob_x).T
उम्मीद है की वो मदद करदे।
संदर्भ:
1. बर्नौली नैवे बेस क्लासिफायर
2. नैवे बेस के साथ स्पैम फिल्टरिंग - कौन सा बेव बेयर्स?