{ "cells": [ { "cell_type": "markdown", "id": "4d5f7f3d", "metadata": {}, "source": [ "# Lesson 20: Naive Bayes text classification demo\n", "\n", "This notebook uses a standard text dataset to show how to classify documents with a simple bag-of-words encoding and sklearn's naive Bayes classifier.\n", "\n", "Dataset source: [20 newsgroups text dataset](https://scikit-learn.org/stable/datasets/real_world.html#the-20-newsgroups-text-dataset).\n", "\n", "1. Introduction\n", "\n", "2. Notebook set up\n", "\n", " - Imports\n", " - Load 3 classes from 20 newsgroups dataset\n", "\n", "3. Clean the text.\n", "\n", " - Remove numbers, special characters and punctuation\n", " - Lowercase all characters\n", "\n", "4. Encode text with word counts.\n", "\n", " - Use `CountVectorizer` as the simplest baseline representation.\n", "\n", "5. Train and evaluate a naive Bayes model.\n", "\n", " - Fit `MultinomialNB` on the encoded text.\n", " - Inspect accuracy, a confusion matrix, and example predictions.\n", "\n", "6. Results\n", "\n", " - Confusion matrix\n", " - Learned words\n", " - Predict new examples\n", "\n", "\n", "## 1. Introduction\n", "\n", "### 1.1. Bag-of-words\n", "\n", "To use any type of model on text we first need to represent that text as numbers. We have seen methods to do this previously, such as one-hot-encoding, but these won't work here. We may have long stings of text and texts of different lengths. One of the simplest ways to 'vectorize' or turn text into numbers is to use word frequencies:\n", "\n", "|text |\n", "|----------------------|\n", "|The food was good |\n", "|The food was awesome |\n", "|The food was terrible |\n", "\n", "In this collection of documents, we have the following word counts:\n", "\n", "```text\n", "the: 3\n", "food: 3\n", "was: 3\n", "good: 1\n", "awesome: 1\n", "terrible: 1\n", "```\n", "\n", "And those words can be used as features:\n", "\n", "|text | the | food | was | good | awesome | terrible |\n", "|----------------------|-----|------|-----|------|---------|----------|\n", "|The food was good | 1 | 1 | 1 | 1 | 0 | 0 |\n", "|The food was awesome | 1 | 1 | 1 | 0 | 1 | 0 |\n", "|The food was terrible | 1 | 1 | 1 | 0 | 0 | 1 |\n", "\n", "This type of analysis is known as bag-of-words because it throws all of the words together, jumbles them up and only looks at their frequencies.\n", "\n", "\n", "### 1.2. Naive bayes\n", "\n", "The naive bayes model learns the probability of the label based on it's co-occurrence with the features in the training set. Let's add a label to our toy data:\n", "\n", "|text | the | food | was | good | awesome | terrible | review sentiment |\n", "|----------------------|-----|------|-----|------|---------|----------|------------------|\n", "|The food was good | 1 | 1 | 1 | 1 | 0 | 0 | positive |\n", "|The food was awesome | 1 | 1 | 1 | 0 | 1 | 0 | positive |\n", "|The food was terrible | 1 | 1 | 1 | 0 | 0 | 1 | negative |\n", "\n", "\n", "The probability that a review is negative in the test set is 33% (1/3). While the probability that a review is negative given that it contains the word bad is 100% (1/1)! Obviously real data is not this simple, but this example demonstrates a how the naive bayes model can 'learn' from data." ] }, { "cell_type": "markdown", "id": "6d08b209", "metadata": {}, "source": [ "## 2. Notebook set up\n", "\n", "### 2.1. Imports" ] }, { "cell_type": "code", "execution_count": 1, "id": "a61bc917", "metadata": {}, "outputs": [], "source": [ "# Standard library imports\n", "import re\n", "\n", "# Third party imports\n", "import matplotlib.pyplot as plt\n", "import pandas as pd\n", "\n", "from sklearn.datasets import fetch_20newsgroups\n", "from sklearn.feature_extraction.text import CountVectorizer\n", "from sklearn.metrics import ConfusionMatrixDisplay, accuracy_score\n", "from sklearn.naive_bayes import MultinomialNB" ] }, { "cell_type": "markdown", "id": "2665fb54", "metadata": {}, "source": [ "### 2.2. Load the dataset" ] }, { "cell_type": "code", "execution_count": 2, "id": "0f9393fa", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
texttargetlabel
0I want to get a car alarm and I am thinking ab...0rec.autos
1I did hear this question asked during a radio ...2talk.politics.misc
2Quoting Jeffrey J. Nucciarone's (nucci@microwa...0rec.autos
3I can not believe the way this thread on candi...1sci.med
4\\n\\n\\n\\n\\nOK, I admit I have no hard data on t...2talk.politics.misc
\n", "
" ], "text/plain": [ " text target \\\n", "0 I want to get a car alarm and I am thinking ab... 0 \n", "1 I did hear this question asked during a radio ... 2 \n", "2 Quoting Jeffrey J. Nucciarone's (nucci@microwa... 0 \n", "3 I can not believe the way this thread on candi... 1 \n", "4 \\n\\n\\n\\n\\nOK, I admit I have no hard data on t... 2 \n", "\n", " label \n", "0 rec.autos \n", "1 talk.politics.misc \n", "2 rec.autos \n", "3 sci.med \n", "4 talk.politics.misc " ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Choose three familiar categories so the example stays readable\n", "categories = ['rec.autos', 'sci.med', 'talk.politics.misc']\n", "\n", "train_data = fetch_20newsgroups(\n", " subset='train',\n", " categories=categories,\n", " remove=('headers', 'footers', 'quotes'),\n", ")\n", "\n", "test_data = fetch_20newsgroups(\n", " subset='test',\n", " categories=categories,\n", " remove=('headers', 'footers', 'quotes'),\n", ")\n", "\n", "label_names = train_data.target_names\n", "label_map = dict(enumerate(label_names))\n", "\n", "train_df = pd.DataFrame({'text': train_data.data, 'target': train_data.target})\n", "test_df = pd.DataFrame({'text': test_data.data, 'target': test_data.target})\n", "\n", "train_df['label'] = train_df['target'].map(label_map)\n", "test_df['label'] = test_df['target'].map(label_map)\n", "\n", "train_df.head()" ] }, { "cell_type": "code", "execution_count": 3, "id": "ea7e44c0", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "label\n", "rec.autos 594\n", "sci.med 594\n", "talk.politics.misc 465\n", "Name: count, dtype: int64" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "train_df['label'].value_counts()" ] }, { "cell_type": "markdown", "id": "4edc3b64", "metadata": {}, "source": [ "## 3. Basic text preprocessing\n", "\n", "Lowercase all text and remove numbers, punctuation, and other non-letter characters before encoding." ] }, { "cell_type": "code", "execution_count": 4, "id": "6e494877", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
textclean_text
0I want to get a car alarm and I am thinking ab...i want to get a car alarm and i am thinking ab...
1I did hear this question asked during a radio ...i did hear this question asked during a radio ...
2Quoting Jeffrey J. Nucciarone's (nucci@microwa...quoting jeffrey j nucciarone s nucci microwave...
\n", "
" ], "text/plain": [ " text \\\n", "0 I want to get a car alarm and I am thinking ab... \n", "1 I did hear this question asked during a radio ... \n", "2 Quoting Jeffrey J. Nucciarone's (nucci@microwa... \n", "\n", " clean_text \n", "0 i want to get a car alarm and i am thinking ab... \n", "1 i did hear this question asked during a radio ... \n", "2 quoting jeffrey j nucciarone s nucci microwave... " ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "def clean_text(text):\n", " '''Removes non-alphabetic characters. Converts to lowercase.'''\n", "\n", " text = text.lower()\n", " text = re.sub(r'[^a-z\\s]', ' ', text)\n", " text = re.sub(r'\\s+', ' ', text).strip()\n", "\n", " return text\n", "\n", "train_df['clean_text'] = train_df['text'].apply(clean_text)\n", "test_df['clean_text'] = test_df['text'].apply(clean_text)\n", "\n", "train_df[['text', 'clean_text']].head(3)" ] }, { "cell_type": "markdown", "id": "77d041d7", "metadata": {}, "source": [ "## 4. Encode text with word counts\n", "\n", "`CountVectorizer` turns each document into a vector of word counts, which is the simplest bag-of-words representation." ] }, { "cell_type": "code", "execution_count": 5, "id": "761994eb", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Training data shape: (1653, 20919)\n" ] } ], "source": [ "vectorizer = CountVectorizer()\n", "\n", "X_train = vectorizer.fit_transform(train_df['clean_text'])\n", "X_test = vectorizer.transform(test_df['clean_text'])\n", "\n", "print(f'Training data shape: {X_train.shape}')" ] }, { "cell_type": "code", "execution_count": null, "id": "a7a3bf25", "metadata": {}, "outputs": [], "source": [ "features = pd.Series(vectorizer.get_feature_names_out(), name='sample vocabulary')\n", "print(f'Num encoded features: {len(features)}')\n", "features[10000:10020]" ] }, { "cell_type": "markdown", "id": "43f7bdf7", "metadata": {}, "source": [ "## 5. Train the classifier\n", "\n", "Multinomial naive Bayes is a simple probabilistic classifier that works well with word-count features, making it a strong baseline for text classification." ] }, { "cell_type": "code", "execution_count": 6, "id": "7014f832", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Test accuracy: 0.886\n" ] } ], "source": [ "naive_bayes = MultinomialNB()\n", "naive_bayes.fit(X_train, train_df['target'])\n", "\n", "predictions = naive_bayes.predict(X_test)\n", "\n", "accuracy = accuracy_score(test_df['target'], predictions)\n", "print(f'Test accuracy: {accuracy:.3f}')" ] }, { "cell_type": "markdown", "id": "2bc55c2a", "metadata": {}, "source": [ "## 6. Results\n", "\n", "### 6.1. Confusion matrix" ] }, { "cell_type": "code", "execution_count": 7, "id": "cdeae6ff", "metadata": {}, "outputs": [ { "data": { "image/png": "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YcMGKleu/J9C/TdVVEVERESczROYTOXn52ezPW6i+m958uQhU6ZMnDhxAoCQkBCuXLlic05CQgIREREPHNf6IEpURUREROSxnT9/nmvXrpElSxYAwsLCuHHjBrt377aes27dOiwWC+XKlUtR2+r6FxEREXEyjrwz1a1bt6zVUYBTp06xb98+AgMDCQwMZOjQoTRo0ICQkBBOnjxJv379yJcvH9WrVwegcOHC1KhRg/fee49vv/2W+Ph4unTpQuPGjVM04x9UURURERGRu+zatYvSpUtTunRpAHr16kXp0qUZPHgwrq6uHDhwgDfeeIMCBQrQpk0bypQpw++//24zlGDOnDkUKlSIypUrU6tWLV566SUmT56c4lhUURURERFxNk9gMlVyVapUCcN48JNWrlz5yDYCAwOZO3duyl74PpSoioiIiDgZR3b9OxN1/YuIiIiIU1JFVURERMTZOLDr35mooioiIiIiTkkVVRERERFno4oqoERVRERExOmY/n+zV1uplbr+RURERMQpqaIqIiIi4mzU9Q+ooioiIiIiTkoVVREREREnowX/EylRFREREXE26voH1PUvIiIiIk5KFVURERERZ5SKK6H2ooqqiIiIiDglVVRFREREnIwmUyVSoioiIiLibDSZClDXv4iIiIg4KVVURURERJyMuv4TqaIqIiIiIk5JFVURERERZ6MxqoASVRERERGno67/REpU5amz3LyJxeTu6DAkFRlY6GVHhyCpUM7foxwdgqQycbfi4FVHRyF3U6IqIiIi4mzU9Q9oMpWIiIiIOClVVEVEREScjSqqgBJVEREREaejyVSJ1PUvIiIiIk5JFVURERERZ6Ouf0AVVRERERFxUqqoioiIiDgZk2FgMuxTCrVXO46gRFVERETE2ajrH1DXv4iIiIg4KVVURURERJyMlqdKpIqqiIiIiDglVVRFREREnI3GqAJKVEVEREScjrr+E6nrX0RERESckiqqIiIiIs5GXf+AKqoiIiIi4qRUURURERFxMhqjmkiJqoiIiIizUdc/oK5/EREREXFSqqiKiIiIOKHU3GVvL6qoioiIiIhTUkVVRERExNkYRuJmr7ZSKSWqIiIiIk5Gs/4TqetfRERERJySKqoiIiIizkbLUwGqqIqIiIiIk1KiKiIiIuJkTBb7bimxadMm6tSpQ9asWTGZTCxZssTm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oioiIiLifByYqAIULVqUS5cuWbfNmzdbj/Xs2ZNly5axcOFCNm7cyMWLF6lfv749r95KY1RFRERExIabmxshISH37I+MjOS7775j7ty5vPbaawBMmzaNwoULs337dsqXL2/XOFRRFREREXE2FjtvQFRUlM0WGxv7wJc/fvw4WbNmJU+ePDRt2pSzZ88CsHv3buLj46lSpYr13EKFCpEjRw62bdtmv+v/f0pURURERNKA0NBQ/P39rdvIkSPve165cuWYPn06v/32GxMnTuTUqVO8/PLL3Lx5k/DwcDw8PAgICLB5TnBwMOHh4XaPWV3/IiIiIk7mSSz4f+7cOfz8/Kz7PT0973t+zZo1rT+XKFGCcuXKkTNnThYsWIC3t7ddYkouVVRFREREnM0TmEzl5+dnsz0oUf23gIAAChQowIkTJwgJCSEuLo4bN27YnHP58uX7jmn9r5SoioiIiMgD3bp1i5MnT5IlSxbKlCmDu7s7a9eutR4/evQoZ8+eJSwszO6vra5/EREREWdjMcBkpztKWVLWTp8+fahTpw45c+bk4sWLfPTRR7i6utKkSRP8/f1p06YNvXr1IjAwED8/P7p27UpYWJjdZ/yDElURERERucv58+dp0qQJ165dI3PmzLz00kts376dzJkzAzB27FhcXFxo0KABsbGxVK9enQkTJjyRWJSoioiIiDibx1yo/4FtpcC8efMeetzLy4vx48czfvz4/xJVsihRFREREXE6dkxUsVc7T58mU4mIiIiIU1JFVURERMTZOLDr35mooioiIiIiTkkVVRERERFnYzGw29jSFC5P5UyUqIqIiIg4G8OSuNmrrVRKXf8iIiIi4pRUURURERFxNppMBaiiKiIiIiJOShVVEREREWejyVSAElURERER56Ouf0Bd/yIiIiLipFRRFREREXE2BnasqNqnGUdQRVVEREREnJIqqiIiIiLORmNUASWqIiIiIs7HYgHsdEcpi+5MJSIiIiJiV6qoioiIiDgbdf0DqqiKiIiIiJNSRVVERETE2aiiCihRFREREXE+uoUqoK5/EREREXFSqqiKiIiIOBnDsGAY9llWyl7tOIIqqiIiIiLilFRRFREREXE2hmG/saWaTCUiIiIidmPYcTJVKk5U1fUvIiIiIk5JFVURERERZ2OxgMlOk6A0mUpERERExL5UURURERFxNhqj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I8yYMYP58+cTHR1NQEAAf/31F2FhYcybN48XXnjBgZFLWqAxqiIOsHnzZl599VUqVaqEq6sr27ZtY/PmzRQvXtzRoclTFBUVxdtvv82LL77IRx99ZN0fHx+Pu7s7ALNmzbJOtvvggw9UsRK7untM6sGDBylQoADHjx/nvffeIzo6mvPnz1OvXj1efPFFXnzxRV566SW+/vpr3nnnHWsbuuOUPEmqqIrYUVJl4ujRowAULFjwnuMAL730EitWrGDKlCkEBATw+eefU6xYsacerzhWbGwsR44c4a233rLZn5SkJiQk0Lx5c1xdXSlVqpSSAbGru5PUwYMHs23bNtq2bUujRo0YNmwYBw8eJE+ePLz88sv4+/tz9epVcuXKRVBQkE07+lzKk6SKqoidJCWpP/30E4MGDeLtt9+mU6dO1i/1u38pxMTE4OXlRVxcHG5ubpq5nUYkfUb27dtHxowZ8ff357XXXqNx48b06dPH5tw9e/awevVqevXqZU1cRezh3139gwcPZsKECfzwww8ULVqUrFmz2pwfHx/P1atXadeuHVevXmXz5s1KTuWp0W9HETsxmUysWrWKZs2a0bVrVzp37mxTeUhKRkeOHMnEiROJjo7Gw8NDSWoacfcNH2rXrs3kyZPx8/OjbNmyfPrpp2zbto276wY//vgja9as4datWw6MWp5FdyepR48eZdmyZcyYMYOqVatak9Skz2JcXBxTp06lVatWXLlyhU2bNml2vzxV6voXsQPDMIiLi2P27Nl06tSJDh06WL/o/73W5bp167h+/TqtW7d2VLjiACaTiV9++YV33nmHr7/+mho1agAwceJErl69St26denUqRPe3t6cPHmSefPmsXnzZjJkyODgyOVZ0b59e2rWrEm9evWs+2JjYzl79iz+/v4255pMJuLi4vDw8KBgwYK8/vrrdOrUCVdX1wfeOU3kSdAnTcQOTCYTnp6enDx5kkyZMln3wf8qqWfPniVHjhysXr2a8+fPExAQ4KhwxQFiYmKYMWMGPXv2pG3btty+fZvjx4+zdOlS2rVrByR29586dYr8+fOzZcsWTa4Tuzlz5gyZM2emdu3aNvtv376Nu7s7t2/fBmwnRq1bt46LFy/y7rvv8tprr1mPK0mVp0mfNpH/IKk71zAMoqOj8fHx4fLly8D/vvANw+DixYt8++23tGzZkoIF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ret169aZoKAgc+vWLavtq6++Mv369TPNzc3GGGNeeeUVc/DgQZ95CgsLTWJiojHGmIaGBgOYixcvPnZdEQlcekdVRAJSRUUF4eHhdHR04PV6efvtt1m/fr3Vn5CQ4PNe6qVLl6ivr8fpdPrM09raisfj4d69ezQ3NzN16lSrLzg4mClTpnR7/P9QbW0tQUFBJCUl9bju+vp6fv/9d1577TWf9vb2diZOnAhAXV2dTx0AiYmJPV7jocOHD1NcXIzH46GlpYXOzk4GDBjgM2bkyJGMGDHCZx2v14vb7cbpdOLxeMjKymLBggXWmM7OTgYOHNjrekQk8CioikhASk5OZufOnYSEhBAVFUVwsO+/w7CwMJ/rlpYWJk+ezIEDB7rNNXTo0KeqwW639/ozLS0tAJw8edInIMKD9277yrlz58jIyKCgoICZM2cycOBADh06xLZt23pd6549e7oF56CgoD6rVUT+vRRURSQghYWFERsb2+PxkyZN4vDhwwwbNqzbruJDw4cP58KFC0ybNg14sHNYU1PDpEmTHjk+ISEBr9fLmTNnmDFjRrf+hzu6XV1dVtvYsWMJDQ2lqanpsTux8fHx1sGwh86fP//XN/lfqquriYmJ4YMPPrDabty40W1cU1MTt2/fJioqylqnX79+xMXFERERQVRUFNevXycjI6NX64uIgA5TiYj0SEZGBkOGDCE1NZWqqioaGho4ffo0S5cu5datWwAsW7aMzZs3U15ezpUrV8jOzn7id6C+9NJLuFwu3nvvPcrLy605jxw5AkBMTAw2m42Kigp++eUXWlpacDqd5ObmkpOTQ1lZGR6Phx9//JGPP/7YOqC0cOFCrl27xqpVq3C73Rw8eJDS0tJe3e+rr75KU1MThw4dwuPxUFxc/MiDYf3798flcnHp0iWqqqpYunQp6enpREZGAlBQUEBRURHFxcVcvXqVy5cvU1JSwocfftirekQkMCmoioj0gMPh4Pvvv2fkyJGkpaURHx9PVlYWra2t1g7rypUreeedd3C5XCQmJuJ0OpkzZ84T5925cydz584lOzubMWPGsGDBAu7fvw/AiBEjKCgoYPXq1URERLBkyRIACgsLyc/Pp6ioiPj4eFJSUjh58iSjRo0CHrw3euzYMcrLyxk/fjy7du1i06ZNvbrfN954g5ycHJYsWcKECROorq4mPz+/27jY2FjS0tKYNWsWr7/+OuPGjfP5+qn58+ezd+9eSkpKSEhIICkpidLSUqtWEZEnsZnHveUvIiIiIvIP0o6qiIiIiPglBVURERER8UsKqiIiIiLilxRURURERMQvKaiKiIiIiF9SUBURERERv6SgKiIiIiJ+SUFVRERERPySgqqIiIiI+CUFVRERERHxSwqqIiIiIuKXFFRFRERExC/9AR7saPn4OboiAAAAAElFTkSuQmCC", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "fig, ax = plt.subplots(figsize=(8, 6))\n", "\n", "ConfusionMatrixDisplay.from_predictions(\n", " test_df['target'],\n", " predictions,\n", " display_labels=label_names,\n", " xticks_rotation=45,\n", " ax=ax\n", ")\n", "\n", "plt.title('Naive Bayes confusion matrix')\n", "plt.tight_layout()\n", "plt.show()" ] }, { "cell_type": "markdown", "id": "ac263cd6", "metadata": {}, "source": [ "### 6.2. Inspect the learned words\n", "\n", "Naive Bayes makes it easy to inspect which words are most associated with each class." ] }, { "cell_type": "code", "execution_count": 8, "id": "2c2fdbba", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
rec.autossci.medtalk.politics.misc
0thethethe
1toofto
2andtoof
3ofandand
4ininthat
5isisin
6itthatis
7thatitit
8youforyou
9foryoufor
\n", "
" ], "text/plain": [ " rec.autos sci.med talk.politics.misc\n", "0 the the the\n", "1 to of to\n", "2 and to of\n", "3 of and and\n", "4 in in that\n", "5 is is in\n", "6 it that is\n", "7 that it it\n", "8 you for you\n", "9 for you for" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "feature_names = vectorizer.get_feature_names_out()\n", "top_n = 10\n", "\n", "top_words = {}\n", "\n", "for class_index, class_name in enumerate(label_names):\n", " top_indices = naive_bayes.feature_log_prob_[class_index].argsort()[-top_n:][::-1]\n", " top_words[class_name] = feature_names[top_indices]\n", "\n", "pd.DataFrame(top_words)" ] }, { "cell_type": "markdown", "id": "917099c4", "metadata": {}, "source": [ "### 6.3. Predict new examples" ] }, { "cell_type": "code", "execution_count": 9, "id": "c2d9fbd0", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
textclean_textpredicted_labelconfidence
0My car needs new brakes and the engine is maki...my car needs new brakes and the engine is maki...rec.autos1.000
1The doctor recommended rest, hydration, and a ...the doctor recommended rest hydration and a fo...sci.med0.951
2The city council held a debate about taxes and...the city council held a debate about taxes and...talk.politics.misc1.000
\n", "
" ], "text/plain": [ " text \\\n", "0 My car needs new brakes and the engine is maki... \n", "1 The doctor recommended rest, hydration, and a ... \n", "2 The city council held a debate about taxes and... \n", "\n", " clean_text predicted_label \\\n", "0 my car needs new brakes and the engine is maki... rec.autos \n", "1 the doctor recommended rest hydration and a fo... sci.med \n", "2 the city council held a debate about taxes and... talk.politics.misc \n", "\n", " confidence \n", "0 1.000 \n", "1 0.951 \n", "2 1.000 " ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sample_texts = [\n", " 'My car needs new brakes and the engine is making a strange noise.',\n", " 'The doctor recommended rest, hydration, and a follow-up appointment.',\n", " 'The city council held a debate about taxes and public policy.',\n", "]\n", "\n", "sample_texts_clean = [clean_text(text) for text in sample_texts]\n", "\n", "sample_counts = vectorizer.transform(sample_texts_clean)\n", "sample_predictions = naive_bayes.predict(sample_counts)\n", "sample_probabilities = naive_bayes.predict_proba(sample_counts)\n", "\n", "prediction_df = pd.DataFrame({\n", " 'text': sample_texts,\n", " 'clean_text': sample_texts_clean,\n", " 'predicted_label': [label_names[index] for index in sample_predictions],\n", " 'confidence': sample_probabilities.max(axis=1).round(3),\n", "})\n", "\n", "prediction_df" ] } ], "metadata": { "kernelspec": { "display_name": ".venv (3.12.3)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.3" } }, "nbformat": 4, "nbformat_minor": 5 }