ดูใน ai.google.dev | ลองใช้ Colab Notebook | ดูสมุดบันทึกใน 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
รับคีย์ API
คุณต้องได้รับคีย์ API ก่อนจึงจะใช้ Gemini API ได้ หากยังไม่มี ให้สร้างคีย์ในคลิกเดียวใน Google AI Studio
ใน Colab ให้เพิ่มคีย์ลงในเครื่องมือจัดการความลับใต้ "🔑" ในแผงด้านซ้าย ตั้งชื่อว่า API_KEY
เมื่อมีคีย์ API แล้ว ให้ส่งคีย์ดังกล่าวไปยัง 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
การเปลี่ยนแปลง API เกี่ยวกับการฝังที่มีการฝังโมเดล-001
สำหรับโมเดลการฝังใหม่ Embed-001 จะมีพารามิเตอร์ประเภทงานใหม่และชื่อที่ไม่บังคับ (ใช้ได้กับ Tasks_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 เพื่อให้เห็นภาพวิธีจัดกลุ่มเอกสารที่ฝังไว้ด้วยกัน คุณจะต้องใช้การลดมิติข้อมูลเนื่องจากคุณสามารถแสดงภาพการฝังในพื้นที่ 2 มิติหรือ 3 มิติเท่านั้น เอกสารที่มีบริบทคล้ายกันควรอยู่ใกล้กันในอวกาศ ไม่ใช่เอกสารที่ไม่เหมือนกัน
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-Distributed Stochastic Neighbor Embedding (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 เป็นอัลกอริทึมการจัดกลุ่มที่ได้รับความนิยมและมักใช้สําหรับการเรียนรู้แบบไม่มีการควบคุมดูแล โมเดลนี้จะกำหนดจุดศูนย์กลาง K ที่ดีที่สุด และกำหนดแต่ละตัวอย่างให้กับเซนทรอยด์ที่ใกล้ที่สุด ป้อนการฝังลงในอัลกอริทึม 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)
นอกจากนี้ยังมีอัลกอริทึมคลัสเตอร์อื่นๆ ที่อยู่นอกเหนือ KMeans เช่นกัน เช่น การจัดคลัสเตอร์เชิงพื้นที่ที่อิงตามความหนาแน่น (DBSCAN)
หากต้องการดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีใช้การฝัง โปรดดูบทแนะนำอื่นๆ เหล่านี้