ClearScape Analytics, неотъемлемая часть Teradata Vantage™, предлагает значительную ценность для организаций, желающих воспользоваться преимуществами генеративного искусственного интеллекта. ClearScape Analytics оптимизирует каждый этап жизненного цикла машинного обучения, включая понимание и определение проблемы, предварительную обработку соответствующих данных, обучение модели, развертывание модели и операции с моделью.

В этом посте мы исследуем комплексный конвейер генеративного искусственного интеллекта, чтобы проиллюстрировать использование различных инструментов в экосистеме Teradata Vantage для простого определения проблемы, сбора, очистки и предварительной обработки данных, интеграции обучающих данных в облачное машинное обучение. инструменты и ввести в действие обученную модель. Начальные шаги, определение проблемы, исследование и подготовка данных описаны в соответствующих фрагментах кода, которые можно воспроизвести. Начиная с этапа обучения, процесс подробно описан в описательной форме, что позволяет читателю легко следовать за ним, а необходимый экземпляр Teradata Vantage предоставляется через ClearScape Analytics Experience™, легкую веб-платформу, которая предоставляет полнофункциональную Teradata. Возможности выгодной среды.

Требования

Для прочтения этого поста единственным требованием является наличие среды ClearScape Analytics Experience. Вы можете бесплатно предоставить среду ClearScape Analytics Experience по адресу https://www.teradata.com/experience.

Оглавление

  1. Определение проблемы
  2. Загрузка образцов данных
  3. Исследование данных
  4. Предварительная обработка данных
  5. Модельное обучение
  6. Операционализация модели

Определение проблемы

Интернет-магазин планирует разработать систему рекомендаций. Целью этой системы является прогнозирование последующего продукта, который клиент добавит в свою онлайн-корзину, предлагая соответствующие рекомендации, связанные с маркетинговыми инициативами, сезонными акциями и т. д. Модели, использующие обработку естественного языка (NLP), превосходно справляются с подобными задачами. Модели НЛП могут предсказать последующее слово в предложении, если задан только его сегмент. Такие системы, как ChatGPT OpenAI, в основном работают по этому принципу.

Рассматривая сценарий корзины покупок через эту призму, мы можем сравнить корзину покупок с предложением, где каждый продукт, добавленный в корзину, выступает в качестве «слова» в этом «предложении». Предыдущие заказы функционируют как контекст, на котором модель может обучаться, пока не сможет делать обоснованные прогнозы. По мере обучения модели она раскрывает внутренние связи между «продуктами» в заказе, что позволяет ей делать точные прогнозы.

Для достижения описанной бизнес-цели нам необходимо изучить доступные данные, провести их предварительную обработку, сделать предварительно обработанные данные доступными для обучения, обучить модель НЛП, а также развернуть и отслеживать полученную модель. В целях иллюстративного сценария мы начнем с загрузки некоторых данных в экземпляр Teradata Vantage.

Загрузка образцов данных

Настройка окружающей среды

Мы будем взаимодействовать с экземпляром Teradata Vantage через блокнот ClearScape Analytics Experience Jupyter Notebook. Чтобы настроить эту среду, выполните следующие действия:

1. Создайте среду ClearScape Analytics Experience.

- Запишите пароль, использованный при создании среды.

2. Нажмите кнопку «Запустить демонстрации с помощью Jupyter».

3. Перейдите в папку «Случаи использования».

4. Создайте новую папку, имя папки не имеет значения для реализации сценария.

5. Создайте в папке новый блокнот Jupyter Python. Имя блокнота Jupyter также не имеет значения для реализации сценария.

Загрузка данных

  • Импортируйте библиотеки машинного обучения Teradata в блокнот.
import teradataml as tdml
import json
import pandas as pd
import seaborn as sns
import plotly.express as px
import tdnpathviz
  • Создайте сеанс базы данных в своем блокноте Jupyter.
%run -i ../startup.ipynb
eng = tdml.create_context(host = 'host.docker.internal', username='demo_user', password = password)
  • На этом этапе мы не будем определять какую-либо базу данных в контексте. Создание базы данных по умолчанию будет первым запросом, который мы выполним.
  • Соединение запросит пароль — это пароль, который вы использовали при создании среды ClearScape Analytics Experience.
  • Мы запускаем следующие команды в нашем блокноте, чтобы создать базу данных по умолчанию.
