Skip to main content

Weights & Biases로 표 형식 데이터의 버전 관리와 중복 제거

표형 데이터의 손쉬운 반복, 중복 제거, 그리고 버전 관리 이 글은 AI 번역본입니다. 오역이 의심되면 댓글로 알려주세요
Created on September 12|Last edited on September 12

소개

이 안내서는 표형 데이터의 버전 관리를 하고 반복적으로 개선하기 위해 W&B를 사용하는 방법에 초점을 맞춥니다. 우리는 사용할 것입니다 Artifacts 그리고 Tables 데이터셋을 로드한 뒤 학습, 검증, 테스트 하위 집합으로 나눕니다. 아티팩트의 버전 관리 기능 덕분에 최소한의 저장 공간만 사용하면서도 지속적인 버전 레이블을 유지할 수 있어, 동료들과 데이터셋의 반복 개선본을 쉽게 공유할 수 있습니다.
우리는 심근경색 환자의 예후를 예측하는 데 초점을 맞춘 표형 의료 데이터를 다룰 것입니다. 이러한 유틸리티를 이미지 데이터 분류 작업에 적용하는 방법을 보고 싶다면, 다음을 확인하세요 다른 예시그리고 이 튜토리얼을 실행 가능한 Colab에서 직접 경험하고 싶다면, 아래를 클릭하세요:

코드를 따라하지 않아도 데이터와 상호작용할 수 있습니다! 이 보고서의 모든 Tables는 완전히 인터랙티브하므로 자유롭게 탐색해 보세요 (문서). 왼쪽 상단의 식 편집기를 사용해 행을 필터링할 수 있습니다. 열의 값을 기준으로 정렬하거나 그룹화하려면 헤더에 마우스를 올리고 오른쪽의 점 세 개 메뉴를 클릭해 작업을 선택하세요. The 테이블 초기화 오른쪽 아래에 있는 버튼을 누르면 각 Table이 원래 구성으로 돌아가며, 페이지를 새로고침하면 전체 보고서가 초기화됩니다.

데이터 소개

우리의 데이터셋 레스터 대학교 연구진이 구축했습니다. 이 데이터셋은 심근경색 관련 증상을 보이는 병원 환자들의 측정값과 설문 응답을 모아 놓은 것입니다. 이러한 데이터셋과 이를 기반으로 만든 모델이 환자 치료 결과를 개선하고 생명을 구할 수 있다고 말해도 과언이 아닙니다. 순수한 머신러닝 관점에서도 이 데이터셋은 다음과 같은 특징 때문에 흥미롭습니다:
  • 혼합형 타입항목은 이진, 서수, 수치, 범주형일 수 있습니다
  • 결측치대부분의 피처에는 일정 비율의 결측치가 있습니다
  • 현실 세계의 복잡성특성 값의 분포가 균일하지 않고 이상치가 있습니다
  • 제한된 크기: 데이터를 수집하기가 어려워서 데이터셋이 작습니다
먼저 Table에서 데이터를 살펴보겠습니다:

ID
AGE
SEX
INF_ANAM
STENOK_AN
FK_STENOK
IBS_POST
IBS_NASL
GB
SIM_GIPERT
DLIT_AG
ZSN_A
nr_11
nr_01
nr_02
nr_03
nr_04
nr_07
nr_08
np_01
np_04
np_05
np_07
np_08
np_09
np_10
endocr_01
endocr_02
endocr_03
zab_leg_01
zab_leg_02
zab_leg_03
zab_leg_04
zab_leg_06
S_AD_KBRIG
D_AD_KBRIG
S_AD_ORIT
D_AD_ORIT
O_L_POST
K_SH_POST
MP_TP_POST
SVT_POST
GT_POST
FIB_G_POST
ant_im
lat_im
inf_im
post_im
IM_PG_P
ritm_ecg_p_01
ritm_ecg_p_02
ritm_ecg_p_04
ritm_ecg_p_06
ritm_ecg_p_07
ritm_ecg_p_08
n_r_ecg_p_01
n_r_ecg_p_02
n_r_ecg_p_03
n_r_ecg_p_04
n_r_ecg_p_05
n_r_ecg_p_06
n_r_ecg_p_08
n_r_ecg_p_09
n_r_ecg_p_10
n_p_ecg_p_01
n_p_ecg_p_03
n_p_ecg_p_04
n_p_ecg_p_05
n_p_ecg_p_06
n_p_ecg_p_07
n_p_ecg_p_08
n_p_ecg_p_09
n_p_ecg_p_10
n_p_ecg_p_11
n_p_ecg_p_12
fibr_ter_01
fibr_ter_02
fibr_ter_03
fibr_ter_05
fibr_ter_06
fibr_ter_07
fibr_ter_08
GIPO_K
K_BLOOD
GIPER_NA
NA_BLOOD
ALT_BLOOD
AST_BLOOD
KFK_BLOOD
L_BLOOD
ROE
TIME_B_S
R_AB_1_n
R_AB_2_n
R_AB_3_n
NA_KB
NOT_NA_KB
LID_KB
NITR_S
NA_R_1_n
1
2
3
위의 Table에서 각 행은 한 명의 환자에 대응하며, 각 열은 특정 질문에 대한 응답 또는 어떤 측정의 결과를 나타냅니다.
보시다시피 항목 유형은 이진형(예: “예/아니오” 질문), 수치형(예: 혈압 측정값), 서열형(예: “1부터 10까지…”와 같은 질문), 또는 범주형(예: 환자 결과)일 수 있습니다. The 데이터셋 홈페이지 더 깊이 살펴보고 싶다면 각 데이터 범주에 대한 완전한 정리가 제공됩니다.
위의 Table은 Artifact로 저장되어 있어 버전 관리가 됩니다. Table이 차지하는 저장 용량을 확인하기 위해 해당 Artifact를 살펴볼 수 있습니다.

data-table.table.json
742.7KB
742.7KB

학습, 검증, 테스트 분할 생성

이 데이터셋은 작을 수 있지만, 인구 센서스, 기상, 자율주행 차량 데이터 등 다양한 분야에서 훨씬 더 큰 표 형식 데이터가 흔히 사용됩니다. 규모와 상관없이, 데이터셋을 반복적으로 개선하거나 재구성할 때 불필요한 중복본을 저장하는 일은 피하고자 합니다.
그래서 다음을 사용하는 것이 유용합니다 데이터셋 버전 관리 W&B에서 제공하는 기능입니다. 일반적인 ML 파이프라인의 첫 단계는 데이터를 무작위로 학습, 검증, 테스트 예시로 분할하는 것입니다. 우리의 데이터가 wandb Table에 저장되어 있으므로, 우리는 이를 사용할 수 있습니다 get_index() 함수 (문서) 데이터를 추가 저장 비용 없이 분할할 수 있습니다.
바로 그 작업을 수행하기 위한 우리의 함수는 다음과 같습니다:
def make_split_artifact(run, raw_data_table, train_rows, val_rows, test_rows):
"""
Creates a w&b artifact that contains a singular reference table (aka a ForeignIndex table).
The ForeignIndex table has a single column that we are naming 'source'.
It contains references to the original table (raw_data_table) for each of the splits.
Arguments:
run (wandb run) returned from wandb.init()
raw_data_table (wandb Table) that contains your original tabular data
train_rows (list of ints) indices that reference the training rows in the raw_data_table
val_rows (list of ints) indices that reference the validation rows in the raw_data_table
test_rows (list of ints) indices that reference the test rows in the raw_data_table
"""
split_artifact = wandb.Artifact(
'data-splits', type='dataset',
description='Train, validation, test dataset splits')
# Our data split artifact will only store index references to the original dataset table to save space
data_table_pointer = raw_data_table.get_index() # ForeignIndex automatically references the source table
split_artifact.add(wandb.Table(
columns=['source'],
data=[[data_table_pointer[i]] for i in train_rows]), 'train-data')
split_artifact.add(wandb.Table(
columns=['source'],
data=[[data_table_pointer[i]] for i in val_rows]), 'val-data')
split_artifact.add(wandb.Table(
columns=['source'],
data=[[data_table_pointer[i]] for i in test_rows]), 'test-data')
run.log_artifact(split_artifact)
이 함수에서는 다음과 같은 새 아티팩트를 생성했습니다, 이름은 split_artifact, 학습, 검증, 테스트 데이터에 해당하는 Tables를 저장하는 저장소가 됩니다.
다음 단계(그리고 이 부분이 정말 흥미롭습니다)는 를 정의하는 것입니다 data_table_pointer, 본질적으로 원본 데이터 테이블을 가리키는 포인터들의 목록입니다. 우리는 자체적인 data 슬라이스된 부분에 할당된 필드들 data_table_pointer 그리고 이를 다음에 저장합니다 split_artifact. 아티팩트를 로그로 남기고 나면, 우리는 이전으로 돌아가서 Files 웹 앱의 보기에서 얼마나 작은지 확인해 보세요:

media /
0.0B1 subfolder, 0 files
test-data.table.json
1.5KB
1.5KB
train-data.table.json
10.2KB
10.2KB
val-data.table.json
1.5KB
1.5KB
분할된 테이블은 원시 데이터 테이블의 위치와 해당 테이블에 접근하기 위한 참조 인덱스만 저장하기 때문에 원시 데이터 테이블보다 훨씬 작습니다. 파일을 다운로드해 보면 인덱스로 이루어진 단일 열임을 확인할 수 있습니다. 웹 앱에서 이를 클릭하면 W&B가 자동으로 역참조하여 원본 데이터를 보여줍니다. 아래는 예시 테이블입니다:

source.ID
source.AGE
source.SEX
source.INF_ANAM
source.STENOK_AN
source.FK_STENOK
source.IBS_POST
source.IBS_NASL
source.GB
source.SIM_GIPERT
source.DLIT_AG
source.ZSN_A
source.nr_11
source.nr_01
source.nr_02
source.nr_03
source.nr_04
source.nr_07
source.nr_08
source.np_01
source.np_04
source.np_05
source.np_07
source.np_08
source.np_09
source.np_10
source.endocr_01
source.endocr_02
source.endocr_03
source.zab_leg_01
source.zab_leg_02
source.zab_leg_03
source.zab_leg_04
source.zab_leg_06
source.S_AD_KBRIG
source.D_AD_KBRIG
source.S_AD_ORIT
source.D_AD_ORIT
source.O_L_POST
source.K_SH_POST
source.MP_TP_POST
source.SVT_POST
source.GT_POST
source.FIB_G_POST
source.ant_im
source.lat_im
source.inf_im
source.post_im
source.IM_PG_P
source.ritm_ecg_p_01
source.ritm_ecg_p_02
source.ritm_ecg_p_04
source.ritm_ecg_p_06
source.ritm_ecg_p_07
source.ritm_ecg_p_08
source.n_r_ecg_p_01
source.n_r_ecg_p_02
source.n_r_ecg_p_03
source.n_r_ecg_p_04
source.n_r_ecg_p_05
source.n_r_ecg_p_06
source.n_r_ecg_p_08
source.n_r_ecg_p_09
source.n_r_ecg_p_10
source.n_p_ecg_p_01
source.n_p_ecg_p_03
source.n_p_ecg_p_04
source.n_p_ecg_p_05
source.n_p_ecg_p_06
source.n_p_ecg_p_07
source.n_p_ecg_p_08
source.n_p_ecg_p_09
source.n_p_ecg_p_10
source.n_p_ecg_p_11
source.n_p_ecg_p_12
source.fibr_ter_01
source.fibr_ter_02
source.fibr_ter_03
source.fibr_ter_05
source.fibr_ter_06
source.fibr_ter_07
source.fibr_ter_08
source.GIPO_K
source.K_BLOOD
source.GIPER_NA
source.NA_BLOOD
source.ALT_BLOOD
source.AST_BLOOD
source.KFK_BLOOD
source.L_BLOOD
source.ROE
source.TIME_B_S
source.R_AB_1_n
source.R_AB_2_n
source.R_AB_3_n
source.NA_KB
source.NOT_NA_KB
source.LID_KB
source.NITR_S
source.NA_R_1_n
1
2
3
4
여기는 검증 데이터 분할이므로, 아래를 보면 전체 데이터셋이 1,700개였던 것과 달리 170개 행만 포함되어 있습니다. 또한 모든 열 제목에 다음이 포함되도록 변경된 것도 눈치채셨을 겁니다 source 원본 제목 앞에 붙는데, 이는 다른 테이블을 참조하고 있음을 나타내기 위한 표시일 뿐입니다(구체적인 이름인 “source”는 임의로 정해진 것이며, 위 코드에서 정의됩니다).

