1. ภาพรวม
ใน Lab นี้ คุณจะได้ใช้ DataFrame ของ BigQuery จาก Notebook ของ Python ใน BigQuery Studio เพื่อรับข้อมูลเชิงลึกจากข้อมูลโดยใช้ Python ใช้ Generative AI ของ Google เพื่อวิเคราะห์และแสดงภาพข้อมูลข้อความที่ไม่มีโครงสร้าง
คุณจะสร้าง Notebook ของ Python เพื่อจัดหมวดหมู่และสรุปฐานข้อมูลการร้องเรียนของลูกค้าแบบสาธารณะ ซึ่งสามารถปรับให้ทำงานกับข้อมูลข้อความที่ไม่มีโครงสร้างได้
วัตถุประสงค์
ในแล็บนี้ คุณจะได้เรียนรู้วิธีทำงานต่อไปนี้
- เปิดใช้งานและใช้ Notebook ของ Python ใน BigQuery Studio
- เชื่อมต่อกับ BigQuery โดยใช้แพ็กเกจ BigQuery DataFrames
- สร้างการฝังจากข้อมูลข้อความที่ไม่มีโครงสร้างโดยใช้ BigQuery ML และการเชื่อมต่อกับปลายทางการฝังข้อความใน Vertex AI
- จัดกลุ่มการฝังโดยใช้ BigQuery ML
- สรุปคลัสเตอร์ด้วย LLM ผ่าน BigQuery ML
2. ข้อกำหนด
ก่อนเริ่มต้น
หากต้องการทำตามวิธีการในโค้ดแล็บนี้ คุณจะต้องมีโปรเจ็กต์ Google Cloud ที่เปิดใช้ BigQuery Studio และบัญชีสำหรับการเรียกเก็บเงินที่เชื่อมต่อ
- ในคอนโซล Google Cloud ให้เลือกหรือสร้างโปรเจ็กต์ Google Cloud ในหน้าตัวเลือกโปรเจ็กต์
- ตรวจสอบว่าได้เปิดใช้การเรียกเก็บเงินสำหรับโปรเจ็กต์ Google Cloud แล้ว ดูวิธีตรวจสอบว่าโปรเจ็กต์เปิดใช้การเรียกเก็บเงินแล้วหรือไม่
- ทำตามวิธีการเพื่อเปิดใช้ BigQuery Studio สำหรับการจัดการชิ้นงาน
เตรียม BigQuery Studio
สร้าง Notebook ว่างเปล่าและเชื่อมต่อกับรันไทม์
- ไปที่ 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 เพื่อวิเคราะห์ฐานข้อมูลการร้องเรียนของผู้บริโภค ใช้วิธี 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)
)
แปลงเป็น pandas DataFrame โดยใช้เมธอด 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")
)
การสำรวจชุมชนอเมริกันระบุรัฐตาม GEOID รวมกับตารางรัฐเพื่อรับประชากรตามรหัสรัฐ 2 ตัวอักษร
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")
)

เมื่อเปรียบเทียบประชากรกับจำนวนการร้องเรียนแล้ว ดูเหมือนว่ารัฐ 2 รัฐจะเป็นค่าผิดปกติ ผู้อ่านสามารถลองใช้ป้ายกำกับจุดเพื่อระบุจุดเหล่านี้ ในทำนองเดียวกัน ให้ตั้งสมมติฐานว่าเหตุใดจึงเป็นเช่นนี้ (เช่น ประชากรศาสตร์ที่แตกต่างกัน จำนวนบริษัทที่ให้บริการทางการเงินที่แตกต่างกัน ฯลฯ) และทดสอบสมมติฐานเหล่านั้น
5. คำนวณการฝัง
บ่อยครั้งที่ข้อมูลสำคัญซ่อนอยู่ในข้อมูลที่ไม่มีโครงสร้าง เช่น ข้อความ เสียง หรือรูปภาพ ในตัวอย่างนี้ ข้อมูลที่เป็นประโยชน์ส่วนใหญ่ในฐานข้อมูลการร้องเรียนจะอยู่ในเนื้อหาข้อความของการร้องเรียน
AI และเทคนิคแบบดั้งเดิม เช่น การวิเคราะห์ความรู้สึก "Bag of Words" และ 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,000 รายการที่ส่งเมื่อวันที่ 01-12-2022 เทียบกับแถวเกือบ 3.5 ล้านแถวในฐานข้อมูลทั้งหมด (ตรวจสอบกับ feedback.shape)
เลือกเฉพาะข้อมูลสำหรับวันที่ 01-12-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 ต้องมีการจัดลําดับแถวทั้งหมดเนื่องจากพยายามเลือกแถวแรกหรือแถวสุดท้ายที่ตรงกัน และเก็บดัชนีที่เชื่อมโยงไว้
แต่ให้รวบรวมด้วยการเรียกใช้เมธอด groupby เพื่อนำแถวที่ซ้ำกันออก
feedback = (
feedback.groupby("consumer_complaint_narrative", as_index=False)
.size()
)[["consumer_complaint_narrative"]]
feedback.shape
สร้างการฝัง
BigQuery DataFrame จะสร้างเวกเตอร์การฝังผ่านคลาส 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)
มาดูกันว่าการฝังจะเป็นอย่างไร เวกเตอร์เหล่านี้แสดงความหมายเชิงความหมายของข้อความตามที่โมเดลการฝังข้อความเข้าใจ
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. คลัสเตอร์โดยใช้การฝังข้อความ
ตอนนี้จัดกลุ่มการฝังโดยใช้ k-means สำหรับการสาธิตนี้ ให้ใช้จำนวนกลุ่ม (หรือที่เรียกว่าเซนทรอยด์) ตามต้องการ โซลูชันคุณภาพระดับการใช้งานจริงควรปรับจำนวนจุดศูนย์กลางโดยใช้เทคนิคต่างๆ เช่น วิธีซิลูเอต
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, Notebook ของ Python ใน BigQuery Studio, BigQuery ML, Vertex AI และฟีเจอร์ภาษาธรรมชาติเป็น Python ของ BigQuery Studio ยอดเยี่ยมมาก
ขั้นตอนถัดไป
- ลองสร้างโค้ด Python ใน Notebook สมุดบันทึก Python ใน BigQuery Studio ขับเคลื่อนโดย Colab Enterprise เคล็ดลับ: ฉันพบว่าการขอความช่วยเหลือในการสร้างข้อมูลทดสอบมีประโยชน์มาก
- สำรวจ Notebook ตัวอย่างสำหรับ BigQuery DataFrame บน GitHub
- สร้างกำหนดเวลาเพื่อเรียกใช้ Notebook ใน BigQuery Studio
- ติดตั้งใช้งานฟังก์ชันระยะไกลด้วย BigQuery DataFrames เพื่อผสานรวมแพ็กเกจ Python ของบุคคลที่สามกับ BigQuery