qry = """
CREATE DATABASE teddy_retailers_ml
AS PERMANENT = 110e6;
"""
eng.execute(qry)
  • После создания базы данных по умолчанию мы снова выполняем команду create_context, чтобы установить базу данных по умолчанию. Это упрощает все дальнейшие запросы.
eng = tdml.create_context(host = 'host.docker.internal', username='demo_user', password = password, database = 'teddy_retailers_ml')
  • Когда база данных создана и определена по умолчанию, мы можем приступить к выполнению запросов, загружающих данные в базу данных. Для этого мы используем созданную нами связь.
qry='''
CREATE MULTISET TABLE teddy_retailers_ml.products AS
(
  SELECT product_id, product_name, department_id
    FROM (
  LOCATION='/gs/storage.googleapis.com/clearscape_analytics_demo_data/DEMO_groceryML/products.csv') as products
) WITH DATA;
'''
eng.execute(qry)

qry='''
CREATE MULTISET TABLE teddy_retailers_ml.order_products AS
(
  SELECT order_id, product_id, add_cart_order
    FROM (
  LOCATION='/gs/storage.googleapis.com/clearscape_analytics_demo_data/DEMO_groceryML/order_products.csv') as orders_products
) WITH DATA;
'''
eng.execute(qry)

Загрузив данные в базу данных, мы можем приступить к их изучению.

Исследование данных

У нас есть два набора данных, импортированных в базу данных в виде таблиц. Таблица «products» содержит общую информацию о продукте: «product_id», «product_name» и «department_id». Эта таблица в основном используется для получения названий продуктов для иллюстрации примеров на этапе исследования данных. Таблица «order_products» содержит записи заказов, идентифицированные по их конкретным идентификаторам, с подробным описанием продуктов «product_id», добавленных в каждый заказ, и последовательности «add_cart_order», в которой они были добавлены в корзину. Эта таблица является центральной для нашего анализа.

Мы можем проанализировать данные в таблице «orders_products», импортировав их в Teradata «DataFrame», используя команду, представленную ниже:

orders = tdml.DataFrame("order_products")
orders

В примере показан список продуктов, добавленных в заказ с номером 3018. В этом примере первым продуктом, добавленным в этот заказ, является продукт с идентификатором 142, а первый продукт, который появляется в списке, 180, соответствует четвертому элементу, добавленному в Корзина.

Какие записи отображаются, зависит от способа индексации и разбиения на страницы DataFrame для отображения.

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

  • Мы группируем данные «order_product» по «order_id» и агрегируем по счетчику «product_id»:
counts_per_order = orders.groupby("order_id").agg({"product_id": "count"})
counts_per_order
  • Отсюда мы получаем DataFrame, который описывает количество продуктов, добавленных в каждый заказ.

  • Мы можем применить функцию гистограммы teradataml к этой таблице, чтобы создать DataFrame, который хорошо подходит для визуализации гистограммы. Чтобы создать визуальное представление с помощью библиотеки построения графиков, мы упорядочиваем полученный DataFrame по Label и преобразуем его в стандартный DataFrame Pandas.
  • В полученном DataFrame каждая строка представляет собой интервал гистограммы, определяющий диапазон, в котором собираются точки данных. Он включает в себя метку интервала, количество точек данных в этом конкретном диапазоне, процент этого количества по отношению к общему количеству точек данных, а также минимальные и максимальные пределы каждого интервала. Для получения более подробной информации изучите документацию по гистограмме машинного обучения Teradata.
count_prod_hist = tdml.Histogram(data=counts_per_order,
                target_columns="count_product_id",
                method_type="Sturges") 
count_prod_hist_pd = count_prod_hist.result.sort("Label").to_pandas()
count_prod_hist_pd

  • Чтобы построить график, мы используем гистограмму «DataFrame» в качестве источника данных, обозначая максимальное значение продуктов, добавленных в заказ, как ось X, а процент продуктов в этой конкретной ячейке — как ось Y. На полученном графике мы видим, что большинство заказов, к северу от 9% (ось X), содержат более 20 продуктов (ось Y).
