# Advanced Topic Modeling with BERTopic

> BERTopic takes advantage of the superior language capabilities of (not yet sentient) transformer models and uses some other ML magic like UMAP and HDBSCAN to produce what is one of the most advanced techniques in language topic modeling today.

James Briggs · 2023-06-23

90% of the world’s data is unstructured. It is built by humans, for humans. That’s great for human consumption, but it is _very_ hard to organize when we begin dealing with the massive amounts of data abundant in today’s information age.

Organization is complicated because unstructured text data is not intended to be understood by machines, and having humans process this abundance of data is wildly expensive and _very slow_.

Fortunately, there is light at the end of the tunnel. More and more of this unstructured text is becoming accessible and understood by machines. We can now [search text based on](https://www.pinecone.io/learn/series/nlp/dense-vector-embeddings-nlp/) [meaning](https://www.pinecone.io/learn/series/nlp/dense-vector-embeddings-nlp/), identify the sentiment of text, extract entities, and much more.

[Transformers](https://www.pinecone.io/learn/transformers/) are behind much of this. These transformers are (unfortunately) not Michael Bay’s Autobots and Decepticons and (fortunately) not buzzing electrical boxes. Our NLP transformers lie somewhere in the middle, they’re not sentient Autobots (yet), but they can understand language in a way that existed only in sci-fi until a short few years ago.

Machines with a human-like comprehension of language are pretty helpful for organizing masses of unstructured text data. In machine learning, we refer to this task as _topic modeling_, the automatic clustering of data into particular topics.

BERTopic takes advantage of the superior language capabilities of these (not yet sentient) transformer models and uses some other ML magic like UMAP and HDBSCAN (more on these later) to produce what is one of the most advanced techniques in language topic modeling today.

---

## BERTopic at a Glance

[Video](https://www.youtube.com/watch?v=fb7LENb9eag)


We will dive into the details behind BERTopic [1], but before we do, let us see how we can use it and take a first glance at its components.

To begin, we need a dataset. We can download the dataset from HuggingFace datasets with:

```python
from datasets import load_dataset

data = load_dataset('jamescalam/python-reddit')
```

The dataset contains data extracted using the Reddit API from the _/r/python_ subreddit. The code used for this (and all other examples) can [be found here](https://github.com/pinecone-io/examples/tree/72549a14ec5fcd0befd6c791386e84fc9af31639/learn/experimental/algos-and-libraries/bertopic).

Reddit thread contents are found in the `selftext` feature. Some are empty or short, so we remove them with:

```python
data = data.filter(
    lambda x: True if len(x['selftext']) > 30 else 0
)
```

We perform topic modeling using the `BERTopic` library. The _“basic”_ approach requires just a few lines of code.

```
from bertopic import BERTopic
from sklearn.feature_extraction.text import CountVectorizer

# we add this to remove stopwords
vectorizer_model = CountVectorizer(ngram_range=(1, 2), stop_words="english")

model = BERTopic(
    vectorizer_model=vectorizer_model,
    language='english', calculate_probabilities=True,
    verbose=True
)
topics, probs = model.fit_transform(text)
```

From `model.fit_transform` we return two lists:

- `topics` contains a one-to-one mapping of inputs to their modeled _topic_ (or cluster).
- `probs` contains a list of probabilities that an input belongs to their assigned topic.

We can then view the topics using `get_topic_info`.

```json
{
  "_key": "4a1290e506cb",
  "_type": "colabBlock",
  "jsonContent": "{\n \"cells\": [\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 5,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/html\": [\n       \"<div>\\n\",\n       \"<style scoped>\\n\",\n       \"    .dataframe tbody tr th:only-of-type {\\n\",\n       \"        vertical-align: middle;\\n\",\n       \"    }\\n\",\n       \"\\n\",\n       \"    .dataframe tbody tr th {\\n\",\n       \"        vertical-align: top;\\n\",\n       \"    }\\n\",\n       \"\\n\",\n       \"    .dataframe thead th {\\n\",\n       \"        text-align: right;\\n\",\n       \"    }\\n\",\n       \"</style>\\n\",\n       \"<table border=\\\"1\\\" class=\\\"dataframe\\\">\\n\",\n       \"  <thead>\\n\",\n       \"    <tr style=\\\"text-align: right;\\\">\\n\",\n       \"      <th></th>\\n\",\n       \"      <th>Topic</th>\\n\",\n       \"      <th>Count</th>\\n\",\n       \"      <th>Name</th>\\n\",\n       \"    </tr>\\n\",\n       \"  </thead>\\n\",\n       \"  <tbody>\\n\",\n       \"    <tr>\\n\",\n       \"      <th>0</th>\\n\",\n       \"      <td>-1</td>\\n\",\n       \"      <td>196</td>\\n\",\n       \"      <td>-1_python_code_data_using</td>\\n\",\n       \"    </tr>\\n\",\n       \"    <tr>\\n\",\n       \"      <th>1</th>\\n\",\n       \"      <td>0</td>\\n\",\n       \"      <td>68</td>\\n\",\n       \"      <td>0_image_ampx200b_code_images</td>\\n\",\n       \"    </tr>\\n\",\n       \"    <tr>\\n\",\n       \"      <th>2</th>\\n\",\n       \"      <td>1</td>\\n\",\n       \"      <td>58</td>\\n\",\n       \"      <td>1_python_learning_programming_just</td>\\n\",\n       \"    </tr>\\n\",\n       \"    <tr>\\n\",\n       \"      <th>3</th>\\n\",\n       \"      <td>2</td>\\n\",\n       \"      <td>44</td>\\n\",\n       \"      <td>2_python_django_flask_library</td>\\n\",\n       \"    </tr>\\n\",\n       \"    <tr>\\n\",\n       \"      <th>4</th>\\n\",\n       \"      <td>3</td>\\n\",\n       \"      <td>32</td>\\n\",\n       \"      <td>3_link_title_thumbnail_datepublished</td>\\n\",\n       \"    </tr>\\n\",\n       \"    <tr>\\n\",\n       \"      <th>5</th>\\n\",\n       \"      <td>4</td>\\n\",\n       \"      <td>28</td>\\n\",\n       \"      <td>4_package_python_like_slap</td>\\n\",\n       \"    </tr>\\n\",\n       \"    <tr>\\n\",\n       \"      <th>6</th>\\n\",\n       \"      <td>5</td>\\n\",\n       \"      <td>27</td>\\n\",\n       \"      <td>5_spectra_space_asteroid_training</td>\\n\",\n       \"    </tr>\\n\",\n       \"    <tr>\\n\",\n       \"      <th>7</th>\\n\",\n       \"      <td>6</td>\\n\",\n       \"      <td>26</td>\\n\",\n       \"      <td>6_make_project ideas_ideas_comment</td>\\n\",\n       \"    </tr>\\n\",\n       \"    <tr>\\n\",\n       \"      <th>8</th>\\n\",\n       \"      <td>7</td>\\n\",\n       \"      <td>23</td>\\n\",\n       \"      <td>7_log_logging_use_conn</td>\\n\",\n       \"    </tr>\\n\",\n       \"    <tr>\\n\",\n       \"      <th>9</th>\\n\",\n       \"      <td>8</td>\\n\",\n       \"      <td>21</td>\\n\",\n       \"      <td>8_questions_thread_response_python</td>\\n\",\n       \"    </tr>\\n\",\n       \"  </tbody>\\n\",\n       \"</table>\\n\",\n       \"</div>\"\n      ],\n      \"text/plain\": [\n       \"   Topic  Count                                  Name\\n\",\n       \"0     -1    196             -1_python_code_data_using\\n\",\n       \"1      0     68          0_image_ampx200b_code_images\\n\",\n       \"2      1     58    1_python_learning_programming_just\\n\",\n       \"3      2     44         2_python_django_flask_library\\n\",\n       \"4      3     32  3_link_title_thumbnail_datepublished\\n\",\n       \"5      4     28            4_package_python_like_slap\\n\",\n       \"6      5     27     5_spectra_space_asteroid_training\\n\",\n       \"7      6     26    6_make_project ideas_ideas_comment\\n\",\n       \"8      7     23                7_log_logging_use_conn\\n\",\n       \"9      8     21    8_questions_thread_response_python\"\n      ]\n     },\n     \"execution_count\": 5,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"freq = model.get_topic_info()\\n\",\n    \"freq.head(10)\"\n   ]\n  }\n ],\n \"metadata\": {\n  \"interpreter\": {\n   \"hash\": \"e81a84c338879f0412495ea98350e80595740634d3ce0fba8d30f35c60f1a4c3\"\n  },\n  \"kernelspec\": {\n   \"display_name\": \"Python 3.8.12 ('stoic')\",\n   \"language\": \"python\",\n   \"name\": \"python3\"\n  },\n  \"language_info\": {\n   \"codemirror_mode\": {\n    \"name\": \"ipython\",\n    \"version\": 3\n   },\n   \"file_extension\": \".py\",\n   \"mimetype\": \"text/x-python\",\n   \"name\": \"python\",\n   \"nbconvert_exporter\": \"python\",\n   \"pygments_lexer\": \"ipython3\",\n   \"version\": \"3.8.12\"\n  },\n  \"orig_nbformat\": 4\n },\n \"nbformat\": 4,\n \"nbformat_minor\": 2\n}"
}
```

The top `-1` topic is typically assumed to be irrelevant, and it usually contains stop words like _“the”_, _“a”_, and _“and”_. However, we removed stop words via the `vectorizer_model` argument, and so it shows us the _“most generic”_ of topics like _“Python”_, _“code”_, and _“data”_.

The library has several built-in visualization methods like `visualize_topics`, `visualize_hierarchy`, and `visualize_barchart`.

![BERTopic’s visualize_hierarchy](https://cdn.sanity.io/images/vr8gru94/production/413b1148ea189a25a5532fcd995958d3a436bf58-2246x678.png)


These represent the surface level of the BERTopic library, which has excellent documentation, so we will not rehash that here. Instead, let’s try and understand _how_ BERTopic works.

## Overview

There are _four_ key components used in BERTopic [2], those are:

- A transformer embedding model
- UMAP dimensionality reduction
- HDBSCAN clustering
- Cluster tagging using c-TF-IDF

We already did _all_ of this in those few lines of BERTopic code; everything is just abstracted away. However, we can optimize the process by understanding the essentials of each component. This section will work through each component _without_ BERTopic, and learn how they work before returning to BERTopic at the end.

### Transformer Embedding

BERTopic supports several libraries for encoding our text to dense vector embeddings. If we build poor quality embeddings, nothing we do in the other steps will be able to help us, so it is _very important_ that we choose a suitable embedding model from one of the supported libraries, which include:

- Sentence Transformers
- Flair
- SpaCy
- Gensim
- USE (from TF Hub)

Of the above, the _Sentence Transformers_ library provides the most extensive library of high-performing [sentence embedding models](https://www.pinecone.io/learn/series/nlp/sentence-embeddings/). They can be found on HuggingFace Hub by searching for _“sentence-transformers”_.

![HuggingFace hub screenshot](https://cdn.sanity.io/images/vr8gru94/production/e6e98a88d69b58dddded76c32331b70606e3cddd-1920x880.png)


The first result of this search is `sentence-transformers/all-MiniLM-L6-v2`, this is a popular high-performing model that creates _384_-dimensional sentence embeddings.

To initialize the model and encode our Reddit topics data, we first `pip install sentence-transformers` and then write:

```json
{
  "_key": "484f12bd13c9",
  "_type": "colabBlock",
  "jsonContent": "{\n \"cells\": [\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 5,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"SentenceTransformer(\\n\",\n       \"  (0): Transformer({'max_seq_length': 256, 'do_lower_case': False}) with Transformer model: BertModel \\n\",\n       \"  (1): Pooling({'word_embedding_dimension': 384, 'pooling_mode_cls_token': False, 'pooling_mode_mean_tokens': True, 'pooling_mode_max_tokens': False, 'pooling_mode_mean_sqrt_len_tokens': False})\\n\",\n       \"  (2): Normalize()\\n\",\n       \")\"\n      ]\n     },\n     \"execution_count\": 5,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"from sentence_transformers import SentenceTransformer\\n\",\n    \"\\n\",\n    \"model = SentenceTransformer('all-MiniLM-L6-v2')\\n\",\n    \"model\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 6,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stderr\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"100%|██████████| 195/195 [08:51<00:00,  2.73s/it]\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"import numpy as np\\n\",\n    \"from tqdm.auto import tqdm\\n\",\n    \"\\n\",\n    \"batch_size = 16\\n\",\n    \"\\n\",\n    \"embeds = np.zeros((n, model.get_sentence_embedding_dimension()))\\n\",\n    \"\\n\",\n    \"for i in tqdm(range(0, n, batch_size)):\\n\",\n    \"    i_end = min(i+batch_size, n)\\n\",\n    \"    batch = data['selftext'][i:i_end]\\n\",\n    \"    batch_embed = model.encode(batch)\\n\",\n    \"    embeds[i:i_end,:] = batch_embed\"\n   ]\n  }\n ],\n \"metadata\": {\n  \"interpreter\": {\n   \"hash\": \"e81a84c338879f0412495ea98350e80595740634d3ce0fba8d30f35c60f1a4c3\"\n  },\n  \"kernelspec\": {\n   \"display_name\": \"Python 3.8.12 ('stoic')\",\n   \"language\": \"python\",\n   \"name\": \"python3\"\n  },\n  \"language_info\": {\n   \"codemirror_mode\": {\n    \"name\": \"ipython\",\n    \"version\": 3\n   },\n   \"file_extension\": \".py\",\n   \"mimetype\": \"text/x-python\",\n   \"name\": \"python\",\n   \"nbconvert_exporter\": \"python\",\n   \"pygments_lexer\": \"ipython3\",\n   \"version\": \"3.8.12\"\n  },\n  \"orig_nbformat\": 4\n },\n \"nbformat\": 4,\n \"nbformat_minor\": 2\n}"
}
```

Here we have encoded our text in batches of `16`. Each batch is added to the `embeds` array. Once we have all of the [sentence embeddings](https://www.pinecone.io/learn/series/nlp/sentence-embeddings/) in `embeds` we’re ready to move on to the next step.

### Dimensionality Reduction

After building our embeddings, BERTopic compresses them into a lower-dimensional space. This means that our 384-dimensional vectors are transformed into two/three-dimensional vectors.

We can do this because 384 dimensions are _a lot_, and it is unlikely that we really need that many dimensions to represent our text [4]. Instead, we attempt to _compress_ that information into two or three dimensions.

We do this so that the following HDBSCAN clustering step can be done more efficiently. Performing the clustering step with 384-dimensions would be desperately slow [5].

Another benefit is that we can visualize our data; this is incredibly helpful when assessing whether our data can be clustered. Visualization also helps when tuning the dimensionality reduction parameters.

To help us understand dimensionality reduction, we will start with a 3D representation of the world. You can find [the code for this part here](https://github.com/pinecone-io/examples/tree/72549a14ec5fcd0befd6c791386e84fc9af31639/learn/experimental/algos-and-libraries/bertopic).

```json
{
  "_key": "2e905e320d59",
  "_type": "plotlyPlot",
  "asset": {
    "_ref": "file-a7e0916e751d0da09777b975052e47fbbe48b88c-json",
    "_type": "reference"
  },
  "caption": "3D scatter plot of points",
  "sourceLink": "https://huggingface.co/datasets/jamescalam/world-cities-geo",
  "sourceName": "jamescalam/world-cities-geo dataset"
}
```

We can apply many dimensionality reduction techniques to this data; two of the most popular choices are PCA and t-SNE.

```json
{
  "_key": "80a73336e029",
  "_type": "plotlyPlot",
  "asset": {
    "_ref": "file-4acb0a3fe10f5ad0811fc3f1a8c3630d9e165ba1-json",
    "_type": "reference"
  },
  "caption": "Our 2D world reduced using PCA."
}
```

PCA works by preserving _larger distances_ (using mean squared error). The result is that the _global structure_ of data is usually preserved [6]. We can see that behavior above as each continent is grouped with its neighboring continent(s). When we have easily distinguishable clusters in datasets, this can be good, but it performs poorly for more nuanced data where _local structures_ are important.

```json
{
  "_key": "f921773e73a0",
  "_type": "plotlyPlot",
  "asset": {
    "_ref": "file-d322623b3ba09e5375a037b55ceb7e3d14998c7c-json",
    "_type": "reference"
  },
  "caption": "2D Earth reduced using t-SNE."
}
```

t-SNE is the opposite; it preserves _local structures_ rather than _global_. This localized focus results from t-SNE building a graph, connecting all of the nearest points. These local structures can indirectly suggest the global structure, but they are not strongly captured.

---

PCA focuses on preserving _dissimilarity_ whereas t-SNE focuses on preserving _similarity_.

---

Fortunately, we can capture the best of both using a lesser-known technique called **U**niform **M**anifold **A**pproximation and **P**roduction (UMAP).

We can apply UMAP in Python using the UMAP library, installed using `pip install umap-learn`. To map to a 3D or 2D space using the default UMAP parameters, all we write is:

```python
import umap

fit = umap.UMAP(n_components=3)  # by default this is 2
u = fit.fit_transform(data)
```

The UMAP algorithm can be fine-tuned using several parameters. Still, the simplest and most effective tuning can be achieved with just the `n_neighbors` parameter.

For each datapoint, UMAP searches through other points and identifies the **k**th nearest neighbors [3]. It is **k**, controlled by the `n_neighbors` parameter.

[Video](https://d33wubrfki0l68.cloudfront.net/86a053139b81f9a4840265eedb8a01ef1e8c696e/58e51/images/bertopic-9.mp4)


Where we have many points (high-density regions), the distance between our point and its **k**th nearest neighbor is usually smaller. In low-density regions with fewer points, the distance will be much greater.

![Umap Density](https://cdn.sanity.io/images/vr8gru94/production/dc1ccacda740c27ecc3ab5fea39eec1090e23c69-1632x888.png)


UMAP will attempt to preserve distances to the **k**th nearest point is what UMAP attempts to preserve when shifting to a lower dimension.

By increasing `n_neighbors` we can preserve more global structures, whereas a lower `n_neighbors` better preserves local structures.

![n_neighbors](https://cdn.sanity.io/images/vr8gru94/production/59f75da46ccff6b9ef101fa397ba2c4f880d4691-2435x1560.png)


Compared to other dimensionality reduction techniques like PCA or t-SNE, finding a good `n_neighbors` value allows us to preserve _both_ local and global structures relatively well.

Applying it to our 3D globe, we can see neighboring countries remain neighbors. At the same time, continents are placed correctly (with North-South inverted), and islands are separated from continents. We even have what seems to be the Spanish Peninsula in “western Europe”.

```json
{
  "_key": "eea99dfe7c8a",
  "_type": "plotlyPlot",
  "asset": {
    "_ref": "file-412f0377965494aa21fc5118da465dc83bd88612-json",
    "_type": "reference"
  },
  "caption": "The UMAP-reduced Earth."
}
```

UMAP maintains distinguishable features that are not preserved by PCA and a better global structure than t-SNE. This is a great overall example of where the benefit of UMAP lies.

UMAP can also be used as a supervised dimensionality reduction method by passing labels to the `target` argument if we have labeled data. It is possible to produce even more meaningful structures using this supervised approach.

With all that in mind, let us apply UMAP to our Reddit topics data. Using `n_neighbors` of `3`-`5` seems to work best. We can add `min_dist=0.05` to allow UMAP to place points closer together (the default value is `1.0`); this helps us separate the three _similar_ topics from _r/Python_, _r/LanguageTechnology_, and _r/pytorch_.

```python
fit = umap.UMAP(n_neighbors=3, n_components=3, min_dist=0.05)
u = fit.fit_transform(embeds)
```

```json
{
  "_key": "91bf8dcf4a93",
  "_type": "plotlyPlot",
  "asset": {
    "_ref": "file-770d8b9f93fecbc6523bbbfbac735b734b093ae9-json",
    "_type": "reference"
  },
  "caption": "Reddit topics data reduced to 3D space using UMAP."
}
```

With our data reduced to a lower-dimensional space and topics easily visually identifiable, we’re in an excellent spot to move on to clustering.

### HDBSCAN Clustering

We have visualized the UMAP reduced data using the existing _sub_ feature to color our clusters. It looks pretty, but we don’t usually perform topic modeling to label already labeled data. If we assume that we have no existing labels, our UMAP visual will look like this:

```json
{
  "_key": "6a16dc0646b4",
  "_type": "plotlyPlot",
  "asset": {
    "_ref": "file-0d5d40cc6e6d052f72997a5fce44c3cbbb0d6c16-json",
    "_type": "reference"
  },
  "caption": "UMAP reduced cities data, we can distinguish many clusters/continents, but it is much more difficult without label coloring."
}
```

Now let us look at how HDBSCAN is used to cluster the (now) low-dimensional vectors.

Clustering methods can be broken into flat or hierarchical _and_ centroid or density-based techniques [5]. Each of which has its own benefits and drawbacks.

Flat or hierarchical focuses simply on whether there is (or is not) a hierarchy in the clustering method. For example, we may (ideally) view our graph hierarchy as moving from continents to countries to cities. These methods allow us to view a given hierarchy and try to identify a logical “cut” along the tree.

![Hierarchical techniques begin from one large cluster and split this cluster into smaller and smaller parts and try to find the ideal number of clusters in the hierarchy.](https://cdn.sanity.io/images/vr8gru94/production/6dbf40355a6f44b18da235cdd1a701f7372f39fb-2843x1776.png)


The other split is between centroid-based or density-based clustering. That is clustering based on proximity to a centroid or clustering based on the density of points. Centroid-based clustering is ideal for _“spherical”_ clusters, whereas density-based clustering can handle more irregular shapes _and_ identify outliers.

![Centroid-based clustering (left) vs density-based clustering (right).](https://cdn.sanity.io/images/vr8gru94/production/a97502796c9ee48d227eab34a177e246cec4da0e-1920x820.png)


HDBSCAN is a hierarchical, density-based method. Meaning we can benefit from the easier tuning and visualization of hierarchical data, handle irregular cluster shapes, _and_ identify outliers.

When we first apply HDBSCAN clustering to our data, we will return _many_ tiny clusters, identified by the red _circles_ in the _condensed tree plot_ below.

```json
{
  "_key": "25453d583d75",
  "_type": "colabBlock",
  "jsonContent": "{\n \"cells\": [\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 22,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"HDBSCAN()\"\n      ]\n     },\n     \"execution_count\": 22,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"import hdbscan\\n\",\n    \"\\n\",\n    \"clusterer = hdbscan.HDBSCAN()\\n\",\n    \"clusterer.fit(u)\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 23,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"<AxesSubplot:ylabel='$\\\\\\\\lambda$ value'>\"\n      ]\n     },\n     \"execution_count\": 23,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    },\n    {\n     \"data\": {\n      \"image/png\": \"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\",\n      \"text/plain\": [\n       \"<Figure size 432x288 with 2 Axes>\"\n      ]\n     },\n     \"metadata\": {\n      \"needs_background\": \"light\"\n     },\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"clusterer.condensed_tree_.plot(select_clusters=True)\"\n   ]\n  }\n ],\n \"metadata\": {\n  \"interpreter\": {\n   \"hash\": \"e81a84c338879f0412495ea98350e80595740634d3ce0fba8d30f35c60f1a4c3\"\n  },\n  \"kernelspec\": {\n   \"display_name\": \"Python 3.8.12 ('stoic')\",\n   \"language\": \"python\",\n   \"name\": \"python3\"\n  },\n  \"language_info\": {\n   \"codemirror_mode\": {\n    \"name\": \"ipython\",\n    \"version\": 3\n   },\n   \"file_extension\": \".py\",\n   \"mimetype\": \"text/x-python\",\n   \"name\": \"python\",\n   \"nbconvert_exporter\": \"python\",\n   \"pygments_lexer\": \"ipython3\",\n   \"version\": \"3.8.12\"\n  },\n  \"orig_nbformat\": 4\n },\n \"nbformat\": 4,\n \"nbformat_minor\": 2\n}"
}
```

_The condensed tree plot shows the drop-off of points into outliers and the splitting of clusters as the algorithm scans by increasing lambda values._

_HDBSCAN chooses the final clusters based on their size and persistence over varying lambda values. The tree’s thickest, most persistent “branches” are viewed as the most stable and, therefore, best candidates for clusters._

---

These clusters are not very useful because the _default_ minimum number of points needed to “create” a cluster is just `5`. Given our ~3K points dataset where we aim to produce ~4 subreddit clusters, this is small. Fortunately, we can increase this threshold using the `min_cluster_size` parameter.

```json
{
  "_key": "693394a42b53",
  "_type": "colabBlock",
  "jsonContent": "{\n \"cells\": [\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 28,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"<AxesSubplot:ylabel='$\\\\\\\\lambda$ value'>\"\n      ]\n     },\n     \"execution_count\": 28,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    },\n    {\n     \"data\": {\n      \"image/png\": \"iVBORw0KGgoAAAANSUhEUgAAAYsAAADxCAYAAAA6LpuYAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjQuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/MnkTPAAAACXBIWXMAAAsTAAALEwEAmpwYAAAyTUlEQVR4nO3deZwU5bXw8d+ZYUcQgUGQRUiCXsHdCeh1XwFjouaNeVHjkmskGjR4441i4hYNcYnGxMTlkgTFmEhIXkRUFhFxSURlUdmMOgpBAgoICqIgM3PeP56qTDP0Uj1d1dXVfb6fz/Opnupanp6BOv3soqoYY4wx2VTFnQFjjDGlz4KFMcaYnCxYGGOMycmChTHGmJwsWBhjjMnJgoUxxpicihIsRGS4iLwpInUiMjbN+yIid3vvLxaRQ4uRL2OMMcFEHixEpBq4BxgBDALOFpFBzQ4bAQz00ijgvqjzZYwxJrhilCyGAHWq+q6qfg5MAk5vdszpwEPqvAR0EZFeRcibMcaYAFoV4R69gfdSfl4NDA1wTG9gbepBIjIKV/Jg0KBBhy1btiz0zJaLxvf3iTsLBanq+VbcWTDlRQq9wLDjO+qHGxsCHbtw8fZZqjq80HuWkmIEi3R/pOZzjAQ5BlUdD4wHqK2ttXlKjDFFs2FjAy/P6hPo2Na93ukecXaKrhjBYjXQN+XnPsCaFhxjjDExUhq0Me5MxKYYbRbzgYEiMkBE2gAjgWnNjpkGnO/1ijoc+FhV1za/kDHGxEWBRjRQKkeRlyxUtV5ELgNmAdXABFVdJiKXeO/fD0wHTgXqgE+Bb0edL2OMyVcjlVuyKEY1FKo6HRcQUvfdn/JagdHFyIsxxrSEouwIoRpKRNoBzwNtcc/gv6rqDSLSFfgz0B9YCXxTVTd551wDXAQ0AN9X1Vne/sOAB4H2uGfsGI1o3QkbwW2MMQEo0IAGSjlsB05Q1YOAg4HhXvX7WGCOqg4E5ng/441LGwkMBoYD93rj18CNSRtF0zi1yHpgWbAwxpiAwmiz8MaTfeL92NpLihtvNtHbPxE4w3t9OjBJVber6gpcdf0QbyxaZ1Wd55UmHko5J3QWLIwxJgAFGlQDpVxEpFpEXgPWAbNV9WVgT79jj7ft4R2eaRxab+918/2RKEqbhTHGlIM8Wiy6i8iClJ/He+PEAFDVBuBgEekCPCoi+2e5VqZxaIHGp4XFgoUxxgSgwdojfBtUtTbnNVU/EpFncW0NH4hIL1Vd61UxrfMOyzQObbX3uvn+SFg1lDHGBKAKOwKmbESkxitRICLtgZOAf+DGm13gHXYB8Jj3ehowUkTaisgAXEP2K15V1RYROVxEBDg/5ZzQWcnCGGMCERoKn2IKoBcw0evRVAVMVtUnRGQeMFlELgJWAWcBeOPSJgPLgXpgtFeNBXApTV1nZ3gpEhYsjDEmAAUaQ2gRUNXFwCFp9n8InJjhnHHAuDT7FwDZ2jtCY8HCGGMCCqlkkUgWLIwxJgA3KM+ChSkzn+n2uLPQYh17/TPuLBizCwV2aOX2CbJgEaYPP4Rp0+Dzz+G442DffePOkTEmJIrQUMEdSC1YhOVXv4Lrr4fNm93PVVXwX/8Fv/41tGsXb96MMaFo1MqthqrcMBmm226DK65wgeK44+Css0AEfvc7GDkSduyIO4fGmAL5bRZBUjmyYFGoJ5+EsWNdcJg4EebOhcmTYf582GMPeOwxuO66uHNpjCmY0KBVgVI5Ks9PVSxbt8L3vude33ILnH9+03uHHOLaL0TgzjthyZJ48miMCYVbKa8qUCpH5fmpiuX222HVKhcYrrxy1/ePOsoFk/p6+P73i58/Y0xoVIXPtTpQKkfWwN1Sn30G99zjXv/yl9Aqw69y3Dj4wx/g2Wdh0SI49NBi5dDkY+tWWLrUtTt9+qlLrVpBhw7Qvj307An/8R+u44KpWI1l2h4RhAWLlvrjH11X2dpaOProzMftvjtcdBHcdZfrMTVxYuZjTXGowrvvwrx5TWnxYmhoyH7e7rvD0KFwxBEuDR0KXboUJcsmfq6Bu3K/LFiwaAlVV5oA1wtKcnzbuPxyFygeecT1nOrZM+ocmnTeesu1Hz36KKxfv/N71dVw0EFQU+NKEu3bu+Dx2WeulPHOO/Dee/DUUy6B+7sPHgwXX+y+EHTsWPzPZIpIyrbxOggLFi3xzDOwbBnstZfrJpvLgAFwxhkwZQrcdx/85CeRZ9GkeOkl1740daoL9OCCgl9COOIIV0LM9bD/1792Lo0sXOiqrsaMcX/T0aPhssugR4/s1zGJ5DdwV6rK/eSF+Mtf3PY734E2bYKdc+mlbvvXv0aTJ7OzxkZ44gk45hgXDB59FFq3dn+zJUvggw9ct+axY+HYY4OVCnr3hm98w5VOXnzRtW9MmQKHHw4bN8LNN8Pee7tODXV10X9GU3QNKoFSOSpKsBCR4SLypojUicjYNO+fKyKLvfSiiBxUjHy1iCrM8KaMP+204OcdcwzsthssX+56UJnorF4Nxx8PX/0qvPCCa2u45hpYuRJ++1vYf//cVYdBtG0LZ57pAscLL7j7bdvmSo/77utKG7naQUxiKMIObRUolaPIg4W3wMc9wAhgEHC2iAxqdtgK4FhVPRC4GRhPqXrjDfewr6mBww4Lfl6bNnDSSe71zJnR5M3A9Olw8MHw/POuOujOO11bw89+Br16RXNPEddNeto0Vz154YXuS8WNN8LJJ8PatdHc1xSV38AdJJWjYnyqIUCdqr6rqp8Dk4DTUw9Q1RdVdZP340vsvK5safFLFcOG5d+NcsSIna9hwrNjB/zwh/CVr7heaqec4qqbfvAD6NSpePkYNAgeeABmzXLBau5c13DuN4qbxFKCVUGVazVUMcpLvYH3Un5eDQzNcvxFZFgaUERGAaMA+vXrF1b+8uM96OXhh+Hhh1t2jalTw6kGKVsh/G6eegr23LPw6xRITzjBdYgYNsxVhd10U+YxOabkVXIDdzH+1ab7n592cUIROR4XLI5K976qjseroqqtrQ1hgcM8ffKJq5sW4eRv3MjH7XbL+xIvL5rgqiqeecbVq5vCvPYanHACbNoEffu67slHHslxc/4n7pzx7Il3uDaLW26BG25w20WLXMN627ZxZ8/kSZWK7jpbjE++Guib8nMfYE3zg0TkQOB3wOneWrSl55ln3FoVQ4a0KFAAVhUVpuXLXZvApk0wfDi8+ioceWTcudpZdTVce62rjqqpcdVT3/ymzUScQK6BuzpQKkfFCBbzgYEiMkBE2gAjgWmpB4hIP2AKcJ6qvlWEPLWM3zDtP/BbwoJFON55x3UY2LDBBYqpU6Fbt7hzldkxx8Ds2W4m4mnT4LzzXPdekyjWwB0hVa0HLgNmAW8Ak1V1mYhcIiKXeIddD3QD7hWR10RkQdT5apEXX3TbE09s+TWOOspVQSxdCh9/HE6+Ks2mTa4he+1aV5U3ZUoyqnUOOsiVLDp1gj//2bVhmMRQhEYNlspRUUKgqk5X1X1U9YuqOs7bd7+q3u+9/o6q7qGqB3upthj5ystnn7kHfFVVYZMBtmnjHhrg6q9NfnbscNU4b74JBxzg6v/bt487V8F9+cuuFNSqlRtV/uCDcefI5MFKFia31193jZWDB7uZSAtR68XCBaVZgCppV18NTz/tuqU+/nhxu8WG5YQTmmYsHjUKXnkl3vyYQBRo1KpAqRyV56eKgv9grw2h0GPBomUWLXITMlZXu2/ne+8dd45abtQoN4/Ujh1uKhgb6Z0AwZZUtWVVK10UwWL+/MKvVSkaG91EfY2NbiGpI46IO0eFu/VW19130SIYX7qTFhhHwXpDmQBee81tDzmk8Gvtt59rkF2xwk1GZ3KbONHNHtuzp5tGI4dGJPaUU8eObp0TgB//eNdp001JUZVQqqFEpK+IzBWRN0RkmYiM8fbfKCL/8jr5vCYip6acc403t96bIjIsZf9hIrLEe+9ukehG+1qwCGLHDjcnFLhJ6ArVqpWbFgJco7nJbtMmuOoq9/qOO6Bz53jzE6avf71prIj1jip5DVoVKOVQD1ypqvsBhwOjU+bLuyulo890AO+9kcBgYDiu16hffLkPN6vFQC8ND/UDp7BgEcRbb7nBeAMGhNegesABbrt4cTjXK2fXXefGUxxzDJxzTty5CZcI/PrXbvr03/8eXn457hyZDNx6FoWXKlV1raou8l5vwQ0p6J3llNOBSaq6XVVXAHXAEBHpBXRW1XmqqsBDwBmFf9L0LFgEsWSJ2/oP+DD41/KvbdJbutRN+V1d7XoQleOcWvvuC1de6V5ffnnTAk2mxEg+JYvuIrIgJY1Ke0WR/sAhgP8t4TJvqYYJIrKHty/d/Hq9vbQ6zf5IWLAIwv/2f+CB4V3Tv5YFi+z+939do/bFF4dTBViqrr3WTQcyf75bgc+UHNd1NvCgvA2qWpuSdunBICK7Af8PuEJVN+OqlL4IHAysBe70D82QncDz7oXBgkUQfnvF4MHhXdO/ln9ts6vt2+FPf3Kvv/vdePMStY4d4dxz3WsbqFeSwpwbSkRa4wLFH1V1CoCqfqCqDaraCPwWt7wDZJ5fbzU7L+eQdt69sFiwCGLlSrf9whfCu2avXq5H1IYNbjZbs6snn3TLlR54oFvQqNxdcIHbPvKIC5Sm5DRSFShl4/VY+j3whqr+ImV/6upcZwJ+75dpwEgRaSsiA3AN2a+o6lpgi4gc7l3zfOCx8D7tzixYBLFihdsOGBDeNauqoH9/99oPRmZnEye6rf8QLXcHH+wC48aNLlCakuKmKA9l8aMjgfOAE5p1k73d6wa7GDge+G93X10GTAaWAzOB0arqj+K8FDdbdx3wDhnWAgqDrcKSy0cfuQn/OnSA7t3DvXb//m6Oo5Ury7s+viXWrXNLpFZXN1XP5CGxk7ldcIFr7J440XWrNSUljH9Xqvo30rc3TM9yzjhgXJr9C4CiPDysZJGL/61/wIDwe+L4JQu/5GKa/OlPUF/vpnQvgRXviubcc12AnD7dBUxTMtysszY3lMnEf5D7D/Yw+dVaVg21q8mT3bZSqqB8e+7pAmR9vZt63ZQMN91HVaBUjsrzU4UptWQRNitZpNfQ0DS9SiFrhyTVSSe57auvxpsP00xllyyszSKXKEsW1sCd3jvvuPVD+vRxK8tVGn8Mjo3uLzmB5vwqUxYscvEf5FFWQ1nJYmdRDIJMktTR/Y2NrueciZ3fG6pS2b/CXKKshqqpcb2sPvrIJeNUerDo3h322gu2brUvEiWmkquhyvNThUU12mooEauKSqfSgwVYVVQJsjW4TWYbN7rR1Z0771J3Lo0tS7uwYLErCxYWLEqQAvVaFSiVI2uzyGa1N6Fj377RzXbar9/O96p0ftVL69awzz5x5yY+fruFrXdSUsq1iikICxbZbNjgtj16RHePmpqd71Xptmxx2z32cAGjUvn/LmwlxdJRxlVMQRQlTIrIcG85wDoRGZvluC+LSIOIfKMY+crJf4CHPc1HKv/aFiycbdvctl27ePMRN//z+78PE7uwFj9KqshLFt7yf/cAJ+Om1J0vItNUdXma424DZkWdp8AsWBSfBQvHgkVJspJFtIYAdar6rqp+DkzCLRPY3OW4+d1LZ0Kc9evd1oJF8ezY4batKryG1P/8/u/DxC7PxY/KTjH+R6ZbEnBo6gEi0hs3f/sJwJeLkKdgrGRRfG3buu3nn8ebj7j5n9//fZjYKUJ9ozVwRynI0n+/BK5W1QbJ0uvIW8d2FEA/vxdRlHIEC2kMYQVDCxY7s+oXx6rjSlK5tkcEUYwwmWlJwFS1wCQRWQl8A7hXRM5ofiFVHe+vaVvj9xaJUpZg8dLDPwjnHqnBQiNbPjc5/IfjZ5/Fm4+4WbAoPWrVUFGbDwz0lgP8FzASOCf1AFX991waIvIg8ISqTi1C3rIrRjVUhw4uffqpGwDYqVN090qCLl1cfb0/IHK33eLOUTxWrXLbKLttm7z4bRaVKvKSharWA5fhejm9AUxW1WUicomIXBL1/QtSjGCRen2rioI2bWC//Vwpa9myuHMTHxvFXpKsZBExVZ1OsyUDVfX+DMdeWIw85aRanN5Q/vVXrXLBIooJC5PmwAPdjKuLF8PQobmPL0cWLEqOIjRUcAN35X7yXD75xPVIad/eVRNFyUoWO6v0eZFULViUqCQPyhOR20Wks4i0FpE5IrJBRL4V9HwLFpn4D+5iNKRbsNhZCMHibyfdHlJmYrBqlZvmo0ePylp/vMRp8hu4T1HVzcBpuI5H+wA/DHpyhY98ymLjRrft2jX6e3Xr5rYffhj9vZIgNVioRjeJY6l6/XW3tVJFydHSDQRB+JOtnQo8oqobsw1VaM5KFpls3eq2HTtGfy//Hp9+Gv29kqBXLxdAP/oI3nsv5+Flx4JFiUr8ehaPi8g/cEMV5ohIDRB4QJMFi0z8fv5Rt1ek3qPSxxb4ROCII9zrxx6LNy9x8D/z4YfHmw+zC1UJlErUDcARQK2q7gA+Bb4W9GQLFpn43/KLGSysZNHkW16724MPxpqNolu6FBYuhN13h69+Ne7cmBSq0NAogVKJmqeqm1S1AUBVtwIzgp5sbRaZFDNYtG+/8z0NnH66e2AuWuQeoPvvH3eOimPiRLcdOdJGb5egUu3plI2I9MTN0ddeRA6haQqmzkDgB5yVLDLxq4T8B3mUrBpqV+3auQcmND1A8xS0yiCqlLf6enj4Yff6ggta9JlNdJRwqqFEpK+IzBWRN0RkmYiM8fZ3FZHZIvK2t90j5ZxrvPWA3hSRYSn7DxORJd57d0v6FuthwB24qZZ+AdzppR8APwr6+S1YZGLVUPHzH5gPP+wepOVu9mx4/30YONDaK0pSaA3c9cCVqrofcDgwWkQGAWOBOao6EJjj/Yz33khgMDAcN3detXet+3CTqw700vDmN1PViap6PHChqh6fkr6mqlOCfnqrhsrEqqHid/jhbh3ut95yD9IRI+LOUbT8EtSFF1Zed+GECGOuT1VdC6z1Xm8RkTdw1USnA8d5h00EngWu9vZPUtXtwAoRqQOGeBOvdlbVeQAi8hBwBpnbIZ4QkXOA/qQ8+1X1piD5tpJFJlayiJ9IU+nirrvKe1belSth6lT3mc87L+7cmAzyqIbqLiILUtKodNcTkf7AIcDLwJ5eIPEDij+LZLo1gXp7aXWa/Zk8hgs89cDWlBSIlSwysTaL0nDxxfDzn7uSxdSpcOaZcecoGldcAdu3w9lnQ9++OQ83xed6QwX+fr1BVWuzHSAiu+FWB71CVTdnGSCXaU2gIGsFpeqjqrtUUwVlJYtMrBqqNNTUwE9/6l5fcUV5/o5mzHBjK3bbDe64I+7cmCxUg6VcRKQ1LlD8MaXd4AMR6eW934umJaYzrQm02nvdfH8mL4rIAQE+ZloWLDKxaqjSccklcPDBbs6kW24JfFrQxsioUiDbtsHll7vXN94Ie+2V96/HFE9IvaEE+D3whqr+IuWtaYDfDe4CXLWRv3+kiLT11gUaCLziVVVtEZHDvWuen3JOOkcBC70eVYu9XlSBJ2CzaqhMbAR36aiuhnvugSOPhNtvh/PPdz2GysEdd8A778CgQfD978edG5OFEtro7COB84AlIvKat+9HwK3AZBG5CFgFnAXgrf8zGViOa28Y7Q+sAy4FHgTa4xq2sw2yK6iHiAWLTPxv+cVos7BqqNz+8z9dL6EHH4QxY+DJJ3P2GCrhaReclSvhZz9zr3/zG2jdOuvhJn5hdLFQ1b+Rvr0B4MQM54wDxqXZvwDIOmJVRDp7s81uyTOrO7FqqEz8b/nFGEXrBwsrWWR3221uVPeMGXDffTkPL+lqqO3bXQnps8/c4MPjjw/pl2Qio6CNEiiVmD9524XAAm+7MOXnQKxkkUljo9u2KsKvqLp653ua9Hr0cN/AzzvPVdkMHAgnn5zx8JLtaasK3/0uvPCCa6P4xS9yn2NKQsmXVtNQ1dO8bUHLcFqwyMR/cBdjcFRV1c73NJl961uwfLlr6D7rLHjxRVffn0aDxldwXnTqTzO/edttbgBehw7w+ONuSnaTCCX7BSQgEfkacIz347Oq+kTQc60aKhP/X0VVEX5FfkCyYBHMT38KX/86fPwxnHQS1NWlPawkq6Duuw+uuca9/sMf4NBDI/gFmSiENTdUXETkVmAMrqF8OTBGRAJ3L7RgkUkcJYukf20plqoqN1/UccfB2rVw4omuW22pmzgRvvc99/qee1zAM8mhgEqwVJpOBU5W1QmqOgE3j9RXgp5swSKTOEoWQUf0GNcpYNo0t0jSqlWut9QLL+x0SGOjxJZ20tAAP/kJfPvb7uc77mgKGiZRwhqUF6MuKa93z+dEa7PIJEDJQhoyvpWf1HtU4prTLdWpE0yfDqedBn//u+tRdNNNMHYsVFWVRnXAmjWunWXuXPd3veUWuPLKuHNlWqQkezrl4xbgVRGZi+u6ewxwTdCTi1KyEJHh3qjBOhEZm+GY40TkNW9+9+eKka+s/K8HxXpwWyN3y3Tp4h7EV1/tvsH/+McwfDh88EHcOYNZs9zI87lzXU+uWbNcIDPJpQFTCVLVR3BTok/BTTVyhKpOCnp+5CULb971e4CTcXOZzBeRaaq6POWYLsC9wHBVXSUiPdJerJwVs9qryLJMkBaN2bOhZ8/i3rMZodmsz+vWwSmnxJOZZrTE60lKliaz62wzR+Cm/VCgGng06ImBg4U398i5wBdU9SYR6Qf0VNVXcpw6BKhT1Xe960zCTZO7POWYc4ApqroKQFXX7XKVYit2o3OxSzJFdMphN2R8b9aCG8O92Zo1cM458JxXOB0+HK66yjWGR/273boVJkxw4yZWrnT/hvxqMX8sTQBfjHDcxTs/+EFk164ICY6zInIv8CXgEW/Xd0XkJFUdHeT8fL7G3ouLSmd7P2/BlRhyyTQXe6p9gD1E5FkRWSgi56e7kIiM8ueHX79+fR5Zb4FidmdNDUhlGCyKaq+9YM4c16DcoQPMnAknnABDhsBf/uKqqsK2fj3ccAP06+cGC65c6QYMzp3rqsXyCBSm1EnAVJKOBYap6gOq+gCud9RxQU/OJ1gM9SLQNgBV3QS0CXBekDnXWwGH4bpxDQOuE5F9djlJdbyq1qpqbU1NTR5Zb4Filiz8gFSGVVCxqK6G6693vaRuugm6d4cFC+Cb33Qr7911F7z+emGBY/NmePppGD3aBYmbboKNG2HoUJgyBd54A445Jvd1TLI0Bkyl6U2gX8rPfYFIZp3d4bU/KICI1BDs15JpLvbmx2xQ1a3AVhF5HjgIeCuP/IWrmCWLYo7pqCTdusF117neRxMnui6r774LflXMbru5EscRR7g0dCh07frvoN2itpaXXy7p8RMSY0+sxLeV+OMskqsb8IaI+E0HXwbmicg0AFX9WraT8wkWd+MaQ/YUkXHAN4BrA5w3HxjozcP+L9zC4+c0O+Yx4Dci0gpXWhkK3JVH3sJXzJJFGTdul4QOHeDSS2HUKPetf+pUmDcPVqyAZ55xKVW7dtC+PVtataNtww5a664lkB1Szdtd9mJJ1/48sfcQVnbuyQuP/k9xPk+JOPqMnwc+9oWpP4wwJ8WT8Hh3fSEnBw4WqvpHEVlI0xS6Z6jqGwHOqxeRy4BZuNb3Cd787Jd479+vqm+IyExckagR+J2qLs33w4TK/1YZRR13c1ayKI7qajef1FlnuZ/ffx9eesnNLzVvHrz6qmuk3rYNtm1jN++0RoSN7TqxbI9+LO26N8u67s2bXfrwebVNKV5xEhwsVLWgIQn59IZqHpXOEhFU9aa0J6RQ1enA9Gb77m/288+B4F9VotbGa47ZsSP6e33+udvaegbF1bMnnHGGS77GRhcsPv2UERfcx/bq1uyoqrZAbpxkV0MVJJ9qqK0pr9sBpwE5SxaJVczV6/x7dOwY/b3i0pCQr2RVVe5v36EDn7QpwsJXJlEkIf+MoxC4klxV70xJ43Bdrpp3gS0fQVavCzqa00sv/jlD42IxV+WLQehjKYyJgwo0BkwlRETmeNvbCrlOISO4OwBfKOTmJc0vWRRjqVP/HsVY79sY03LJLFn0EpFjga95g6J3imaquijIRfJps1hC06+qGqiB5nMalJFiBgu/GsqChTGlLZnB4npgLG7YQvPpARQ4IchF8ilZnJbyuh74QFXr8zg/WYq5LnaZV0MZUzYSGCxU9a/AX0XkOlW9uaXXyafr7D9bepNEClCykMaQ/uVYNZRJICndkcrRSPigPFW9uZBlVXMGCxHZQvp4Ku7+2jnozRLFqqGMMc0kuTeUt4TqEOCP3q4xInKkqgZa0yJnsFDVTgXkL7msgdsY01yCgwVu7r2DVbURQEQmAq8ScAGkvHpDicgewEDcOAsAVPX5fK6RGAG6zoZWDLc2C2MSIcklC08XYKP3OpplVUXkO8AYXIv6a7gVl+YRsCU9cYo5KM9KFsYkQ4LbLCjisqpjcLMU/lNVjwcOASJeVCJG1mZR8aRRA6dKm0SwIuUzCDcHEZkgIutEZGnKvhtF5F/e8tKvicipKe9d4y1L/aaIDEvZf5iILPHeu1uyTJXcbFnVKUS4rOo2Vd0mIohIW1X9h4jsm8f5yRJkBHdYrBrKJJAkZQqXMIX3kR8EfgM81Gz/Xap6R+oOERmEm617MLAX8LSI7KOqDcB9wCjgJdz8e8OBGZluqqprgWktyXA+wWK1t1b2VGC2iGxi13Upyoc1cIdKEj63szEQXjulqj4vIv0DHn46MElVtwMrRKQOGCIiK4HOqjoPQEQeAs4gS7AoRD7jLM70Xt7o1XntDsyMIlMlobPXI/jjj6O/1+bNbtupMjueGZMYwb/zdBeRBSk/j1fV8QHOu8xbVnoBcKW3ImlvXMnB5y9NvcN73Xx/JPJp4P5v4C+qurrQedEToXt3t/3ww4yHhDYob8MGt416qVhjQlRpg/JE8+oNtUFVa/O8xX3AzbiQdDNwJ/BfZF6aOsiS1QCISBWwWFX3zzNP/5ZPA3dnYJaIvCAio0Vkz5beNBG6dnXbjRujXwBpvddPwA9QxpjSpBIsteTSqh+oaoM3DuK3uAF0kHlp6tXe6+b70127EXhdRPqlez+IfKYo/4mqDgZG4xpZnhORp1t645LXujV06eIWw/noo2jv5ZcsyjlYNDamT8YkSUi9odIRkV4pP54J+D2lpgEjRaSttzz1QOAVr7F6i4gc7vWCOh+3RHUmvYBlIjJHRKb5KWj+WjJF+TrgfeBDoEcLzk+O7t1doFi/Hrp1i+4+lRAsjCkDYQ3KE5FHcGsCdReR1cANwHEicjAu3KwEvgvgLUM9GViOm8R1tNcTCuBSXM+q9riG7WyN2z8pJM/5tFlcCvxf3NTkfwUuVtXlhdy85NXUQF1d08M8Cg0NrqoLmqq+TEmQeuvBZVJoqL2hzk6z+/dZjh8HjEuzfwEQqB1CVZ8Tkb2Bgar6tIh0wC03EUg+JYu9gStU9bU8zkk2/5t+lMHio49cdUyXLrYGtzGlLsHfH0TkYtyYjK7AF3E9p+4HTgxyfj5tFmMrKlBAzmDxwtQfIo0ETmlVShWUavpkTJJE2GZRBKOBI4HNAKr6Nnk0JeTTG6ryFKNk4feEsm6zJmGenXFV5i8BZfqlwO8+myuVqO2q+rn/g4i0Io/QVpRgISLDvTlN6kRkbJr3dxeRx0XkdRFZJiLfLka+cgoQLIL+48n4D6hSShYJ9NyTVyENGigZkwDPiciPgPYicjLwF+DxoCdHHixEpBq4BxgBDALO9uY6STUaWK6qB+F6CNwpIm2izltO/rf9KEsWFiyMSY5kV0ONxU3+ugTX02o6cG3Qk/Ndz6IvbjKr/YEDgMEBRikOAepU9V3vGpNwc52k9qRSoJPXV3g33Hzr8a/vXYxqKAsWJsGC9A6a+9TV0WekGELsDRUHVW30Fjx6GffMfVM1eB1hzpKFiHxXRF4UkY+At4Dv4B7o04BzAtyjN/Beys/p5i/5DbAfbvThEmCMv5pTs7yMEpEFIrJg/foizI5uwSI0Vn1jykKCSxYi8hXgHeBu3DO3TkRGBD0/SMniGtz4ig3ArbjBHxNUdVXQPKbZ1/zXOQy3oNIJuC5ds0XkBVXdvNNJbiKu8QC1tbXR/0l6eB0F1q7NfEzAB95z069K/8b77+98L2NMSRJKuvE6iDuB41W1DkBEvgg8ScBZaoO0WZymqi+r6juqehYuIj0uIv/tTU6VS6Z5TVJ9G5iiTh2wAviPANeOVt++IAKrV8OOHdHcY8UKt+3fP5rrl4qGxvSpxFU1aKBkKkSCSxbAOj9QeN7FzcgRSM6HvaoubfbzTFw7RFfg7wHuMR8YKCIDvEbrkey6+MYqvIEh3gSF++I+SLzatIHevd2gudWrcx/fEitXum25BwtTliqqp1ihPR9jIiJfF5Gv4+aFmi4iF4rIBbieUPODXqclc0PhLcJxnYj8IcCx9SJyGTALN7R8gjfXySXe+/fjpuN9UESW4Ep7V6tqhA0FeRgwwAWKFSvc62YKmqZ82zZYswaqq6FPn9zHG2PiVfqF4XS+mvL6A+BY7/V6YI+gF2lRsPCp6lsBj5uO66aVuu/+lNdrgFMKyUtk+veHF15oKgGEaZXX7NO3L7Qq6E9hjCmCUis1BKGqoYxbsydULn71kN+20ExBXen8AJSmxFJ20vTQm/HWbTFkxIQptAXAkiLBH9eb3vxyoD8pz35V/VqQ8y1Y5OI/yKMoWVRK47Yx5aC0G6+DmIqb2fZxWlChZsEil1wli0Ia8CqpZJFQQaYpnzP3miLkxJSCJFZDpdimqne39GQLFrn4wcJKFsaYZAeLX4nIDcBTwHZ/p6ouCnKyzTqbS9++rrfSmjWwffsubz8zZyyimjOlVUElixlv3WZLqpYhadScqZwUtBxB/A4ALsYNrr7TS3cEPdlKFrm0auW6tf7zn6730sCB4V3bxlgYkxzJb7M4E/hC6jTl+bCSRRD+N/8M7RY0au7U3KefwgcfuNXx9toruryXkly/E5M4lTQoT/JIJep1oEtLT7ZgEcQXv+i2bwUaVhLM22+77YABUGV/hlI1Z+41SENj1mQqSLKn+9gT+IeIzBKRaX4KerJVQwWxv7ce+pIl4V3Tv9YBB4R3TWNMpBLeG+qGQk62YBHEgQe67eLFad/O1Yj39PM/3nWnf61KChaNDXHnwJjCJDhYqOpzhZxvwSII/4G+dKnrxRNGtZFfsvADkTGmtCV88SMR2UJTuGsDtAa2qmrnIOdbZXkQNTXQsyd88kna8RYtauCrxJJFQkm9Zk2VbPbffpx/544kS3Cbhap2UtXOXmoH/B/ckhOBWLAIyi8BvP564dfasMGN2+jQAb7whcKvlxTl/BAxFSGJU5RnoqpTcQvOBWLVUEEdeig89RQsXAhnnlnYtRYubLqm9YQyJjkSEgjS8da08FUBteTxiexJFVRtrdsuWLDLW3mPYPWv4V+zUtgI7rIkjY0Z0+wXr407e6EKq2QhIhNEZJ2ILE3Z11VEZovI2952j5T3rhGROhF5U0SGpew/TESWeO/dLSLZhnl8NSUNA7YApwf97FayCCo1WKi65VZbqlKDRUJJvQU2g/sOHt4/hQdx7QUPpewbC8xR1VtFZKz389UiMgi3wuhgYC/gaRHZR1UbgPuAUcBLuDWDhpNhTe1C17WwYBFUv37Qvbtrb/jnPwubosOChSkj5TRKOxshvPYIVX1eRPo32306cJz3eiLwLHC1t3+St0LpChGpA4aIyEqgs6rOAxCRh4AzaBYsROT67FnRm4Pk2aqhghKBL3/Zvf57kKXHM3jvPbdMa+fO4c4zZYyJXvDeUN1FZEFKGhXg6nuq6loAb9vD298beC/luNXevt7e6+b7m9uaJgFchAtGgVjJIh8nnggzZsDMmXDuuS27xgwv6J9wgjVuJ4RkaV+ZteDG4mXExC7jDNK72qCqYVUdpKvz1iz7d96heue/LyTSCRgDfBuYhJt5NhB7WuVjxAi3nTVr5wbaBs2eUvnBwr9WJVHdOZny0PzvWq5/46ClipZ/7A9EpBeAt13n7V8N9E05rg+wxtvfJ83+XXiN5z8FFuMKCYeq6tWqui7d8elYsMjHfvu5tov165u6v+bj88/h6afd60oMFsYkXMTjLKYBF3ivLwAeS9k/UkTaeutoDwRe8aqqtojI4V4vqPNTzmnKs8jPgfm43k8HqOqNqrop38xZsMiHSNNDfkbaDgfZ/f3vbhT44MFuUSVjTKKEtfiRiDwCzAP2FZHVInIRblGik0XkbeBk72dUdRkwGVgOzARGez2hAC4FfgfUAe+QvifUlbheVNcCa0Rks5e2iMjmoJ898jYLEZkAnAasU9X907wvwK+AU4FPgQuDLvOXZz7CveANN7gU6N7Njlu2rLCutx5NWjG/oWkiwRnv3xtjRvIza8GNDD84W4eSClchvaGA0AblqerZGd46McPx44BxafYvAHZ5rjY7JpRCQTEauB9k1/7EqUbgilUDgaG4fsNDw87EsEE/Srt/5rJdfv/ZbdkC3bpBfb2rjurWLfi5BxzgJiN8+mnXWN4Cwzu7rtIzNz/QovONMS2UoKk8ohB5NZSqPg9szHLI6cBD6rwEdPEbeUpSp05w9NGu8e6pp4Kf9957LlB07AhHHRVd/krYjPfvhYZGl0zZyDaCu+wkeCLBQpVCm0WmPsS7EJFRfr/l9evX53WTUP8xn3qq2z7ySPBzJk1y25NOgrZtW3ZfE5+GhvTJVAx/UF65TCSYr1IIFoH6CgOo6nhVrVXV2pqamoizlcV550GbNvDEE1BXl/v4+nr4jTcT8MUXR5s3Y0xkcs0Dl3E+uDJQCsEiUx/iUM1445bw5trv0cMNylOFX/869/FTp8KqVbDPPtZl1pSdma/fvOskkeU4WWT04yxKWikEi2nA+eIcDnzsD3kvaVdc4bYTJsDHH2c/9pe/dNsxYyp+1LZqI6rJe4hIfeMuaeaSPDtHmMQLq+tsEkX+5ErXn1hELhGRS7xDpgPv4voJ/xb4XmSZCXOE6YEHuik7PvkEfvGLzMfNmePGV3TpAuef3/L7ebSxES23b2wm8dKtEFmWwbSCSxaRd53N0p/Yf1+B0VHnIxI33gjPPAO33grnnAP77rvz+9u2wSVeTLzqKthtt6Jn0RgTnnJtvA6isutECnX00XDRRW4aj5Ej4aOPmt5rbHSBoq7Ojdi+8srYsmlM5Pwu0amp3CjZ58Eq1zmxPJUVLKL4o95+O3zpS/Daa65b7PPPwz/+4UoaEye6dbYfeMD1njLJVd+wazIVp5LbLGyK8kJ17epGZB99tJtc8Nhjm95r0wYee6xpHQxjylUFtKOFufhRElVWySKqYvLee8Prr8OPfgR9+kBNDZx9thuxfdJJ4d2nHJRrFYUpf0GroMq0GqqiSxYz3r49vIvtsQeMG+eSMaYsVXLJoqKDhTGVJvTZl7Pe6+eRXj+WWZctWBhTJAmt257x9u2MGPCDuLNRsGH+rMUfT4g5J/kbUXPJv1/PWH9/LHmwkkWlSODIYWNMiVAqa+2OZiorWJSDMm08MyaXUpgmxkoWxhhjcqvgL2uVFSwq+A9dKjTJa0B8tq3pdft28eWjEPZ/oCBWsqgUZTrPvCm+GSuyTB5pylMZTxIYRGUFizIwa2umpcyTYdYnE+POgjEtIrjZdStVZQWLhHbbNMaUBqngarzKChbGGGZufiDuLCSTVUMZY4zJrXznfQqioiYSnLH67rKf7MtEZ8b799pEiHFq1KYUE9FgqRxZycIYY4Kq4C+ZFVWyMMaYFtP0a42nS7mIyEoRWSIir4nIAm9fVxGZLSJve9s9Uo6/RkTqRORNERkW4afMyIKFMcYEpQFTMMer6sGqWuv9PBaYo6oDgTnez4jIIGAkMBgYDtwrItVhfJx8VF6waGxsSsaYZIm5vVFUA6UWOh3wByJNBM5I2T9JVber6gqgDhhSyOdoicoLFsZUME3wl6SZG38bdxbyWSmvu4gsSEmjml8JeEpEFqa8t6eqrnW30bVAD29/b+C9lHNXe/uKKvIGbhGZAJwGrFPV/dO8fy5wtffjJ8Clqvp61Pkyxpi8KBA81m5IqV5K50hVXSMiPYDZIvKPLMemW7Gq6MWrYpQsHsTVs2WyAjhWVQ8EbgbGFyFPxrSI1tej9fVxZ8PEQAhWBRWkGkpV13jbdcCjuGqlD0SkF4C3Xecdvhrom3J6H2BNiB8tkMiDhao+D2zM8v6LqrrJ+/El3C8iygzFXu9pjEmo1DbPbCkLEekoIp3818ApwFJgGnCBd9gFwGPe62nASBFpKyIDgIHAKxF8uqxKbZzFRcCMTG96dXujAPr161esPBljSsjMTb+L58b5VUNlsyfwqLceeivgT6o6U0TmA5NF5CJgFXAWgKouE5HJwHKgHhitqkWf679kgoWIHI8LFkdlOkZVx+NVU9XW1lrRwJhKE3MDfRgTCarqu8BBafZ/CJyY4ZxxwLiCb16AkggWInIg8DtghPcLi473x57xwX2R3sYYU4YquPo69mAhIv2AKcB5qvpW3PkxpqxV8MOucJXd1lmMrrOPAMfh+h2vBm4AWgOo6v3A9UA33KhEgPocXc6MMZUqzoe1Arb4UXRU9ewc738H+E7U+fj3/ZK8BrSJne7YkejV/pK+0mLcbPEjY4wxuVmwqCAxzoVvjClMrNOVKBX9/Ki8YGFMAZJcBWUKZQ3cxhhjgrBgUUEq+I9tjCmAUtFL6lZesDDGmBZRUAsWxhhT+uKuGYj7/jGyYGGMSYxYx4lYb6gKk+CVwowxMbOShTHGmJwsWBhjjMlKFSp4uqCKCxY2N5QxpsWsZGGMMSYnCxbGGGOyU+sNVUlsbh9jTIsoqA3KM8YYk5NN92GMMSYr1Yoep2XBwhhjgrIGbmOMMbnEuvhSzCxYGGNMILb4kTHGmFxsIkFjjDG5KJU9A0RV3BkwxphEUG/xoyApBxEZLiJvikidiIwtQu4LZiULY4wJSEOohhKRauAe4GRgNTBfRKap6vKCLx4hK1kYY0xQ4ZQshgB1qvquqn4OTAJOjzzvBUpsyWLhwoWzgOFx58MYUxm2sGnW0/rX7gEPbyciC1J+Hq+q473XvYH3Ut5bDQwNI49RSmywUFULFMaYognxmSPpLh/StSNj1VDGGFNcq4G+KT/3AdbElJfALFgYY0xxzQcGisgAEWkDjASmxZynnBJbDWWMMUmkqvUichkwC6gGJqjqspizlZNoBQ9fN8YYE4xVQxljjMnJgoUxxpicLFgYY4zJyYKFMcaYnCxYGGOMycmChTHGmJwsWBhjjMnp/wNdnJi8sDjv0QAAAABJRU5ErkJggg==\",\n      \"text/plain\": [\n       \"<Figure size 432x288 with 2 Axes>\"\n      ]\n     },\n     \"metadata\": {\n      \"needs_background\": \"light\"\n     },\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"clusterer = hdbscan.HDBSCAN(\\n\",\n    \"    min_cluster_size=80)\\n\",\n    \"clusterer.fit(u)\\n\",\n    \"\\n\",\n    \"clusterer.condensed_tree_.plot(select_clusters=True)\"\n   ]\n  }\n ],\n \"metadata\": {\n  \"interpreter\": {\n   \"hash\": \"e81a84c338879f0412495ea98350e80595740634d3ce0fba8d30f35c60f1a4c3\"\n  },\n  \"kernelspec\": {\n   \"display_name\": \"Python 3.8.12 ('stoic')\",\n   \"language\": \"python\",\n   \"name\": \"python3\"\n  },\n  \"language_info\": {\n   \"codemirror_mode\": {\n    \"name\": \"ipython\",\n    \"version\": 3\n   },\n   \"file_extension\": \".py\",\n   \"mimetype\": \"text/x-python\",\n   \"name\": \"python\",\n   \"nbconvert_exporter\": \"python\",\n   \"pygments_lexer\": \"ipython3\",\n   \"version\": \"3.8.12\"\n  },\n  \"orig_nbformat\": 4\n },\n \"nbformat\": 4,\n \"nbformat_minor\": 2\n}"
}
```

Better, but not quite there, we can try to reduce the `min_cluster_size` to `60` to pull in the three clusters below the green block.

```json
{
  "_key": "323fb7b4b839",
  "_type": "colabBlock",
  "jsonContent": "{\n \"cells\": [\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 29,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"<AxesSubplot:ylabel='$\\\\\\\\lambda$ value'>\"\n      ]\n     },\n     \"execution_count\": 29,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    },\n    {\n     \"data\": {\n      \"image/png\": \"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\",\n      \"text/plain\": [\n       \"<Figure size 432x288 with 2 Axes>\"\n      ]\n     },\n     \"metadata\": {\n      \"needs_background\": \"light\"\n     },\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"clusterer = hdbscan.HDBSCAN(\\n\",\n    \"    min_cluster_size=60)\\n\",\n    \"clusterer.fit(u)\\n\",\n    \"\\n\",\n    \"clusterer.condensed_tree_.plot(select_clusters=True)\"\n   ]\n  }\n ],\n \"metadata\": {\n  \"interpreter\": {\n   \"hash\": \"e81a84c338879f0412495ea98350e80595740634d3ce0fba8d30f35c60f1a4c3\"\n  },\n  \"kernelspec\": {\n   \"display_name\": \"Python 3.8.12 ('stoic')\",\n   \"language\": \"python\",\n   \"name\": \"python3\"\n  },\n  \"language_info\": {\n   \"codemirror_mode\": {\n    \"name\": \"ipython\",\n    \"version\": 3\n   },\n   \"file_extension\": \".py\",\n   \"mimetype\": \"text/x-python\",\n   \"name\": \"python\",\n   \"nbconvert_exporter\": \"python\",\n   \"pygments_lexer\": \"ipython3\",\n   \"version\": \"3.8.12\"\n  },\n  \"orig_nbformat\": 4\n },\n \"nbformat\": 4,\n \"nbformat_minor\": 2\n}"
}
```

Unfortunately, this still pulls in the green block and even allows _too small_ clusters (as on the left). Another option is to keep `min_cluster_size=80` but add `min_samples=40`, to allow for more sparse core points.

```json
{
  "_key": "7132bef85d12",
  "_type": "colabBlock",
  "jsonContent": "{\n \"cells\": [\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 30,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"<AxesSubplot:ylabel='$\\\\\\\\lambda$ value'>\"\n      ]\n     },\n     \"execution_count\": 30,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    },\n    {\n     \"data\": {\n      \"image/png\": \"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\",\n      \"text/plain\": [\n       \"<Figure size 432x288 with 2 Axes>\"\n      ]\n     },\n     \"metadata\": {\n      \"needs_background\": \"light\"\n     },\n     \"output_type\": \"display_data\"\n    }\n   ],\n   \"source\": [\n    \"clusterer = hdbscan.HDBSCAN(\\n\",\n    \"    min_cluster_size=80, min_samples=40)\\n\",\n    \"clusterer.fit(u)\\n\",\n    \"\\n\",\n    \"clusterer.condensed_tree_.plot(select_clusters=True)\"\n   ]\n  }\n ],\n \"metadata\": {\n  \"interpreter\": {\n   \"hash\": \"e81a84c338879f0412495ea98350e80595740634d3ce0fba8d30f35c60f1a4c3\"\n  },\n  \"kernelspec\": {\n   \"display_name\": \"Python 3.8.12 ('stoic')\",\n   \"language\": \"python\",\n   \"name\": \"python3\"\n  },\n  \"language_info\": {\n   \"codemirror_mode\": {\n    \"name\": \"ipython\",\n    \"version\": 3\n   },\n   \"file_extension\": \".py\",\n   \"mimetype\": \"text/x-python\",\n   \"name\": \"python\",\n   \"nbconvert_exporter\": \"python\",\n   \"pygments_lexer\": \"ipython3\",\n   \"version\": \"3.8.12\"\n  },\n  \"orig_nbformat\": 4\n },\n \"nbformat\": 4,\n \"nbformat_minor\": 2\n}"
}
```

Now we have four clusters, and we can visualize them using the data in `clusterer.labels_`.

```json
{
  "_key": "121d93669b4b",
  "_type": "plotlyPlot",
  "asset": {
    "_ref": "file-f3fc69b38094280d0aca94a15f87e43f3b653e67-json",
    "_type": "reference"
  },
  "caption": "HDBSCAN clustered Reddit topics, accurately identifying the different subreddit clusters. The sparse blue points are outliers and are not identified as belonging to any cluster."
}
```

A few outliers are marked in blue, some of which make sense (pinned daily discussion threads) and others that do not. However, overall, these clusters are very accurate. With that, we can try to identify the meaning of these clusters.

### Topic Extraction with c-TF-IDF

The final step in BERTopic is extracting topics for each of our clusters. To do this, BERTopic uses a modified version of TF-IDF called c-TF-IDF.

TF-IDF is a popular technique for identifying the most relevant _“documents”_ given a term or set of terms. c-TF-IDF turns this on its head by finding the most relevant _terms_ given all of the “documents” within a cluster.

![c-TF-IDF looks at the most relevant terms from each class (cluster) to create topics.](https://cdn.sanity.io/images/vr8gru94/production/9b3a9573203e8a0a39c2768f7fdf44a8ba42bf05-4580x1476.png)


In our Reddit topics dataset, we have been able to identify very distinct clusters. However, we still need to determine what these clusters talk about. We start by preprocessing the `selftext` to create tokens.

```json
{
  "_key": "ef8f1100be5f",
  "_type": "colabBlock",
  "jsonContent": "{\n \"cells\": [\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 75,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stderr\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"100%|██████████| 3118/3118 [00:00<00:00, 7893.81ex/s]\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"import re\\n\",\n    \"import nltk\\n\",\n    \"\\n\",\n    \"# first lowercase and remove punctuation\\n\",\n    \"alpha = re.compile(r'[^a-zA-Z ]+')\\n\",\n    \"data = data.map(lambda x: {\\n\",\n    \"    'tokens': alpha.sub('', x['selftext']).lower()\\n\",\n    \"})\\n\",\n    \"# tokenize, separating by whitespace\\n\",\n    \"data = data.map(lambda x: {\\n\",\n    \"    'tokens': nltk.tokenize.wordpunct_tokenize(x['tokens'])\\n\",\n    \"})\\n\",\n    \"# remove stopwords\\n\",\n    \"stopwords = set(nltk.corpus.stopwords.words('english'))\\n\",\n    \"# stopwords from nltk are all lowercase (so are our tokens)\\n\",\n    \"data = data.map(lambda x: {\\n\",\n    \"    'tokens': word for word in x['tokens'] if word not in stopwords\\n\",\n    \"})\\n\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 76,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"{'sub': 'investing',\\n\",\n       \" 'title': 'Daily General Discussion and Advice Thread - March 03, 2022',\\n\",\n       \" 'selftext': 'Have a general question?  Want to offer some commentary on markets?  Maybe... financial decisions!',\\n\",\n       \" 'upvote_ratio': 0.84,\\n\",\n       \" 'id': 't3_t5o82m',\\n\",\n       \" 'created_utc': 1646301670.0,\\n\",\n       \" 'class': -1,\\n\",\n       \" 'tokens': ['have',\\n\",\n       \"  'general',\\n\",\n       \"  'question',\\n\",\n       \"  'want',\\n\",\n       \"  '...',\\n\",\n       \"  'financial',\\n\",\n       \"  'decisions']}\"\n      ]\n     },\n     \"execution_count\": 76,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"data[0]\"\n   ]\n  }\n ],\n \"metadata\": {\n  \"interpreter\": {\n   \"hash\": \"e81a84c338879f0412495ea98350e80595740634d3ce0fba8d30f35c60f1a4c3\"\n  },\n  \"kernelspec\": {\n   \"display_name\": \"Python 3.8.12 ('stoic')\",\n   \"language\": \"python\",\n   \"name\": \"python3\"\n  },\n  \"language_info\": {\n   \"codemirror_mode\": {\n    \"name\": \"ipython\",\n    \"version\": 3\n   },\n   \"file_extension\": \".py\",\n   \"mimetype\": \"text/x-python\",\n   \"name\": \"python\",\n   \"nbconvert_exporter\": \"python\",\n   \"pygments_lexer\": \"ipython3\",\n   \"version\": \"3.8.12\"\n  },\n  \"orig_nbformat\": 4\n },\n \"nbformat\": 4,\n \"nbformat_minor\": 2\n}"
}
```

Part of c-TF-IDF requires calculating the frequency of term _t_ in class _c_. For that, we need to see which tokens belong in each class. We first add the cluster/class labels to `data`.

```python
# add the cluster labels to our dataset
data = data.add_column('class', clusterer.labels_)
```

Now create class-specific lists of tokens.

```python
classes = {label: {'tokens': []} for label in set(clusterer.labels_)}
# add tokenized sentences to respective class
for row in data:
    classes[row['class']]['tokens'].extend(row['tokens'])
```

We can calculate **T**erm **F**requency (TF) per class.

```json
{
  "_key": "af8e1b55385c",
  "_type": "colabBlock",
  "jsonContent": "{\n    \"cells\": [\n     {\n      \"cell_type\": \"code\",\n      \"execution_count\": 80,\n      \"metadata\": {},\n      \"outputs\": [\n       {\n        \"name\": \"stderr\",\n        \"output_type\": \"stream\",\n        \"text\": [\n         \"100%|██████████| 31250/31250 [00:26<00:00, 1177.96it/s]\\n\",\n         \"100%|██████████| 31250/31250 [00:15<00:00, 1979.75it/s]\\n\",\n         \"100%|██████████| 31250/31250 [00:17<00:00, 1758.14it/s]\\n\",\n         \"100%|██████████| 31250/31250 [00:10<00:00, 3052.47it/s]\\n\",\n         \"100%|██████████| 31250/31250 [00:03<00:00, 8385.79it/s] \\n\"\n        ]\n       }\n      ],\n      \"source\": [\n       \"tf = np.zeros((len(classes.keys()), len(vocab)))\\n\",\n       \"\\n\",\n       \"for c, _class in enumerate(classes.keys()):\\n\",\n       \"    for t, term in enumerate(tqdm(vocab)):\\n\",\n       \"        tf[c, t] = classes[_class]['tokens'].count(term)\"\n      ]\n     },\n     {\n      \"cell_type\": \"code\",\n      \"execution_count\": 81,\n      \"metadata\": {},\n      \"outputs\": [\n       {\n        \"data\": {\n         \"text/plain\": [\n          \"array([[  1.,   0.,   4., ...,   1., 177.,   1.],\\n\",\n          \"       [  0.,   0.,  20., ...,   0.,  16.,   1.],\\n\",\n          \"       [  0.,   1.,   4., ...,   0.,  51.,   5.],\\n\",\n          \"       [  0.,   0.,   0., ...,   0.,  36.,   0.],\\n\",\n          \"       [  0.,   0.,   0., ...,   0.,   0.,   0.]])\"\n         ]\n        },\n        \"execution_count\": 81,\n        \"metadata\": {},\n        \"output_type\": \"execute_result\"\n       }\n      ],\n      \"source\": [\n       \"tf\"\n      ]\n     }\n    ],\n    \"metadata\": {\n     \"interpreter\": {\n      \"hash\": \"e81a84c338879f0412495ea98350e80595740634d3ce0fba8d30f35c60f1a4c3\"\n     },\n     \"kernelspec\": {\n      \"display_name\": \"Python 3.8.12 ('stoic')\",\n      \"language\": \"python\",\n      \"name\": \"python3\"\n     },\n     \"language_info\": {\n      \"codemirror_mode\": {\n       \"name\": \"ipython\",\n       \"version\": 3\n      },\n      \"file_extension\": \".py\",\n      \"mimetype\": \"text/x-python\",\n      \"name\": \"python\",\n      \"nbconvert_exporter\": \"python\",\n      \"pygments_lexer\": \"ipython3\",\n      \"version\": \"3.8.12\"\n     },\n     \"orig_nbformat\": 4\n    },\n    \"nbformat\": 4,\n    \"nbformat_minor\": 2\n   }\n   "
}
```

Note that this can take some time; our TF process prioritizes readability over any notion of efficiency. Once complete, we’re ready to calculate **I**nverse **D**ocument **F**requency (IDF), which tells us how common a term is. Rare terms signify greater relevance than common terms (and will output a greater IDF score).

```json
{
  "_key": "d8e2b39a4e4c",
  "_type": "colabBlock",
  "jsonContent": "{\n    \"cells\": [\n     {\n      \"cell_type\": \"code\",\n      \"execution_count\": 82,\n      \"metadata\": {},\n      \"outputs\": [\n       {\n        \"name\": \"stderr\",\n        \"output_type\": \"stream\",\n        \"text\": [\n         \"100%|██████████| 31250/31250 [00:00<00:00, 215843.43it/s]\\n\"\n        ]\n       }\n      ],\n      \"source\": [\n       \"idf = np.zeros((1, len(vocab)))\\n\",\n       \"\\n\",\n       \"# calculate average number of words per class\\n\",\n       \"A = tf.sum() / tf.shape[0]\\n\",\n       \"\\n\",\n       \"for t, term in enumerate(tqdm(vocab)):\\n\",\n       \"    # frequency of term t across all classes\\n\",\n       \"    f_t = tf[:,t].sum()\\n\",\n       \"    # calculate IDF\\n\",\n       \"    idf_score = np.log(1 + (A / f_t))\\n\",\n       \"    idf[0, t] = idf_score\"\n      ]\n     },\n     {\n      \"cell_type\": \"code\",\n      \"execution_count\": 83,\n      \"metadata\": {},\n      \"outputs\": [\n       {\n        \"data\": {\n         \"text/plain\": [\n          \"array([[10.65296781, 10.65296781,  7.32140112, ..., 10.65296781,\\n\",\n          \"         5.0247495 ,  8.70719943]])\"\n         ]\n        },\n        \"execution_count\": 83,\n        \"metadata\": {},\n        \"output_type\": \"execute_result\"\n       }\n      ],\n      \"source\": [\n       \"idf\"\n      ]\n     }\n    ],\n    \"metadata\": {\n     \"interpreter\": {\n      \"hash\": \"e81a84c338879f0412495ea98350e80595740634d3ce0fba8d30f35c60f1a4c3\"\n     },\n     \"kernelspec\": {\n      \"display_name\": \"Python 3.8.12 ('stoic')\",\n      \"language\": \"python\",\n      \"name\": \"python3\"\n     },\n     \"language_info\": {\n      \"codemirror_mode\": {\n       \"name\": \"ipython\",\n       \"version\": 3\n      },\n      \"file_extension\": \".py\",\n      \"mimetype\": \"text/x-python\",\n      \"name\": \"python\",\n      \"nbconvert_exporter\": \"python\",\n      \"pygments_lexer\": \"ipython3\",\n      \"version\": \"3.8.12\"\n     },\n     \"orig_nbformat\": 4\n    },\n    \"nbformat\": 4,\n    \"nbformat_minor\": 2\n   }\n   "
}
```

We now have TF and IDF scores for every term, and we can calculate the c-TF-IDF score by simply multiplying both.

```json
{
  "_key": "95a5dda58afe",
  "_type": "colabBlock",
  "jsonContent": "{\n    \"cells\": [\n     {\n      \"cell_type\": \"code\",\n      \"execution_count\": 84,\n      \"metadata\": {},\n      \"outputs\": [],\n      \"source\": [\n       \"tf_idf = tf*idf\"\n      ]\n     },\n     {\n      \"cell_type\": \"code\",\n      \"execution_count\": 85,\n      \"metadata\": {},\n      \"outputs\": [\n       {\n        \"data\": {\n         \"text/plain\": [\n          \"array([[ 10.65296781,   0.        ,  29.28560448, ...,  10.65296781,\\n\",\n          \"        889.38066222,   8.70719943],\\n\",\n          \"       [  0.        ,   0.        , 146.42802238, ...,   0.        ,\\n\",\n          \"         80.39599207,   8.70719943],\\n\",\n          \"       [  0.        ,  10.65296781,  29.28560448, ...,   0.        ,\\n\",\n          \"        256.26222471,  43.53599715],\\n\",\n          \"       [  0.        ,   0.        ,   0.        , ...,   0.        ,\\n\",\n          \"        180.89098215,   0.        ],\\n\",\n          \"       [  0.        ,   0.        ,   0.        , ...,   0.        ,\\n\",\n          \"          0.        ,   0.        ]])\"\n         ]\n        },\n        \"execution_count\": 85,\n        \"metadata\": {},\n        \"output_type\": \"execute_result\"\n       }\n      ],\n      \"source\": [\n       \"tf_idf\"\n      ]\n     }\n    ],\n    \"metadata\": {\n     \"interpreter\": {\n      \"hash\": \"e81a84c338879f0412495ea98350e80595740634d3ce0fba8d30f35c60f1a4c3\"\n     },\n     \"kernelspec\": {\n      \"display_name\": \"Python 3.8.12 ('stoic')\",\n      \"language\": \"python\",\n      \"name\": \"python3\"\n     },\n     \"language_info\": {\n      \"codemirror_mode\": {\n       \"name\": \"ipython\",\n       \"version\": 3\n      },\n      \"file_extension\": \".py\",\n      \"mimetype\": \"text/x-python\",\n      \"name\": \"python\",\n      \"nbconvert_exporter\": \"python\",\n      \"pygments_lexer\": \"ipython3\",\n      \"version\": \"3.8.12\"\n     },\n     \"orig_nbformat\": 4\n    },\n    \"nbformat\": 4,\n    \"nbformat_minor\": 2\n   }\n   "
}
```

In `tf_idf`, we have a `vocab` sized list of TF-IDF scores for each class. We can use Numpy’s `argpartition` function to retrieve the index positions containing the greatest TF-IDF scores per class.

```json
{
  "_key": "757d4128d9d0",
  "_type": "colabBlock",
  "jsonContent": "{\n    \"cells\": [\n     {\n      \"cell_type\": \"code\",\n      \"execution_count\": 86,\n      \"metadata\": {},\n      \"outputs\": [],\n      \"source\": [\n       \"n = 5\"\n      ]\n     },\n     {\n      \"cell_type\": \"code\",\n      \"execution_count\": 87,\n      \"metadata\": {},\n      \"outputs\": [\n       {\n        \"data\": {\n         \"text/plain\": [\n          \"array([[31130,  7677, 15408, 24406, 24165],\\n\",\n          \"       [ 1248, 15408,  4873, 17200, 27582],\\n\",\n          \"       [29860, 10373, 17200,  2761,  1761],\\n\",\n          \"       [21275, 21683, 15519,   802,  7088],\\n\",\n          \"       [ 9974,  8792, 19143, 12105,  3664]])\"\n         ]\n        },\n        \"execution_count\": 87,\n        \"metadata\": {},\n        \"output_type\": \"execute_result\"\n       }\n      ],\n      \"source\": [\n       \"top_idx = np.argpartition(tf_idf, -n)[:, -n:]\\n\",\n       \"top_idx\"\n      ]\n     }\n    ],\n    \"metadata\": {\n     \"interpreter\": {\n      \"hash\": \"e81a84c338879f0412495ea98350e80595740634d3ce0fba8d30f35c60f1a4c3\"\n     },\n     \"kernelspec\": {\n      \"display_name\": \"Python 3.8.12 ('stoic')\",\n      \"language\": \"python\",\n      \"name\": \"python3\"\n     },\n     \"language_info\": {\n      \"codemirror_mode\": {\n       \"name\": \"ipython\",\n       \"version\": 3\n      },\n      \"file_extension\": \".py\",\n      \"mimetype\": \"text/x-python\",\n      \"name\": \"python\",\n      \"nbconvert_exporter\": \"python\",\n      \"pygments_lexer\": \"ipython3\",\n      \"version\": \"3.8.12\"\n     },\n     \"orig_nbformat\": 4\n    },\n    \"nbformat\": 4,\n    \"nbformat_minor\": 2\n   }\n   "
}
```

Now we map those index positions back to the original words in the `vocab`.

```json
{
  "_key": "d044db32fb2e",
  "_type": "colabBlock",
  "jsonContent": "{\n    \"cells\": [\n     {\n      \"cell_type\": \"code\",\n      \"execution_count\": 88,\n      \"metadata\": {},\n      \"outputs\": [\n       {\n        \"name\": \"stdout\",\n        \"output_type\": \"stream\",\n        \"text\": [\n         \"['like', 'im', 'would', 'stock', 'market']\\n\",\n         \"['data', 'would', 'nlp', 'model', 'text']\\n\",\n         \"['training', 'pytorch', 'model', 'gt', 'x']\\n\",\n         \"['using', 'project', 'use', 'code', 'python']\\n\",\n         \"['useful', 'include', 'consider', 'financial', 'relevant']\\n\"\n        ]\n       }\n      ],\n      \"source\": [\n       \"vlist = list(vocab)\\n\",\n       \"\\n\",\n       \"for c, _class in enumerate(classes.keys()):\\n\",\n       \"    topn_idx = top_idx[c, :]\\n\",\n       \"    topn_terms = [vlist[idx] for idx in topn_idx]\\n\",\n       \"    print(topn_terms)\"\n      ]\n     }\n    ],\n    \"metadata\": {\n     \"interpreter\": {\n      \"hash\": \"e81a84c338879f0412495ea98350e80595740634d3ce0fba8d30f35c60f1a4c3\"\n     },\n     \"kernelspec\": {\n      \"display_name\": \"Python 3.8.12 ('stoic')\",\n      \"language\": \"python\",\n      \"name\": \"python3\"\n     },\n     \"language_info\": {\n      \"codemirror_mode\": {\n       \"name\": \"ipython\",\n       \"version\": 3\n      },\n      \"file_extension\": \".py\",\n      \"mimetype\": \"text/x-python\",\n      \"name\": \"python\",\n      \"nbconvert_exporter\": \"python\",\n      \"pygments_lexer\": \"ipython3\",\n      \"version\": \"3.8.12\"\n     },\n     \"orig_nbformat\": 4\n    },\n    \"nbformat\": 4,\n    \"nbformat_minor\": 2\n   }\n   "
}
```

Here we have the top five most relevant words for each cluster, each identifying the most relevant topics in each subreddit.

## Back to BERTopic

We’ve covered a considerable amount, but can we apply what we have learned to the BERTopic library?

Fortunately, all we need are a few lines of code. As before, we initialize our custom embedding, UMAP, and HDBSCAN components.

```python
from sentence_transformers import SentenceTransformer
from umap import UMAP
from hdbscan import HDBSCAN

embedding_model = SentenceTransformer('all-MiniLM-L6-v2')
umap_model = UMAP(n_neighbors=3, n_components=3, min_dist=0.05)
hdbscan_model = HDBSCAN(min_cluster_size=80, min_samples=40,
                        gen_min_span_tree=True,
                        prediction_data=True)
```

You might notice that we have added `prediction_data=True` as a new parameter to `HDBSCAN`. We need this to avoid an **AttributeError** when integrating our custom HDBSCAN step with BERTopic. Adding `gen_min_span_tree` adds another step to HDBSCAN that can improve the resultant clusters.

We must also initialize a `vectorizer_model` to handle stopword removal during the c-TF-IDF step. We will use the list of stopwords from NLTK but add a few more tokens that seem to pollute the results.

```python
from sklearn.feature_extraction.text import CountVectorizer
from nltk.corpus import stopwords

stopwords = list(stopwords.words('english')) + ['http', 'https', 'amp', 'com']

# we add this to remove stopwords that can pollute topcs
vectorizer_model = CountVectorizer(ngram_range=(1, 2), stop_words=stopwords)
```

We’re now ready to pass all of these to a `BERTopic` instance and process our Reddit topics data.

```python
from bertopic import BERTopic

model = BERTopic(
    umap_model=umap_model,
    hdbscan_model=hdbscan_model,
    embedding_model=embedding_model,
    vectorizer_model=vectorizer_model,
    top_n_words=5,
    language='english',
    calculate_probabilities=True,
    verbose=True
)
topics, probs = model.fit_transform(data['selftext'])
```

We can visualize the new topics with `model.visualize_barchart()`

![Our final topics produced using the BERTopic library with the tuned UMAP and HDBSCAN parameters.](https://cdn.sanity.io/images/vr8gru94/production/187d913efbab0120010f5adc0b70f9070953f15f-1000x325.png)


We can see the topics align perfectly with _r/investing_, _r/pytorch_, _r/LanguageTechnology_, and _r/Python_.

Transformers, UMAP, HDBSCAN, and c-TF-IDF are clearly powerful components that have huge applications when working with unstructured text data. BERTopic has abstracted away much of the complexity of this stack, allowing us to apply these technologies with nothing more than a few lines of code.

Although BERTopic can be simple, you have seen that it is possible to dive quite deeply into the individual components. With a high-level understanding of those components, we can greatly improve our topic modeling performance.

We have covered the essentials here, but we genuinely are just scratching the surface of topic modeling in this article. There is much more to BERTopic and each component than we could ever hope to cover in a single article.

So go and apply what you have learned here, and remember that despite showing the incredible performance of BERTopic shown here, there is even more that it can do.

## Resources

🔗 [All Notebook Scripts](https://github.com/pinecone-io/examples/tree/72549a14ec5fcd0befd6c791386e84fc9af31639/learn/experimental/algos-and-libraries/bertopic)

[1] M. Grootendorst, [BERTopic Repo](https://github.com/MaartenGr/BERTopic), GitHub

[2] M. Grootendorst, [BERTopic: Neural Topic Modeling with a Class-based TF-IDF Procedure](https://arxiv.org/abs/2203.05794) (2022)

[3] L. McInnes, J. Healy, J. Melville, [UMAP: Uniform Manifold Approximation and Projection for Dimension Reduction](https://arxiv.org/abs/1802.03426) (2018)

[4] L. McInnes, [Talk on UMAP for Dimension Reduction](https://www.youtube.com/watch?v=nq6iPZVUxZU) (2018), SciPy 2018

[5] J. Healy, [HDBSCAN, Fast Density Based Clustering, the How and the Why](https://www.youtube.com/watch?v=dGsxd67IFiU) (2018), PyData NYC 2018

[6] L. McInnes, [A Bluffer’s Guide to Dimension Reduction](https://www.youtube.com/watch?v=9iol3Lk6kyU) (2018), PyData NYC 2018

[UMAP Explained](https://www.youtube.com/watch?v=6BPl81wGGP8), AI Coffee Break with Letitia, YouTube