تجميع HDBSCAN مع ميلفوس
يمكن تحويل البيانات إلى تجميعات باستخدام نماذج التعلم العميق، والتي تلتقط تمثيلات ذات معنى للبيانات الأصلية. من خلال تطبيق خوارزمية تجميع غير خاضعة للإشراف، يمكننا تجميع نقاط البيانات المتشابهة معًا استنادًا إلى أنماطها المتأصلة. HDBSCAN (التجميع المكاني القائم على الكثافة الهرمي للتطبيقات مع الضوضاء) هي خوارزمية تجميع مستخدمة على نطاق واسع تقوم بتجميع نقاط البيانات بكفاءة من خلال تحليل كثافتها ومسافتها. وهي مفيدة بشكل خاص لاكتشاف التكتلات ذات الأشكال والأحجام المختلفة. في هذا الدفتر، سنستخدم HDBSCAN مع قاعدة بيانات Milvus، وهي قاعدة بيانات متجهة عالية الأداء، لتجميع نقاط البيانات في مجموعات متميزة بناءً على تضميناتها.
HDBSCAN (التجميع المكاني القائم على الكثافة الهرمية للتطبيقات مع الضوضاء) هي خوارزمية تجميع تعتمد على حساب المسافات بين نقاط البيانات في مساحة التضمين. تمثل هذه التضمينات، التي تم إنشاؤها بواسطة نماذج التعلم العميق، البيانات في شكل عالي الأبعاد. لتجميع نقاط البيانات المتشابهة، تحدد 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، ونستخرج تضمينات كثيفة باستخدام نموذج 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، استخدم "<your_username>: <your_password>" كرمز مميز، وإلا فلا تقم بتعيين الرمز المميز. - إذا كنت تستخدم Zilliz Cloud، الخدمة السحابية المُدارة بالكامل لـ Milvus، اضبط
uri
وtoken
، والتي تتوافق مع نقطة النهاية العامة ومفتاح واجهة برمجة التطبيقات في 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 = []
سنقوم بتكرار جميع التضمينات في مجموعة ميلفوس. لكل تضمين، سنبحث في كل تضمين عن جيرانه الأعلى-ك في نفس المجموعة، ونحصل على معرّفاتهم ومسافاتهم. ثم نحتاج أيضًا إلى إنشاء قاموس لتعيين المعرف الأصلي إلى فهرس متصل في مصفوفة المسافة. عند الانتهاء، نحتاج إلى إنشاء مصفوفة المسافة التي تمت تهيئتها بجميع العناصر على أنها ما لا نهاية وملء العناصر التي بحثنا عنها. بهذه الطريقة، سيتم تجاهل المسافة بين النقاط البعيدة. أخيرًا نستخدم مكتبة HDBSCAN لتجميع النقاط باستخدام مصفوفة المسافة التي أنشأناها. نحتاج إلى ضبط المقياس على "محسوب مسبقاً" للإشارة إلى أن البيانات هي مصفوفة المسافة بدلاً من التضمينات الأصلية.
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 هي طريقة فعّالة تُستخدم لتقليل الأبعاد، حيث تحافظ على بنية البيانات عالية الأبعاد مع إسقاطها في فضاء منخفض الأبعاد لتصورها أو إجراء مزيد من التحليل. باستخدامه، يمكننا تصور البيانات الأصلية عالية الأبعاد في فضاء ثنائي الأبعاد أو ثلاثي الأبعاد، ورؤية المجموعات بوضوح. هنا مرة أخرى، نقوم بتكرار نقاط البيانات ونحصل على المعرف والنص للبيانات الأصلية، ثم نستخدم التخطيط لرسم نقاط البيانات مع هذه المعلومات الوصفية في شكل، ونستخدم ألوانًا مختلفة لتمثيل المجموعات المختلفة.
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()
الصورة
نوضح هنا أن البيانات متجمعة بشكل جيد، ويمكنك التمرير فوق النقاط للتحقق من النص الذي تمثله. من خلال هذا الدفتر، نأمل أن تتعلم كيفية استخدام HDBSCAN لتجميع التضمينات باستخدام Milvus بكفاءة، والتي يمكن تطبيقها أيضًا على أنواع أخرى من البيانات. يسمح هذا النهج، إلى جانب نماذج اللغة الكبيرة، بتحليل أعمق لبياناتك على نطاق واسع.