fig = px.bar(count_prod_hist_pd, x="MaxValue", y="Bin_Percent")
fig.show()

Учитывая, что мы работаем с смоделированным набором данных, распределение может не отражать типичные тенденции, но мы продолжим его.

Другой стандартный исследовательский шаг включает в себя определение наиболее популярных продуктов и наиболее частых последовательностей, в которых эти продукты добавляются в корзину.

  • Для этого нам нужно перенести таблицу «products» в соответствующий DataFrame Teradata.
products = tdml.DataFrame('products')
products

  • Мы можем объединить две структуры DataFrame — заказы и продукты — на основе идентификатора продукта. Это позволяет получить доступ к сведениям о продукте из заказов DataFrame. Префиксы необходимы для устранения неоднозначности между столбцами с одинаковыми именами.
orders_products_merged = orders.join(
    other = products,
    on = "product_id",
    how = "inner",
    lsuffix = "ordrs", 
    rsuffix = "prdt")
orders_products_merged

  • В этом «DataFrame» мы можем просмотреть наиболее часто заказываемые продукты. Мы делаем это путем группировки на основе «product_name», подсчета количества «orders_product_id», а затем сортировки этих результатов в порядке убывания.
product_counts = orders_products_merged.groupby('product_name').agg({"ordrs_product_id": "count"})
product_counts.sort("count_ordrs_product_id", ascending=False)

  • Чтобы выявить наиболее распространенные последовательности добавления товаров в корзину, нам необходимо определить последовательности, в которых товары были включены в каждый из заказов. Для удобства анализа мы представим эти последовательности парами. Это означает, что мы определим пары продуктов, в которых один продукт часто следует за другим.
  • Для таких целей обычно используется функция Teradata nPath®. Эта функция особенно полезна для выявления последовательных шаблонов в данных. Основными входными данными для nPath являются анализируемые строки, столбец, используемый для разделения данных, и столбец, определяющий порядок последовательности.
  • В нашем случае мы выполним анализ пути к данным в «orders_products_merged». Поскольку мы стремимся идентифицировать последовательные шаблоны в отношении заказов, наш столбец раздела — «order_id». Учитывая, что мы хотим построить последовательность на основе порядка добавления продуктов в корзину, наш порядковый столбец — `add_cart_order`.
  • Другие ключевые компоненты функции nPath включают условия, которым должна соответствовать точка данных для включения в последовательность, а также шаблоны, которые мы выявляем среди строк, соответствующих условию. Они передаются в nPath как параметры «символ» и «шаблон» соответственно.
  • Функция nPath для нашей цели будет выглядеть следующим образом:
common_seqs = tdml.NPath(
    data1=orders_products_merged,
    data1_partition_column="order_id",
    data1_order_column="add_cart_order",
    mode="OVERLAPPING",
    pattern="A.A",
    symbols="TRUE as A",
    result=[
        "FIRST (order_id OF A) AS order_id",
        "ACCUMULATE (product_name OF A) AS path",
        "COUNT (* OF A) AS countrank"
        ]
    ).result
  • Если символ `A` просто подразумевает, что `product_id` `A` существует в заказе, то есть `True as A`. Шаблон «А.А» выполняется каждый раз, когда данный продукт «А» следует за другим продуктом «А», добавленным ранее в корзину. Мы установили режим перекрытия, поскольку второй элемент данной пары может быть первым элементом другой пары.
  • Функция FIRST извлекает идентификатор order_id из начальной строки, соответствующей шаблону, а функция ACUMULATE создает путь с именем Product_name, найденным в каждой совпавшей строке, следуя последовательности, определенной `add_cart_order`.
  • Чтобы получить количество наиболее распространенных пар, мы группируем их по «пути» и агрегируем по количеству «order_id», сортируя результаты в порядке убывания на основе количества.
common_seqs.groupby('path').agg({"order_id": "count"}).sort('count_order_id',ascending=False)
  • Ниже перечислены наиболее часто заказываемые пары. Важно отметить, что данные моделируются, поэтому наблюдаются закономерности:

  • Мы можем визуализировать пути, импортировав график «plot_first_main_paths» из пакета Teradata tdnpathviz:
from tdnpathviz.visualizations import plot_first_main_paths
plot_first_main_paths(common_seqs,path_column='path',id_column='order_id')

Предварительная обработка данных

Модели НЛП, такие как BERT, разрабатываются с использованием обширных текстовых корпусов. Чтобы облегчить их обучение, эти модели переводят слова на таких языках, как английский, в серию токенов, которые являются последовательными идентификаторами. Суть процесса обучения заключается в обучении модели прогнозированию конкретного токена на основе окружающего его контекста. Этот метод оказался эффективным способом предсказания и генерации языка компьютерными системами.

Пытаясь предсказать следующий продукт, который покупатель добавит в свою корзину, мы используем метод, аналогичный обучению языковых моделей. В этом случае наш корпус обучения состоит из предыдущих заказов в нашей системе или наших данных order_products. Каждый продукт в заказе должен быть заменен соответствующим токеном — последовательным идентификатором.

Как и ранее на этапе исследования данных, мы преобразуем каждый заказ в упорядоченную последовательность продуктов, но на этот раз мы создадим последовательность, используя последовательные идентификаторы или токены, а не названия продуктов. Кроме того, мы добавим маркеры для обозначения начала и конца каждого заказа. Эти специально отформатированные данные затем передаются на этап обучения. Здесь модель выводит распределение вероятностей, прогнозирующее вероятность добавления определенного продукта в корзину на основе продуктов, которые были добавлены ранее.

Чтобы подготовить данные для обработки с помощью библиотеки машинного обучения или предварительно обученной модели, особенно тех, которые необходимы для генеративного ИИ посредством НЛП, нам необходимо проверить несколько вещей:

  • Идентификаторы продуктов должны быть последовательными. Это гарантирует, что модель НЛП сможет обрабатывать их так же, как и слова в предложении.
  • Точно так же, как в английской грамматике мы используем заглавную букву для начала предложения и точку для обозначения его конца, наши последовательности порядка (аналогичные «предложениям» в этом контексте) также нуждаются в определенных маркерах для обозначения начала и конца каждого предложения. последовательность.
  • Нам нужно исключить нулевые значения. Обучение машинному обучению с помощью инструментов НЛП по сути включает в себя умножение матриц, которое можно выполнять только с числовыми значениями.

Добавление последовательных идентификаторов продуктов

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

Мы собираемся определить число «101» в качестве маркера начала «предложения», а число «102» в качестве маркера конца предложения. Определив эти две константы, мы собираемся присвоить последовательный идентификатор элементам в нашей таблице «products». Этот последовательный идентификатор будет начинаться с «103» и продолжаться оттуда.

  • Мы создаем изменчивую таблицу temp, которая сопоставляет каждый продукт Product_id с последовательным идентификатором, который мы создаем. Для этого мы используем операторы SQL ROW_NUMBER() и OVER. Эта таблица будет иметь первичный индекс по `product_id`. Мы хотим, чтобы эта таблица сохранялась во время сеанса, поэтому мы определяем параметр `ON_COMMIT_PRESERVE_ROWS`:
create_table_qry = '''
CREATE VOLATILE TABLE temp AS (
    SELECT product_id, 
    ROW_NUMBER() OVER (ORDER BY product_id) + 102 as seq_product_id
    FROM products
) WITH DATA PRIMARY INDEX (product_id) ON COMMIT PRESERVE ROWS;
'''
eng.execute(create_table_qry)
  • Чтобы создать последовательный `product_id`, этот оператор извлекает номер строки каждой записи в таблице `products`, упорядоченной по `product_id`, и добавляет 102 к этому номеру, после чего результат определяется как `seq_product_id`.
  • Мы создаем новый столбец в нашей таблице «продукты» для хранения последовательных идентификаторов продуктов:
add_column_qry = '''
ALTER TABLE products
ADD seq_product_id INTEGER;
'''
eng.execute(add_column_qry)
  • Наконец, мы добавляем последовательные идентификаторы в таблицу нашего продукта как seq_product_id:
modify_table_qry = '''
UPDATE products
SET seq_product_id = (
    SELECT temp.seq_product_id
    FROM temp
    WHERE products.product_id = temp.product_id
);
'''
eng.execute(modify_table_qry)
  • Полученную таблицу можно снова загрузить в наши продукты DataFrame.
