เราสามารถเห็นได้จากคำตอบนี้ว่าจำนวนที่น้อยที่สุดใน Python (ยกตัวอย่างเช่น) นั้น5e-324
เกิดจากIEEE754และสาเหตุของฮาร์ดแวร์จะนำไปใช้กับภาษาอื่นเช่นกัน
In [2]: np.nextafter(0, 1)
Out[2]: 5e-324
และทุ่นใด ๆ ที่เล็กกว่านั้นจะนำไปสู่ 0
In [3]: np.nextafter(0, 1)/2
Out[3]: 0.0
และมาดูฟังก์ชั่นของ Naive Bayes with discrete features and two classes
ตามที่คุณต้องการ:
p ( s= 1 | W1, . . . Wn) = p ( S= 1 ) ∏ni = 1p ( wผม| S= 1 ) Σs = { 0 , 1 }p ( s= s ) ∏ni = 1p ( wผม| S= s )
ให้ฉันยกตัวอย่างฟังก์ชั่นนั้นโดยงานร้อง NLP ง่าย
เราตัดสินใจที่จะตรวจสอบว่าอีเมลที่เข้ามาเป็นสแปม ( ) หรือไม่เป็นสแปม ( ) และเรามีคำศัพท์ที่มีขนาด 5,000 คำ ( ) และข้อกังวลเดียวคือถ้ามีคำ ( ) เกิดขึ้น ( ) ในอีเมลหรือไม่ ( ) เพื่อความเรียบง่าย ( Bernoulli naive Bayes )S= 1S= 0n = 5 , 000Wผมp ( wผม| S= 1 )1 - p ( wผม| 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) ในและด้วยเหตุนี้เรามั่นใจว่าสินค้าจะมีขนาดเล็กกว่าและเราก็จะได้รับ0/0p ( s= s ) ∏ni = 1p ( wผม| S= s )p ( wผม| S= 1 )1 - p ( wผม| S= 1 )Π5000ผม5 จ- 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)
เราสามารถเห็นการดำเนินการอย่างเป็นทางการในsklearn :
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
สำหรับตัวเศษมันจะแปลงผลคูณของความน่าจะเป็นผลรวมของความน่าจะเป็นของบันทึกและสำหรับตัวส่วนที่มันใช้งานlogumexp ใน scipyซึ่งก็คือ:
out = log(sum(exp(a - a_max), axis=0))
out += a_max
เนื่องจากเราไม่สามารถเพิ่มความน่าจะเป็นร่วมสองข้อด้วยการเพิ่มโอกาสในการบันทึกร่วมและเราควรออกจากพื้นที่บันทึกไปยังพื้นที่ความน่าจะเป็น แต่เราไม่สามารถเพิ่มความน่าจะเป็นที่แท้จริงทั้งสองได้เนื่องจากมันมีขนาดเล็กเกินไปและเราควรปรับขนาดและทำการเพิ่ม: และนำผลลัพธ์กลับมา ในพื้นที่บันทึกจากนั้นให้ขายอีกครั้ง:ในพื้นที่การบันทึกโดยการเพิ่มสูงสุดΣs = { 0 , 1 }อีj l ls- m a x _ j l lเข้าสู่ระบบΣs = { 0 , 1 }อีj l ls- m a x _ j l lm a x _ j l l + บันทึก∑s = { 0 , 1 }อีj l ls- m a x _ j l lm a x _ j l l
และนี่คือที่มา:
เข้าสู่ระบบΣs = { 0 , 1 }อีj l ls= บันทึกΣs = { 0 , 1 }อีj l lsอีm a x _ j l l - m a x _ j l l= บันทึกอีm a x _ j l l+ บันทึกΣs = { 0 , 1 }อีj l ls- m a x _ j l l= m a x _ j l l + บันทึกΣs = { 0 , 1 }อีj l ls- m a x _ j l l
โดยที่คือในรหัสm a x _ j l la _ m a x
เมื่อเราได้รับทั้งเศษและส่วนในพื้นที่บันทึกเราจะได้รับความน่าจะเป็นตามเงื่อนไขของบันทึก ( ) โดยการลบตัวส่วนจากเศษ : logp(S=1|w1,...wn)
return jll - np.atleast_2d(log_prob_x).T
หวังว่าจะช่วย
การอ้างอิง:
1. ตัวแยกประเภท Bernoulli Naive Bayes
2. การกรองสแปมด้วย Naive Bayes - Naive Bayes ใด?