🚀 Попробуйте Zilliz Cloud, полностью управляемый Milvus, бесплатно — ощутите 10-кратное увеличение производительности! Попробовать сейчас>

milvus-logo
LFAI
Главная
  • Home
  • Docs
  • Учебники

  • Кластеризация HDBSCAN

Кластеризация HDBSCAN с помощью Milvus

Open In Colab GitHub Repository

С помощью моделей глубокого обучения данные могут быть преобразованы во вкрапления, которые отражают значимые представления исходных данных. Применяя алгоритм кластеризации без контроля, мы можем объединить похожие точки данных в группы на основе присущих им закономерностей. HDBSCAN (Hierarchical Density-Based Spatial Clustering of Applications with Noise) - это широко используемый алгоритм кластеризации, который эффективно группирует точки данных, анализируя их плотность и расстояние. Он особенно полезен для обнаружения кластеров различной формы и размера. В этом блокноте мы будем использовать HDBSCAN с Milvus, высокопроизводительной векторной базой данных, для группировки точек данных в отдельные группы на основе их вкраплений.

HDBSCAN (Hierarchical Density-Based Spatial Clustering of Applications with Noise) - это алгоритм кластеризации, основанный на вычислении расстояний между точками данных в пространстве вкраплений. Эти вкрапления, созданные моделями глубокого обучения, представляют данные в высокоразмерной форме. Чтобы сгруппировать похожие точки данных, HDBSCAN определяет их близость и плотность, но эффективное вычисление этих расстояний, особенно для больших наборов данных, может быть сложной задачей.

Milvus, высокопроизводительная база данных векторов, оптимизирует этот процесс, сохраняя и индексируя вкрапления, что позволяет быстро находить похожие векторы. При совместном использовании HDBSCAN и Milvus обеспечивают эффективную кластеризацию больших наборов данных в пространстве вкраплений.

В этом блокноте мы используем модель встраивания BGE-M3 для извлечения встраиваний из набора данных новостных заголовков, используем Milvus для эффективного вычисления расстояний между встраиваниями, чтобы помочь HDBSCAN в кластеризации, а затем визуализируем результаты для анализа с помощью метода UMAP. Этот блокнот является адаптацией Milvus к статье Дилана Кастильо.

Подготовка

загрузите набор данных новостей с сайта https://www.kaggle.com/datasets/dylanjcastillo/news-headlines-2024/.

$ pip install "pymilvus[model]"
$ pip install hdbscan
$ pip install plotly
$ pip install umap-learn

Загрузить данные

Загрузите новостной набор данных с https://www.kaggle.com/datasets/dylanjcastillo/news-headlines-2024/, извлеките news_data_dedup.csv и поместите его в текущую директорию.

Извлечение вкраплений в Milvus

Мы создадим коллекцию с помощью Milvus и извлечем плотные вкрапления с помощью модели BGE-M3.

import pandas as pd
from dotenv import load_dotenv
from pymilvus.model.hybrid import BGEM3EmbeddingFunction
from pymilvus import FieldSchema, Collection, connections, CollectionSchema, DataType

load_dotenv()

df = pd.read_csv("news_data_dedup.csv")


docs = [
    f"{title}\n{description}" for title, description in zip(df.title, df.description)
]
ef = BGEM3EmbeddingFunction()

embeddings = ef(docs)["dense"]

connections.connect(uri="milvus.db")
  • Если вам нужна локальная векторная база данных только для небольшого масштаба данных или прототипирования, установка uri в качестве локального файла, например./milvus.db, является наиболее удобным методом, так как он автоматически использует Milvus Lite для хранения всех данных в этом файле.
  • Если у вас большой объем данных, скажем, более миллиона векторов, вы можете настроить более производительный сервер Milvus на Docker или Kubernetes. В этом случае используйте адрес и порт сервера в качестве uri, например,http://localhost:19530. Если вы включили функцию аутентификации на Milvus, используйте "<ваше_имя_пользователя>:<ваш_пароль>" в качестве токена, в противном случае не задавайте токен.
  • Если вы используете Zilliz Cloud, полностью управляемый облачный сервис для Milvus, настройте uri и token, которые соответствуют публичной конечной точке и ключу API в Zilliz Cloud.
fields = [
    FieldSchema(
        name="id", dtype=DataType.INT64, is_primary=True, auto_id=True
    ),  # Primary ID field
    FieldSchema(
        name="embedding", dtype=DataType.FLOAT_VECTOR, dim=1024
    ),  # Float vector field (embedding)
    FieldSchema(
        name="text", dtype=DataType.VARCHAR, max_length=65535
    ),  # Float vector field (embedding)
]

schema = CollectionSchema(fields=fields, description="Embedding collection")

collection = Collection(name="news_data", schema=schema)

for doc, embedding in zip(docs, embeddings):
    collection.insert({"text": doc, "embedding": embedding})
    print(doc)

index_params = {"index_type": "FLAT", "metric_type": "L2", "params": {}}

collection.create_index(field_name="embedding", index_params=index_params)

collection.flush()

Построение матрицы расстояний для HDBSCAN

