Nhận thông tin chi tiết từ dữ liệu có cấu trúc và không có cấu trúc bằng cách sử dụng gói BigQuery DataFrames có khả năng AI

1. Tổng quan

Trong bài thực hành này, bạn sẽ sử dụng BigQuery DataFrames từ một sổ tay Python trong BigQuery Studio để thu thập thông tin chi tiết từ dữ liệu bằng Python. Tận dụng AI tạo sinh của Google để phân tích và trực quan hoá dữ liệu văn bản không có cấu trúc.

Bạn sẽ tạo một sổ tay Python để phân loại và tóm tắt cơ sở dữ liệu công khai về khiếu nại của khách hàng. Bạn có thể điều chỉnh để sử dụng trên mọi dữ liệu văn bản không có cấu trúc.

Mục tiêu

Trong bài thực hành này, bạn sẽ tìm hiểu cách thực hiện các thao tác sau:

  • Kích hoạt và sử dụng sổ tay Python trong BigQuery Studio
  • Kết nối với BigQuery bằng gói BigQuery DataFrames
  • Tạo các mục nhúng từ dữ liệu văn bản không có cấu trúc bằng BigQuery ML và kết nối với một điểm cuối nhúng văn bản trong Vertex AI
  • Nhúng cụm bằng BigQuery ML
  • Tóm tắt các cụm bằng một LLM thông qua BigQuery ML

2. Yêu cầu

  • Một trình duyệt, chẳng hạn như Chrome hoặc Firefox
  • Một dự án trên Google Cloud đã bật tính năng thanh toán

Trước khi bắt đầu

Để làm theo hướng dẫn trong lớp học lập trình này, bạn cần có một Dự án Google Cloud đã bật BigQuery Studio và một tài khoản thanh toán được kết nối.

  1. Trong Google Cloud Console, trên trang chọn dự án, hãy chọn hoặc tạo một dự án trên Google Cloud
  2. Đảm bảo bạn đã bật tính năng thanh toán cho dự án trên Google Cloud của mình. Tìm hiểu cách kiểm tra xem tính năng thanh toán có được bật trên một dự án hay không
  3. Làm theo hướng dẫn để Bật BigQuery Studio để quản lý tài sản.

Chuẩn bị BigQuery Studio

Tạo một sổ tay trống và kết nối sổ tay đó với một thời gian chạy.

  1. Chuyển đến BigQuery Studio trong Google Cloud Console.
  2. Nhấp vào biểu tượng bên cạnh nút +.
  3. Chọn Sổ tay Python.
  4. Đóng bộ chọn mẫu.
  5. Chọn + Code (Mã) để tạo một ô mã mới.
  6. Cài đặt phiên bản mới nhất của gói BigQuery DataFrames từ ô mã.Nhập lệnh sau.
    %pip install --upgrade bigframes --quiet
    
    Nhấp vào nút 🞂 hoặc nhấn tổ hợp phím Shift + Enter để chạy ô mã.

3. Đọc một tập dữ liệu công khai

Khởi chạy gói BigQuery DataFrames bằng cách chạy đoạn mã sau trong một ô mã mới:

import bigframes.pandas as bpd

bpd.options.bigquery.ordering_mode = "partial"

Lưu ý: trong hướng dẫn này, chúng ta sẽ sử dụng "chế độ sắp xếp một phần" thử nghiệm, cho phép thực hiện các truy vấn hiệu quả hơn khi được dùng với tính năng lọc tương tự như pandas. Một số tính năng của pandas yêu cầu một thứ tự hoặc chỉ mục nghiêm ngặt có thể không hoạt động.

Cơ sở dữ liệu về đơn khiếu kiện của người tiêu dùng

Cơ sở dữ liệu về khiếu nại của người tiêu dùng được cung cấp trên BigQuery thông qua chương trình tập dữ liệu công khai của Google Cloud. Đây là một bộ sưu tập các khiếu nại về sản phẩm và dịch vụ tài chính tiêu dùng, đồng thời dữ liệu này do Cục Bảo vệ tài chính người tiêu dùng Hoa Kỳ thu thập.

Trong BigQuery, hãy truy vấn bảng bigquery-public-data.cfbp_complaints.complaint_database để phân tích Cơ sở dữ liệu khiếu nại của người tiêu dùng. Sử dụng phương thức bigframes.pandas.read_gbq() để tạo DataFrame từ một chuỗi truy vấn hoặc mã nhận dạng bảng.

Chạy mã sau trong một ô mã mới để tạo DataFrame có tên "feedback":

feedback = bpd.read_gbq(
    "bigquery-public-data.cfpb_complaints.complaint_database"
)

Khám phá thông tin cơ bản về DataFrame

Sử dụng phương thức DataFrame.peek() để tải một mẫu nhỏ của dữ liệu xuống.

Chạy ô này:

