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 lớp học 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. Sử 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ề đơn khiếu nại của khách hàng. Bạn có thể điều chỉnh để thuật toán này hoạt động trên mọi dữ liệu văn bản không có cấu trúc.

Mục tiêu

Trong lớp học này, bạn sẽ tìm hiểu cách thực hiện các nhiệm vụ 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 nội dung 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 đ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 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 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 bộ chọn dự án, hãy chọn hoặc tạo 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. Tìm hiểu cách kiểm tra xem tính năng thanh toán có được bật trên dự án hay không
  3. Làm theo hướng dẫn để Bật BigQuery Studio để quản lý thành phần.

Chuẩn bị BigQuery Studio

Tạo một sổ ghi chú trống và kết nối sổ ghi chú đó với một môi trường 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 + 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 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ử dụng "chế độ sắp xếp một phần" thử nghiệm, cho phép truy vấn hiệu quả hơn khi sử dụng với bộ lọc giống như pandas. Một số tính năng của pandas yêu cầu 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 nại của người tiêu dùng

Cơ sở dữ liệu về đơn 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 tập hợp các đơn khiếu nại về sản phẩm và dịch vụ tài chính dành cho người tiêu dùng. 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 một DataFrame có tên là "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ỏ dữ liệu xuống.

Chạy ô này:

feedback.peek()

Kết quả 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.

Tương tự 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à loại dữ liệu tương ứng. Các thuộc tính 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ả 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ó hiển thị thông tin tóm tắt về số lượng giá trị khác 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ả 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 đi sâu vào xem xét các đơn 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.

Hình ảnh hoá DataFrame

Có một số phương thức trực quan tích hợp sẵ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ố phép tổng hợp để tìm hiểu thêm về nhiều cột.

Đếm số lượng đơn khiếu nại 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 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á 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 nại 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 đơn khiếu nại theo tiểu bang, nhưng cách này sẽ bỏ lỡ bối cảnh quan trọng. Một số tiểu bang có dân số đông 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ê 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")
)

Cuộc 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 tiểu bang để lấy số dân theo mã tiểu bang gồm hai 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 bảng này với cơ sở dữ liệu về đơn khiếu nại để so sánh dân số với số lượng đơn khiếu nại.

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 nại.

(
  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 nại

Một số tiểu bang có vẻ như là ngoại lệ khi so sánh dân số với số lượng đơn khiếu nại. Đây là bài tập cho người đọc để vẽ biểu đồ với nhãn điểm để xác định các đ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ụ: thông tin 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 thử các giả thuyết đó.

5. Tính toán các phần nhúng

Thông thường, thông tin quan trọng được ẩ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 đơn khiếu nại nằm trong nội dung văn bản của đơn khiếu nại.

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úi 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, các mô hình "nhúng vectơ" có liên quan chặt chẽ với LLM có thể tạo một chuỗi số 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 so với 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 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 nại được gửi vào ngày 1 tháng 12 năm 2022 so với gần 3,5 triệu hàng trong tổng cơ sở dữ liệu (kiểm tra bằng feedback.shape).

Chỉ chọn dữ liệu cho ngày 1 tháng 12 năm 2022 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 thứ tự tổng thể của các hàng vì phương thức này cố gắng chọn hàng đầu tiên hoặc hàng cuối cùng khớp và giữ nguyên chỉ mục liên kết với hàng đó.

Thay vào đó, hãy tổng hợp bằng lệnh gọi đến 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 nội dung nhúng

BigQuery DataFrames tạo các vectơ nhúng thông qua lớp TextEmbeddingGenerator. Phương thức này dựa trên phương thức ML.GENERATE_EMBEDDING trong BigQuery ML, 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 nội dung nhúng trông như thế nào. Các vectơ này thể hiện ý 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ả 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 đơn:

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

Quá trình tạo nội dung 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ể gặp lỗi và không tạo được mục nhúng. Thông báo lỗi được hiển thị trong 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 nhúng văn bản

Bây giờ, hãy nhóm các phần nhúng bằng thuật toán k-means. Đối với bản minh hoạ này, hãy sử dụng số lượng nhóm tuỳ ý (còn gọi là tâm điểm). Một giải pháp chất lượng cao phải điều chỉnh số lượng tâm điểm bằng một kỹ thuật như Phương thức hình dáng.

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 trước và xem mức phân phối bình luận theo trọng tâm.

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

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

Cung cấp một số nhận xét liên kết với mỗi tâm điểm và yêu cầu Gemini tóm tắt các đơn 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()

Sử dụng Gemini để viết báo cáo từ các 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 Google Cloud mới 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à không có cấu trúc bằng cách sử dụ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 ngôn ngữ tự nhiên đến Python của BigQuery Studio. Thật tuyệt vời!

Các bước tiếp theo