Получайте аналитическую информацию о структурированных и неструктурированных данных с помощью пакета BigQuery DataFrames с поддержкой искусственного интеллекта. Получайте аналитическую информацию о структурированных и неструктурированных данных с помощью пакета BigQuery DataFrames с поддержкой искусственного интеллекта.

1. Обзор

В этой лабораторной работе вы будете использовать DataFrames из блокнота Python в BigQuery Studio для получения аналитических данных с помощью Python. Воспользуйтесь генеративным искусственным интеллектом 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 DataFrames выполните следующую команду в новой ячейке кода:

import bigframes.pandas as bpd

bpd.options.bigquery.ordering_mode = "partial"

Примечание: в этом руководстве мы используем экспериментальный «режим частичного упорядочивания», который позволяет выполнять более эффективные запросы при использовании с фильтрацией, аналогичной той, что применяется в pandas. Некоторые функции 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 не содержит числовых столбцов, он отображает сводку количества ненулевых значений и числа уникальных значений.

Запустите эту ячейку:

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

В рамках Американского обследования сообществ (American Community Survey) штаты определяются по GEOID. Для получения данных о численности населения по двухбуквенному коду штата используйте объединение таблиц со штатами.

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

диаграмма рассеяния, сравнивающая численность населения с количеством жалоб.

При сравнении численности населения с количеством жалоб несколько штатов, по-видимому, являются аномальными. Читателю предлагается самостоятельно составить график с точечными метками, чтобы определить эти штаты. Также следует выдвинуть несколько гипотез о причинах такого положения дел (например, различия в демографических характеристиках, различное количество компаний, предоставляющих финансовые услуги и т. д.) и проверить их.

5. Вычислите векторные представления.

Often, important information is hidden in unstructured data, such as text, audio, or images. In this example, much of the useful information in the complaints database is contained in the text content of the complaint.

Искусственный интеллект и традиционные методы, такие как анализ настроений, «мешок слов» и 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 декабря 2022 года было подано около 1000 жалоб, тогда как в общей базе данных содержится почти 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 DataFrames векторы встраивания генерируются с помощью класса 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-средних. Для этой демонстрации используйте произвольное количество групп (или центроидов). В решении, соответствующем производственным стандартам, количество центроидов следует настраивать с помощью таких методов, как метод силуэта .

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. Поздравляем!

Вы проанализировали структурированные и неструктурированные данные с помощью DataFrames BigQuery. В процессе работы вы изучили общедоступные наборы данных Google Cloud, блокноты Python в BigQuery Studio, BigQuery ML, Vertex AI и возможности преобразования естественного языка в Python в BigQuery Studio. Отличная работа!

Следующие шаги