清理数据:为 SageMaker 管道整理数据
作者:互联网
将数据整理成可用形式是任何现实世界机器学习问题的重要组成部分。在处理这些类型的问题时,有几件事通常是正确的:
首先,用于理解和/或解决所提出的业务问题的信息通常存储在多个位置或文件中。无论是多个 Excel 文件、同一数据库中的不同表格,还是完全不同的系统,必须从多个来源提取信息然后将它们组合起来是很常见的。
其次,数据通常是原始形式。这意味着需要对数据进行特征化。自由文本需要转换为某种数字表示,类别需要分箱或编码,数字特征可能需要标准化,值列表转换为单个数字表示,或者可能需要应用其他自定义转换。
因为它让我展示了其中一些现实世界的问题:
- 它存储在多个文件中
- 它同时具有数字和分类特征
- 这是一个二元分类问题
目标
与生产级问题一样,需要组合此数据集并将其转化为可用形式。以下是我将在本文中完成的数据整理步骤:
- 将训练、测试和标签数据集组合成一个完整的数据集
- 生产数据集通常不会预先拆分
- 弄清楚何时、何地以及如何拆分数据是一个重要的生产考虑因素
- 将列名更新为人类可读的内容
- 这让我在完成探索性数据分析以了解数据是什么时变得更轻松
- 盲数据处理通常不是一个好主意
- 将分类特征返回到它们的文本表示
- 允许我在创建 SageMaker 管道时演示数字和分类处理
先决条件
上一篇文章中的所有先决条件1_read_from_s3.ipynb
仍然适用(已设置 SageMaker 环境和适用的 IAM 角色)。还需要上一篇文章中加载到 S3 中的数据。下面是从UCI 页面提取数据并将其加载到 S3 的代码,以防你删除了上一篇文章中的文件。
# Only run this if you deleted the output from the previous post or didn't run it at all
# If you run it accidentally, oh well, it'll just overwrite the previous files
import pandas as pd
import sagemaker
session = sagemaker.session.Session()
bucket = session.default_bucket()
prefix = '1_ins_dataset/raw'
train_uri = 'https://archive.ics.uci.edu/ml/machine-learning-databases/tic-mld/ticdata2000.txt'
test_uri = 'https://archive.ics.uci.edu/ml/machine-learning-databases/tic-mld/ticeval2000.txt'
gt_uri = 'https://archive.ics.uci.edu/ml/machine-learning-databases/tic-mld/tictgts2000.txt'
cols_uri = 'https://archive.ics.uci.edu/ml/machine-learning-databases/tic-mld/dictionary.txt'
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.to_csv(f's3://{bucket}/{prefix}/train.csv', index=False)
test.to_csv(f's3://{bucket}/{prefix}/test.csv', index=False)
ground_truth.to_csv(f's3://{bucket}/{prefix}/gt.csv', index=False)
columns.to_csv(f's3://{bucket}/{prefix}/metadata/col_info.csv', index=False)
设置 AWS 变量
每当我在 SageMaker 笔记本中运行任何东西时,几乎都需要完成此步骤。这些变量使我能够与 AWS 资源对话并确定我有权使用所述资源。
import sagemaker
import boto3
import pandas as pd
session = sagemaker.session.Session()
bucket = session.default_bucket()
prefix = '1_ins_dataset/raw'
读入数据
首先,我读入了 S3 中的所有数据。在上一篇文章中尝试了多个选项后,我决定更喜欢使用boto3.resource
. 有关如何创建此函数的上下文,包括有关我为何使用objects.filter
和split
函数以及为何将数据放入字典的信息,请阅读上一篇文章。
def read_mult_txt(bucket, prefix):
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}"
df_dict = {}
for df_name in files.keys():
df_dict[df_name] = pd.read_csv(files[df_name])
return df_dict
df_dict = read_mult_txt(bucket, prefix)
合并数据
如前所述,在处理真实世界的数据集时,数据通常不会拆分为测试和训练。我想在我的 SageMaker 管道中考虑这个现实世界的事实,所以我需要将测试数据标签添加到测试数据,然后将其与训练数据结合起来。这将使我能够解决何时以及如何为自己拆分我的训练/测试/验证数据。
注意,原始拆分仅将数据分为训练数据集和测试数据集。我会将数据拆分为训练、测试和验证。这将允许我在训练(训练数据)和优化超参数(测试数据)之后保留数据以评估我的最终模型(验证数据)。自己拆分数据使我能够做出这些类型的决定。