1. ภาพรวม
ในชั้นเรียนนี้ คุณจะใช้ DataFrame ของ BigQuery จากโน้ตบุ๊ก Python ใน BigQuery Studio เพื่อรับข้อมูลเชิงลึกจากข้อมูลโดยใช้ Python ใช้ Generative AI ของ Google เพื่อวิเคราะห์และแสดงข้อมูลข้อความที่ไม่มีโครงสร้างเป็นภาพ
คุณจะต้องสร้างโน้ตบุ๊ก Python เพื่อจัดหมวดหมู่และสรุปฐานข้อมูลการร้องเรียนของลูกค้าแบบสาธารณะ ซึ่งสามารถปรับให้ทํางานกับข้อมูลข้อความที่ไม่มีโครงสร้างได้
วัตถุประสงค์
ในบทแนะนำนี้ คุณจะได้เรียนรู้วิธีทํางานต่อไปนี้
- เปิดใช้งานและใช้โน้ตบุ๊ก 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
สร้างสมุดบันทึกเปล่าและเชื่อมต่อกับรันไทม์
- ไปที่ BigQuery Studio ในคอนโซล Google Cloud
- คลิก ▼ ข้างปุ่ม +
- เลือกโน้ตบุ๊ก Python
- ปิดตัวเลือกเทมเพลต
- เลือก + โค้ดเพื่อสร้างเซลล์โค้ดใหม่
- ติดตั้งแพ็กเกจ BigQuery DataFrames เวอร์ชันล่าสุดจากเซลล์โค้ด โดยพิมพ์คำสั่งต่อไปนี้
คลิกปุ่ม 🞂 หรือกด Shift + Enter เพื่อเรียกใช้เซลล์โค้ด%pip install --upgrade bigframes --quiet
3. อ่านชุดข้อมูลสาธารณะ
เริ่มต้นใช้งานแพ็กเกจ BigQuery DataFrame โดยเรียกใช้โค้ดต่อไปนี้ในเซลล์โค้ดใหม่
import bigframes.pandas as bpd
bpd.options.bigquery.ordering_mode = "partial"
หมายเหตุ: ในบทแนะนํานี้ เราจะใช้ "โหมดการจัดเรียงบางส่วน" เวอร์ชันทดลอง ซึ่งช่วยให้การค้นหามีประสิทธิภาพมากขึ้นเมื่อใช้ร่วมกับการกรองแบบแพนด้า ฟีเจอร์บางอย่างของ 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)
)
แปลงข้อมูลนี้เป็น 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")
)
การสํารวจชุมชนอเมริกันระบุรัฐตาม 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-3 รัฐดูเหมือนจะเป็นค่าเบี่ยงเบนเมื่อเปรียบเทียบจำนวนประชากรกับจำนวนการร้องเรียน ให้ผู้อ่านพล็อตจุดที่มีป้ายกำกับเพื่อระบุจุดเหล่านี้ ในทํานองเดียวกัน ให้ตั้งสมมติฐานว่าเหตุใดกรณีนี้จึงเกิดขึ้น (เช่น ข้อมูลประชากรที่แตกต่างกัน จํานวนบริษัทบริการทางการเงินที่แตกต่างกัน ฯลฯ) และทดสอบสมมติฐานเหล่านั้น
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,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 ในการสาธิตนี้ ให้ใช้กลุ่ม (หรือที่เรียกว่าจุดศูนย์กลางมวล) ตามความสะดวก โซลูชันที่มีคุณภาพระดับการผลิตควรปรับจํานวนจุดศูนย์กลางโดยใช้เทคนิค เช่น วิธีการ 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. ยินดีด้วย
คุณได้วิเคราะห์ข้อมูลที่มีโครงสร้างและไม่มีโครงสร้างโดยใช้ DataFrame ของ BigQuery คุณได้สำรวจชุดข้อมูลสาธารณะของ Google Cloud, โน้ตบุ๊ก Python ใน BigQuery Studio, BigQuery ML, Vertex AI และฟีเจอร์ภาษาธรรมชาติเป็น Python ของ BigQuery Studio ยอดเยี่ยมมาก
ขั้นตอนถัดไป
- ลองสร้างโค้ด Python ในโน้ตบุ๊ก สมุดบันทึก Python ใน BigQuery Studio ทำงานด้วย Colab Enterprise เคล็ดลับ: เราพบว่าการขอความช่วยเหลือในการสร้างข้อมูลทดสอบมีประโยชน์มาก
- สำรวจโน้ตบุ๊กตัวอย่างสําหรับ DataFrame ของ BigQuery ใน GitHub
- สร้างกำหนดเวลาเพื่อเรียกใช้โน้ตบุ๊กใน BigQuery Studio
- ติดตั้งใช้งานฟังก์ชันระยะไกลด้วย DataFrame ของ BigQuery เพื่อผสานรวมแพ็กเกจ Python ของบุคคลที่สามกับ BigQuery