feedback.peek()

Kết quả đầu ra dự kiến:

  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   

Lưu ý: head() yêu cầu sắp xếp và thường kém hiệu quả hơn peek() nếu bạn muốn trực quan hoá một mẫu dữ liệu.

Giống như với pandas, hãy sử dụng thuộc tính DataFrame.dtypes để xem tất cả các cột có sẵn và các kiểu dữ liệu tương ứng. Các thông tin này được hiển thị theo cách tương thích với pandas.

Chạy ô này:

feedback.dtypes

Kết quả đầu ra dự kiến:

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

Phương thức DataFrame.describe() truy vấn một số số liệu thống kê cơ bản từ DataFrame. Vì DataFrame này không chứa cột số, nên nó cho thấy thông tin tóm tắt về số lượng giá trị không rỗng và số lượng giá trị riêng biệt.

Chạy ô này:

# 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()

Kết quả đầu ra dự kiến:

         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. Khám phá dữ liệu

Trước khi xem xét các khiếu nại thực tế, hãy sử dụng các phương thức tương tự như pandas trên DataFrame để trực quan hoá dữ liệu.

Trực quan hoá DataFrame

Có một số phương thức trực quan hoá tích hợp sẵn, chẳng hạn như DataFrame.plot.hist(). Vì DataFrame này chủ yếu chứa dữ liệu chuỗi và boolean, nên trước tiên, chúng ta có thể thực hiện một số hoạt động tổng hợp để tìm hiểu thêm về nhiều cột.

Đếm số lượng đơn khiếu kiện nhận được từ mỗi tiểu bang.

complaints_by_state = (
  feedback.groupby(
    "state", as_index=False,
  ).size()
  .rename(columns={"size": "total_complaints"})
  .sort_values(by="total_complaints", ascending=False)
)

Chuyển đổi dữ liệu này thành DataFrame bằng pandas bằng phương thức DataFrame.to_pandas().

complaints_pd = complaints_by_state.head(10).to_pandas()

Sử dụng các phương thức trực quan hoá của pandas trên DataFrame đã tải xuống này.

complaints_pd.plot.bar(x="state", y="total_complaints")

biểu đồ thanh cho thấy California là tiểu bang có nhiều đơn khiếu kiện nhất

Kết hợp với các tập dữ liệu khác

Trước đây, bạn xem xét các khiếu nại theo tiểu bang, nhưng điều này làm mất đi bối cảnh quan trọng. Một số tiểu bang có dân số lớn hơn các tiểu bang khác. Kết hợp với một tập dữ liệu dân số, chẳng hạn như Khảo sát cộng đồng Hoa Kỳ của Cục Thống kê dân số Hoa Kỳbảng 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")
)

Khảo sát cộng đồng Hoa Kỳ xác định các tiểu bang theo GEOID. Kết hợp với bảng states để lấy dân số theo mã tiểu bang gồm 2 chữ cái.

pops = us_states.set_index("geo_id")[["state"]].join(
  us_survey.set_index("geo_id")[["total_pop"]]
)

Bây giờ, hãy kết hợp dữ liệu này với cơ sở dữ liệu về khiếu nại để so sánh dân số với số lượng đơn khiếu kiện.

complaints_and_pops = complaints_by_state.set_index("state").join(
    pops.set_index("state")
)

Tạo biểu đồ tán xạ để so sánh dân số của các tiểu bang với số lượng đơn khiếu kiện.

(
  complaints_and_pops
  .to_pandas()
  .plot.scatter(x="total_pop", y="total_complaints")
)

biểu đồ tán xạ so sánh dân số với số lượng đơn khiếu kiện

Có vẻ như một số tiểu bang là trường hợp ngoại lệ khi so sánh dân số với số lượng đơn khiếu kiện. Bạn đọc có thể tự vẽ biểu đồ có nhãn điểm để xác định những điểm này. Tương tự, hãy đưa ra một số giả thuyết về lý do có thể dẫn đến trường hợp này (ví dụ: nhân khẩu học khác nhau, số lượng công ty dịch vụ tài chính khác nhau, v.v.) và kiểm tra các giả thuyết đó.

5. Tính toán các mục nhúng

Thông thường, thông tin quan trọng bị ẩn trong dữ liệu không có cấu trúc, chẳng hạn như văn bản, âm thanh hoặc hình ảnh. Trong ví dụ này, phần lớn thông tin hữu ích trong cơ sở dữ liệu khiếu kiện nằm trong nội dung văn bản của đơn khiếu kiện.

AI và các kỹ thuật truyền thống (chẳng hạn như phân tích cảm xúc, "tập hợp từ" và word2vec) có thể trích xuất một số thông tin định lượng từ dữ liệu không có cấu trúc. Gần đây hơn, các mô hình "nhúng vectơ" (có liên quan chặt chẽ đến LLM) có thể tạo ra một chuỗi các số thực dấu phẩy động biểu thị thông tin ngữ nghĩa của văn bản.

