รับข้อมูลเชิงลึกจากข้อมูลที่จัดโครงสร้างและไม่จัดโครงสร้างโดยใช้แพ็กเกจ DataFrame ของ BigQuery ที่ทำงานร่วมกับ AI ได้

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. ข้อกำหนด

  • เบราว์เซอร์ เช่น Chrome หรือ Firefox
  • โปรเจ็กต์ Google Cloud ที่เปิดใช้การเรียกเก็บเงิน

ก่อนเริ่มต้น

หากต้องการทําตามวิธีการในโค้ดแล็บนี้ คุณจะต้องมีโปรเจ็กต์ Google Cloud ที่เปิดใช้ BigQuery Studio และบัญชีการเรียกเก็บเงินที่เชื่อมต่อ

  1. ในคอนโซล Google Cloud ให้เลือกหรือสร้างโปรเจ็กต์ Google Cloud ในหน้าตัวเลือกโปรเจ็กต์
  2. ตรวจสอบว่าเปิดใช้การเรียกเก็บเงินสำหรับโปรเจ็กต์ Google Cloud แล้ว ดูวิธีตรวจสอบว่าเปิดใช้การเรียกเก็บเงินในโปรเจ็กต์หรือไม่
  3. ทําตามวิธีการเพื่อเปิดใช้ BigQuery Studio สําหรับการจัดการชิ้นงาน

เตรียม BigQuery Studio

สร้างสมุดบันทึกเปล่าและเชื่อมต่อกับรันไทม์

  1. ไปที่ BigQuery Studio ในคอนโซล Google Cloud
  2. คลิก ข้างปุ่ม +
  3. เลือกโน้ตบุ๊ก Python
  4. ปิดตัวเลือกเทมเพลต
  5. เลือก + โค้ดเพื่อสร้างเซลล์โค้ดใหม่
  6. ติดตั้งแพ็กเกจ BigQuery DataFrames เวอร์ชันล่าสุดจากเซลล์โค้ด โดยพิมพ์คำสั่งต่อไปนี้
    %pip install --upgrade bigframes --quiet
    
    คลิกปุ่ม 🞂 หรือกด Shift + Enter เพื่อเรียกใช้เซลล์โค้ด

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 ยอดเยี่ยมมาก

ขั้นตอนถัดไป