<jupyter_start><jupyter_text>Text Bag of Words with Naive Bayes <NAME><jupyter_code>import numpy as np
import matplotlib.pyplot as plt
import glob
def estimate_log_prob_params(strings):
    """
    Estimate the log multinomial probability parameters for a
    particular set of strings.  This will be our model
    
    Parameters
    ----------
    strings: list of string
        A list of strings
    
    Returns
    -------
    probs: dict
        word->log probability in model
    total: int
        Total number of words in the model, plus smoothing
    """
    probs = {}
    total = 0
    for s in strings:
        for word in s.split():
            if not word in probs:
                probs[word] = 1 # Do this for smoothing
                total += 1
            probs[word] += 1
            total += 1
    # Convert to log probabilities
    for word in probs:
        probs[word] = np.log(probs[word]/total)
    return (probs, total)

def get_log_probability_words(model, words):
    """
    Compute the log probability of a set of words using
    a model
    
    Parameters
    ----------
    model: (probs, total)
        probs: dict
            word->log probability in model
        total: int
            Total number of words in the model, plus smoothing
    words: list of string
        Words to which to apply the model
    
    Returns
    -------
    float: The log probability of the set of words under the model
    """
    (probs, total) = model
    res = 0
    for word in words:
        if not word in probs:
            # If this word has never been seen, give it a low
            # but nonzero probability before taking the log
            res += np.log(1/total)
        else:
            res += probs[word] 
    return res<jupyter_output><empty_output><jupyter_text>2016 Presidential DebatesFirst, we load the first two debates and use them to build two different bag of words models: one for Trump and one for Clinton.  Below is some code that uses lists so we don't have to repeat the same code too much<jupyter_code>categories = ["clinton", "trump"]
models = []
for c in categories:
    fin = open("text/2016Debates/{}1.txt".format(c))
    strings = [fin.read()]
    fin.close()
    fin = open("text/2016Debates/{}2.txt".format(c))
    strings.append(fin.read())
    fin.close()
    model = estimate_log_prob_params(strings)
    models.append(model)<jupyter_output><empty_output><jupyter_text>Next, we apply the models to each example in the third debate, and we get nearly perfect accuracy!  In the process, we construct something called a "confusion matrix," where the row is the true class of the example we're classifying, and the columns count how often they were classified as another class.  The more elements along the diagonal, the better<jupyter_code># Apply test data
confusion = np.zeros((2, 2), dtype=int)
for i, c in enumerate(categories):
    for f in glob.glob("text/2016Debates/{}3*.txt".format(c)):
        fin = open(f)
        test = fin.read()
        words = test.split()
        log_probs = [get_log_probability_words(models[j], words) for j in range(len(categories))]
        j = np.argmax(log_probs)
        confusion[i, j] += 1
        fin.close()
#print(confusion, ":", np.sum(np.diag(confusion))/np.sum(confusion), "accuracy")

plt.imshow(confusion)
for i in range(len(confusion)):
    for j in range(len(confusion)):
        plt.text(j, i, confusion[i, j])
plt.xticks(np.arange(len(confusion)), categories)
plt.yticks(np.arange(len(confusion)), categories)
plt.title("{:f}%s Accuracy".format(100*np.sum(np.diag(confusion))/np.sum(confusion)));<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.10491623180444933, 'fraction_numerical': 0.008788794287283713, 'mean_word_length': 2.6974619289340103, 'pattern_counts': {'":': 1, '<': 14, '<?xml version=': 0, '>': 16, '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': '3', 'dir': 'jupyter-structured-clean-dedup', 'id': '85380', 'license': 'Apache-2.0', 'n_tokens_mistral': 1132, 'n_tokens_neox': 1079, 'n_words': 382, 'path': 'ClassExercises/Week5_BagOfWords/Solution.ipynb', 'repo_name': 'Ursinus-CS477-F2021/CoursePage', 'size': '3647'}