HDBSCAN требует вычисления расстояний между точками для кластеризации, что может потребовать больших вычислительных затрат. Поскольку удаленные точки оказывают меньшее влияние на назначение кластеризации, мы можем повысить эффективность, вычислив топ-к ближайших соседей. В этом примере мы используем индекс FLAT, но для больших наборов данных Milvus поддерживает более продвинутые методы индексации, чтобы ускорить процесс поиска. Во-первых, нам нужно получить итератор для итерации коллекции Milvus, которую мы ранее создали.

import hdbscan
import numpy as np
import pandas as pd
import plotly.express as px
from umap import UMAP
from pymilvus import Collection

collection = Collection(name="news_data")
collection.load()

iterator = collection.query_iterator(
    batch_size=10, expr="id > 0", output_fields=["id", "embedding"]
)

search_params = {
    "metric_type": "L2",
    "params": {"nprobe": 10},
}  # L2 is Euclidean distance

ids = []
dist = {}

embeddings = []

Мы будем итерировать все вкрапления в коллекции Milvus. Для каждого вкрапления мы будем искать его топ-к соседей в той же коллекции, получать их идентификаторы и расстояния. Затем нам также нужно построить словарь для сопоставления исходного идентификатора с непрерывным индексом в матрице расстояний. После этого нужно создать матрицу расстояний, которая инициализируется всеми элементами как бесконечность, и заполнить ее искомыми элементами. Таким образом, расстояние между удаленными точками будет игнорироваться. Наконец, мы используем библиотеку HDBSCAN для кластеризации точек с помощью созданной матрицы расстояний. Нам нужно установить метрику на 'precomputed', чтобы указать, что данные - это матрица расстояний, а не оригинальные вкрапления.

while True:
    batch = iterator.next()
    batch_ids = [data["id"] for data in batch]
    ids.extend(batch_ids)

    query_vectors = [data["embedding"] for data in batch]
    embeddings.extend(query_vectors)

    results = collection.search(
        data=query_vectors,
        limit=50,
        anns_field="embedding",
        param=search_params,
        output_fields=["id"],
    )
    for i, batch_id in enumerate(batch_ids):
        dist[batch_id] = []
        for result in results[i]:
            dist[batch_id].append((result.id, result.distance))

    if len(batch) == 0:
        break

ids2index = {}

for id in dist:
    ids2index[id] = len(ids2index)

dist_metric = np.full((len(ids), len(ids)), np.inf, dtype=np.float64)

for id in dist:
    for result in dist[id]:
        dist_metric[ids2index[id]][ids2index[result[0]]] = result[1]

h = hdbscan.HDBSCAN(min_samples=3, min_cluster_size=3, metric="precomputed")
hdb = h.fit(dist_metric)

После этого кластеризация HDBSCAN завершена. Мы можем получить некоторые данные и показать их кластер. Обратите внимание, что некоторые данные не будут отнесены ни к одному кластеру, что означает, что они являются шумом, поскольку расположены в какой-то разреженной области.

Визуализация кластеров с помощью UMAP

Мы уже кластеризовали данные с помощью HDBSCAN и можем получить метки для каждой точки данных. Однако, используя некоторые методы визуализации, мы можем получить полную картину кластеров для интуитивного анализа. Сейчас мы будем использовать UMAP для визуализации кластеров. UMAP - это эффективный метод, используемый для уменьшения размерности, сохраняющий структуру высокоразмерных данных и проецирующий их в более низкоразмерное пространство для визуализации или дальнейшего анализа. С его помощью мы можем визуализировать исходные высокоразмерные данные в 2D- или 3D-пространстве и четко видеть кластеры. Здесь мы снова итерируем точки данных и получаем идентификатор и текст исходных данных, затем с помощью ploty строим график точек данных с этими метаданными на рисунке и используем разные цвета для представления различных кластеров.

import plotly.io as pio

pio.renderers.default = "notebook"

umap = UMAP(n_components=2, random_state=42, n_neighbors=80, min_dist=0.1)

df_umap = (
    pd.DataFrame(umap.fit_transform(np.array(embeddings)), columns=["x", "y"])
    .assign(cluster=lambda df: hdb.labels_.astype(str))
    .query('cluster != "-1"')
    .sort_values(by="cluster")
)
iterator = collection.query_iterator(
    batch_size=10, expr="id > 0", output_fields=["id", "text"]
)

ids = []
texts = []

while True:
    batch = iterator.next()
    if len(batch) == 0:
        break
    batch_ids = [data["id"] for data in batch]
    batch_texts = [data["text"] for data in batch]
    ids.extend(batch_ids)
    texts.extend(batch_texts)

show_texts = [texts[i] for i in df_umap.index]

df_umap["hover_text"] = show_texts
fig = px.scatter(
    df_umap, x="x", y="y", color="cluster", hover_data={"hover_text": True}
)
fig.show()

image изображение

Здесь мы демонстрируем, что данные хорошо кластеризованы, и вы можете навести курсор на точки, чтобы проверить текст, который они представляют. Мы надеемся, что с помощью этого блокнота вы узнаете, как эффективно использовать HDBSCAN для кластеризации вкраплений с помощью Milvus, что также может быть применено к другим типам данных. В сочетании с большими языковыми моделями этот подход позволяет проводить более глубокий анализ данных в больших масштабах.

Попробуйте Managed Milvus бесплатно

Zilliz Cloud работает без проблем, поддерживается Milvus и в 10 раз быстрее.

Начать
Обратная связь

Была ли эта страница полезной?