Chọn một tập hợp con của cơ sở dữ liệu

Việc chạy mô hình nhúng vectơ sẽ sử dụng nhiều tài nguyên hơn các thao tác khác. Để giảm chi phí và các vấn đề về hạn mức, hãy chọn một tập hợp con của dữ liệu cho phần còn lại của hướng dẫn này.

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

Có khoảng 1.000 đơn khiếu kiện được gửi vào ngày 1/12/2022 so với gần 3,5 triệu hàng trong toàn bộ cơ sở dữ liệu (hãy kiểm tra với feedback.shape).

Chỉ chọn dữ liệu cho ngày 2022-12-01 và chỉ chọn cột 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

Phương thức drop_duplicates của pandas yêu cầu sắp xếp các hàng theo tổng số vì phương thức này cố gắng chọn hàng khớp đầu tiên hoặc cuối cùng và giữ lại chỉ mục được liên kết với hàng đó.

Thay vào đó, hãy tổng hợp bằng cách gọi phương thức groupby để loại bỏ các hàng trùng lặp.

feedback = (
  feedback.groupby("consumer_complaint_narrative", as_index=False)
  .size()
)[["consumer_complaint_narrative"]]

feedback.shape

Tạo vectơ nhúng

BigQuery DataFrames tạo vectơ nhúng thông qua lớp TextEmbeddingGenerator. Phương pháp này dựa trên phương thức ML.GENERATE_EMBEDDING trong BigQuery ML. Phương thức này gọi các mô hình nhúng văn bản do Vertex AI cung cấp.

from bigframes.ml.llm import TextEmbeddingGenerator

embedding_model = TextEmbeddingGenerator(
    model_name="text-embedding-004"
)
feedback_embeddings = embedding_model.predict(feedback)

Hãy xem các vectơ nhúng trông như thế nào. Các vectơ này biểu thị ý nghĩa ngữ nghĩa của văn bản theo cách mà mô hình nhúng văn bản hiểu được.

feedback_embeddings.peek()

Kết quả đầu ra dự kiến:

                        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-...   

Các vectơ này có nhiều phương diện. Hãy xem một vectơ nhúng duy nhất:

feedback_embeddings["ml_generate_embedding_result"].peek().iloc[0]

Việc tạo vectơ nhúng hoạt động theo hợp đồng "thành công một phần". Điều này có nghĩa là một số hàng có thể có lỗi và không tạo ra một mục nhúng. Thông báo lỗi xuất hiện ở cột 'ml_generate_embedding_status'. Trống có nghĩa là không có lỗi.

Lọc các mục nhúng để chỉ bao gồm những hàng không xảy ra lỗi.

mask = feedback_embeddings["ml_generate_embedding_status"] == ""
valid_embeddings = feedback_embeddings[mask]
valid_embeddings.shape

6. Nhóm bằng cách sử dụng vectơ nhúng văn bản

Giờ đây, hãy phân cụm các vectơ nhúng bằng cách sử dụng thuật toán k-means. Đối với bản minh hoạ này, hãy sử dụng một số lượng nhóm (còn gọi là tâm cụm) tuỳ ý. Một giải pháp chất lượng sản xuất nên điều chỉnh số lượng tâm cụm bằng cách sử dụng một kỹ thuật như Phương pháp 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()

Xoá mọi lỗi nhúng.

mask = clusters["ml_generate_embedding_status"] == ""
clusters = clusters[mask]

Xem nhanh và xem phân phối bình luận theo tâm điểm.

clusters.groupby("CENTROID_ID").size()

7. Tóm tắt các cụm

Nhập một số bình luận liên kết với từng tâm và yêu cầu Gemini tóm tắt các khiếu nại. Thiết kế câu lệnh là một lĩnh vực mới nổi, nhưng có nhiều ví dụ hay trên Internet, chẳng hạn như 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()

Dùng Gemini để viết báo cáo dựa trên bản tóm tắt.

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. Dọn dẹp

Nếu đã tạo một dự án trên đám mây mới trên Google Cloud cho hướng dẫn này, bạn có thể xoá dự án đó để tránh bị tính thêm phí cho các bảng hoặc tài nguyên khác đã tạo.

9. Xin chúc mừng!

Bạn đã phân tích dữ liệu có cấu trúc và dữ liệu không có cấu trúc bằng BigQuery DataFrames. Trong quá trình này, bạn đã khám phá Tập dữ liệu công khai của Google Cloud, sổ tay Python trong BigQuery Studio, BigQuery ML, Vertex AI và các tính năng chuyển đổi ngôn ngữ tự nhiên sang Python của BigQuery Studio. Thật tuyệt vời!

Các bước tiếp theo