Project Workshop: Interpretation & Presentation
A great model is useless if you can't explain how it works! In this final project step, we will interpret our model's predictions and visualize the results.
Which words strongly indicate a positive review? Which indicate a negative review? By looking at the coefficients of our Logistic Regression model or the feature importances of our Random Forest, we can extract the most predictive words.
No model is perfect. It's crucial to look at where your model failed. By examining the false positives and false negatives, you can often find clues on how to improve the model. For instance, models often struggle with sarcasm!
In a Logistic Regression trained on TF-IDF features, each word has one coefficient. A large positive value pushes the prediction toward the second class in model.classes_ (here assumed to be positive), and a large negative value pushes it toward the first. Sorting the coefficients and mapping them back to the vocabulary shows what the model relies on:
import numpy as np
print(model.classes_) # confirm which label is "positive"
names = np.array(vec.get_feature_names_out())
order = np.argsort(model.coef_[0]) # ascending: most negative first
print("Pushes toward class 0:", names[order[:10]])
print("Pushes toward class 1:", names[order[-10:]])Expect words like "excellent" or "boring" near the extremes. Treat the list as a description of the model, not of the world: a coefficient reflects correlation in your training set, and it can be inflated by words that happen to show up in a few very polarized reviews. For a Random Forest, feature_importances_ gives a similar ranking, but it only measures how useful a word was for splitting, not which direction it points.
A confusion matrix from scikit-learn has true labels on the rows and predicted labels on the columns. With labels ordered [negative, positive] it reads [[TN, FP], [FN, TP]]. From it you get precision (of the reviews predicted positive, how many really were) and recall (of the truly positive reviews, how many did we find).
from sklearn.metrics import confusion_matrix, classification_report
y_pred = model.predict(X_test_tfidf)
print(confusion_matrix(y_test, y_pred))
print(classification_report(y_test, y_pred))
# Pull out the actual text of the mistakes (assumes labels are 0 and 1)
y_true = np.asarray(y_test)
false_pos = X_test[(y_pred == 1) & (y_true == 0)]
false_neg = X_test[(y_pred == 0) & (y_true == 1)]
for text in false_pos.head(5):
print(text[:300], "...")
print("---")Here X_testis the raw test text from your split, not the TF-IDF matrix. If your labels are strings such as "positive", compare against those strings instead. When reading the errors, sort them into patterns: negation ("not good"), sarcasm, reviews that praise the acting but dislike the plot, or labels that look wrong. Each pattern suggests a different fix, such as adding bigrams with ngram_range=(1, 2)so "not good" becomes its own feature.
State the problem in one sentence, give the baseline and final scores side by side, and show the confusion matrix rather than only a single accuracy figure. Mention the size of the test set so readers can judge how much a small difference matters: with 400 test reviews, the standard error on an accuracy near 85% is about 1.8 percentage points. End with limitations, such as the model being trained on movie reviews only and likely to degrade on other domains.
LinearSVC or MultinomialNB on the same TF-IDF features.predict_proba and inspect reviews close to 0.5.Interpretation turns a score into understanding: coefficients show what the model relies on, the confusion matrix shows what kind of mistakes it makes, and reading the errors tells you what to try next.
Let's find out where your model is struggling.
In the real world, you'd present your findings to stakeholders. A great way to do this is a dashboard summarizing the class distribution, confusion matrix, top features, and a model comparison chart.