العرض على ai.google.dev | تجربة ورقة ملاحظات Colab | الاطّلاع على ورقة الملاحظات على GitHub |
نظرة عامة
يشرح هذا الدليل التوجيهي طريقة إنشاء نموذج مرئي وتنفيذ التجميع العنقودي باستخدام التضمينات من Gemini API. يمكنك عرض مجموعة فرعية من مجموعة بيانات Newsgroup البالغ عددها 20 مجموعة باستخدام t-SNE وتجميع هذه المجموعة الفرعية باستخدام خوارزمية KMeans.
لمزيد من المعلومات حول بدء استخدام التضمينات التي يتم إنشاؤها من Gemini API، يُرجى الاطّلاع على مقالة التشغيل السريع على Python.
المتطلبات الأساسية
يمكنك تشغيل دليل البدء السريع هذا في Google Colab.
لإكمال هذه البدء السريع في بيئة التطوير الخاصة بك، تأكد من أن بيئتك تفي بالمتطلبات التالية:
- Python 3.9+
- يجب تثبيت
jupyter
لتشغيل ورقة الملاحظات.
ضبط إعدادات الجهاز
أولاً، عليك تنزيل مكتبة Gemini API Python وتثبيتها.
pip install -U -q google.generativeai
import re
import tqdm
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import google.generativeai as genai
# Used to securely store your API key
from google.colab import userdata
from sklearn.datasets import fetch_20newsgroups
from sklearn.manifold import TSNE
from sklearn.cluster import KMeans
from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay
الحصول على مفتاح واجهة برمجة التطبيقات
لكي تتمكّن من استخدام Gemini API، يجب أولاً الحصول على مفتاح واجهة برمجة تطبيقات. إذا لم يكن لديك مفتاح، يمكنك إنشاء مفتاح بنقرة واحدة في Google AI Studio.
الحصول على مفتاح واجهة برمجة التطبيقات
في Colab، أضِف المفتاح إلى مدير المفاتيح السرّية ضمن "🔑". في اللوحة اليمنى. أدخِل الاسم API_KEY
.
بعد حصولك على مفتاح واجهة برمجة التطبيقات، أرسِله إلى حزمة تطوير البرامج (SDK). هناك طريقتان لإجراء ذلك:
- ضَع المفتاح في متغيّر البيئة
GOOGLE_API_KEY
(ستتولى حزمة تطوير البرامج (SDK) استلامه تلقائيًا من هناك). - تمرير المفتاح إلى
genai.configure(api_key=...)
genai.configure(api_key=GOOGLE_API_KEY)
for m in genai.list_models():
if 'embedContent' in m.supported_generation_methods:
print(m.name)
models/embedding-001 models/embedding-001
مجموعة البيانات
تضم مجموعة البيانات النصية لـ 20 مجموعة إخبارية 18,000 مجموعة إخبارية حول 20 موضوعًا مقسّمًا إلى مجموعات تدريب واختبار. يعتمد التقسيم بين مجموعات بيانات التدريب والاختبار على الرسائل المنشورة قبل وبعد تاريخ محدد. في هذا البرنامج التعليمي، ستستخدم المجموعة الفرعية للتدريب.
newsgroups_train = fetch_20newsgroups(subset='train')
# View list of class names for dataset
newsgroups_train.target_names
['alt.atheism', 'comp.graphics', 'comp.os.ms-windows.misc', 'comp.sys.ibm.pc.hardware', 'comp.sys.mac.hardware', 'comp.windows.x', 'misc.forsale', 'rec.autos', 'rec.motorcycles', 'rec.sport.baseball', 'rec.sport.hockey', 'sci.crypt', 'sci.electronics', 'sci.med', 'sci.space', 'soc.religion.christian', 'talk.politics.guns', 'talk.politics.mideast', 'talk.politics.misc', 'talk.religion.misc']
فيما يلي المثال الأول في مجموعة التطبيق.
idx = newsgroups_train.data[0].index('Lines')
print(newsgroups_train.data[0][idx:])
Lines: 15 I was wondering if anyone out there could enlighten me on this car I saw the other day. It was a 2-door sports car, looked to be from the late 60s/ early 70s. It was called a Bricklin. The doors were really small. In addition, the front bumper was separate from the rest of the body. This is all I know. If anyone can tellme a model name, engine specs, years of production, where this car is made, history, or whatever info you have on this funky looking car, please e-mail. Thanks, - IL ---- brought to you by your neighborhood Lerxst ----
# Apply functions to remove names, emails, and extraneous words from data points in newsgroups.data
newsgroups_train.data = [re.sub(r'[\w\.-]+@[\w\.-]+', '', d) for d in newsgroups_train.data] # Remove email
newsgroups_train.data = [re.sub(r"\([^()]*\)", "", d) for d in newsgroups_train.data] # Remove names
newsgroups_train.data = [d.replace("From: ", "") for d in newsgroups_train.data] # Remove "From: "
newsgroups_train.data = [d.replace("\nSubject: ", "") for d in newsgroups_train.data] # Remove "\nSubject: "
# Put training points into a dataframe
df_train = pd.DataFrame(newsgroups_train.data, columns=['Text'])
df_train['Label'] = newsgroups_train.target
# Match label to target name index
df_train['Class Name'] = df_train['Label'].map(newsgroups_train.target_names.__getitem__)
# Retain text samples that can be used in the gecko model.
df_train = df_train[df_train['Text'].str.len() < 10000]
df_train
بعد ذلك، ستقوم بعمل عينة من بعض البيانات عن طريق أخذ 100 نقطة بيانات في مجموعة بيانات التدريب، وإسقاط بعض الفئات لتشغيلها من خلال هذا البرنامج التعليمي. اختيار فئات العلوم التي تريد مقارنتها.
# Take a sample of each label category from df_train
SAMPLE_SIZE = 150
df_train = (df_train.groupby('Label', as_index = False)
.apply(lambda x: x.sample(SAMPLE_SIZE))
.reset_index(drop=True))
# Choose categories about science
df_train = df_train[df_train['Class Name'].str.contains('sci')]
# Reset the index
df_train = df_train.reset_index()
df_train
df_train['Class Name'].value_counts()
sci.crypt 150 sci.electronics 150 sci.med 150 sci.space 150 Name: Class Name, dtype: int64
إنشاء التضمينات
سنشرح في هذا القسم كيفية إنشاء تضمينات للنصوص المختلفة في إطار البيانات باستخدام التضمينات من Gemini API.
تغييرات واجهة برمجة التطبيقات على عمليات التضمين باستخدام نموذج التضمين -001
بالنسبة إلى نموذج التضمينات الجديد بما في ذلك 001-001، هناك مَعلمة نوع مهمة جديدة وعنوان اختياري (صالحة فقط مع نوع الإجراء (task_type)=RETRIEVAL_DOCUMENT
).
تنطبق هذه المعلمات الجديدة فقط على أحدث نماذج التضمينات.وأنواع المهام هي:
نوع المهمّة | الوصف |
---|---|
RETRIEVAL_QUERY | لتحديد أن النص المقدم هو طلب بحث في إعداد البحث/الاسترجاع. |
RETRIEVAL_DOCUMENT | لتحديد أن النص المحدّد هو مستند في إعداد البحث/الاسترجاع. |
SEMANTIC_SIMILARITY | لتحديد أنه سيتم استخدام النص المحدّد في التشابه النصي الدلالي (STS). |
التصنيف | لتحديد أن التضمينات سيتم استخدامها للتصنيف. |
التصنيف | لتحديد أن التضمينات سيتم استخدامها للتجميع العنقودي. |
from tqdm.auto import tqdm
tqdm.pandas()
from google.api_core import retry
def make_embed_text_fn(model):
@retry.Retry(timeout=300.0)
def embed_fn(text: str) -> list[float]:
# Set the task_type to CLUSTERING.
embedding = genai.embed_content(model=model,
content=text,
task_type="clustering")
return embedding["embedding"]
return embed_fn
def create_embeddings(df):
model = 'models/embedding-001'
df['Embeddings'] = df['Text'].progress_apply(make_embed_text_fn(model))
return df
df_train = create_embeddings(df_train)
0%| | 0/600 [00:00<?, ?it/s]
خفض الأبعاد
طول متجه تضمين المستند هو 768. لعرض كيفية تجميع المستندات المضمّنة معًا، ستحتاج إلى تطبيق تقليل الأبعاد، إذ يمكنك فقط عرض عمليات التضمين في مساحة ثنائية أو ثلاثية الأبعاد. يجب أن تكون المستندات المتشابهة من حيث السياق أقرب إلى بعضها البعض في المساحة مقارنةً بالمستندات غير المتشابهة.
len(df_train['Embeddings'][0])
768
# Convert df_train['Embeddings'] Pandas series to a np.array of float32
X = np.array(df_train['Embeddings'].to_list(), dtype=np.float32)
X.shape
(600, 768)
ستقوم بتطبيق منهج التضمين العشوائي الموزع (t-SNE) الموزَّع بتنسيق t-SNE لخفض الأبعاد. يقلل هذا الأسلوب من عدد الأبعاد، مع الحفاظ على المجموعات العنقودية (النقاط القريبة من بعضها تظل قريبة من بعضها). بالنسبة إلى البيانات الأصلية، يحاول النموذج إنشاء توزيع تكون عليه نقاط البيانات الأخرى "جيران" (مثلاً، تحملان المعنى نفسه). ثم يحسن دالة موضوعية للحفاظ على توزيع مشابه في التصور.
tsne = TSNE(random_state=0, n_iter=1000)
tsne_results = tsne.fit_transform(X)
df_tsne = pd.DataFrame(tsne_results, columns=['TSNE1', 'TSNE2'])
df_tsne['Class Name'] = df_train['Class Name'] # Add labels column from df_train to df_tsne
df_tsne
fig, ax = plt.subplots(figsize=(8,6)) # Set figsize
sns.set_style('darkgrid', {"grid.color": ".6", "grid.linestyle": ":"})
sns.scatterplot(data=df_tsne, x='TSNE1', y='TSNE2', hue='Class Name', palette='hls')
sns.move_legend(ax, "upper left", bbox_to_anchor=(1, 1))
plt.title('Scatter plot of news using t-SNE');
plt.xlabel('TSNE1');
plt.ylabel('TSNE2');
plt.axis('equal')
(-46.191162300109866, 53.521015357971194, -39.96646995544434, 37.282975387573245)
مقارنة النتائج بالخوارزمية التصنيفية
التجميع العنقودي KMeans هو خوارزمية تجميع شائعة وتستخدم كثيرًا في التعلُّم غير الخاضع للإشراف. حيث تحدد بالتكرار أفضل نقاط مركزية لها، وتحدد كل مثال بأقرب نقطة مركزية لها. إدخال التضمينات مباشرة في خوارزمية KMeans لمقارنة تصوير التضمينات بأداء خوارزمية التعلم الآلي.
# Apply KMeans
kmeans_model = KMeans(n_clusters=4, random_state=1, n_init='auto').fit(X)
labels = kmeans_model.fit_predict(X)
df_tsne['Cluster'] = labels
df_tsne
fig, ax = plt.subplots(figsize=(8,6)) # Set figsize
sns.set_style('darkgrid', {"grid.color": ".6", "grid.linestyle": ":"})
sns.scatterplot(data=df_tsne, x='TSNE1', y='TSNE2', hue='Cluster', palette='magma')
sns.move_legend(ax, "upper left", bbox_to_anchor=(1, 1))
plt.title('Scatter plot of news using KMeans Clustering');
plt.xlabel('TSNE1');
plt.ylabel('TSNE2');
plt.axis('equal')
(-46.191162300109866, 53.521015357971194, -39.96646995544434, 37.282975387573245)
def get_majority_cluster_per_group(df_tsne_cluster, class_names):
class_clusters = dict()
for c in class_names:
# Get rows of dataframe that are equal to c
rows = df_tsne_cluster.loc[df_tsne_cluster['Class Name'] == c]
# Get majority value in Cluster column of the rows selected
cluster = rows.Cluster.mode().values[0]
# Populate mapping dictionary
class_clusters[c] = cluster
return class_clusters
classes = df_tsne['Class Name'].unique()
class_clusters = get_majority_cluster_per_group(df_tsne, classes)
class_clusters
{'sci.crypt': 1, 'sci.electronics': 3, 'sci.med': 2, 'sci.space': 0}
يمكنك الحصول على غالبية المجموعات في كل مجموعة، وملاحظة عدد الأعضاء الفعليين بهذه المجموعة.
# Convert the Cluster column to use the class name
class_by_id = {v: k for k, v in class_clusters.items()}
df_tsne['Predicted'] = df_tsne['Cluster'].map(class_by_id.__getitem__)
# Filter to the correctly matched rows
correct = df_tsne[df_tsne['Class Name'] == df_tsne['Predicted']]
# Summarise, as a percentage
acc = correct['Class Name'].value_counts() / SAMPLE_SIZE
acc
sci.space 0.966667 sci.med 0.960000 sci.electronics 0.953333 sci.crypt 0.926667 Name: Class Name, dtype: float64
# Get predicted values by name
df_tsne['Predicted'] = ''
for idx, rows in df_tsne.iterrows():
cluster = rows['Cluster']
# Get key from mapping based on cluster value
key = list(class_clusters.keys())[list(class_clusters.values()).index(cluster)]
df_tsne.at[idx, 'Predicted'] = key
df_tsne
للحصول على تمثيل بصري أفضل لأداء خوارزمية الخوارزمية التصنيفية (KMeans) المطبّقة على بياناتك، يمكنك استخدام مصفوفة التشويش. وتتيح لك مصفوفة التشويش تقييم أداء نموذج التصنيف بطريقة تتجاوز الدقة. يمكنك الاطّلاع على النقاط التي تم تصنيفها عن طريق الخطأ. ستحتاج إلى القيم الفعلية والقيم المتوقعة، التي جمعتها في إطار البيانات أعلاه.
cm = confusion_matrix(df_tsne['Class Name'].to_list(), df_tsne['Predicted'].to_list())
disp = ConfusionMatrixDisplay(confusion_matrix=cm,
display_labels=classes)
disp.plot(xticks_rotation='vertical')
plt.title('Confusion Matrix for Actual and Clustered Newsgroups');
plt.grid(False)
الخطوات التالية
لقد أنشأت الآن تصورك الخاص للتضمينات باستخدام التجميع العنقودي! حاول استخدام بياناتك النصية لعرضها على شكل تضمينات. يمكنك تقليل الأبعاد لإكمال خطوة العرض المرئي. يُرجى العلم أنّ TSNE هي أداة جيدة في تجميع الإدخالات، ولكن يمكن أن تستغرق وقتًا أطول للدمج أو قد تتعثر في الحد الأدنى المحلي. إذا واجهت هذه المشكلة، يمكنك استخدام أسلوب آخر وهو تحليل المكوّنات الأساسية (PCA).
وهناك أيضًا خوارزميات تجميع عنقودية أخرى بخلاف خوارزمية الخوارزمية التصنيفية، مثل التجميع المكاني القائم على الكثافة (DBSCAN).
لمزيد من المعلومات حول كيفية استخدام التضمينات، اطّلِع على هذه الفيديوهات التعليمية الأخرى: