При переходе от локальной модели, используемой для обучения и прогнозирования пакетных данных, к производственной модели необходимо учитывать множество соображений. В этой серии публикаций рассказывается, как создать производственный конвейер, совместимый с MLOps, с помощью AWS SageMaker Studio.

SageMaker Studio — это набор инструментов, который помогает управлять инфраструктурой и совместной работой для проекта машинного обучения в экосистеме AWS. Некоторые из самых больших преимуществ SageMaker Studio включают в себя:

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

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


Предпосылки

Для краткости я предполагаю, что настроены SageMaker Studio и роль IAM с соответствующими разрешениями. В корпоративной/корпоративной среде они обычно настраиваются администратором или кем-то из команды архитекторов.

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


Записать данные в S3

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

Первая часть любого проекта по науке о данных — получение данных. При работе с AWS и SageMaker лучшим выбором для хранения данных является S3. S3 используется по умолчанию для входных и выходных данных SageMaker, включая такие вещи, как наборы обучающих данных и артефакты модели.

Во-первых, давайте поместим некоторые данные в S3. В приведенной ниже ячейке считываются четыре файла из Набор контрольных данных страховой компании размещен на Репозиторий машинного обучения UCI.

Я выбрал этот набор данных по двум основным причинам:

  • Функции представляют как текстовые/категориальные, так и числовые типы данных.
  • Несколько файлов используются для хранения данных

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


Чтение данных из репозитория UCI

Сначала нам нужно получить наши образцы данных из репозитория машинного обучения UCI. Мы можем сделать это с pandas. Как и многие специалисты по данным pandas это моя библиотека для импорта/экспорта данных, хранения и обработки.

pandas библиотека теперь использует функциональность из s3fs библиотека, которая позволяет вам работать с файлами S3 так же, как с файлами на локальном компьютере. Примечание, s3fs должен быть установлен на компьютере, на котором вы работаете, но нет необходимо импортировать в блокнот. По моему опыту, он установлен по умолчанию в ноутбуках SageMaker.

import pandas as pd

train_uri = '
test_uri = '
gt_uri = '
cols_uri = '

train = pd.read_table(train_uri, header=None)
test = pd.read_table(test_uri, header=None)
ground_truth = pd.read_table(gt_uri, header=None)
columns = pd.read_table(cols_uri, encoding='latin-1')
train.head()
Войти в полноэкранный режим

Выйти из полноэкранного режима

012345678976777879808182838485
0331328051370001000000
1371228141460001000000
2371228042430001000000
391333232450001000000
44014210141470001000000

5 строк × 86 столбцов


Установить переменные AWS

Существует несколько переменных, которые вам понадобятся при отправке информации туда и обратно по инфраструктуре AWS. Обычно это переменные типа разрешения/доступа. Также полезно фиксировать часто используемую информацию, такую ​​как ведро и префикс для конкретной папки, в которую вы будете читать и писать. Это также упрощает изменение пути к папке, если вы хотите использовать другое базовое местоположение.

import sagemaker.session

session = sagemaker.session.Session()
region = session.boto_region_name
role = sagemaker.get_execution_role()
bucket = session.default_bucket()
prefix = 'ins_dataset'
Войти в полноэкранный режим

Выйти из полноэкранного режима


Пишите на S3

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

train.to_csv(f's3://{bucket}/{prefix}/raw/train.csv', index=False)
test.to_csv(f's3://{bucket}/{prefix}/raw/test.csv', index=False)
ground_truth.to_csv(f's3://{bucket}/{prefix}/raw/gt.csv', index=False)
columns.to_csv(f's3://{bucket}/{prefix}/raw/metadata/col_info.csv', index=False)
Войти в полноэкранный режим

Выйти из полноэкранного режима

Чтобы увидеть свои данные в AWS, просто распечатайте bucket а также prefix name и откройте эту папку в консоли AWS.

f'{bucket}/{prefix}'
Войти в полноэкранный режим

Выйти из полноэкранного режима

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

пример file_path


Установить зависимости библиотеки

Часто версия библиотеки не соответствует версии, необходимой для запуска вашего кода. В приведенной ниже ячейке показано, как загружать пакеты, а также обновлять версии. Одно из наиболее частых несоответствий библиотек, с которыми я столкнулся в последнее время, это pandas. По умолчанию было pandas 1.0.X на момент создания этого поста. Мой код обычно требует обновлений от pandas 1.3.5 или позже.

pandas версия, которую вы видите, вероятно, будет отличаться от той, что указана в приведенном ниже выводе. Вторая ячейка ниже — это код для установки или обновления пакетов. Третья ячейка включена для двойной проверки правильности применения необходимых изменений. Примечаниекод для этого конкретного ноутбука должен работать практически на любом pandas версия >= 1.X.

pd.__version__
Войти в полноэкранный режим

Выйти из полноэкранного режима

'1.0.1'
Войти в полноэкранный режим

Выйти из полноэкранного режима

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

import sys
!{sys.executable} -m pip install category_encoders
!{sys.executable} -m pip install pandas numpy --upgrade
Войти в полноэкранный режим

Выйти из полноэкранного режима

pd.__version__
Войти в полноэкранный режим

Выйти из полноэкранного режима

'1.3.5'
Войти в полноэкранный режим

Выйти из полноэкранного режима


Чтение из S3

Вот мы и подошли к главному пункту этого поста. Чтение файлов и метаданных из S3. Сначала нам нужно numpy, pandasа также boto3. numpy а также pandas пакеты для управления данными, boto3 облегчает взаимодействие с AWS.

import numpy as np
import pandas as pd
import boto3
Войти в полноэкранный режим

Выйти из полноэкранного режима


Прочитать один файл

Чтение одного файла легко, если вы знаете S3 URI. По сути, мы можем сделать это так же, как мы изначально прочитали файл из репозитория UCI.

example = pd.read_csv(f's3://{bucket}/{prefix}/raw/train.csv')
example.head()
Войти в полноэкранный режим

Выйти из полноэкранного режима

012345678976777879808182838485
0331328051370001000000
1371228141460001000000
2371228042430001000000
391333232450001000000
44014210141470001000000

5 строк × 86 столбцов

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


Список файлов в подкаталоге

Вам может понадобиться или не понадобиться видеть, что находится в папке. Но обычно мне удобно иметь возможность подтвердить, что там есть, а чего нет. Есть несколько способов сделать это:

  • boto3.client
  • boto3.resource
  • командная строка

Примечаниевсе три метода возвращают имя подкаталога, а также файлы в нем.

Я посмотрю на них один за другим. Вот где иметь bucket а также prefix переменные очень кстати. Примечание, для ячеек не включены выходные данные, которые раскрывали бы информацию об учетной записи, включая полные URI S3. Чтобы увидеть эту информацию самостоятельно, клонируйте репозиторий и запустите блокнот.


boto3.client

s3_client = boto3.client("s3")
s3_client.list_objects_v2(Bucket=bucket, Prefix=prefix)
Войти в полноэкранный режим

Выйти из полноэкранного режима

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

1_2_client_output.png

Это много информации и довольно беспорядочно. Мы можем сузить его до информации о файлах, просмотрев «Содержание».

s3_client = boto3.client("s3")
s3_client.list_objects_v2(Bucket=bucket, Prefix=prefix)['Contents']
Войти в полноэкранный режим

Выйти из полноэкранного режима

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

1_3_client_output_contents.png


boto3.resource

s3_resource = boto3.resource("s3")
s3_bucket = s3_resource.Bucket(bucket)

for object_summary in s3_bucket.objects.filter(Prefix=prefix):
    print(object_summary.key)
Войти в полноэкранный режим

Выйти из полноэкранного режима

ins_dataset/raw/gt.csv
ins_dataset/raw/metadata/col_info.csv
ins_dataset/raw/test.csv
ins_dataset/raw/train.csv
Войти в полноэкранный режим

Выйти из полноэкранного режима


Командная строка

file_path = f's3://{bucket}/{prefix}/raw/'
file_path
Войти в полноэкранный режим

Выйти из полноэкранного режима

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

1_4_s3_uri_ex.png

Затем мы включаем file_path переменная в команде bash, введенная прямо в ячейку Jupyter.

!aws s3 ls $file_path
Войти в полноэкранный режим

Выйти из полноэкранного режима

                           PRE metadata/
2022-10-25 18:56:26       8002 gt.csv
2022-10-25 18:56:26     683549 test.csv
2022-10-25 18:56:25    1006399 train.csv
Войти в полноэкранный режим

Выйти из полноэкранного режима

Размер файлов (средние значения в приведенном выше выводе) может быть полезен для определения объема необходимой памяти. Я также использовал его для выбора файлов меньшего размера для тестирования/прототипирования кода, прежде чем запускать более крупные экземпляры для обработки больших файлов.

Информацию можно вывести в CSV-файл, используя следующий код:

!aws s3 ls $file_path | cat >> files.csv
Войти в полноэкранный режим

Выйти из полноэкранного режима


Захват имен файлов и чтение

я нахожу boto3.resource с выводом проще всего работать, поэтому я буду использовать его для захвата имен файлов и чтения того, что мне нужно.

s3_resource = boto3.resource("s3")
s3_bucket = s3_resource.Bucket(bucket)

file_names = []

for object_summary in s3_bucket.objects.filter(Prefix=prefix):
    if (len(object_summary.key.rsplit('.')) == 2):
        file_names.append(object_summary.key)

file_names
Войти в полноэкранный режим

Выйти из полноэкранного режима

['ins_dataset/raw/gt.csv',
 'ins_dataset/raw/metadata/col_info.csv',
 'ins_dataset/raw/test.csv',
 'ins_dataset/raw/train.csv']
Войти в полноэкранный режим

Выйти из полноэкранного режима

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

Эти типы условных выражений можно использовать разными способами для возврата только определенных типов файлов (csv, parquet, txt и т. д.) или для захвата только частей пути к файлу. Одним из вариантов использования для этого может быть словарь, где ключ — это имя файла, а значение — путь к файлу.

s3_resource = boto3.resource("s3")
s3_bucket = s3_resource.Bucket(bucket)

files = {}

for object_summary in s3_bucket.objects.filter(Prefix=prefix):
    if (len(object_summary.key.rsplit('.')) == 2) & (len(object_summary.key.split(")) <= 3):
        files[object_summary.key.split(")[-1].split('.')[0]] = f"s3://{bucket}/{object_summary.key}"

files
Войти в полноэкранный режим

Выйти из полноэкранного режима

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

1_5_resource_output.png

Из словаря «имя» и «URI» легко создать словарь фреймов данных.

Словарь структуры данных фреймов данных чрезвычайно полезен тем, что легко назвать фрейм данных и иметь неопределенное количество фреймов данных для чтения.

df_dict = {}

for df_name in files.keys():
    print(df_name)
    df_dict[df_name] = pd.read_table(files[df_name], header=None)

df_dict
Войти в полноэкранный режим

Выйти из полноэкранного режима

gt
test
train

{'gt':       0
 0     0
 1     0
 2     1
 ...  ..
 3998  0
 3999  0
 4000  0

 [4001 rows x 1 columns],

 'test':                                                       0
 0     0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18...
 1     33,1,4,2,8,0,6,0,3,5,0,4,1,1,8,2,2,6,0,0,1,2,6...
 2     6,1,3,2,2,0,5,0,4,5,2,2,1,4,5,5,4,0,5,0,0,4,0,...
 ...                                                 ...
 3998  36,1,2,3,8,1,5,1,3,7,0,2,2,5,3,2,3,4,2,0,0,3,4...
 3999  33,1,3,3,8,1,4,2,3,7,1,2,2,3,4,1,3,5,1,1,1,2,3...
 4000  8,1,2,3,2,4,3,0,3,5,2,2,0,6,3,8,0,1,8,0,0,0,0,...

 [4001 rows x 1 columns],

 'train':                                                       0
 0     0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18...
 1     33,1,3,2,8,0,5,1,3,7,0,2,1,2,6,1,2,7,1,0,1,2,5...
 2     37,1,2,2,8,1,4,1,4,6,2,2,0,4,5,0,5,4,0,0,0,5,0...
 ...                                                 ...
 5820  33,1,3,4,8,0,6,0,3,5,1,4,3,3,4,0,1,8,1,0,0,2,3...
 5821  34,1,3,2,8,0,7,0,2,7,2,0,0,4,5,0,2,7,0,2,0,2,4...
 5822  33,1,3,3,8,0,6,1,2,7,1,2,1,4,4,1,2,6,1,0,1,3,2...

 [5823 rows x 1 columns]}
Войти в полноэкранный режим

Выйти из полноэкранного режима


Удалить файлы

Чтобы с вашей учетной записи не взимались текущие платежи, вы можете удалить файлы из S3.

prefix = prefix + "
Войти в полноэкранный режим

Выйти из полноэкранного режима

s3_bucket = s3_resource.Bucket(bucket)
s3_bucket.objects.filter(Prefix=prefix).delete()
Войти в полноэкранный режим

Выйти из полноэкранного режима

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

1_6_delete_files.png