Dapatkan insight dari data terstruktur dan tidak terstruktur menggunakan paket BigQuery DataFrames yang kompatibel dengan AI

1. Ringkasan

Di lab ini, Anda akan menggunakan BigQuery DataFrames dari notebook Python di BigQuery Studio untuk mendapatkan insight dari data menggunakan Python. Manfaatkan AI generatif Google untuk menganalisis dan memvisualisasikan data teks tidak terstruktur.

Anda akan membuat notebook Python untuk mengategorikan dan meringkas database keluhan pelanggan publik. Hal ini dapat disesuaikan untuk menangani data teks tidak terstruktur apa pun.

Tujuan

Di lab ini, Anda akan mempelajari cara melakukan tugas berikut:

  • Mengaktifkan dan menggunakan notebook Python di BigQuery Studio
  • Menghubungkan ke BigQuery menggunakan paket DataFrame BigQuery
  • Membuat embedding dari data teks tidak terstruktur menggunakan BigQuery ML dan koneksi ke endpoint embedding teks di Vertex AI
  • Mengelompokkan embedding menggunakan BigQuery ML
  • Meringkas cluster dengan LLM melalui BigQuery ML

2. Persyaratan

  • Browser, seperti Chrome atau Firefox
  • Project Google Cloud yang mengaktifkan penagihan

Sebelum memulai

Untuk mengikuti petunjuk dalam codelab ini, Anda memerlukan Project Google Cloud dengan BigQuery Studio yang diaktifkan dan akun penagihan yang terhubung.

  1. Di Konsol Google Cloud, di halaman pemilih project, pilih atau buat project Google Cloud.
  2. Pastikan penagihan telah diaktifkan untuk project Google Cloud Anda. Pelajari cara memeriksa apakah penagihan telah diaktifkan pada suatu project.
  3. Ikuti petunjuk untuk Mengaktifkan BigQuery Studio untuk pengelolaan aset.

Menyiapkan BigQuery Studio

Buat notebook kosong dan hubungkan ke runtime.

  1. Buka BigQuery Studio di Konsol Google Cloud.
  2. Klik di samping tombol +.
  3. Pilih Python notebook.
  4. Tutup pemilih template.
  5. Pilih + Code untuk membuat sel kode baru.
  6. Instal paket BigQuery DataFrames versi terbaru dari sel kode.Ketik perintah berikut.
    %pip install --upgrade bigframes --quiet
    
    Klik tombol 🞂 atau tekan Shift + Enter untuk menjalankan sel kode.

3. Membaca set data publik

Inisialisasi paket BigQuery DataFrames dengan menjalankan kode berikut di sel kode baru:

import bigframes.pandas as bpd

bpd.options.bigquery.ordering_mode = "partial"

Catatan: dalam tutorial ini, kita menggunakan "mode pengurutan parsial" eksperimental, yang memungkinkan kueri yang lebih efisien saat digunakan dengan pemfilteran seperti pandas. Beberapa fitur pandas yang memerlukan pengurutan atau indeks yang ketat mungkin tidak berfungsi.

Database Keluhan Konsumen

Consumer Complaint Database disediakan di BigQuery melalui program set data publik Google Cloud. Ini adalah kumpulan keluhan tentang produk dan layanan keuangan konsumen dan data dikumpulkan oleh Consumer Financial Protection Bureau Amerika Serikat.

Di BigQuery, kueri bigquery-public-data.cfbp_complaints.complaint_database table untuk menganalisis Database Keluhan Konsumen. Gunakan metode bigframes.pandas.read_gbq() untuk membuat DataFrame dari string kueri atau ID tabel.

Jalankan kode berikut di sel kode baru untuk membuat DataFrame bernama "feedback":

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

Menemukan informasi dasar tentang DataFrame

Gunakan metode DataFrame.peek() untuk mendownload sampel kecil data.

Jalankan sel ini:

feedback.peek()

Output yang diharapkan:

  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   

Catatan: head() memerlukan pengurutan dan umumnya kurang efisien dibandingkan peek() jika Anda ingin memvisualisasikan sampel data.

Sama seperti pandas, gunakan properti DataFrame.dtypes untuk melihat semua kolom yang tersedia dan jenis datanya yang sesuai. Data ini diekspos dengan cara yang kompatibel dengan pandas.

Jalankan sel ini:

feedback.dtypes

Output yang diharapkan:

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

Metode DataFrame.describe() membuat kueri beberapa statistik dasar dari DataFrame. Karena DataFrame ini tidak berisi kolom numerik, DataFrame ini menampilkan ringkasan jumlah nilai non-null dan jumlah nilai berbeda.

Jalankan sel ini:

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

Output yang diharapkan:

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

Sebelum mempelajari keluhan sebenarnya, gunakan metode seperti pandas pada DataFrame untuk memvisualisasikan data.

Memvisualisasikan DataFrame

Ada beberapa metode visualisasi bawaan seperti DataFrame.plot.hist(). Karena DataFrame ini sebagian besar berisi data string dan boolean, kita dapat melakukan beberapa agregasi terlebih dahulu untuk mempelajari lebih lanjut berbagai kolom.

Hitung jumlah keluhan yang diterima dari setiap negara bagian.

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

Konversikan ini menjadi DataFrame pandas menggunakan metode DataFrame.to_pandas().

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