products = tdml.DataFrame('products')
products.sort('seq_product_id')

Заказать токенизацию

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

  • Во-первых, нам нужно воссоздать DataFrame «orders_products_merged», на этот раз с обновленным DataFrame «products» в соединении. Мы сохраняем все столбцы в DataFrame `products` для справки и простоты. В реальном сценарии мы сохраняем только идентификаторы.
orders_products_merged = orders.join(
    other = products,
    on = "product_id",
    how = "inner",
    lsuffix = "ordrs", 
    rsuffix = "prdt")
orders_products_merged

  • Из этого модифицированного «orders_products_merged» мы сгенерируем предварительный «DataFrame», в котором заказы будут представлены как последовательности продуктов.
  • На этом этапе каждая запись будет содержать как минимум два элемента. Например, в тех случаях, когда в корзину был добавлен только один товар, запись будет заполнена маркером начала предложения и добавлен последовательный идентификатор продукта. Для достижения этой цели мы добавим новый столбец в DataFrame «orders_products_merged» с постоянным значением «101», который является нашим маркером начала предложения.
orders_products_merged = orders_products_merged.assign(
    bgn = 101
).select(["order_id", "add_cart_order", "seq_product_id", "bgn"])
orders_products_merged

  • В этом обновленном DataFrame мы будем использовать функцию nPath Teradata для генерации последовательности продуктов для каждого заказа. Этот процесс очень похож на то, что мы делали на этапе исследования данных. Разница здесь в том, что мы не будем включать «order_id», поскольку он не является частью «предложения» и не имеет отношения к обучению модели. Также мы не будем накапливать все токены в одном столбце; вместо этого у нас будет отдельный столбец для каждого токена.
  • Кроме того, шаблон не будет искать совпадения по парам товаров; мы добавим любую последовательность, даже если она содержит только один товар. Для этого мы будем использовать подстановочный знак `*`.
  • В ходе исследования данных мы обнаружили важную информацию, которая сейчас полезна. Дело в том, что максимальное количество товаров в заказе в нашем наборе данных равно «21». На этом этапе нам также необходимо выделить столбец для каждого токена, а также мы намерены упростить создание столбцов, добавляя их только там, где существуют токены.
  • Кроме того, нам необходимо выделить хотя бы один дополнительный столбец для размещения маркера конца предложения для более длинных списков. Учитывая, что 25 — достаточно круглая цифра, мы включим 25 столбцов в готовящийся набор данных.
  • Выполнение всех вышеописанных процессов значительно упрощается благодаря функции nPath компании Teradata.
prepared_ds = tdml.NPath(
    data1=orders_products_merged,
    data1_partition_column="order_id",
    data1_order_column="add_cart_order",
    mode="NONOVERLAPPING",
    pattern="A*",
    symbols="TRUE as A",
    result=["FIRST (bgn OF A) AS c0",
            "NTH (seq_product_id, 1 OF A) as c1",
            "NTH (seq_product_id, 2 OF A) as c2",
            "NTH (seq_product_id, 3 OF A) as c3",
            "NTH (seq_product_id, 4 OF A) as c4",
            "NTH (seq_product_id, 5 OF A) as c5",
            "NTH (seq_product_id, 6 OF A) as c6",
            "NTH (seq_product_id, 7 OF A) as c7",
            "NTH (seq_product_id, 8 OF A) as c8",
            "NTH (seq_product_id, 9 OF A) as c9",
            "NTH (seq_product_id, 10 OF A) as c10",
            "NTH (seq_product_id, 11 OF A) as c11",
            "NTH (seq_product_id, 12 OF A) as c12",
            "NTH (seq_product_id, 13 OF A) as c13",
            "NTH (seq_product_id, 14 OF A) as c14",
            "NTH (seq_product_id, 15 OF A) as c15",
            "NTH (seq_product_id, 16 OF A) as c16",
            "NTH (seq_product_id, 17 OF A) as c17",
            "NTH (seq_product_id, 18 OF A) as c18",
            "NTH (seq_product_id, 19 OF A) as c19",
            "NTH (seq_product_id, 20 OF A) as c20",
            "NTH (seq_product_id, 21 OF A) as c21",
            "NTH (seq_product_id, 22 OF A) as c22",
            "NTH (seq_product_id, 23 OF A) as c23",
            "NTH (seq_product_id, 24 OF A) as c24",
            "NTH (seq_product_id, 25 OF A) as c25",
    ]
).result
prepared_ds

  • Агрегатная функция NTH используется для извлечения seq_product_id из каждой строки последовательности (где каждый продукт, добавленный в заказ, соответствует строке в последовательности). Затем этот идентификатор присваивается соответствующему столбцу в зависимости от его положения в определенном порядке. Это достигается путем указания индексов от «1» до «25» в приведенном выше фрагменте.
  • Если заказ не содержит продукта, добавленного в определенную позицию, мы встречаем значение «Нет». Эти нулевые значения, говоря языком базы данных, необходимо будет устранить и очистить на последующих шагах.

Окончательная очистка и сохранение данных

На этом этапе нам просто нужно управлять нулевыми значениями и добавлять маркеры конца предложения. Для достижения этой цели мы будем использовать надежные возможности Teradata в базе данных.

  • В качестве первого шага мы сохраним DataFrame `prepared_ds` в хранилище данных.
prepared_ds.to_sql("prepared_ds", if_exists="replace")
  • На следующем этапе нам необходимо создать таблицу со следующими характеристиками:
  1. Нам нужно вставить последний маркер предложения «102» после последнего продукта, добавленного в каждый заказ.
  2. Значение столбцов, в которых нет товаров, должно быть равно «0» вместо «null».
  • Чтобы удовлетворить указанным условиям, мы должны проверить для каждого столбца, является ли значение столбца «нулевым», и применить условные модификации в зависимости от того, содержит ли предыдущий столбец токен продукта. Если в предыдущем столбце есть токен продукта, «ноль» следует заменить маркером конца предложения; в противном случае, если оно содержит другое «нулевое» значение, его следует заменить на «0».
  • Функция COALESCE позволяет нам эффективно применять условие, когда мы обнаруживаем, что значение столбца равно null. В этом контексте он используется для проверки каждого столбца, и если значение столбца равно null, он затем проверяет значение предыдущего столбца с помощью оператора CASE. Оператор CASE позволяет использовать условную логику в SQL. В этой ситуации, если значение предыдущего столбца равно «null», возвращается «0»; в противном случае возвращается `102`.
  • Мы можем использовать следующий скрипт, чтобы сохранить очищенную версию, подготовленную для этапа обучения.
create_cleaned_ds_qry = '''
CREATE TABLE cleaned_ds AS (
  SELECT
    c0,
    c1,
    COALESCE(c2, CASE WHEN c1 IS NULL THEN 0 ELSE 102 END) AS c2,
    COALESCE(c3, CASE WHEN c2 IS NULL THEN 0 ELSE 102 END) AS c3,
    COALESCE(c4, CASE WHEN c3 IS NULL THEN 0 ELSE 102 END) AS c4,
    COALESCE(c5, CASE WHEN c4 IS NULL THEN 0 ELSE 102 END) AS c5,
    COALESCE(c6, CASE WHEN c5 IS NULL THEN 0 ELSE 102 END) AS c6,
    COALESCE(c7, CASE WHEN c6 IS NULL THEN 0 ELSE 102 END) AS c7,
    COALESCE(c8, CASE WHEN c7 IS NULL THEN 0 ELSE 102 END) AS c8,
    COALESCE(c9, CASE WHEN c8 IS NULL THEN 0 ELSE 102 END) AS c9,
    COALESCE(c10, CASE WHEN c9 IS NULL THEN 0 ELSE 102 END) AS c10,
    COALESCE(c11, CASE WHEN c10 IS NULL THEN 0 ELSE 102 END) AS c11,
    COALESCE(c12, CASE WHEN c11 IS NULL THEN 0 ELSE 102 END) AS c12,
    COALESCE(c13, CASE WHEN c12 IS NULL THEN 0 ELSE 102 END) AS c13,
    COALESCE(c14, CASE WHEN c13 IS NULL THEN 0 ELSE 102 END) AS c14,
    COALESCE(c15, CASE WHEN c14 IS NULL THEN 0 ELSE 102 END) AS c15,
    COALESCE(c16, CASE WHEN c15 IS NULL THEN 0 ELSE 102 END) AS c16,
    COALESCE(c17, CASE WHEN c16 IS NULL THEN 0 ELSE 102 END) AS c17,
    COALESCE(c18, CASE WHEN c17 IS NULL THEN 0 ELSE 102 END) AS c18,
    COALESCE(c19, CASE WHEN c18 IS NULL THEN 0 ELSE 102 END) AS c19,
    COALESCE(c20, CASE WHEN c19 IS NULL THEN 0 ELSE 102 END) AS c20,
    COALESCE(c21, CASE WHEN c20 IS NULL THEN 0 ELSE 102 END) AS c21,
    COALESCE(c22, CASE WHEN c21 IS NULL THEN 0 ELSE 102 END) AS c22,
    COALESCE(c23, CASE WHEN c22 IS NULL THEN 0 ELSE 102 END) AS c23,
    COALESCE(c24, CASE WHEN c23 IS NULL THEN 0 ELSE 102 END) AS c24,
    CASE WHEN c25 IS NULL THEN 0 ELSE 102 END AS c25
  FROM prepared_ds
) WITH DATA;
'''
eng.execute(create_cleaned_ds_qry)
  • Полученные данные будут выглядеть следующим образом:
