OK, so as mentioned, the next step is to populate the A's in the Pies with the appropriate counts
from the training set.
Now, because we're going to do the same procedure for both sets of A's and pies, it's useful to put
this into a function and then use the same function for both classes.
So we'll create a function called compute counts as input.
It's going to take in three arguments the text for the specific class and the pointer to a pie.
Note that because a prior objects, any modifications we made to them inside this function will be remembered
outside the function as well.
The important part of this is to note that the data we pass in will be only for a single class at a
time.
So inside the function will begin by looping through a variable called text as it each element of this
is a line of a poem represented by a list events.
The next step is to set a variable called the last index to none.
This will help us keep track of whether we are populating a pie.
The next step is to live through each index in our list of tokens represented as it's inside a loop.
We'll check whether or not last night is none.
If it is, then we know that we're at the beginning of a sentence.
If that is the case, we would like to populate PI, which is for the initial state distribution.
So at this point, we index pie at the index RDX, and we increment this value by one.
The next step is the Ellis Block.
This is when last study is not done, and so we're dealing with the transition from one word to the
next.
What we would like to do here is index a at the row last three weeks and add the column index and then
increment the value by one.
As you recall, the first index to a is the starting word.
And the second index today is the next word.
The final step in the inner loop is to update a last 30 x 280 x so that it has the correct a value on
the next iteration of the loop.
OK, so once we've defined our computer counts function, the next step is to call the function the
first time we call the function, we're going to filter the trained text in list.
So include only the entries where the corresponding value in Y train is zero.
That is, we only want the samples for one class, which is class zero.
This will be used to populate A0 and PI zero.
The second time we call a function, we'll do the same thing, except the label is one and we want to
populate A1 and pie one.
You may want to look at the list comprehension slowly.
If you don't understand what it does right away.
Alternatively, you may want to write your own version if this does not make sense.
So at this point, there is in the pies contain on the counts.
We, of course, need these to be probabilities.
So the next step is to divide the A's in the pies by the appropriate numbers so that they are valid
probabilities.
As you recall, each row of they must sum to one.
Therefore, we need to divide a by its row.
Sometimes we can do so by setting axis equals one and keep them as equals true.
Note that chiefdoms equals true, ensures that the sum is still two dimensional, which is required
for the division to broadcast correctly in Nampai for PI.
There is no need to do this since it's just a 1D array.
The next step is to take the log of our A's and her pies, as you recall, we normally work with log
probabilities.
And thus we have no need for the originals.
The next step is to compute the priors will begin by counting how many samples belong to class zero
and how many samples belong to Class one in the training set.
The next step is to compute the total, which is just the length of the train.
The next step is to compute the prior probabilities, which we'll call P0 and P1.
As usual, a reasonable estimate for these is simply the proportion of samples belonging to each class.
So P zero is just the number of data points belonging to Class zero, divided by the total number of
data points.
The next step is again to take the log of P0 and P1.
Since these are what will be using to do our computations.
Note that we'll also print out P zero and P one just so we know what they are.
OK, so we can see that P0 is about 33 percent and P one is about sixty six percent because of this,
it wouldn't make sense to use the maximum likelihood method.
Instead, we should look at the posterior, which corresponds to the map method.
Note also that because the classes are slightly imbalanced, we may want to use a metric other than
the accuracy to evaluate a classifier.
OK, so the next step is to build our classifier.
Now normally we build classifiers to have a circuit learn kind of interface with methods called fit
and predict.
Note that we could have done that, but we've already done the fitting part by finding the A's in the
pot.
If you'd like to try it as an exercise, you could restructure this code so that the model does have
a fit method.
And we do the training within that method.
OK, so the first step will be to look at the constructor.
The constructor will take in three arguments a list of log A's, a list of log pies and a list of log
priors inside.
The constructor will simply save these as attributes of the object.
We'll also assign the number of classes to an attribute called K, which is just equal to the size of
the list that we passed in.
The next step is to define a function called compute log likelihood, this will take as input a line
of text represented by a list of integers and a class.
As you recall, the class tells us which Markov model to use since we have one for every class inside.
The function will begin by retrieving log and log pi, by indexing our lists by the class.
The next step is to live through each index in the input.
As usual, we're going to follow the pattern of creating a variable called the last study X so that
we know whether or not we're at the beginning of a sentence.
We'll also initialize log probe to zero, which will hold the final answer.
The next step is to enter our loop inside a loop.
We're going to check whether or not last RDX is none.
If it is, then we know it's the first token in the sentence.
So we index log pie and add the result to log prop.
Otherwise, last study is not known, and we are not at the beginning of a sentence in this case, we
need to use our state transition matrix again.
We index log a at least 30 eccentrics and we add the result to two log prob.
The next step is to increment last three weeks for the next iteration of the Loop.
When we're outside the loop, we simply return leg crab.
The next step is to define the predict function, the input into this function as the list of input
sequences inside the function will begin by initializing an array to store the predictions.
The next step is to live through each input note that we use enumerate so that we get the index as well.
Inside the loop, we compute the posterior for each class using a list comprehension.
So for the loop, we use the index see and we leave through each integer from zero up to K minus one.
Inside the loop, we compute the log likelihood under the Class C and add it to the log prior for the
Class C.
This will give us a list of posteriors one for each class.
The next step is to obtain a prediction, which is simply the ARG max of the list of posteriors.
The next step is to store the prediction in our array of predictions at the index of the final step,
once we are outside the loop is to return the predictions.
OK, so at this point, the hard work is basically over, the next step is to instantiate a classifier
object.
As you recall, we'd like to pass in a list of log A's, a list of log PIs and a list of log priors.
Note that these must be passed in in the correct order, since each position in the list must correspond
to the correct class label.
That is, the log prior at index zero in this list should correspond with the label zero.
Since we've done everything in corresponding order, this doesn't really matter too much.
OK, so the next step is to use our classifier to obtain a prediction for the train sets.
We'll call the result p train.
We'll also print out the accuracy, which is just the mean of p train equals equals y train.
OK, so as you can see, we get nearly a perfect score.
The next step is to do the same thing for the test that.
OK, so as you can see, we do pretty well, but not as well as for the train set.
Now, as you recall, our data set has imbalanced classes, so it's helpful to look at some metrics
that take this into account.
We'll begin by importing the confusion matrix function and the F1 score function from Saikia.
Learn.
The next step is to compute the confusion matrix for the train set.
OK, so as expected, most of the samples fall along the diagonal, leading to a higher accuracy.
The next step is to compute the confusion matrix for the tests set.
OK, so this time we have more samples off the diagonal, which leads to a lower accuracy.
The next step is to compute the F1 score for the train set.
So, as expected, the train scores nearly one.
The next step is to compute the F1 score for the test set.
So again, we perform decently well, but not as well as for the train set.