AllTopicsTodayAllTopicsToday
Notification
Font ResizerAa
  • Home
  • Tech
  • Investing & Finance
  • AI
  • Entertainment
  • Wellness
  • Gaming
  • Movies
Reading: Clustering Unstructured Text with LLM Embeddings and HDBSCAN
Share
Font ResizerAa
AllTopicsTodayAllTopicsToday
  • Home
  • Blog
  • About Us
  • Contact
Search
  • Home
  • Tech
  • Investing & Finance
  • AI
  • Entertainment
  • Wellness
  • Gaming
  • Movies
Have an existing account? Sign In
Follow US
©AllTopicsToday 2026. All Rights Reserved.
AllTopicsToday > Blog > AI > Clustering Unstructured Text with LLM Embeddings and HDBSCAN
AI

Clustering Unstructured Text with LLM Embeddings and HDBSCAN

AllTopicsToday
Last updated: June 28, 2026 11:06 am
AllTopicsToday
Published: June 28, 2026
Share
SHARE

On this article, you’ll learn to construct a textual content clustering pipeline by combining massive language mannequin embeddings with HDBSCAN, a density-based clustering algorithm, to robotically uncover matters in unlabeled textual content knowledge.

Subjects we are going to cowl embrace:

Easy methods to generate textual content embeddings for uncooked paperwork utilizing a pre-trained sentence-transformers mannequin.
Easy methods to scale back the dimensionality of these embeddings with UMAP to arrange them for clustering.
Easy methods to apply HDBSCAN to robotically uncover matter clusters and visualize the outcomes.

Clustering Unstructured Text with LLM Embeddings and HDBSCAN

Clustering Unstructured Textual content with LLM Embeddings and HDBSCAN

Introduction

The present period of Generative AI appears to primarily concentrate on chat interfaces and prompts, however the vary of purposes of enormous language fashions, or LLMs for brief, just isn’t restricted to simply that. Certainly, one in all their strongest downstream skills consists of turning uncooked, messy, unstructured textual content into semantically wealthy mathematical representations referred to as embeddings. As soon as that’s accomplished, we are able to use these textual content representations for a wide range of machine studying use circumstances, with clustering being no exception.

Particularly, embeddings will be mixed with superior, density-based clustering methods like HDBSCAN, permitting in consequence for the invention of hidden matters, patterns, or classes in your assortment of textual content paperwork: all with out the necessity for prior labeling.

This text exhibits methods to assemble a text-based clustering pipeline from scratch. We are going to use a freely out there dataset containing textual content situations, in addition to an open-source LLM that has been educated for producing embeddings — i.e. a so-called embedding mannequin. The icing on the cake: we’ll use free and helpful, trendy Python libraries offering implementations of clustering algorithms like HDBSCAN.

Step-by-Step Walkthrough

First, let’s begin by putting in the important thing Python libraries we are going to want:

Sentence transformers, to load a pre-trained LLM for embedding technology from Hugging Face — you’ll want a Hugging Face API key, additionally referred to as an entry token, to have the ability to load the mannequin.
Umap-learn, to use an algorithm to cut back the dimensionality of embeddings.

Likewise, in case you are engaged on an area IDE as an alternative of a cloud pocket book atmosphere and don’t have scikit-learn and pandas, it’s possible you’ll want to put in them too.

!pip set up sentence-transformers umap-learn

!pip set up sentence–transformers umap–study

Now we begin the coding half by getting some contemporary knowledge. The fetch_20newsgroups operate, which fetches a dataset containing texts from categorized information articles, will do. Observe that though the dataset comprises labels, we are going to omit them, as we’re pretending to not know this data for the sake of clustering these knowledge situations into teams primarily based on similarity. Additionally, we pattern down the dataset to 150 situations, which shall be consultant sufficient for our instance.

import pandas as pd
from sklearn.datasets import fetch_20newsgroups

# Fetching a extremely focused subset of knowledge (~150-200 docs)
classes = [‘sci.space’, ‘sci.med’, ‘rec.autos’]
newsgroups = fetch_20newsgroups(subset=”practice”, classes=classes, take away=(‘headers’, ‘footers’, ‘quotes’))

# Sampling down right into a consultant, illustrative subset
df = pd.DataFrame({‘textual content’: newsgroups.knowledge, ‘true_label’: newsgroups.goal})
df = df[df[‘text’].str.strip().str.len() > 100].pattern(150, random_state=42).reset_index(drop=True)

