Naive Bayes'te log-sum-exp numarasının nasıl çalıştığına örnek


14

Birçok yerde (örneğin, burada ve burada ) log-sum-exp hile hakkında okudum ama özellikle Naive Bayes sınıflandırıcı (örneğin ayrık özellikleri ve iki sınıf ile) nasıl uygulandığına dair bir örnek görmedim

Bu hileyi kullanarak sayısal taşma problemini tam olarak nasıl önleyebiliriz?


2
Naif Bayes için mutlaka açık olmasa da, burada kullanımının birkaç örneği vardır . Ancak, bu önemli değil, çünkü hile fikri oldukça basit ve kolayca uyarlanabilir.
Glen_b -Reinstate Monica

Problemin taşmadan daha düşük olması muhtemeldir.
Henry

Underflow'da bir arama yapmayı denemenizi ve ardından sorunuzu, daha önce ele alınmamış olanları daha spesifik olarak ele alacak şekilde güncellemenizi öneririm .
Glen_b

Ayrıca açıklığa kavuşturabilir misiniz - bu Bernoulli model naif Bayes mi? belki başka bir şey?
Glen_b-Monica

Buradaki örneğe bakın , hemen altta (günlükleri aldıkları 'Ayrıca Bkz.' 'Dan hemen önce; her iki tarafı da üstlenmek, ancak RHS'yi "olduğu gibi" bırakmak (günlüklerin toplamı olarak) günlük için bir örnek olacaktır. -sum-exp hile Bu size daha spesifik bir soru sormak için Naive Bayes kullanımıyla ilgili yeterli bilgi veriyor mu?
Glen_b -Restate Monica

Yanıtlar:


26

Olarak

p(Y=C|x)=p(x|Y=C)p(Y=C) Σk=1|C|p(x|Y=Ck)p(Y=Ck)

hem payda hem de pay çok küçük olabilir, çünkü 0'a yakın olabilir ve çoğunu birbirimizle çarparız. Düşük akışları önlemek için, payın günlüğünü alabilir, ancak payda için log-sum-exp hilesi kullanılmalıdır.p(xben|Ck)


Daha spesifik olarak, yetersiz akışları önlemek için:

  • Biz sadece hangi sınıf bilerek önem veriyorsanız girişi ( x = x 1 , ... , x n ) büyük olasılıkla maksimum a posteriori (MAP) karar kuralı ile aittir biz log uygulamak gerekmez sum-exp hilesi, çünkü bu durumda paydayı hesaplamak zorunda değiliz . Pay için düşük akışları önlemek için günlük kaydı yapılabilir: l o g ( p ( x | Y = C ) p ( Y = C ) )(y^)(x=x1,...,xn)lÖg(p(x|Y=C)p(Y=C)). Daha spesifik olarak:

    y^=argmaxk{1,...,|C|}p(Ck|x1,...,xn)=argmaxk{1,...,|C|} p(Ck)Πben=1np(xben|Ck)

    bu günlük alındıktan sonra olur:

y^=argmaxk{1,...,|C|}günlük(p(Ck|x1,...,xn))=argmaxk{1,...,|C|}günlük( p(Ck)Πben=1np(xben|Ck))=argmaxk{1,...,|C|}(günlük(p(Ck))+ Σben=1ngünlük(p(xben|Ck)))
  • Sınıf olasılığı hesaplamak istiyorsak , paydayı hesaplamamız gerekecek:p(Y=C|x)

    günlük(p(Y=C|x))=günlük(p(x|Y=C)p(Y=C) Σk=1|C|p(x|Y=Ck)p(Y=Ck))=günlük(p(x|Y=C)p(Y=C)pay)-günlük( Σk=1|C|p(x|Y=Ck)p(Y=Ck)payda)

    Eleman günlük( Σk=1|C|p(x|Y=Ck)p(Y=Ck))Çünkü Yetersizlik edebilir çok küçük olabilir: o payında aynı konudur, ancak bu kez biz logaritma içine bir özet, sahip olduğu dönüştürerek gelen önler bize p ( x i | C k ) (0'a yakın) içine olabilir günlüğüne ( p ( x i | C k ) ) (negatif değil 0'a yakın artık, çünkü 0 p ( x i | C k ) 1p(xben|Ck)p(xben|Ck)günlük(p(xben|Ck))0p(xben|Ck)1). Bu sorunu atlatmak için, elde etmek için şunu kullanabiliriz:p(xben|Ck)=tecrübe(günlük(p(xben|Ck)))

    günlük( Σk=1|C|p(x|Y=Ck)p(Y=Ck))=günlük( Σk=1|C|tecrübe(günlük(p(x|Y=Ck)p(Y=Ck))))

    Bu noktada yeni bir sorun ortaya çıkar: oldukça negatif olabilir, bu da exp ( log ( p ( x | Y = C k ) p ( Y = C k ) ) ) 0'a çok yakın olabilir, yani taşma. Log-sum-exp hilesini burada kullanıyoruz :günlük(p(x|Y=Ck)p(Y=Ck))tecrübe(günlük(p(x|Y=Ck)p(Y=Ck)))

    günlükΣkebirk=günlükΣkebirkebir-bir=bir+günlükΣkebirk-bir

    ile:

    • ,birk=günlük(p(x|Y=Ck)p(Y=Ck))
    • bir=maksimumk{1,...,|C|}birk.

    değişkeninin getirilmesinin taşmaları önlediğini görebiliriz . Örneğin k = 2 , a 1 = - 245 , a 2 = - 255 ile :birk=2,bir1=-245,bir2=-255

    • exp(a1)=exp(245)=3.96143×10107
    • exp(a2)=exp(255)=1.798486×10111

    Log-sum-exp hilesi kullanarak, günlük akışından kaçınırız : log flow k e a kA=max(245,255)=245günlükΣkebirk=günlükΣkebirkebir-bir=bir+günlükΣkebirk-bir=-245+günlükΣkebirk+245=-245+günlük(e-245+245+e-255+245)=-245+günlük(e0+e-10)

    O zamandan beri Yetersizlik kaçınılması daha uzağa 0 daha ila 3,96143 x 10 - 107 veya 1,798486 x 10 - 111 .e-103.96143×101071.798486×10111


2

İki veritabanından hangisinin bir kelime grubu oluşturma olasılığının daha yüksek olduğunu tanımlamak istediğimizi varsayalım (örneğin, hangi kelime bu kelime grubunun daha olasıdır). Veritabanında koşullu kelimelerin bağımsızlığını varsayabiliriz (Naive Bayes varsayımı).

birebt


1

Biz de görebileceğiniz bu cevap Python en küçük sayıdır (sadece örneğin götürün) olduğu 5e-324nedeniyle ieee754 ve donanım neden sıra diğer diller için de geçerlidir.

In [2]: np.nextafter(0, 1)
Out[2]: 5e-324

Ve bundan daha küçük herhangi bir şamandıra 0'a yol açacaktır.

In [3]: np.nextafter(0, 1)/2
Out[3]: 0.0

Ve Naif Bayes'in işlevini with discrete features and two classesistediğiniz gibi görelim :

p(S=1|w1,...wn)=p(S=1)Πben=1np(wben|S=1) Σs={0,1}p(S=s)Πben=1np(wben|S=s)

Bu işlevi, aşağıdaki basit bir NLP göreviyle başlatmama izin verin.

S=1S=0n=5,000wbenp(wben|S=1)1-p(wben|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)

p(S=s)Πben=1np(wben|S=s)p(wben|S=1)1-p(wben|S=1)Πben50005e-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)

Resmi uygulamayı sklearn'de görebiliyoruz :

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

Pay için olasılıkların ürününü log olabilirlik toplamına dönüştürdü ve payda için logsumexp'i scipy'de kullandı :

out = log(sum(exp(a - a_max), axis=0))
out += a_max

Σs={0,1}ejlls-mbirx_jllgünlükΣs={0,1}ejlls-mbirx_jllmbirx_jll+günlükΣs={0,1}ejlls-mbirx_jllmbirx_jll

Ve işte türetme:

günlükΣs={0,1}ejlls=günlükΣs={0,1}ejllsembirx_jll-mbirx_jll=günlükembirx_jll+günlükΣs={0,1}ejlls-mbirx_jll=mbirx_jll+günlükΣs={0,1}ejlls-mbirx_jll

mbirx_jllbir_mbirx

günlükp(S=1|w1,...wn)

return jll - np.atleast_2d(log_prob_x).T

Umarım yardımcı olur.

Referans:
1. Bernoulli Naif Bayes Sınıflandırıcı
2. Naif Bayes ile Spam Filtreleme - Hangi Naif Bayes?

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.