<jupyter_start><jupyter_text>Naive Bayes classifiers A naive Bayes classifier uses the Bayes theorem to classify data. It is frequently used to filter out SPAM documents. To classify a document as SPAM/NONSPAM (HAM) we want\begin{equation}    p(\text{SPAM}|\text{TEXT})\end{equation}using the Bayes theorem we get\begin{equation}    p(\text{SPAM}|\text{TEXT}) =    \frac{p(\text{TEXT}|\text{SPAM})p(\text{SPAM})}{p(\text{TEXT})}\end{equation}The Bayes theorem allows us to express a classification problem as a generation problem: we will create a model for generating texts ($p(\text{TEXT}|\text{SPAM})$) and combine it with the prior probability of getting a spam ($p(\text{SPAM})$). However, we will not need  $p(\text{TEXT})$: the probability of ever seeing a given document.To estimate $p(\text{TEXT}|\text{SPAM})$ we need to define a data generation model. A text is a sequence of words:$$\text{TEXT} = W_1, W_2, W_3,\ldots,W_n.$$Thus, $$p(\text{TEXT}|\text{SPAM}) = p(W_1|\text{SPAM})p(W_2|W_1,\text{SPAM})p(W_n|W_1, ..., W_{n-1}, \text{SPAM})$$We will further simply this by (naively) assuming that \begin{equation}    \begin{split} p(\text{TEXT}|\text{SPAM}) &=  (W_1|\text{SPAM})p(W_2|W_1,\text{SPAM})p(W_n|W_1, ..., W_{n-1}, \text{SPAM}) \\ &\approx p(W_1|\text{SPAM})p(W_2|\text{SPAM})p(W_n|\text{SPAM}) \\ &= \prod_{W_i \in \text{TEXT}}p(W_i|\text{SPAM})\end{split}\end{equation}This corresponds to a generative models in which the sender first flips a biased coin to see if the generated document will be a spam or ham one. Then, he picks a box labeled spam or ham. Finally, the sender draws with replacement words from the appropriate box.The full sampling model has the following parameters:1. $\phi$ - the probability of generating a SPAM.2. $\theta_{w,s}$ - the probability of generating word $w$ in a SPAM document, $\sum_w \theta_{w,s}=1$,3. $\theta_{w,h}$ - the probability of generating word $w$ in a HAM document, $\sum_w \theta_{w,h}=1$.All parameters are easy to estimate using maximum likelihood principle:1. $\phi = p(\text{SPAM}=s)$ is just the fraction of all spams in our corpus.2. $\theta_{w,s} = p(W=w|SPAM=s)$ is the fraction of the number of occurrences of word $w$ in all spams.3. $\theta_{w,h} = p(W=w|SPAM=h)$ is the fraction of the number of occurrences of word $w$ in all non-spams.The derivation is somewhat tedious, and requires the use of Langrange multipliers: Example:suppose our corpus has 4 documents:1. "buy much now": SPAM2. "many dollars gain": SPAM3. "like you much": HAM4. "do your nice homework": HAMThen:$\phi = p(\text{SPAM}=s) = 2/4 = 0.5$$\theta_{w,h}$ is given by the following table|       | buy | much | now | dollars | gain | like | you/your | do  | homework | nice ||------|-----|------|-----|---------|------|------|----------|-----|----------|------|| SPAM | 1/6 | 2/6  | 1/6 | 1/6     | 1/6  | 0/6  | 0/6      | 0/6 | 0/6      | 0/6  || HAM  | 0/7 | 1/7  | 0/7 | 0/7     | 0/7  | 1/7  | 2/7      | 1/7 | 1/7      | 1/7  |To classify a new phrase "much much gain" we compute$$\begin{split}p(\text{SPAM} = s | \text{"much much gain"}) &= p(\text{SPAM}=s) p(\text{much}|\text{SPAM}=s)p(\text{much}|\text{SPAM}=s)p(\text{gain}|\text{SPAM}=s) / p(\text{TEXT} = \text{"much much gain"}) = \\&= 1/2 \cdot 2/6 \cdot 2/6  \cdot 1/6  \cdot 1/Z = 4/216 \cdot 1/Z\end{split}$$$$\begin{split}p(\text{HAM} = s | \text{"much much gain"}) &= p(\text{HAM}=s) p(\text{much}|\text{HAM}=s)p(\text{much}|\text{HAM}=s)p(\text{gain}|\text{HAM}=s) / p(\text{TEXT} = \text{"much much gain"}) = \\&= 1/2 \cdot 1/7 \cdot 1/7  \cdot 0/6  \cdot 1/Z = 0\end{split}$$Thus the text is classified as SPAM.  In fact all text with word "gain" will never be classified as non-spam, because "gain" never appeared in a non-spam document. This is a problem with modeling: for rare words, we are using maximum likelihood estimation to compute the frequencies. However MLE estimation doesn't work well with low data counts.  Inspired by the Bayesian approach to polling (estimating counts) a common technique is called Laplace smoothing - assuming that each word in the vocabulary was seen at least once (or even a fraction of times) in each kind of document.  With Laplace smoothing (assuming each word occurred 0.5 times in spam and 0.5 times in ham) the table becomes |       | buy | much | now | dollars | gain | like | you/your | do  | homework | nice ||------|-----|------|-----|---------|------|------|----------|-----|----------|------|| SPAM | 1.5/11 | 2.5/11  | 1.5/11 | 1.5/11     | 1.5/11  | 0.5/11  | 0.5/11      | 0.5/11 | 0.5/11      | 0.5/11  || HAM  | 0.5/12 | 1.5/12  | 0.5/12 | 0.5/12     | 0.5/12  | 1.5/12  | 2.5/12      | 1.5/12 | 1.5/12      | 1.5/12  |Now:$$\begin{split}p(\text{SPAM} = s | \text{"much much gain"}) &= 1/2 \cdot 2.5/11 \cdot 2.5/11  \cdot 1.5/11  \cdot 1/Z = 9.375/2662 \cdot 1/Z \\p(\text{SPAM} = h | \text{"much much gain"}) &= 1/2 \cdot 1.5/12 \cdot 1.5/12  \cdot 0.5/12  \cdot 1/Z = 1.125/3456 \cdot 1/Z\end{split}$$Since $p(\text{SPAM} = s | \text{"much much gain"})  + p(\text{SPAM} = h | \text{"much much gain"})  = 1$ we can work out that $Z=0.00385$ and$$\begin{split}p(\text{SPAM} = s | \text{"much much gain"}) &= 9.375/2662 \cdot 1/Z  = 0.915 = 91.5\%\\p(\text{SPAM} = h | \text{"much much gain"}) &= 1.125/3456 \cdot 1/Z = 0.085 = 8.5\%\end{split}$$Thus the modelpredicts that with $91.5\%$ the new text is SPAM.<jupyter_code><jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.2000736241487208, 'fraction_numerical': 0.04951224001472483, 'mean_word_length': 3.15761285386381, 'pattern_counts': {'":': 4, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '1', 'dir': 'jupyter-structured-clean-dedup', 'id': '400354', 'license': 'MIT', 'n_tokens_mistral': 2153, 'n_tokens_neox': 1925, 'n_words': 624, 'path': 'ML/Lectures/03_naive_bayes.ipynb', 'repo_name': 'TheFebrin/Machine-Learning', 'size': '5433'}