cleaned_ds_dtf = tdml.DataFrame('cleaned_ds')
cleaned_ds_dtf

Очищенный набор обучающих данных можно сохранить в объектном хранилище, чтобы его можно было легко использовать любым инструментом машинного обучения в любом облаке.

Мы могли бы легко сохранить данные в файле Parquet в Microsoft Azure, например, с помощью простого оператора, подобного приведенному ниже. Аналогично, данные также могут быть сохранены в любом другом поставщике объектного хранилища, поддерживаемом Teradata’s Native Object Storage — NOS.

SELECT NodeId, AmpId, Sequence, ObjectName, ObjectSize, RecordCount
FROM WRITE_NOS_FM (
    ON (
        select * from cleaned_ds
    )

    USING
    LOCATION('/AZ/<azure_blob_storage_folder>/')
    STOREDAS('PARQUET')
    COMPRESSION('GZIP')
    NAMING('RANGE')
    INCLUDE_ORDERING('TRUE')
    MAXOBJECTSIZE('4MB')
) AS d 
ORDER BY AmpId;

Эту команду можно запустить непосредственно в Jupyter Notebook через соответствующий механизм или любой клиент базы данных. Фрагмент предоставлен только для справки, поскольку в этом пошаговом руководстве не рассматривается блочное хранилище.

Модельное обучение

Теперь мы готовы начать обучение модели. Teradata можно легко интегрировать с машинным обучением Azure, особенно если у вас уже есть экземпляр Teradata VantageCloud Lake на платформе. Интеграция также очень удобна с AWS SageMaker и Google Cloud Vertex AI.

В исследуемом нами примере данные, используемые для обучения, состоят из данных «заказов», которые систематически упорядочены на основе последовательного добавления продуктов в каждый заказ. На этапе обучения цель состоит в том, чтобы выявить связи между продуктами, уделяя особое внимание последовательности их добавления в корзину. По сути, мы пытаемся присвоить вероятность событию добавления определенного товара (например, хот-догов) после добавления в корзину другого товара (например, хлеба). Это аналогично обнаружению порядка слов в предложении на основе контекста.

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

Поскольку нейронные сети обнаруживают взаимосвязи, маскируя некоторые значения в предложении и пытаясь угадать, какое «слово» должно занимать это пространство, этот процесс требует больших вычислительных затрат.

Обучение в облаке дает преимущества масштабируемости и экономичности, поскольку вычислительные ресурсы можно задействовать тогда, когда они самые дешевые, и в том объеме, который строго необходим.

В ходе обучения постоянно проверяются прогностические возможности модели. Для этого обычно доступные данные делятся между обучающим набором, используемым для обучения модели, и тестовым набором. Когда прогностические возможности модели считаются достаточно хорошими в соответствии с бизнес-требованиями, а также бизнес- и техническими ограничениями, модель готова к внедрению.

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