print(f”Loaded {len(df)} textual content paperwork.”)
print(“nSample doc:”)
print(df[‘text’].iloc[0][:150] + “…”)

import pandas as pd

from sklearn.datasets import fetch_20newsgroups

 

# Fetching a extremely focused subset of knowledge (~150-200 docs)

classes = [‘sci.space’, ‘sci.med’, ‘rec.autos’]

newsgroups = fetch_20newsgroups(subset=‘practice’, classes=classes, take away=(‘headers’, ‘footers’, ‘quotes’))

 

# Sampling down right into a consultant, illustrative subset

df = pd.DataFrame({‘textual content’: newsgroups.knowledge, ‘true_label’: newsgroups.goal})

df = df[df[‘text’].str.strip().str.len() > 100].pattern(150, random_state=42).reset_index(drop=True)

 

print(f“Loaded {len(df)} textual content paperwork.”)

print(“nSample doc:”)

print(df[‘text’].iloc[0][:150] + “…”)

Output:

Loaded 150 textual content paperwork.

Pattern doc:

Okay Mr. Dyer, we’re correctly impressed together with your philosophical abilities and
capability to insult individuals. You are an exquisite speaker and an adept politic…

Loaded 150 textual content paperwork.

 

Pattern doc:

 

Okay Mr. Dyer, we‘re correctly impressed together with your philosophical abilities and

capability to insult individuals. You’re a great speaker and an adept politic...

The subsequent step is to acquire the embeddings from uncooked texts. To do that, we load all-MiniLM-L6-v2 from Hugging Face’s sentence-transformers library. It is a light-weight but efficient mannequin to acquire embeddings shortly.

from sentence_transformers import SentenceTransformer

# Loading the free, open-source mannequin
mannequin = SentenceTransformer(‘all-MiniLM-L6-v2’)

# Encoding textual content paperwork into dense vector embeddings
print(“Producing embeddings…”)
embeddings = mannequin.encode(df[‘text’].tolist(), show_progress_bar=True)

print(f”Embedding matrix form: {embeddings.form}”)

from sentence_transformers import SentenceTransformer

 

# Loading the free, open-source mannequin

mannequin = SentenceTransformer(‘all-MiniLM-L6-v2’)

 

# Encoding textual content paperwork into dense vector embeddings

print(“Producing embeddings…”)

embeddings = mannequin.encode(df[‘text’].tolist(), show_progress_bar=True)

 

print(f“Embedding matrix form: {embeddings.form}”)

For the reason that embedding dimension is initially too excessive for clustering functions, we now apply a dimensionality discount method through the use of the UMAP algorithm from the namesake library put in earlier:

import umap

# Decreasing embedding dimensions to five, to retain sufficient density data for clustering
reducer = umap.UMAP(n_neighbors=15, n_components=5, min_dist=0.0, random_state=42)
reduced_embeddings = reducer.fit_transform(embeddings)

print(f”Lowered matrix form: {reduced_embeddings.form}”)

import umap

 

# Decreasing embedding dimensions to five, to retain sufficient density data for clustering

reducer = umap.UMAP(n_neighbors=15, n_components=5, min_dist=0.0, random_state=42)

reduced_embeddings = reducer.fit_transform(embeddings)

 

print(f“Lowered matrix form: {reduced_embeddings.form}”)

Now our numerical embedding vectors related to information articles consist of 5 dimensions (attributes) solely. Let’s see if this compact illustration is significant sufficient to acquire insightful clustering by making use of the HDBSCAN algorithm, which is a density-based clustering strategy:

from sklearn.cluster import HDBSCAN

# Initializing HDBSCAN
# min_cluster_size=8: we specified that every cluster will need to have no less than 8 paperwork
clusterer = HDBSCAN(min_cluster_size=8, min_samples=3, store_centers=”centroid”)
df[‘cluster’] = clusterer.fit_predict(reduced_embeddings)

# Counting situations per cluster
cluster_counts = df[‘cluster’].value_counts()
print(“nCluster Distribution:”)
print(cluster_counts)

from sklearn.cluster import HDBSCAN

 

# Initializing HDBSCAN

# min_cluster_size=8: we specified that every cluster will need to have no less than 8 paperwork

clusterer = HDBSCAN(min_cluster_size=8, min_samples=3, store_centers=‘centroid’)

df[‘cluster’] = clusterer.fit_predict(reduced_embeddings)

 

# Counting situations per cluster

cluster_counts = df[‘cluster’].value_counts()

print(“nCluster Distribution:”)

