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

1. Обзор

В этом лабораторном занятии вы будете использовать кадры данных BigQuery из блокнота 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 Console на странице выбора проекта выберите или создайте проект Google Cloud.
  2. Убедитесь, что для вашего проекта Google Cloud включена оплата. Узнайте, как проверить, включена ли оплата в проекте.
  3. Следуйте инструкциям, чтобы включить BigQuery Studio для управления активами .

Подготовьте BigQuery Studio

Создайте пустой блокнот и подключите его к среде выполнения.

  1. Перейдите в BigQuery Studio в Google Cloud Console.
  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, требующие строгого порядка или индексации, могут не работать.

База данных жалоб потребителей

База данных жалоб потребителей предоставляется в BigQuery через программу общедоступных наборов данных Google Cloud . Это сборник жалоб на потребительские финансовые продукты и услуги, данные собираются Бюро финансовой защиты потребителей США.

В BigQuery выполните запрос к таблице bigquery-public-data.cfbp_complaints.complaint_database . для анализа базы данных жалоб потребителей. Используйте метод bigframes.pandas.read_gbq() , чтобы создать DataFrame из строки запроса или идентификатора таблицы.

Выполните следующую команду в новой ячейке кода, чтобы создать DataFrame с именем «обратная связь»:

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() если вы хотите визуализировать выборку данных.

Как и в случае с пандами, используйте свойство 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")
)

Исследование американского сообщества определяет штаты по 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. Вычисление вложений

Часто важная информация скрыта в неструктурированных данных, таких как текст, аудио или изображения. В этом примере большая часть полезной информации в базе данных жалоб содержится в текстовом содержимом жалобы.

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

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

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