{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":14747,"databundleVersionId":459177,"sourceType":"competition"}],"dockerImageVersionId":30558,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# What Kaggle WON'T Tell You About Your Notebooks!\n\n## (A Notebook about Clickbait Detection 😉)\n![Example_clickbait_adverts.jpg](attachment:ec87dcdc-f45a-43f0-8bc2-a9ebc5687542.jpg)\n<figure>\n    <figcaption align=\"center\"><i>Source: Wikipedia</i></figcaption>\n</figure>\n\n\n## Background\n\nI read a lot of news online, and so for this project, I wanted to apply my Natural Language Processing (NLP) skills to a problem I find highly annoying.. that is, **the problem of Clickbait**.  I don't know how many times I've clicked on a headline like *Sports World Reacts to What Jim Harbaugh Just Said* only to read the article and find, of course, a short snippet of some mundane quote or non-newsworthy announcement.  Nothing controversial was actually said; no sports world was reacting.\n\nSo what makes clickbait, clickbait?\n\nAnd why does it work so well?\n\n<div class=\"alert alert-info\">\n  💡 Opinions vary, but most agree that what makes something clickbait is a headline that creates a <b>curiosity gap</b> in the readers mind, making you wonder what you are missing out on, and compelling you to click the link to close that gap.  It's a form of preying on people's FOMO.\n</div>\n\nAnd yes, I realize that I did that here to grab your attention.  But hopefully you will get a lot more from this notebook than the typical clickbait article and don't feel too tricked.  😎\n\nSo rather than simply practicing my ML skills on another sentiment analysis dataset, like Tweets, Amazon Reviews, or IMDB Ratings, I decided to focus on something that actually could be put to good use.\n\n<div class=\"alert alert-success\">\n  <strong>\n      💲teal my business idea! \n  </strong>\n      You could use this model or one like it to make a Chrome extension that detects news articles, and it could gray out the image and unlink the URL for any article deemed clickbait.  Who knows, if enough people used the extension, maybe editors would stop the practice?  Then you could be like AdBlock and charge money to let the articles back through your filter. 🤣.. 😒.. 😭  Let's pretend for the sake of this notebook that we're buiding this Chrome extension for our fictional startup named <i>BaitBlock</i>.\n</div>\n\nThe data we'll be using for this study comes originally from a [Kaggle competition](https://www.kaggle.com/competitions/clickbait-news-detection).  I'm not going to try to enter the competition, but just see how I do on a validation subset of the data.  So since we don't have the final answers for the `test.csv` files, we won't use that at all.","metadata":{},"attachments":{"ec87dcdc-f45a-43f0-8bc2-a9ebc5687542.jpg":{"image/jpeg":"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"}}},{"cell_type":"markdown","source":"---\n\n# Topics We'll Discuss\n\nThis is a classification problem.  We'll simply look at article headlines (aka titles), such as *My boss made me think I was going mad and suffering from maternity paranoia* and we'll classify it as either `clickbait` or `news`.  \n\nWe will consider what text preprocessing, if any, is necessary.  For example, should we remove stopwords from our dataset?  We'll talk about why we are using the `F1 Score` as the main metric for this particular problem.  And we'll consider several different architectures, like LSTMs and see how they do versus Transformers as well.\n\nFirst, let's start by getting the dataset loaded.","metadata":{}},{"cell_type":"markdown","source":"---\n\n# Notebook Setup\n\nOnly **one** of the below code flow flags should be set to `True` for an individual run.  I've left it set to the Average Pooling model, as that ended up performing best overall without overfitting, but feel free to change these and see the performance of a different model.","metadata":{}},{"cell_type":"code","source":"# Define some constants\nRANDOM_SEED = 42\nBATCH_SIZE = 32\n\nEMBEDDING_SIZE = 128  # How many dimensions are our learned word representations.  Keep same across all models\n\n# Code flow flags\n# Turn on to see results of these models\n\n# RNN/LSTM Models\ntrain_simple_model = False               # accuracy: 0.9738 val_accuracy: 0.7539\ntrain_regularized_simple_model = False   # accuracy: 0.9513 val_accuracy: 0.7668\ntrain_average_pooling_model = True       # accuracy: 0.8293 val_accuracy: 0.8150  ==> Best Results\n\n# Google's Universal Sentence Encoder (Transformer)\ntrain_USE_model = False                  # accuracy: 0.9987 val_accuracy: 0.7877\n","metadata":{"execution":{"iopub.status.busy":"2023-09-18T19:40:23.069440Z","iopub.execute_input":"2023-09-18T19:40:23.069843Z","iopub.status.idle":"2023-09-18T19:40:23.101577Z","shell.execute_reply.started":"2023-09-18T19:40:23.069807Z","shell.execute_reply":"2023-09-18T19:40:23.100463Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nimport numpy as np\nimport pandas as pd\n\nimport tensorflow as tf\nfrom tensorflow import keras\nimport matplotlib.pyplot as plt","metadata":{"execution":{"iopub.status.busy":"2023-09-18T19:40:23.103634Z","iopub.execute_input":"2023-09-18T19:40:23.104260Z","iopub.status.idle":"2023-09-18T19:40:31.574204Z","shell.execute_reply.started":"2023-09-18T19:40:23.104222Z","shell.execute_reply":"2023-09-18T19:40:31.573052Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Text Preprocessing\n\nProbably 80% of the work is done right here, in analyzing and formatting the dataset.  \n\nThe following function takes a flag `explore_only` which we will first call the function with that set to `True` so we can explore the data.  In both cases, when we are exploring the data and later when we actually create the dataset, we'll start by first combining the Train and Validation sets provided by the contest into one large dataset.  We'll later shuffle that and set aside a portion of it for evaluation of our models.\n\nLet's run that next and see what we get.","metadata":{}},{"cell_type":"code","source":"# Let's make a function that allows us to explore the data as well as create the datasets\n\ndef process_dataset(explore_only=False):\n    \"\"\"Print out information about the dataset, but default is to actually create it.\n    If explore_only=True, this function will report information about the dataset\n    but won't actually create it.  Run this way first before creating.\"\"\"\n\n    # Load both the training and validation data from CSV files\n    # We'll combine these and perform the train/val split ourselves\n    df_train = pd.read_csv('/kaggle/input/clickbait-news-detection/train.csv')\n    df_val = pd.read_csv('/kaggle/input/clickbait-news-detection/valid.csv')\n    \n    # Combine the two first\n    df_all = pd.concat([df_train, df_val])\n    \n    # Run function first with this flag set to understand the data (doesn't return anything)\n    if explore_only:\n        print(\"\\n\\nHeads and Tails of all data:\")\n        print(df_all.head())\n        print(\"\")\n        print(df_all.tail())\n        print(\"\\n\\nInfo():\")\n        print(df_all.info())\n        print(\"\\n\\nDescribe():\")\n        print(df_all.describe())\n        \n        # See unique values for labels\n        unique_labels = df_all['label'].unique()\n        print(\"\\n\\nUnique Labels:\")\n        print(unique_labels)\n        \n        # Count how many are in each label.  Look at histogram of types, to see how balanced dataset is\n        # df.hist(column='label')  # ERROR: hist() only works on numerical column values\n\n        # Instead, we can get the value counts\n        # print(df_all.label.value_counts())\n        print(\"\\n\\nValue Counts:\")\n        print(df_all['label'].value_counts())  # Either this addressing of df_all.label.value_counts() works.\n\n        # Can even plot it with chaining once have counts\n        print(\"\\n\\nValue Count Bar Plot:\")\n        df_all.label.value_counts().plot.bar()\n        \n        # Print examples of each kind\n        test_df = df_all.groupby('label').sample(n=10)\n        print(\"\\n\\nExamples of each label kind:\")\n        print(test_df)\n        \n        # Check for any unclean data\n        print(\"\\n\\nAny null values?\")\n        print(df_all.isnull().any())\n        print(\"\\n\\nAny na values?\")\n        print(df_all.isna().any())\n                \n        # See how long the maximum headline is\n        # First test this on the 'label' column, we know 'clickbait' should be the longest \n        # (longer than 'news'), so should return '9'\n        # Just for debug purposes:\n        # print(\"\\n\\nMax Length of Labels:\")\n        # print(df_all['label'].apply(lambda x : len(x)).max())\n        # For some reason when I moved this same code to a function, it stopped working\n        # print(df_all['title'].apply(lambda x : len(x)).max())\n        \n        # Snippet to view the longest headline\n        lengths = df_all['title'].str.len()\n        argmax = np.where(lengths == lengths.max())[0]\n        print(\"\\n\\nLongest title (headline):\")\n        longest_title = df_all.iloc[argmax].title\n        print(longest_title)  # Prints:  Top stories Top stories Theresa May delays tri...\n                              # Looks like it's sorta a summary headline, and most won't be like this.\n        print(f\"\\nLength of longest title: {len(str(longest_title))}\")  # Prints '84'\n\n    \n    # Actually process and return a dataset\n    else:\n        # NOTE: We're not using the Test set for this notebook since we don't have the correct answers\n        # (this was originally created for a competition that I'm not planning to enter).\n        \n        # Strip out all but title and label\n        print(\"Processing dataset..\")\n        print(\"\\n\\nDropping all but 'title' and 'label' columns..\")\n        df_all = df_all[['title', 'label']]\n                                \n        # Delete any 'other' category, don't care about this for my purposes\n\n        # To do this, we get the *index* on the table where a condition is met.\n        # We then pass that into drop().  This can all be done on one line.\n\n        # Index the dataframe on a condition\n        # df['label'] == 'other'   ==> returns a 24,871 x 2 table like [[0, False]\n        #                                                               [1, True]\n        #                                                               [..., ...]\n        #                                                               [24870, False]\n        print(\"\\n\\nDropping data with 'other' labels (leaving just 'news' and 'clickbait')..\")\n        df_all = df_all.drop(df_all[df_all['label'] == 'other'].index)\n        print(\"\\n\\nNew processed dataframe:\")\n        print(df_all)  # 18398 rows total.  Used to be 24871, minus 6473 (this info doesn't count the headers!)\n        \n        # Convert the labels to class numbers\n        print(\"\\n\\nConverting labels to class numbers..\")\n        df_all['label'] = df_all['label'].replace({'news': 0, 'clickbait': 1})\n        \n        print(\"\\nClass counts:\")\n        print(df_all['label'].value_counts())\n                \n        # Dataset is imbalanced.  What's the problem?\n        # \n        # Say, for example, we had a dataset with 5% clickbait and 95% news.\n        # If we hardcoded a classifier to just always predict \"news\", it'd be right 95%\n        # of the time!  But obviously it could never predict clickbait. \n        # So we'll look at Precision and Recall for cases of imbalanced datasets, and\n        # combine those into an F1 score to get a fair comparison of \"accuracy\"\n\n        # NOTE: We could also discard data to make these balanced, but at the cost of losing valuable training data\n\n        # Let's shuffle it and split it\n        from sklearn.model_selection import train_test_split\n\n        # Splits the dataset, from Pandas Dataframe.  Returns a Pandas Dataframe still!\n        print(\"\\n\\nSplitting Train/Val dataframes..\")\n        train_pd_df, val_pd_df = train_test_split(df_all, test_size=0.1, shuffle=True, random_state=RANDOM_SEED)\n        \n        print(\"\\nTrain / Val dataframe shapes:\")\n        print(train_pd_df.shape, val_pd_df.shape)\n\n        # Inspect the dataframes\n        print(\"\\n\\nTrain head/tail:\")\n        print(train_pd_df.head())\n        print(train_pd_df.tail())\n\n        print(\"\\n\\nVal head/tail:\")\n        print(val_pd_df.head())\n        print(val_pd_df.tail())\n        \n        \n        # Convert to TensorFlow datasets\n        print(\"\\n\\nConverting to TensorFlow datasets..\")\n        train_ds = tf.data.Dataset.from_tensor_slices((train_pd_df['title'], train_pd_df['label']))\n        val_ds = tf.data.Dataset.from_tensor_slices((val_pd_df['title'], val_pd_df['label']))\n        \n        # Inspect a few\n        print(\"\\n\\nTraining examples:\")\n        for title, label in train_ds.take(10):\n            print(title.numpy().decode('utf-8'))\n            print(label.numpy())\n            \n        # Shuffle (redundant), batch, and prefetch them for performance\n        AUTOTUNE = tf.data.AUTOTUNE\n\n        print(\"\\n\\nBatching for performance..\")\n        train_ds = train_ds.shuffle(buffer_size=train_ds.cardinality()).batch(BATCH_SIZE).prefetch(1)  # Only shuffle Train (already shuffled anyway)\n        val_ds = val_ds.batch(BATCH_SIZE).prefetch(1)\n        \n        print(f\"\\n\\ntype(train_ds) = {type(train_ds)}\")\n        print(f\"\\n\\ntrain_ds.cardinality() = {train_ds.cardinality()}\")  # Prints 566.  18097 samples / 32 batchsize = 565.5 (rounds up)\n        print(f\"\\n\\nOne example batch ({BATCH_SIZE} samples):\")\n        for title, label in train_ds.take(1):\n            print(title)\n            print(label.numpy())\n        \n        return train_ds, val_ds","metadata":{"execution":{"iopub.status.busy":"2023-09-18T19:40:31.575725Z","iopub.execute_input":"2023-09-18T19:40:31.576481Z","iopub.status.idle":"2023-09-18T19:40:31.595488Z","shell.execute_reply.started":"2023-09-18T19:40:31.576449Z","shell.execute_reply":"2023-09-18T19:40:31.594422Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# First just look through the data before we create the dataset\nprocess_dataset(explore_only=True)","metadata":{"execution":{"iopub.status.busy":"2023-09-18T19:40:31.597646Z","iopub.execute_input":"2023-09-18T19:40:31.597998Z","iopub.status.idle":"2023-09-18T19:40:34.150981Z","shell.execute_reply.started":"2023-09-18T19:40:31.597974Z","shell.execute_reply":"2023-09-18T19:40:34.149968Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Inspecting the dataset..\n\nThe first thing I'll note is that we won't use anything in the dataset except the title and the label.  (What this dataset calls \"title\" I'll often refer to as the \"headline\").  The data also comes with an `id` field, which isn't useful for our case, and a `text` field, which contains large chunks, if not all, of the contents of the actual article.  \n\nIn our example case of building the Chrome extension for our fictitious company, *BaitBlock*, we want the Chrome extension to be able to determine if it's clickbait from the article title alone; we don't want the extension to have to sideload every article on the page.  Therefore we'll toss the `id` and the `text` fields and just look at `title`.  \n\nWhen we look at the dataset, we can see there are three unique labels, \"news\", \"clickbait\", and \"other\".  The \"other\" category is anything that doesn't fit nicely into the other two buckets.  One option would be to say \"clickbait vs. all\" and lump \"other\" with \"news\", and if you were truly building *BaitBlock* that would probably be a good idea, but for the sake of this demo project I've just decided to drop the \"other\"-labeled data altogether.  \n\nWe can also see from the bar graph that we're working with an imbalanced dataset, where we have about three times as many \"news\" labels as we have clickbait.  \n\n<div class=\"alert alert-warning\">\n  <strong>So what's the problem with an imbalanced dataset?</strong>\n  Imbalanced dataset can make it hard to fairly see how well your classifier performs.  For example, let's say you had a dataset with 5% clickbait and 95% news.  If you just hardcoded your classifier to always predict \"news,\" it'd be 95% accurate!  But it could obviously never detect clickbait and would be worthless for <i>BaitBlock</i>.  \n</div>\n\nTo resolve the issue with the imbalanced dataset, one option would be to discard data with the \"news\" label so that they were more balanced.  However, this comes at the cost of losing a large amount of valuable labeled training data.\n\nInstead, we'll look at the **Precision** and **Recall** of the classifier, which we'll discuss more later, and combine those into an **F1 Score**, which will more fairly judge our classifier's performance.\n\nNow that we've inspected the data, let's actually process it to get our Training and Validation sets.","metadata":{}},{"cell_type":"code","source":"# Now that we've inspected and understood the data, we can actually create the dataset\ntrain_ds, val_ds = process_dataset()","metadata":{"execution":{"iopub.status.busy":"2023-09-18T19:40:34.152673Z","iopub.execute_input":"2023-09-18T19:40:34.153083Z","iopub.status.idle":"2023-09-18T19:40:36.151289Z","shell.execute_reply.started":"2023-09-18T19:40:34.153045Z","shell.execute_reply":"2023-09-18T19:40:36.149979Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Processing the Dataset\n\nThe previous code actually processed and created our training and validation sets.  \n\nThis consisted of:\n1. Combining the original training and validation sets into one large set\n2. Dropping all columns but the two of interest\n3. Dropping the data with an \"other\" label, leaving just \"news\" and \"clickbait\"\n4. Converting the class labels from text to integers 0 or 1\n5. Shuffling the data and splitting 90% of it into the Training set and 10% into the Validation set\n6. Converting the datasets from a Pandas DataFrame into a TensorFlow DataSet.  This allows it to be batched, cached, and prefetched from disk during training for performance.\n\n👉 Note:  From here on out, a label of **1** will denote **clickbait** and a **0** will denote **news**","metadata":{}},{"cell_type":"markdown","source":"# Tokenization / TextVectorization Layer\n\nAt this point, you can see from the code block's output above, the format of the datasets is still as sentence strings.  We need to convert this into numbers so that the ML model can learn from it.  One way to do this is to use a Tokenizer.  However, the TensorFlow Tokenizer is deprecated because the library isn't optimized for GPUs.  Instead, we'll use the Keras TextVectorization layer, which will result in the same output format, but in a way that is optimized for running on GPUs.\n\nWe'll set a vocab size of the top 1000 most common words in the corpus, and a max headline length of 70 words.  Earlier when inspecting the dataset, we saw that most of the headlines should easily fit into this length.  If headlines are longer than this, they'll be truncated.  And for most that are shorter than this, they'll be padded with zeros so that every input tensor is of the same length.\n\nWhen we run the `.adapt()` method using the training set, we use a lambda function to pass in the training set and ignore the labels for the sake of tokenization.  Adapting on the data creates the vocabulary dictionary of the most common top 1000 words.  This dictionary is an index of strings to integers.","metadata":{}},{"cell_type":"code","source":"# Preprocess the text using TextVectorization layer from Keras\nVOCAB_SIZE = 1000 # Let's try just keeping the 1000 most popular words.  \n                   # Unlikely that rare words has big effect on if clickbait or not\n                   # and will train faster\n\n# We found earlier that the longest headline is 81 characters!\n# That one was a summary type headline, which is probably rare and I think it's safe\n# to truncate these to something reasonable for a headline.\nMAX_SEQUENCE_LENGTH = 70 # None should really be longer than this.  Rough guess based on about 300 chars and about 5 chars per word, since tokenizing at word level!\n\n# Splits on whitespace, lowercases and strips punctuation by default\ntext_vec_layer = keras.layers.TextVectorization(max_tokens=VOCAB_SIZE, output_sequence_length=MAX_SEQUENCE_LENGTH)  \n\n# Adapt on the data\ntext_vec_layer.adapt(train_ds.map(lambda title, label : title))  # map dataset to just the titles for purposes of adapting this layer\n\n","metadata":{"execution":{"iopub.status.busy":"2023-09-18T19:40:36.152601Z","iopub.execute_input":"2023-09-18T19:40:36.152920Z","iopub.status.idle":"2023-09-18T19:40:37.027466Z","shell.execute_reply.started":"2023-09-18T19:40:36.152891Z","shell.execute_reply":"2023-09-18T19:40:37.026622Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Let's look at an example tensor from the data\ndef vectorize_text(text, label):\n    text = tf.expand_dims(text, -1)\n    return text_vec_layer(text), label\n\n# retrieve a batch (of 32 reviews and labels) from the dataset\nprint(\"Example from dataset (1 is <UNK> word):\")\ntext_batch, label_batch = next(iter(train_ds))\nfirst_title, first_label = text_batch[0], label_batch[0]\nprint(\"Title\", first_title)\n# print(\"Label\", train_ds.class_names[first_label])\nprint(\"Vectorized review\", vectorize_text(first_title, first_label))\n\n# Look at some tokens and words they correspond to.  Lower rank is most popular,\n# except 1 or <UNK> token\nprint(\"\\n\\nExample tokens from vocab:\")\nprint(\"1 ---> \",text_vec_layer.get_vocabulary()[1])\nprint(\"2 ---> \",text_vec_layer.get_vocabulary()[2])\nprint(\"3 ---> \",text_vec_layer.get_vocabulary()[3])\nprint(\"4 ---> \",text_vec_layer.get_vocabulary()[4])\nprint(\"5 ---> \",text_vec_layer.get_vocabulary()[5])\nprint(\"100 ---> \",text_vec_layer.get_vocabulary()[100])\nprint(\"200 ---> \",text_vec_layer.get_vocabulary()[200])\nprint(\"500 ---> \",text_vec_layer.get_vocabulary()[500])\nprint(\"999 ---> \",text_vec_layer.get_vocabulary()[999])","metadata":{"execution":{"iopub.status.busy":"2023-09-18T19:40:37.028919Z","iopub.execute_input":"2023-09-18T19:40:37.029187Z","iopub.status.idle":"2023-09-18T19:40:37.195941Z","shell.execute_reply.started":"2023-09-18T19:40:37.029162Z","shell.execute_reply":"2023-09-18T19:40:37.194667Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"The previous code grabs a batch of training data, grabs the first training sample from within that batch, and then displays the tokenized/vectorized version of that string.  Note that we have to add another dimension to the data so it can process a batch of size one.  \n\nWe can see that the tokenizer has set the word `Apple` to token `413` in this dataset.  And the token `1` is for `<UNK>` tokens.  We also see that a large swath of the resulting tensor is just 0s for padding.\n\nLastly, we can use the `.get_vocabulary()` method on the vectorization layer to look up a particular index in the dictionary.","metadata":{}},{"cell_type":"markdown","source":"# Simple Model\n\nLet's start with a simple model that just uses an Embedding layer, followed by an LSTM, followed by a single-neuron Dense layer since this is a binary-classification problem.\n\n<div class=\"alert alert-info\">\n  <strong>Embedding Layer</strong>\n    It's not enough to just convert the input strings into integer tokens.  Passing these integer tokens straight into an LSTM would not have enough complexity to learn any patterns.  We need to also use an Embedding layer to turn the integer indexes into dense vectors that contain word representation.  These word representations are learned based on the training data and allow a richer representation for words than a simple number could ever contain.\n</div>\n\nNote: If you enable `train_simple_model`, the following code will run and this simple model will be trained and the loss curves plotted.  I've disabled it in the main version of this notebook as it wasn't the best performing.\n","metadata":{}},{"cell_type":"code","source":"# Create basic model\n\ndef get_model():\n    \n    model = keras.Sequential([\n        text_vec_layer,\n        # To support masking, you need to use VOCAB_SIZE+1 because that takes a token!\n        keras.layers.Embedding(VOCAB_SIZE + 1, EMBEDDING_SIZE, mask_zero=True, ), # input dim., output dim., turn on masking\n        keras.layers.LSTM(128),  # Try simple LSTM first\n        keras.layers.Dense(1, activation='sigmoid')  # Binary classification problem\n    ])\n    \n    model.compile(loss='binary_crossentropy',\n                 optimizer='nadam',\n                 metrics=['accuracy'])\n    \n    return model\n\nif train_simple_model:\n    model = get_model()\n    model.summary()","metadata":{"execution":{"iopub.status.busy":"2023-09-18T19:40:37.197238Z","iopub.execute_input":"2023-09-18T19:40:37.197528Z","iopub.status.idle":"2023-09-18T19:40:37.203901Z","shell.execute_reply.started":"2023-09-18T19:40:37.197502Z","shell.execute_reply":"2023-09-18T19:40:37.202864Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Try to train\nif train_simple_model:\n    epochs = 25\n    history = model.fit(train_ds,\n                       validation_data=val_ds,\n                       epochs=epochs,\n                       verbose=1)\n\n# This simple model will only reach about an 75% val accuracy, as it overfits to the training set","metadata":{"execution":{"iopub.status.busy":"2023-09-18T19:40:37.206471Z","iopub.execute_input":"2023-09-18T19:40:37.207129Z","iopub.status.idle":"2023-09-18T19:40:37.215010Z","shell.execute_reply.started":"2023-09-18T19:40:37.207090Z","shell.execute_reply":"2023-09-18T19:40:37.214064Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Plot the loss and accuracy curves for training and validation \nif train_simple_model:\n    fig, ax = plt.subplots(2,1)\n    ax[0].plot(history.history['loss'], color='b', label=\"Training loss\")\n    ax[0].plot(history.history['val_loss'], color='r', label=\"validation loss\",axes =ax[0])\n    legend = ax[0].legend(loc='best', shadow=True)\n\n    ax[1].plot(history.history['accuracy'], color='b', label=\"Training accuracy\")\n    ax[1].plot(history.history['val_accuracy'], color='r',label=\"Validation accuracy\")\n    legend = ax[1].legend(loc='best', shadow=True)","metadata":{"execution":{"iopub.status.busy":"2023-09-18T19:40:37.216095Z","iopub.execute_input":"2023-09-18T19:40:37.216360Z","iopub.status.idle":"2023-09-18T19:40:37.229585Z","shell.execute_reply.started":"2023-09-18T19:40:37.216338Z","shell.execute_reply":"2023-09-18T19:40:37.228825Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"The Simple Model overfits to the training data and is unable to achieve better than about 75% on the validation accuracy.","metadata":{}},{"cell_type":"markdown","source":"# Model with some Regularization techniques\n\nThe previous Simple Model is powerful enough to overfit to 97% accuracy on the training set, but unable to achieve better than about 75% validation accuracy, meaning we are overfitting.\n\nLet's try to add some regularizion techniques such as **dropout** to the model so that we can perform better generalization.  Here we have added dropout directly to each of the LSTMs as well as more dropout before going into the Dense layer.\n\n<div class=\"alert alert-info\">\n  <strong>Bi-Directional Layer</strong>\n    I also added a bi-directional layer to the model since a classifier has access to the whole sentence before making a determination.  Oftentimes a bi-directional layer can improve performance for sentiment analysis (like essentially this case).  For example, if the LSTM sees the word \"Apple\" in the sentence, it can use context from the remaining parts of the sentence to know if we're talking about the tech company, or the fruit.  However, this didn't add any benefit, and on hindsight it's not shocking that this didn't help greatly.  I mean, we're able to overfit the training data already, which shows that with padding masking enabled, the single-directional LSTM was plenty powerful enough.\n</div>","metadata":{}},{"cell_type":"code","source":"# The model is clearly overfitting.  Let's try some regularization techniques.\n\n# But also, it makes sense that a classifier should have access to the whole sentence\n# before it has to start forming its guesses, so let's make this bi-directional as well.\ndef get_model_reg():\n    \n    model = keras.Sequential([\n        text_vec_layer,\n        # To support masking, you need to use VOCAB_SIZE+1 because that takes a token!\n        keras.layers.Embedding(VOCAB_SIZE + 1, EMBEDDING_SIZE, mask_zero=True, ), # input dim., output dim., turn on masking\n        # Make bi-directional, and add dropout too\n        keras.layers.Bidirectional(keras.layers.LSTM(128, dropout=0.3)),  # Try simple LSTM first\n        keras.layers.Dropout(0.4),\n        keras.layers.Dense(1, activation='sigmoid')  # Binary classification problem\n    ])\n    \n    model.compile(loss='binary_crossentropy',\n                 optimizer='nadam',\n                 metrics=['accuracy'])\n    \n    return model\n\nif train_regularized_simple_model:\n    model = get_model_reg()\n    model.summary()","metadata":{"execution":{"iopub.status.busy":"2023-09-18T19:40:37.230751Z","iopub.execute_input":"2023-09-18T19:40:37.231606Z","iopub.status.idle":"2023-09-18T19:40:37.241594Z","shell.execute_reply.started":"2023-09-18T19:40:37.231568Z","shell.execute_reply":"2023-09-18T19:40:37.240713Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Try to train\nif train_regularized_simple_model:\n    epochs = 25\n    history = model.fit(train_ds,\n                       validation_data=val_ds,\n                       epochs=epochs,\n                       verbose=1)","metadata":{"execution":{"iopub.status.busy":"2023-09-18T19:40:37.242765Z","iopub.execute_input":"2023-09-18T19:40:37.243043Z","iopub.status.idle":"2023-09-18T19:40:37.251639Z","shell.execute_reply.started":"2023-09-18T19:40:37.243019Z","shell.execute_reply":"2023-09-18T19:40:37.250861Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if train_regularized_simple_model:\n    # Plot the loss and accuracy curves for training and validation \n    fig, ax = plt.subplots(2,1)\n    ax[0].plot(history.history['loss'], color='b', label=\"Training loss\")\n    ax[0].plot(history.history['val_loss'], color='r', label=\"validation loss\",axes =ax[0])\n    legend = ax[0].legend(loc='best', shadow=True)\n\n    ax[1].plot(history.history['accuracy'], color='b', label=\"Training accuracy\")\n    ax[1].plot(history.history['val_accuracy'], color='r',label=\"Validation accuracy\")\n    legend = ax[1].legend(loc='best', shadow=True)","metadata":{"execution":{"iopub.status.busy":"2023-09-18T19:40:37.252678Z","iopub.execute_input":"2023-09-18T19:40:37.253045Z","iopub.status.idle":"2023-09-18T19:40:37.265714Z","shell.execute_reply.started":"2023-09-18T19:40:37.253009Z","shell.execute_reply":"2023-09-18T19:40:37.264850Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Sadly, this model doesn't perform much better.  It does end up performing about 1% better on the validation set, so it's slightly more regularized, but still not good enough.  \n\n<div class=\"alert alert-info\">\n  <strong>Stemming or Stopwords Removal?</strong>\n    At this point I stopped to think some more about if we should be doing more text preprocessing before training these models.  In the end, I didn't think stemming would provide much benefit for the work it would take, and it's possible that removing stopwords can even break sentiment analysis (a higher-level class for this problem) by removing negating words like \"not\" or words that change subject/object assignment, such as removing \"to the.\"\n</div>\n\nIn the end, I decided that I might end up using a pretrained language model, which would already embed lots of contextual meaning into the words.  For example, \"right\" could mean \"right foot\" or \"correct\" or a \"right of passage.\"  So, if we end up fine-tuning a model on the full text, then more powerful models like BERT or Google's Universal Sentence Encoder will have been trained by keeping stop words in the corpus, and so removing them would create a data mismatch.","metadata":{}},{"cell_type":"markdown","source":"# Universal Sentence Encoder (Transformer based)\n\nLet's test that hypothesis.  Let's see if a pretrained language model, which already has a lot of contextual meanings baked into the word embeddings, can do better.  \n\n<div class=\"alert alert-warning\">\n  <strong>A transformer is a much more powerful model, and we're already overfitting, but the hope is that the extra word context can make it better at generalizing.</strong>\n</div>\n\nWe'll use the Universal Sentence Encoder, by Google, a transformer-based architecture based on [this paper](https://arxiv.org/abs/1803.11175) by Cer et al., 2018.  TensorFlow Hub makes it easy to download and use it directly as a layer in our model.  Note that for this model, we can also fine tune it (not true for all models).  If we couldn't fine tune it, we could still use it and only train our following dense layers.  If you enable the following code, you'll see that there are about 256M parameters to fine-tune!","metadata":{}},{"cell_type":"code","source":"# Let's try a more powerful model using a pretrained language model.  Already overfitting but want to see.\n# This model is based on the Universal Sentence Encoder, a model introduced in 2018 by Google and based \n# on the transformer architecture.\ndef get_USE_model():\n\n    import os\n    import tensorflow_hub as hub\n\n    os.environ[\"TFHUB_CACHE_DIR\"] = \"my_tfhub_cache\"  # Cache the download since it's 1 GB.  Doesn't help us too much since this is a VM, but still best practice!\n\n    model = keras.Sequential([\n        hub.KerasLayer(\"https://tfhub.dev/google/universal-sentence-encoder/4\",  # model to download, and documentation\n                   trainable=True,    # ability to fine-tune it\n                   dtype=tf.string,\n                   input_shape=[]),\n        keras.layers.Dense(64, activation='relu'),\n        keras.layers.Dense(1, activation='sigmoid')\n    ])\n    \n    model.compile(loss='binary_crossentropy',\n                 optimizer='nadam',\n                 metrics=['accuracy'])  # Same as all the previous models\n    \n    return model\n\n\nif train_USE_model:\n    model = get_USE_model()\n    model.summary()","metadata":{"execution":{"iopub.status.busy":"2023-09-18T19:40:37.266834Z","iopub.execute_input":"2023-09-18T19:40:37.267287Z","iopub.status.idle":"2023-09-18T19:40:37.277960Z","shell.execute_reply.started":"2023-09-18T19:40:37.267240Z","shell.execute_reply":"2023-09-18T19:40:37.276357Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Try to train\nif train_USE_model:\n    epochs = 25\n    history = model.fit(train_ds,\n                       validation_data=val_ds,\n                       epochs=epochs,\n                       verbose=1)","metadata":{"execution":{"iopub.status.busy":"2023-09-18T19:40:37.279780Z","iopub.execute_input":"2023-09-18T19:40:37.280787Z","iopub.status.idle":"2023-09-18T19:40:37.287024Z","shell.execute_reply.started":"2023-09-18T19:40:37.280756Z","shell.execute_reply":"2023-09-18T19:40:37.286128Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if train_USE_model:\n    # Plot the loss and accuracy curves for training and validation \n    fig, ax = plt.subplots(2,1)\n    ax[0].plot(history.history['loss'], color='b', label=\"Training loss\")\n    ax[0].plot(history.history['val_loss'], color='r', label=\"validation loss\",axes =ax[0])\n    legend = ax[0].legend(loc='best', shadow=True)\n\n    ax[1].plot(history.history['accuracy'], color='b', label=\"Training accuracy\")\n    ax[1].plot(history.history['val_accuracy'], color='r',label=\"Validation accuracy\")\n    legend = ax[1].legend(loc='best', shadow=True)","metadata":{"execution":{"iopub.status.busy":"2023-09-18T19:40:37.288138Z","iopub.execute_input":"2023-09-18T19:40:37.288789Z","iopub.status.idle":"2023-09-18T19:40:37.303776Z","shell.execute_reply.started":"2023-09-18T19:40:37.288760Z","shell.execute_reply":"2023-09-18T19:40:37.302592Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Unfortunately, the Universal Sentence Encoder just overfits even more and cannot generalize any better, despite having pre-trained word embeddings.","metadata":{}},{"cell_type":"markdown","source":"# Global Average Pooling Model\n\nWe've seen that our simple models are overfitting, and a more powerful Transformer-based model is overfitting as well.\n\nCan we find a model that is a little bit *less* powerful so that it doesn't overfit, but is still able to learn?\n\nAs it turns out, Global Average Pooling is another popular technique for classification problems.  How it works is it returns a fixed-length output vector for each example by averaging over the feature dimension.  For example, if the dimensionality of the data going *into* that layer were `(batch, sequence, embedding)`, like `(None, 70, 128)` in our case, then the tensors coming *out of* the Global Average Pooling layers will just be `(batch, embedding)`, or in our case, `(None, 128)`.  All of the embeddings for all 70 tokens in the input string have been averaged together!  For a classification problem like sentiment analysis, it's kindof like treating it as a bag-of-words model.","metadata":{}},{"cell_type":"code","source":"# Still overfitting.  Let's try a Global Average Pooling model, another popular architecture\n# for classification problems.  Averaging out all the word embeddings, similar to a bag of words model.\ndef get_model_avgpool():\n    \n    model = keras.Sequential([\n        text_vec_layer,\n        # To support masking, you need to use VOCAB_SIZE+1 because that takes a token!\n        keras.layers.Embedding(VOCAB_SIZE + 1, EMBEDDING_SIZE, mask_zero=True, ), # input dim., output dim., turn on masking\n        keras.layers.Dropout(0.25),\n        keras.layers.GlobalAveragePooling1D(),\n        keras.layers.Dropout(0.25),\n        keras.layers.Dense(1, activation='sigmoid')  # Binary classification problem\n    ])\n    \n    model.compile(loss='binary_crossentropy',\n                 optimizer='nadam',\n                 metrics=['accuracy'])\n    \n    return model\n\nif train_average_pooling_model:\n    model = get_model_avgpool()\n    model.summary()","metadata":{"execution":{"iopub.status.busy":"2023-09-18T19:41:16.184106Z","iopub.execute_input":"2023-09-18T19:41:16.184498Z","iopub.status.idle":"2023-09-18T19:41:16.374762Z","shell.execute_reply.started":"2023-09-18T19:41:16.184466Z","shell.execute_reply":"2023-09-18T19:41:16.373653Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Try to train\nif train_average_pooling_model:\n    epochs = 25\n    history = model.fit(train_ds,\n                       validation_data=val_ds,\n                       epochs=epochs,\n                       verbose=1)","metadata":{"execution":{"iopub.status.busy":"2023-09-18T19:47:04.868405Z","iopub.execute_input":"2023-09-18T19:47:04.868837Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if train_average_pooling_model:\n    # Plot the loss and accuracy curves for training and validation \n    fig, ax = plt.subplots(2,1)\n    ax[0].plot(history.history['loss'], color='b', label=\"Training loss\")\n    ax[0].plot(history.history['val_loss'], color='r', label=\"validation loss\",axes =ax[0])\n    legend = ax[0].legend(loc='best', shadow=True)\n\n    ax[1].plot(history.history['accuracy'], color='b', label=\"Training accuracy\")\n    ax[1].plot(history.history['val_accuracy'], color='r',label=\"Validation accuracy\")\n    legend = ax[1].legend(loc='best', shadow=True)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"This model using global average pooling generalizes much better than the other models, reaching about 81.5% classification accuracy on the validation set.\n\n⚠ But remember earlier when we said we had an unbalanced dataset and that therefore we couldn't trust accuracy alone?\n\nThis is where **F1 Scores** come into play.  Let's talk about that now.","metadata":{}},{"cell_type":"markdown","source":"---\n\n# Precision and Recall\n\nBefore we can talk about F1 Scores, we need to understand two other terms, **Precision** and **Recall**.\n\n### A Thought Experiment\n\nIn order to gain an intuitive understanding of these, let's escape the world of Machine Learning for a second and pretend for the moment that you are writing the firmware for a biometric safe.  Your code will determine if the safe opens based on the user scanning a fingerprint on a sensor on the front of the safe.  We don't know what's in the safe — could be cash and diamonds, could be guns, could be keys to a crypto wallet.  But it's your job to decide, *what threshold should you set to determine if a user is a match or not?*  After all, even if it's the correct person, a scan will usually not get every single measured minutiae on the fingerprint to match.  So you will need to say, if we get 25% match, is that good enough?  Or should it be 75%?  95 or 99%?  🤷‍♀️\n\n<div class=\"alert alert-info\">\n  <strong>The Precision-Recall Tradeoff</strong>\n  As you start to play with the threshold number for your biometric safe, you will quickly realize a tradeoff occurs between false positives and false negatives.  For example, let's say your safe is a handgun safe.  If you set a 10% threshold, then when the correct gun owner scans their finger, they will definitely get in.  But now it's more likely that the wrong person could gain access to the safe, for example, children in the house.  So you decide to set a super high threshold, say 99%.  Now the children are far less likely to gain access, but you increase the chance that the gun owner can't open the safe during a home invasion due to their sweaty fingers.. also not a good situation!\n</div>\n\nThis fundamental tradeoff is known as the Precision-Recall Tradeoff.  Whereas the **Precision, P** is a way of judging the accuracy of the true positives predicted (what percent of predicted positives were actually positive?), the **Recall, R** is a measure of sensitivity (what percentage of actual positives in the set were correctly detected?).  \n\nBack to our biometric safe example, setting a high threshold of 99% is an example of having high Precision (of all the fingerprints that opened the safe, nearly all of them will be true positives) at the cost of having low Recall (many valid fingerprints will be wrongly rejected).  \n\n# F1 Scores\n\nTo compare classifiers against each other, it's helpful to have a single metric instead of two.  For this reason, the **F1 Score** was invented to combine these two metrics in a way that makes sense.  The F1 Score is just the [harmonic mean](https://en.wikipedia.org/wiki/Harmonic_mean) of the two numbers, P and R.\n\nEven within using the F1 Score, there are a few different ways to do the calculation.  There is both the **Macro F1 Score** and the **Micro F1 Score**.  What's the difference?  The Macro score computes the F1 Score for each class individually, and then takes the arithmetic mean of those.  For example, it would mean computing an F1 Score on \"news\" alone, and then on \"clickbait\" alone, and then summing those F1 Scores and dividing by 2 (since in this case we only have two classes).  On the other hand, the Micro score is computed by aggregating all the contributions (e.g. true positives, false positives, false negatives) across all the classes.  In other words, the Macro score gives equal weights to each class, where the Micro scores gives equal weight to each sample.\n\n<div class=\"alert alert-warning\">\n  <strong>So which should we use?  🤔  Micro or Macro?</strong>\n</div>\n\nWell, in our case, the choice was made for us.  The original competition decided to use the Micro F1 Score as their metric.  **By using the same metric, I can compare my results to those on the leaderboard and make sure I'm in the ballpark.**\n\nBut say you weren't constrained by that.. then you pick a metric according to your objective for that particular problem.  If you care about overall accuracy and no classes are more important than others, then you should select Macro, as it weighs classes equally.  However, if a particular class is rare but very important, you would probably select Micro, as it weighs observations equally.  This makes Micro also the natural choice when you have an imbalanced dataset, otherwise the score will be weighted unfairly towards whichever class had more samples.  Also if the class labels are perfectly balanced, then both Micro and Macro averages will be identical.\n\nI believe it's for these reasons that the competition chose Micro F1-Score as its metric, given the imbalanced classes.\n\nLet's actually calculate the F1 Scores now.  We'll let SciKit-Learn handle the actual computation for us, but first we'll need to get our predictions into the right format.","metadata":{}},{"cell_type":"code","source":"# The main metric we're actually competing on is Micro-averaged F1 score, so let's calculate that.\n# SciKit-Learn has it built in.\nfrom sklearn.metrics import f1_score\n\n# model.predict() for this dataset will return a (n x 1) array of predictions for the dataset\n# These are probabilities of which class they belong to.  We can just convert them to 0 or 1\n# by snapping classes that are larger than 0.5 to a 1.\n\ny_hat = (model.predict(val_ds) > 0.5).astype(\"int32\")  # Snap predictions to binary class labels\n\nprint(\"y_hat:\")\nprint(y_hat)\nprint(f\"y_hat.shape: {y_hat.shape}\")\n\nprint(\"\\n\\n15 Headlines, True labels, and Predictions: \")\nfor i, (title, label) in enumerate(val_ds.unbatch()):\n    print(f\"idx: {i}   title: {title.numpy()}   label: {label.numpy()}  pred: {y_hat[i, 0]}\")\n    if i > 15:\n        break\n\nprint(\"\\n\\n10 first headlines with accurate predictions:\")\ncnt = 0\nfor i, (title, label) in enumerate(val_ds.unbatch()):\n    if label.numpy() == y_hat[i, 0]:\n        print(f\"idx: {i}   title: {title.numpy()}   label: {label.numpy()}  pred: {y_hat[i, 0]}\")\n        cnt += 1\n    if cnt > 10:\n        break\n\nprint(\"\\n\\n10 first headlines with WRONG predictions:\")\ncnt = 0\nfor i, (title, label) in enumerate(val_ds.unbatch()):\n    if label.numpy() != y_hat[i, 0]:\n        print(f\"idx: {i}   title: {title.numpy()}   label: {label.numpy()}  pred: {y_hat[i, 0]}\")\n        cnt += 1\n    if cnt > 10:\n        break\n\nprint(\"\\n\\n10 first News:\")\ncnt = 0\nfor i, (title, label) in enumerate(val_ds.unbatch()):\n    if label.numpy() == 0:\n        print(f\"idx: {i}   title: {title.numpy()}   label: {label.numpy()}  pred: {y_hat[i, 0]}\")\n        cnt += 1\n    if cnt > 10:\n        break\n\nprint(\"\\n\\n10 first Clickbaits:\")\ncnt = 0\nfor i, (title, label) in enumerate(val_ds.unbatch()):\n    if label.numpy() == 1:\n        print(f\"idx: {i}   title: {title.numpy()}   label: {label.numpy()}  pred: {y_hat[i, 0]}\")\n        cnt += 1\n    if cnt > 10:\n        break\n\n\n\nprint(\"\\n\\nBuilding y_true (ground truth)..\")\ny_true = np.zeros((y_hat.shape))  # Start by filling a zeroed array, of size (2011, 1)\n\n# Iterate over all the labels and fill y_true to match same shape as y_pred\n# Need to unbatch the samples to do one at a time\nfor i, (_, label) in enumerate(val_ds.unbatch()):\n    y_true[i, 0] = label.numpy()\n    \nprint(f\"y_true.shape: {y_true.shape}\")\n\n# And Finally!...\n# Calculate F1 score using Scikit-Learn\nf1_micro = f1_score(y_true, y_hat, average='micro')\nprint(f\"\\n\\nMicro-F1 Score: {f1_micro}\")","metadata":{"execution":{"iopub.status.busy":"2023-09-09T00:06:29.475028Z","iopub.execute_input":"2023-09-09T00:06:29.475746Z","iopub.status.idle":"2023-09-09T00:06:31.684643Z","shell.execute_reply.started":"2023-09-09T00:06:29.475710Z","shell.execute_reply":"2023-09-09T00:06:31.683647Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"---\n\n# Conclusion\n\nIf we run through the various models, we get these resulting Micro F1-Scores:\n\n| Model | Micro F1-Score |\n|-------|----------------|\n| LSTM w/Regularization | 0.7737 |\n| Universal Sentence Encoder | 0.7841 |\n| **Global Average Pooling** | **0.8125** |","metadata":{}},{"cell_type":"markdown","source":"The best-performing model uses Global Average Pooling, with a Micro F1-Score of 0.8125.  This is actually pretty good, given that the winning entry for the competition scored a 0.8639.\n\n## Label Consistency Limits Accuracy\n\nYou might be wondering, why is it hard to do much better on this problem?  \n\nI think the answer lies in the actual labels in the dataset.  I think there are many inconsistencies in the labeling.  Perhaps, for example, the dataset was labeled by many different people, all with varying opinions of what makes clickbait, clickbait?  If that were the case, it will be very hard to build an accurate classifier if the opinions of data labelers are somewhat inconsistent, given the subjective nature of this problem.  This isn't as hard-and-fast as labeling all bicycles in an image, for instance.  So, given that \"clickbait\" doesn't even have a strict definition, this is probably about the best results one could get.\n\nFor example, \"12 Oven-Baked Foil Packet Dinners To Try\" was labeled as \"news\" even though I'd probably personally label any listicles as \"clickbait.\"  Then again, listicles don't *have* to be clickbait, so long as they deliver the information that was promised in the headline.\n\n## Contrary Examples\n\nLet's take a look at some labeled examples that I disagree with (and again, this is now just *my* opinion!) to make my point:\n\n<span style=\"color:red\">The Top Beaches In The World, According To National Geographic</span>\nThis is labeled as clickbait in the data.  It might not exactly be newsworthy information, but I bet that article does exactly what it says on the tin.\n\n<span style=\"color:blue\">This Is How Differently Priced Spanx Can Actually Make Your Body Look</span>\nThis is labeled as news in the dataset.  I'd say this is classic clickbait.\n\n<span style=\"color:red\">National Photographic Portrait Prize finalists share the stories behind the pictures</span>\nThis sounds to me like a descriptive headline with no curiosity gap whatsoever, yet it's been labeled as clickbait.  Perhaps the labelers aren't familiar with National Geographic?\n\n<span style=\"color:blue\">Dude Gets Blazed With His Grandma for the First Time, Ends Up Talking About Porn</span>\nApparently the labelers think a guy talking about porn while high with his grandma is news.  I'd say clickbait.  **However**, even though I doubt the newsworthiness of this one, I could understand not labeling it as clickbait, since the article could be exactly about what it says in the headline.  \n\nI think this just further illustrates the subjectiveness and ambiguity of such a classifier.  If the labelers are not able to label the data consistently, that is going to severely limit the accuracy of any machine learning model.\n\nGood luck using this model to build your *BaitBlock* Chrome extension.  Might want to get a different dataset first though!\n\n## One last thing..\n\n<div class=\"alert alert-info\">\n    If you've enjoyed following along with me or have learned something new, ☝ <b>please consider UPVOTING this notebook!</b> 🔼 It helps others discover my notebook and encourages me to spend my time writing more of these.  Thank you!  😊\n</div>","metadata":{}},{"cell_type":"markdown","source":"💡 **You might also enjoy these other notebooks of mine as well:**\n\n**Natural Language Processing**\n* [Generate Amazon Book Reviews with Transformers](https://www.kaggle.com/code/quackaddict7/generate-amazon-book-reviews-with-transformers/)  \n* [Write Your Own CliffNotes (Book Text Summarizer)](https://www.kaggle.com/code/quackaddict7/write-your-own-cliffnotes-book-text-summarizer/)  \n* [Answering Questions from Product Reviews](https://www.kaggle.com/code/quackaddict7/answering-questions-from-product-reviews/)  \n* [Ingredient Standardization via Machine Translation](https://www.kaggle.com/code/quackaddict7/ingredient-standardization-via-machine-translation/)  \n* [What Kaggle WON'T Tell You About Your Notebooks](https://www.kaggle.com/code/quackaddict7/what-kaggle-won-t-tell-you-about-your-notebooks/)  \n\n**Computer Vision**\n* [Enhance, enhance, enhance! (image upscaling)](https://www.kaggle.com/code/quackaddict7/enhance-enhance-enhance-image-upscaling)  \n* [Detecting Vehicles in Traffic (Object Detection)](https://www.kaggle.com/code/quackaddict7/object-detection-detecting-vehicles-in-traffic/)  \n* [Legions of Lesions (Detecting Skin Cancer with Computer Vision)](https://www.kaggle.com/code/quackaddict7/legions-of-lesions-detecting-skin-cancer-with-cv/)  \n* [Creating Synthetic Wildfire Images with Unreal Engine (Blog Post)](https://joelwigton.com/synthetic-data-for-machine-learning-with-unreal-engine)  \n* [How I scored Top 5% on MNIST (without cheating!)](https://www.kaggle.com/code/quackaddict7/how-i-scored-top-5-on-mnist-without-cheating/)  \n\n**Machine Learning**\n* [Detecting Android Malware from App Permissions](https://www.kaggle.com/code/quackaddict7/detecting-android-malware-from-app-permissions/)  \n","metadata":{}}]}