1. סקירה כללית
בשיעור Lab הזה תלמדו איך להשתמש ב-BigQuery DataFrames מ-notebook של Python ב-BigQuery Studio כדי להפיק תובנות מהנתונים באמצעות Python. שימוש ב-AI גנרטיבי מבית Google כדי לנתח נתוני טקסט לא מובנה ולהציג אותם כגרפיקה.
תלמדו ליצור מסמך Python כדי לסווג ולסכם מסד נתונים ציבורי של תלונות של לקוחות. אפשר להתאים את הפתרון הזה לכל נתוני טקסט לא מובְנים.
מטרות
בשיעור ה-Lab הזה תלמדו איך לבצע את המשימות הבאות:
- הפעלה של מחברות Python ושימוש בהן ב-BigQuery Studio
- התחברות ל-BigQuery באמצעות החבילה BigQuery DataFrames
- יצירת הטמעות (embeddings) מנתוני טקסט לא מובנים באמצעות BigQuery ML וחיבור לנקודת קצה להטמעת טקסט ב-Vertex AI
- הטמעת מודלים של אשכולות באמצעות BigQuery ML
- סיכום אשכולות באמצעות LLM דרך BigQuery ML
2. דרישות
לפני שמתחילים
כדי לפעול לפי ההוראות במדריך הזה, תצטרכו פרויקט ב-Google Cloud שבו מופעל BigQuery Studio וחשבון חיוב מחובר.
- במסוף Google Cloud, בדף לבחירת הפרויקט, בוחרים או יוצרים פרויקט ב-Google Cloud.
- מוודאים שהחיוב מופעל בפרויקט שלכם ב-Google Cloud. כך בודקים אם החיוב מופעל בפרויקט
- פועלים לפי ההוראות להפעלת BigQuery Studio לניהול נכסים.
הכנת BigQuery Studio
יוצרים מחברת ריקה ומחברים אותה לסביבת זמן ריצה.
- עוברים אל BigQuery Studio במסוף Google Cloud.
- לוחצים על ▼ לצד הלחצן +.
- בוחרים באפשרות Python notebook.
- סוגרים את בורר התבניות.
- בוחרים באפשרות + קוד כדי ליצור תא קוד חדש.
- מתקינים את הגרסה האחרונה של חבילת BigQuery DataFrames מתא הבקרה של הקוד.מקלידים את הפקודה הבאה.
לוחצים על הלחצן 🞂 או על Shift + Enter כדי להריץ את תא הקוד.%pip install --upgrade bigframes --quiet
3. קריאה של מערך נתונים ציבורי
כדי לאתחל את החבילה BigQuery DataFrames, מריצים את הפקודה הבאה בתא קוד חדש:
import bigframes.pandas as bpd
bpd.options.bigquery.ordering_mode = "partial"
הערה: במדריך הזה אנחנו משתמשים ב'מצב סדר חלקי' הניסיוני, שמאפשר לבצע שאילתות יעילות יותר כשמשתמשים בו עם סינון מסוג pandas. יכול להיות שחלק מהתכונות של pandas שדורשות סדר או אינדקס קפדניים לא יפעלו.
מסד נתונים של תלונות צרכנים
מסד הנתונים של תלונות הצרכנים זמין ב-BigQuery דרך תוכנית מערכי הנתונים הציבוריים של Google Cloud. מדובר באוסף של תלונות על מוצרים ושירותים פיננסיים לצרכן. הנתונים נאספים על ידי הלשכה להגנה על זכויות צרכן בארצות הברית.
ב-BigQuery, מריצים שאילתה על הטבלה bigquery-public-data.cfbp_complaints.complaint_database כדי לנתח את מסד הנתונים של תלונות הצרכנים. משתמשים ב-method bigframes.pandas.read_gbq()
כדי ליצור DataFrame ממחרוזת שאילתה או ממזהה טבלה.
מריצים את הקוד הבא בתא קוד חדש כדי ליצור DataFrame בשם feedback:
feedback = bpd.read_gbq(
"bigquery-public-data.cfpb_complaints.complaint_database"
)
מידע בסיסי על DataFrame
משתמשים בשיטה DataFrame.peek()
כדי להוריד דגימה קטנה של הנתונים.
מריצים את התא הזה:
feedback.peek()
הפלט הצפוי:
date_received product ... timely_response consumer_disputed complaint_id
0 2014-03-05 Bank account or service ... True False 743665
1 2014-01-21 Bank account or service ... True False 678608
2 2020-12-31 Debt collection ... True <NA> 4041190
3 2014-02-12 Debt collection ... True False 714350
4 2015-02-23 Debt collection ... True False 1251358
הערה: כדי להציג גרפית דגימת נתונים, צריך להשתמש ב-head()
, אבל בדרך כלל האפשרות הזו פחות יעילה מ-peek()
.
בדומה ל-pandas, משתמשים במאפיין DataFrame.dtypes
כדי לראות את כל העמודות הזמינות ואת סוגי הנתונים התואמים שלהן. הם נחשפים באופן תואם ל-pandas.
מריצים את התא הזה:
feedback.dtypes
הפלט הצפוי:
date_received date32[day][pyarrow]
product string[pyarrow]
subproduct string[pyarrow]
issue string[pyarrow]
subissue string[pyarrow]
consumer_complaint_narrative string[pyarrow]
company_public_response string[pyarrow]
company_name string[pyarrow]
state string[pyarrow]
zip_code string[pyarrow]
tags string[pyarrow]
consumer_consent_provided string[pyarrow]
submitted_via string[pyarrow]
date_sent_to_company date32[day][pyarrow]
company_response_to_consumer string[pyarrow]
timely_response boolean
consumer_disputed boolean
complaint_id string[pyarrow]
dtype: object
השיטה DataFrame.describe()
שולחת שאילתות על נתונים סטטיסטיים בסיסיים מ-DataFrame. מאחר ש-DataFrame הזה לא מכיל עמודות מספריות, מוצג בו סיכום של מספר הערכים שאינם null ומספר הערכים הייחודיים.
מריצים את התא הזה:
# Exclude some of the larger columns to make the query more efficient.
feedback.drop(columns=[
"consumer_complaint_narrative",
"company_public_response",
"company_response_to_consumer",
]).describe()
הפלט הצפוי:
product subproduct issue subissue company_name state ... timely_response consumer_disputed complaint_id
count 3458906 3223615 3458906 2759004 3458906 3417792 ... 3458906 768399 3458906
nunique 18 76 165 221 6694 63 ... 2 2 3458906
4. ניתוח הנתונים
לפני שמתעמקים בבדיקה של התלונות בפועל, משתמשים בשיטות שדומות ל-pandas ב-DataFrame כדי להציג את הנתונים באופן חזותי.
הצגה חזותית של DataFrame
יש כמה שיטות מובנות להצגה חזותית, כמו DataFrame.plot.hist(). מכיוון ש-DataFrame הזה מכיל בעיקר מחרוזות ונתונים בוליאניים, אפשר קודם לבצע צבירת נתונים כדי לקבל מידע נוסף על עמודות שונות.
ספירת מספר התלונות שמתקבלות מכל מדינה.
complaints_by_state = (
feedback.groupby(
"state", as_index=False,
).size()
.rename(columns={"size": "total_complaints"})
.sort_values(by="total_complaints", ascending=False)
)
ממירים את זה ל-DataFrame של pandas באמצעות השיטה DataFrame.to_pandas()
.
complaints_pd = complaints_by_state.head(10).to_pandas()
משתמשים בשיטות להמחשה חזותית של pandas ב-DataFrame שהורדתם.
complaints_pd.plot.bar(x="state", y="total_complaints")
איחוד עם מערכי נתונים אחרים
בעבר, בדקתם את התלונות לפי מדינה, אבל כך אתם מפספסים הקשר חשוב. בחלק מהמדינות יש אוכלוסייה גדולה יותר מאשר במדינות אחרות. יצירת צירוף עם מערך נתונים של אוכלוסייה, כמו הסקר האמריקאי של הקהילות של מפקד האוכלוסין בארה"ב והטבלה bigquery-public-data.geo_us_boundaries.states
.
us_states = bpd.read_gbq("bigquery-public-data.geo_us_boundaries.states")
us_survey = bpd.read_gbq("bigquery-public-data.census_bureau_acs.state_2020_5yr")
# Ensure there are leading 0s on GEOIDs for consistency across tables.
us_states = us_states.assign(
geo_id=us_states["geo_id"].str.pad(2, fillchar="0")
)
us_survey = us_survey.assign(
geo_id=us_survey["geo_id"].str.pad(2, fillchar="0")
)
ב-American Community Survey, המדינות מזוהות לפי GEOID. משלבים עם טבלת המדינות כדי לקבל את האוכלוסייה לפי קוד המדינה בן שתי האותיות.
pops = us_states.set_index("geo_id")[["state"]].join(
us_survey.set_index("geo_id")[["total_pop"]]
)
עכשיו משלבים את הטבלה הזו עם מסד הנתונים של התלונות כדי להשוות בין האוכלוסייה למספר התלונות.
complaints_and_pops = complaints_by_state.set_index("state").join(
pops.set_index("state")
)
יוצרים תרשים פיזור כדי להשוות בין אוכלוסיית המדינה למספר התלונות.
(
complaints_and_pops
.to_pandas()
.plot.scatter(x="total_pop", y="total_complaints")
)
יש כמה מדינות שנראות כחריגות בהשוואה בין האוכלוסייה למספר התלונות. הקוראים יכולים לתרגל את הנושא הזה על ידי הצגת הנקודות עם תוויות כדי לזהות אותן. כמו כן, כדאי לנסח כמה השערות לגבי הסיבות לכך (למשל, מאפיינים דמוגרפיים שונים, מספר שונה של חברות שירותים פיננסיים וכו') ולבדוק אותן.
5. חישוב הטמעות
לעיתים קרובות, מידע חשוב מוסתר בנתונים לא מובְנים, כמו טקסט, אודיו או תמונות. בדוגמה הזו, רוב המידע השימושי במסד הנתונים של התלונות נכלל בתוכן הטקסט של התלונה.
טכניקות קיימות ו-AI, כמו ניתוח סנטימנטים, 'תיקיית מילים' ו-word2vec, יכולים לחלץ מידע כמותי מסוים מנתונים לא מובְנים. לאחרונה, מודלים של 'הטמעת וקטורים', שקשורים מאוד ל-LLM, יכולים ליצור רצף של מספרים בנקודה צפה שמייצגים את המידע הסמנטי של הטקסט.
בחירת קבוצת משנה של מסד הנתונים
הפעלת מודל הטמעת וקטורים צורכת יותר משאבים מפעולות אחרות. כדי לצמצם את העלויות ואת הבעיות שקשורות למכסות, כדאי לבחור קבוצת משנה של הנתונים לצורך המשך המדריך.
import bigframes.pandas as bpd
bpd.options.bigquery.ordering_mode = "partial"
feedback = bpd.read_gbq(
"bigquery-public-data.cfpb_complaints.complaint_database"
)
# Note: if not using ordering_mode = "partial", you must specify these in read_gbq
# for these to affect query efficiency.
# feedback = bpd.read_gbq(
# "bigquery-public-data.cfpb_complaints.complaint_database",
# columns=["consumer_complaint_narrative"],
# filters= [
# ("consumer_complaint_narrative", "!=", ""),
# ("date_received", "==", "2022-12-01")])
feedback.shape
ב-1 בדצמבר 2022 נשלחו כ-1,000 תלונות, לעומת כ-3.5 מיליון שורות בסך הכול במסד הנתונים (לבדוק עם feedback.shape
).
בוחרים רק את הנתונים של 01 בדצמבר 2022 ורק את העמודה consumer_complaint_narrative
.
import datetime
feedback = feedback[
# Filter rows by passing in a boolean Series.
(feedback["date_received"] == datetime.date(2022, 12, 1))
& ~(feedback["date_received"].isnull())
& ~(feedback["consumer_complaint_narrative"].isnull())
& (feedback["consumer_complaint_narrative"] != "")
& (feedback["state"] == "CA")
# Uncomment the following if using free credits for a workshop.
# Billing accounts with free credits have limited Vertex AI quota.
# & (feedback["product"] == "Mortgage")
][
# Filter columns by passing in a list of strings.
["consumer_complaint_narrative"]
]
feedback.shape
כדי להשתמש בשיטה drop_duplicates
מ-pandas, צריך לסדר את השורות באופן מלא כי היא מנסה לבחור את השורה התואמת הראשונה או האחרונה ולשמור את המדד שמשויך אליה.
במקום זאת, מבצעים צבירה באמצעות קריאה ל-method groupby
כדי לבטל כפילויות בשורות.
feedback = (
feedback.groupby("consumer_complaint_narrative", as_index=False)
.size()
)[["consumer_complaint_narrative"]]
feedback.shape
יצירת הטמעות (embeddings)
BigQuery DataFrames יוצר וקטורים של הטמעה באמצעות הקלאס TextEmbeddingGenerator. הבדיקה מבוססת על השיטה ML.GENERATE_EMBEDDING
ב-BigQuery ML, שמפעילה את המודלים להטמעת טקסט ש-Vertex AI מספק.
from bigframes.ml.llm import TextEmbeddingGenerator
embedding_model = TextEmbeddingGenerator(
model_name="text-embedding-004"
)
feedback_embeddings = embedding_model.predict(feedback)
איך נראים הטמעות (embeddings) הווקטורים האלה מייצגים את המשמעות הסמנטית של הטקסט כפי שהיא מובנת למודל הטמעת הטקסט.
feedback_embeddings.peek()
הפלט הצפוי:
ml_generate_embedding_result \
0 [ 7.36380890e-02 2.11779331e-03 2.54309829e-...
1 [-1.10935252e-02 -5.53950183e-02 2.01338865e-...
2 [-7.85628427e-03 -5.39347418e-02 4.51385677e-...
3 [ 0.02013054 -0.0224789 -0.00164843 0.011354...
4 [-1.51684484e-03 -5.02693094e-03 1.72322839e-...
לווקטורים האלה יש הרבה מאפיינים. נבחן וקטור הטמעה יחיד:
feedback_embeddings["ml_generate_embedding_result"].peek().iloc[0]
היצירה של הטמעות פועלת בכפוף לחוזה מסוג 'הצלחה חלקית'. כלומר, יכול להיות שבחלק מהשורות יהיו שגיאות והן לא ייצרו הטמעה. הודעות השגיאה מוצגות בעמודה 'ml_generate_embedding_status'
. אם השדה ריק, סימן שאין שגיאות.
מסננים את הטמעות הקוד כך שיכללו רק שורות שבהן לא התרחשה שגיאה.
mask = feedback_embeddings["ml_generate_embedding_status"] == ""
valid_embeddings = feedback_embeddings[mask]
valid_embeddings.shape
6. קיבוץ באמצעות הטמעות טקסט
עכשיו, מקצים את ה-embeddings לאשכולות באמצעות k-means. בדגמה הזו, נשתמש במספר שרירותי של קבוצות (נקראות גם מרכזי מסה). בפתרון באיכות ייצור, צריך לשנות את מספר מרכזי הכובד באמצעות שיטה כמו שיטת Silhouette.
from bigframes.ml.cluster import KMeans
num_clusters = 5
cluster_model = KMeans(n_clusters=num_clusters)
cluster_model.fit(valid_embeddings["ml_generate_embedding_result"])
clusters = cluster_model.predict(valid_embeddings)
clusters.peek()
מסירים את כל הכשלים בהטמעה.
mask = clusters["ml_generate_embedding_status"] == ""
clusters = clusters[mask]
הצצה לחלוקת התגובות לפי מרכז כובד.
clusters.groupby("CENTROID_ID").size()
7. סיכום של האשכולות
מזינים כמה הערות שמשויכות לכל מרכז כובד ומבקשים מ-Gemini לסכם את התלונות. הנדסת הנחיות היא תחום חדש יחסית, אבל יש דוגמאות טובות באינטרנט, כמו https://www.promptingguide.ai/.
from bigframes.ml.llm import GeminiTextGenerator
preamble = "What is the main concern in this list of user complaints:"
suffix = "Write the main issue using a formal tone."
# Now let's sample the raw comments and get the LLM to summarize them.
prompts = []
for centroid_id in range(1, num_clusters + 1):
cluster = clusters[clusters["CENTROID_ID"] == centroid_id]
comments = "\n".join(["- {0}".format(x) for x in cluster.content.peek(40)])
prompts.append("{}:\n{}\n{}".format(preamble, comments, suffix))
prompt_df = bpd.DataFrame(prompts)
gemini = GeminiTextGenerator(model_name="gemini-1.5-flash-001")
issues = gemini.predict(X=prompt_df, temperature=0.0)
issues.peek()
משתמשים ב-Gemini כדי לכתוב דוח מהסיכומים.
from IPython.display import display, Markdown
prompt = "Turn this list of issues into a short, concise report:"
for value in issues["ml_generate_text_llm_result"]:
prompt += "- {}".format(value)
prompt += "Using a formal tone, write a markdown text format report."
summary_df = bpd.DataFrame(([prompt]))
summary = gemini.predict(X=summary_df, temperature=0.0)
report = (summary["ml_generate_text_llm_result"].values[0])
display(Markdown(report))
8. הסרת המשאבים
אם יצרתם פרויקט חדש ב-Google Cloud לצורך המדריך הזה, תוכלו למחוק אותו כדי למנוע חיובים נוספים על טבלאות או משאבים אחרים שיצרתם.
9. מעולה!
ניתחתם נתונים מובְנים ולא מובְנים באמצעות BigQuery DataFrames. לאורך הדרך, הכרתם את מערכי הנתונים הציבוריים של Google Cloud, את ספרי הקוד של Python ב-BigQuery Studio, את BigQuery ML, את Vertex AI ואת התכונות של BigQuery Studio להמרת שפה טבעית ל-Python. עבודה נהדרת!
השלבים הבאים
- כדאי לנסות ליצור קוד Python ב-notebook. קובצי notebook של Python ב-BigQuery Studio מבוססים על Colab Enterprise. טיפ: אני ממליץ לבקש עזרה ביצירת נתוני בדיקה.
- ב-GitHub תוכלו למצוא חיבורים לדפי קוד לדוגמה של BigQuery DataFrames.
- יצירת לוח זמנים להרצת מסמך ב-BigQuery Studio
- פריסת פונקציה מרוחקת עם BigQuery DataFrames כדי לשלב חבילות Python של צד שלישי עם BigQuery.