Gunakan metode visualisasi pandas pada DataFrame yang didownload ini.

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

diagram batang yang menunjukkan California sebagai negara bagian dengan keluhan terbanyak

Gabungkan dengan set data lain

Sebelumnya, Anda melihat keluhan per negara bagian, tetapi hal ini menghilangkan konteks penting. Beberapa negara bagian memiliki populasi yang lebih besar daripada yang lain. Gabungkan dengan set data populasi seperti Survei Komunitas Amerika (ACS) dari Biro Sensus AS dan tabel 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")
)

American Community Survey mengidentifikasi negara bagian berdasarkan GEOID. Gabungkan dengan tabel negara bagian untuk mendapatkan populasi menurut kode negara bagian dua huruf.

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

Sekarang, gabungkan ini ke database keluhan untuk membandingkan populasi dengan jumlah keluhan.

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

Buat diagram sebar untuk membandingkan populasi negara bagian dengan jumlah keluhan.

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

diagram sebar yang membandingkan populasi dengan keluhan

Beberapa negara bagian tampaknya merupakan pencilan saat membandingkan populasi dengan jumlah keluhan. Sebagai latihan bagi pembaca untuk memplot dengan label titik guna mengidentifikasi titik-titik tersebut. Demikian pula, buat beberapa hipotesis tentang alasan terjadinya hal ini (misalnya, demografi yang berbeda, jumlah perusahaan jasa keuangan yang berbeda, dll.) dan uji hipotesis tersebut.

5. Menghitung embedding

Sering kali, informasi penting tersembunyi dalam data tidak terstruktur, seperti teks, audio, atau gambar. Dalam contoh ini, sebagian besar informasi berguna dalam database keluhan terdapat dalam konten teks keluhan.

AI dan teknik tradisional, seperti analisis sentimen, "bag of words", dan word2vec, dapat mengekstrak beberapa informasi kuantitatif dari data tidak terstruktur. Baru-baru ini, model "embedding vektor", yang terkait erat dengan LLM, dapat membuat urutan angka floating point yang merepresentasikan informasi semantik teks.

Memilih subset database

Menjalankan model penyematan vektor menggunakan lebih banyak resource daripada operasi lainnya. Untuk mengurangi biaya dan masalah kuota, pilih subset data untuk bagian tutorial ini.

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

Ada sekitar 1.000 keluhan yang dikirimkan pada 01-12-2022 dibandingkan dengan hampir 3,5 juta baris dalam total database (periksa dengan feedback.shape).

Pilih hanya data untuk 01-12-2022 dan hanya kolom 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

Metode drop_duplicates dari pandas memerlukan pengurutan total baris karena mencoba memilih baris yang cocok pertama atau terakhir dan mempertahankan indeks yang terkait dengannya.

Sebagai gantinya, gabungkan dengan panggilan ke metode groupby untuk menghapus duplikat baris.

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

feedback.shape

Membuat embedding

BigQuery DataFrames membuat vektor sematan melalui class TextEmbeddingGenerator. Hal ini didasarkan pada metode ML.GENERATE_EMBEDDING, di BigQuery ML yang memanggil model penyematan teks yang disediakan oleh Vertex AI.

from bigframes.ml.llm import TextEmbeddingGenerator

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

Lihat seperti apa tampilan embedding. Vektor ini merepresentasikan makna semantik teks sebagaimana dipahami oleh model embedding teks.

feedback_embeddings.peek()

Output yang diharapkan:

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

Vektor ini memiliki banyak dimensi. Lihat satu vektor embedding:

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

Pembuatan penyematan beroperasi berdasarkan kontrak "sebagian berhasil". Artinya, beberapa baris mungkin mengalami error dan tidak menghasilkan penyematan. Pesan error ditampilkan oleh kolom 'ml_generate_embedding_status'. Kosong berarti tidak ada error.

Filter sematan untuk hanya menyertakan baris yang tidak mengalami error.

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

6. Mengelompokkan menggunakan embedding teks

Sekarang, kelompokkan embedding menggunakan k-means. Untuk demo ini, gunakan sejumlah grup arbitrer (alias centroid). Solusi berkualitas produksi harus menyesuaikan jumlah centroid menggunakan teknik seperti metode Siluet.

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

Hapus semua kegagalan penyematan.

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

Lihat dan amati distribusi komentar per sentroid.

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

7. Meringkas cluster

Berikan beberapa komentar yang terkait dengan setiap sentroid dan minta Gemini meringkas keluhan tersebut. Rekayasa perintah adalah bidang yang baru muncul, tetapi ada contoh bagus di Internet, seperti 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()

Menggunakan Gemini untuk menulis laporan dari ringkasan.

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

Jika telah membuat project Google Cloud baru untuk tutorial ini, Anda dapat menghapusnya untuk mencegah biaya tambahan untuk tabel atau resource lain yang dibuat.

9. Selamat!

Anda telah menganalisis data terstruktur dan tidak terstruktur menggunakan DataFrame BigQuery. Selama ini, Anda telah menjelajahi Set Data Publik Google Cloud, notebook Python di BigQuery Studio, BigQuery ML, Vertex AI, dan fitur natural language ke Python di BigQuery Studio. Hebat!

Langkah berikutnya