print(cluster_counts)

Vital: the clustering outcomes are partly influenced by the hyperparameter settings we outlined for HDBSCAN. I like to recommend you check out different configurations for the minimal cluster dimension and different hyperparameters to discover how this impacts outcomes.

Outcome:

Cluster Distribution:
cluster
0 101
1 49
Identify: rely, dtype: int64

Cluster Distribution:

cluster

0    101

1     49

Identify: rely, dtype: int64

It appears to be like like HDBSCAN detected two clusters related to high-density areas within the knowledge house. Would there even be noisy factors that weren’t allotted to both of those two clusters? Let’s examine:

for cluster_id in sorted(df[‘cluster’].distinctive()):
if cluster_id == -1:
print(“n=== CLUSTER: NOISE / UNCLASSIFIED ===”)
else:
print(f”n=== CLUSTER: Found Matter #{cluster_id} ===”)

# Getting as much as 3 pattern texts from this cluster
samples = df[df[‘cluster’] == cluster_id][‘text’].head(3).tolist()
for i, pattern in enumerate(samples, 1):
clean_sample = ” “.be part of(pattern.break up())[:120]
print(f” {i}. {clean_sample}…”)

for cluster_id in sorted(df[‘cluster’].distinctive()):

    if cluster_id == –1:

        print(“n=== CLUSTER: NOISE / UNCLASSIFIED ===”)

    else:

        print(f“n=== CLUSTER: Found Matter #{cluster_id} ===”)

        

    # Getting as much as 3 pattern texts from this cluster

    samples = df[df[‘cluster’] == cluster_id][‘text’].head(3).tolist()

    for i, pattern in enumerate(samples, 1):

        clean_sample = ” “.be part of(pattern.break up())[:120]

        print(f”  {i}. {clean_sample}…”)

Output:

=== CLUSTER: Found Matter #0 ===
1. Okay Mr. Dyer, we’re correctly impressed together with your philosophical abilities and skill to insult individuals. You are an exquisite …
2. I used to be at an attention-grabbing seminar at work (UK’s R.A.L. House Science Dept.) on this topic, particularly on a small-scale…
3. That is the second put up which appears to be blurring the excellence between actual illness attributable to Candida albicans and t…

=== CLUSTER: Found Matter #1 ===
1. It is nice that every one these different automobiles can out-handle, out-corner, and out- speed up an Integra. However, you have to ask …
2. l diamond star automobiles (Talon/Eclipse/Laser) put out 190 hp within the turbo fashions, and 195 hp within the AWD turbo fashions, These …
3. Sorry for the mis-spelling, however I forgot methods to spell it after my collection of exams and NO-on hand reference right here. Is it s…

=== CLUSTER: Found Matter #0 ===

  1. Okay Mr. Dyer, we‘re correctly impressed together with your philosophical abilities and skill to insult individuals. You’re a great ...

  2. I was at an attention-grabbing seminar at work (UK‘s R.A.L. House Science Dept.) on this topic, particularly on a small-scale…

  3. That is the second put up which appears to be blurring the excellence between actual illness attributable to Candida albicans and t…

 

=== CLUSTER: Found Matter #1 ===

  1. It’s nice that all these different automobiles can out–deal with, out–nook, and out– speed up an Integra. However, you‘ve obtained to ask ...

  2. l diamond star automobiles (Talon/Eclipse/Laser) put out 190 hp in the turbo fashions, and 195 hp in the AWD turbo fashions, These ...

  3. Sorry for the mis–spelling, however I forgot how to spell it after my collection of exams and NO–on hand reference right here. Is it s...

Looks as if all knowledge factors within the pattern of 150 had been allotted to both one of many two clusters recognized, thus hinting on the clue that the information articles would possibly simply separable in response to matter.

For additional perception, we are able to present some cluster visualizations with the help of the supplementary code offered beneath, which exhibits a scatterplot for each pairwise mixture of the 5 present elements that describe every knowledge level:

import matplotlib.pyplot as plt
import seaborn as sns
import itertools

# Making a DataFrame for the 5 decreased embeddings and cluster labels
reduced_df = pd.DataFrame(reduced_embeddings, columns=[f’UMAP_D{i+1}’ for i in range(reduced_embeddings.shape[1])])
reduced_df[‘cluster’] = df[‘cluster’]

# Getting all distinctive pairwise combos of the 5 dimensions
dim_pairs = checklist(itertools.combos(reduced_df.columns[:-1], 2))

num_plots = len(dim_pairs)
num_cols = 3
num_rows = (num_plots + num_cols – 1) // num_cols

plt.determine(figsize=(num_cols * 5, num_rows * 4))

for i, (dim1, dim2) in enumerate(dim_pairs):
plt.subplot(num_rows, num_cols, i + 1)
sns.scatterplot(
x=dim1,
y=dim2,
hue=”cluster”,
knowledge=reduced_df,
palette=”viridis”,
s=70,
alpha=0.7,
legend=’full’
)
plt.title(f'{dim1} vs {dim2}’)
plt.xlabel(dim1)
plt.ylabel(dim2)
plt.grid(True, linestyle=”–“, alpha=0.6)

plt.tight_layout()
plt.present()

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

import matplotlib.pyplot as plt

import seaborn as sns

import itertools

 

# Making a DataFrame for the 5 decreased embeddings and cluster labels

reduced_df = pd.DataFrame(reduced_embeddings, columns=[f‘UMAP_D{i+1}’ for i in range(reduced_embeddings.shape[1])])

reduced_df[‘cluster’] = df[‘cluster’]

 

# Getting all distinctive pairwise combos of the 5 dimensions

dim_pairs = checklist(itertools.combos(reduced_df.columns[:–1], 2))

 

num_plots = len(dim_pairs)

num_cols = 3

num_rows = (num_plots + num_cols – 1) // num_cols

 

plt.determine(figsize=(num_cols * 5, num_rows * 4))

 

for i, (dim1, dim2) in enumerate(dim_pairs):

    plt.subplot(num_rows, num_cols, i + 1)

    sns.scatterplot(

        x=dim1,

        y=dim2,

        hue=‘cluster’,

        knowledge=reduced_df,

        palette=‘viridis’,

        s=70,

        alpha=0.7,

        legend=‘full’

    )

    plt.title(f‘{dim1} vs {dim2}’)

    plt.xlabel(dim1)

    plt.ylabel(dim2)

    plt.grid(True, linestyle=‘–‘, alpha=0.6)

 

plt.tight_layout()

plt.present()

Outcome:

Clustering visualizations

By making an attempt totally different configurations for HDBSCAN, it’s possible you’ll come throughout outcomes during which the variety of recognized clusters might be totally different from two. Simply give it a attempt!

Wrapping Up

As soon as we now have gone via the method of constructing the text-based clustering pipeline, it’s value concluding by mentioning the important thing explanation why placing collectively LLM embeddings with HDBSCAN is value it. These embrace the power to retain and seize, to some extent, the true semantic which means and linguistic nuances of the unique textual content, due to the properties inherent to embeddings obtained via sentence-transformers. Furthermore, HDBSCAN robotically determines an optimum variety of clusters and is ready to detect outlying factors that is likely to be noise or outliers that will distort group-level statistics.

Iran may ‘lash out harder’ following Khamenei’s death
Embedding Gemma: On-Device RAG Made Easy
Omada (OMDA) Q2 2025 earnings
Anthropic reveals the dark side of AI
Meta pay $375 million for violating New Mexico law in child exploitation case
Share This Article
Facebook Email Print
Leave a Comment

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Follow US

Find US on Social Medias
FacebookLike
XFollow
YoutubeSubscribe
TelegramFollow

Weekly Newsletter

Subscribe to our newsletter to get our newest articles instantly!
Popular News
Pizzaquinoabites5.png
Wellness

High-Protein Pizza Quinoa Bites

AllTopicsToday
AllTopicsToday
October 28, 2025
Top 10 Open-Source Libraries to Fine-Tune LLMs Locally
Top LLM Inference Providers Compared
How to Romance All Characters in Starsand Island
OpenAI denies that it’s weighing a ‘last-ditch’ California exit amid regulatory pressure over its restructuring
- Advertisement -
Ad space (1)

Categories

  • Tech
  • Investing & Finance
  • AI
  • Entertainment
  • Wellness
  • Gaming
  • Movies

About US

We believe in the power of information to empower decisions, fuel curiosity, and spark innovation.
Quick Links
  • Home
  • Blog
  • About Us
  • Contact
Important Links
  • About Us
  • Privacy Policy
  • Terms and Conditions
  • Disclaimer
  • Contact

Subscribe US

Subscribe to our newsletter to get our newest articles instantly!

©AllTopicsToday 2026. All Rights Reserved.
1 2
Welcome Back!

Sign in to your account

Username or Email Address
Password

Lost your password?