버전 관리형 전처리 파이프라인

전처리를 위해 누락된 값을 0으로 채우고, 각 행을 PyTorch 텐서로 캐스팅하며, 레이블을 원-핫 형식으로 변환하는 것부터 시작하겠습니다.
전처리 파이프라인도 버전 관리할 수 있어야 모델과 데이터셋과는 독립적으로 반복 개선할 수 있습니다. 이를 구현하는 방법은 여러 가지가 있지만, 가장 간단한 방법 중 하나는 이름이 지정된 단계들을 순서대로 담은 사전과 이를 해석하는 함수를 사용하는 것입니다.
다음은 OrderedDictionary를 아티팩트에 기록하는 코드입니다. 이어서 Colab 노트북여기에서 이 사전을 파싱해 PyTorch 변환 함수를 반환하는 코드를 확인할 수 있습니다.
with wandb.init(project=PROJECT_NAME, job_type='define-transforms', config=config) as run:
# Define an initial set of transforms that we think will be useful
transform_dict = OrderedDict()
transform_dict['NoneToVal'] = {
'value': 0 # for the first pass we will replace missing values with 0
}
transform_dict['ToTensor'] = {
'device': DEVICE
}
transform_dict['OneHot'] = {
'num_classes': config['num_classes']
}
# Include an operational index to verify the order
for key_idx, key in enumerate(transform_dict.keys()):
transform_dict[key]['order'] = key_idx
# Create an artifact for logging the transforms
data_transform_artifact = wandb.Artifact(
'data-transforms', type='parameters',
description='Data preprocessing functions and parameters.',
metadata=transform_dict) # Optional for viewing on the web app; the data is also stored in the txt file below
# Log the transforms in JSON format
with data_transform_artifact.new_file('transforms.txt') as f:
f.write(json.dumps(transform_dict, indent=4))
run.log_artifact(data_transform_artifact)
config.update(transform_dict) # Log the transforms in the config so that we can sweep over them in future iterations

# Now we can make the data loaders with the preprocessing pipeline
train_loader, val_loader, test_loader = make_loaders(config)
생성된 아티팩트에는 순서가 보장된 JSON 형식의 전처리 단계가 담긴 텍스트 파일이 포함되어 있습니다.

{
    "NoneToVal": {
        "value": 0,
        "order": 0
    },
    "ToTensor": {
        "device": "cpu",
        "order": 1
    },
    "OneHot": {
        "num_classes": 8,
        "order": 2
    }
}
이 파일도 다른 모든 것과 마찬가지로 버전 관리되기 때문에, 과정을 쉽게 추적하고 특정 전처리 파이프라인을 공유할 수 있습니다. 모든 Artifact 버전은 다음을 통해 확인할 수 있습니다. Artifacts 개요: 사용자 환경 Projects 페이지입니다. 여기에서 쉽게 추가할 수 있습니다 특정 버전에 대한 별칭 동료와 공유하려는 내용입니다.

Weights & Biases로 아티팩트와 버전 관리하기

결론

여기까지입니다! 직접 해보고 싶다면, 다음을 실행하세요 Colab 노트북 그리고 다른 시드나 비율로 학습/검증/테스트 분할 인덱스를 수정할 수도 있습니다. 또는 전처리 단계를 추가해도 됩니다. 무엇을 하든 모두 기록되고 공유할 수 있습니다!

이 문서는 AI로 번역되었습니다. 오역이 있을 수 있으니 댓글로 알려 주세요. 원문 보고서 링크는 다음과 같습니다: 원문 보고서 보기
File<(table)>
Dir
Dir
File<(table)>
File<{extension: txt}>