Операционализация модели

Развертывание модели

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

Teradata Vantage включает пакет Build Your Own Model (BYOM). BYOM позволяет импортировать модель, например, в виде файла ONNX в хранилище данных или озеро данных. В рамках этой парадигмы модель становится еще одним активом в вашей среде данных. Прогнозы можно делать в виде запросов к хранилищу данных или озеру данных. Оценка модели также становится операцией внутри базы данных, оптимизируя процесс обновления и уточнения модели.

Развертывание модели в этом сценарии может быть таким простым, как приведенный ниже код, в котором вы определяете свою модель и таблицу, в которую хотите ее экспортировать, и вуаля!

#deploy downloaded model to Teradata
print(f'Deploying model with id "%s" to table "%s"...' % (deployment_conf["model_id"], deployment_conf['model_table']))
tdml.delete_byom(
    deployment_conf["model_id"],
    deployment_conf['model_table'])
tdml.save_byom(
    deployment_conf["model_id"], 
    './' + model_file_path,
    deployment_conf['model_table'])

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

def get_context_based_recommendations(product_names, rec_number = 5, overwrite_cache = False):
    seq_ids = collect_seq_ids(prouct_names)
    select_tensor = generate_select_tensor(seq_ids, 32)

    query = f"""query to the model"""%(
        select_tensor, 
        deployment_conf["model_table"], 
        deployment_conf["model_id"], 
        f"OverwriteCachedModel('%s')"%deployment_conf["model_id"] if overwrite_cache else "",
        rec_number
        )

    result = {}

    sql_res = conn.execute(query)

    for row in sql_res:
        result[row["num"]] = {"product_name": row["product_name"], "product_id": row["product_id"], "department_id": row["department_id"], "aisle_id": row["aisle_id"]}

    return result

Модельные операции

В контексте нашего примера мы могли бы запускать очень простые команды SQL для получения рекомендаций из модели, развернутой в нашем хранилище данных или озере данных. Это имеет дополнительное преимущество, заключающееся в том, что рекомендации модели могут быть дополнительно уточнены с учетом контекста других данных в нашей среде данных, предыдущей истории конкретного клиента, местных предложений в зависимости от местоположения клиента и многих других параметров. Это преимущество, которое изолированная генеративная модель ИИ не сможет интегрировать.

Наконец, с помощью таких инструментов, как ModelOps, мы можем легко измерить производительность модели и следить за тем, когда ее следует обновить или уточнить.

Заключение

В этой статье мы описали аналитические возможности Teradata Vantage, связанные с различными этапами жизненного цикла машинного обучения. Когда дело доходит до анализа и преобразования данных на этапе определения проблемы и подготовки данных, аналитические возможности Teradata Vantage являются мощными. Надежные облачные предложения Teradata Vantage обеспечивают плавный переход от операционных данных к обучению моделей на передовых платформах. Наконец, такие инструменты, как Build Your Own Model и ModelOps, облегчают немедленное развертывание, ввод в эксплуатацию и мониторинг моделей не изолированно, а в бизнес-контексте, где эти модели предназначены для повышения ценности.

Обратная связь и вопросы

Мы ценим ваше мнение и точку зрения! Поделитесь своими мыслями, отзывами и идеями в комментариях ниже. Не стесняйтесь также изучить множество ресурсов, доступных на Портале разработчиков Teradata и Сообществе разработчиков Teradata.

об авторе

Дэниел — строитель и специалист по решению проблем, которого постоянно вдохновляет возможность создавать инструменты, помогающие людям извлекать ценную информацию из данных.

Дэниел занимал должность технического менеджера по продуктам, специализируясь на приеме данных и ETL (извлечение, преобразование, загрузка) для корпоративных приложений. За последние три года он активно участвовал в качестве разработчика, защитника разработчиков и участника открытого исходного кода в области разработки данных для традиционных и децентрализованных приложений.

Дэниел имеет сертификат архитектора облачных решений в Microsoft Azure. Его знания распространяются на ряд языков программирования, включая SQL, Python, JavaScript и Solidity.

Свяжитесь с Дэниел в LinkedIn.