Nous pouvons voir à partir de cette réponse que le plus petit nombre en Python (prenez-le par exemple) est 5e-324
dû à l' IEEE754 , et la cause matérielle s'applique également aux autres langages.
In [2]: np.nextafter(0, 1)
Out[2]: 5e-324
Et tout flotteur plus petit que cela conduirait à 0.
In [3]: np.nextafter(0, 1)/2
Out[3]: 0.0
Et voyons la fonction de Naive Bayes with discrete features and two classes
selon vos besoins:
p(S=1|w1,...wn)=p(S=1)∏ni=1p(wi|S=1) ∑s={0,1}p(S=s)∏ni=1p(wi|S=s)
Permettez-moi d'instancier cette fonction par un simple soufflet de tâche PNL.
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)
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)
Nous pouvons voir l'implémentation officielle dans 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
Pour le numérateur, il a converti le produit des probabilités en la somme du log vraisemblance et pour le dénominateur, il a utilisé le logsumexp en scipy qui est:
out = log(sum(exp(a - a_max), axis=0))
out += a_max
∑s = { 0 , 1 }ej l ls- m a x _ j l lJournal∑s = { 0 , 1 }ej l ls- m a x _ j l lm a x _ j l l + log∑s = { 0 , 1 }ej l ls- m a x _ j l lm a x _ j l l
Et voici la dérivation:
Journal∑s = { 0 , 1 }ej l ls= journal∑s = { 0 , 1 }ej l lsem a x _ j l l - m a x _ j l l= journalem a x _ j l l+ journal∑s = { 0 , 1 }ej l ls- m a x _ j l l=max_jll+log∑s={0,1}ejlls−max_jll
max_jlla_max dans le code.
logp(S=1|w1,...wn) soustrayant le dénominateur du numérateur :
return jll - np.atleast_2d(log_prob_x).T
J'espère que cela pourra aider.
Référence:
1. Bernoulli Naive Bayes Classifier
2. Filtrage des spams avec Naive Bayes - Quels Naive Bayes?