메인 콘텐츠로 건너뛰기
W&B Tables를 사용하여 표 형식(tabular) 데이터를 시각화하고 기록할 수 있습니다. W&B Table은 각 열이 하나의 데이터 타입만 가지는 2차원 그리드입니다. 각 행은 W&B 실행에 로그된 하나 이상의 데이터 포인트를 나타냅니다. W&B Tables는 기본 및 숫자형 데이터 타입뿐만 아니라 중첩 리스트, 딕셔너리, 리치 미디어 타입도 지원합니다. W&B Table은 W&B의 특수한 데이터 타입으로, 아티팩트 객체로 로그됩니다. W&B Python SDK를 사용하여 테이블 객체를 생성하고 로그합니다. 테이블 객체를 생성할 때 테이블의 열과 데이터, 그리고 모드를 지정합니다. 모드에 따라 ML 실험 동안 테이블이 어떻게 로그되고 업데이트될지가 결정됩니다.
INCREMENTAL 모드는 W&B Server v0.70.0 이상에서 지원됩니다.

테이블 생성 및 로깅

  1. wandb.init()으로 새 실행을 초기화합니다.
  2. wandb.Table 클래스로 Table 객체를 생성합니다. columnsdata 매개변수에 각각 테이블의 열과 데이터를 지정합니다. 선택적 매개변수인 log_mode는 기본값 IMMUTABLE을 포함해 MUTABLE, INCREMENTAL 중 하나로 설정할 것을 권장합니다. 자세한 내용은 다음 섹션의 Table Logging Modes를 참고하세요.
  3. run.log()를 사용하여 테이블을 W&B에 로그합니다.
다음 예시는 두 개의 열 ab, 그리고 두 개의 데이터 행 ["a1", "b1"]["a2", "b2"]를 가진 테이블을 생성하고 로그하는 방법을 보여줍니다:
import wandb

# 새 실행 시작
with wandb.init(project="table-demo") as run:

    # 두 개의 열과 두 개의 행으로 구성된 테이블 객체 생성
    my_table = wandb.Table(
        columns=["a", "b"],
        data=[["a1", "b1"], ["a2", "b2"]],
        log_mode="IMMUTABLE"
        )

    # W&B에 테이블 로깅
    run.log({"Table Name": my_table})

로깅 모드

wandb.Tablelog_mode 매개변수는 ML 실험 중 테이블이 어떻게 로깅되고 업데이트되는지를 결정합니다. log_mode 매개변수는 IMMUTABLE, MUTABLE, INCREMENTAL 세 가지 값 중 하나를 받습니다. 각 모드는 테이블이 어떻게 로깅되는지, 어떻게 수정할 수 있는지, 그리고 W&B App에서 어떻게 렌더링되는지에 대해 서로 다른 특성을 가집니다. 다음은 세 가지 로깅 모드, 각 모드 간의 고수준 차이점, 그리고 각 모드의 일반적인 사용 사례를 설명합니다:
ModeDefinitionUse CasesBenefits
IMMUTABLE테이블이 W&B에 한 번 로깅되면 수정할 수 없습니다.- 추가 분석을 위해 실행이 끝날 때 생성된 테이블형 데이터를 저장할 때- 실행 종료 시점에 로깅할 경우 오버헤드 최소화
- 모든 행이 UI에 렌더링됨
MUTABLE테이블을 W&B에 로깅한 이후, 기존 테이블을 새로운 테이블로 덮어쓸 수 있습니다.- 기존 테이블에 열이나 행을 추가할 때
- 결과를 새로운 정보로 보강할 때
- 테이블 변경 사항 캡처
- 모든 행이 UI에 렌더링됨
INCREMENTAL머신러닝 실험 전체에 걸쳐 새로운 행 배치를 테이블에 계속 추가합니다.- 테이블에 행을 배치 단위로 추가할 때
- 장시간 실행되는 학습 작업
- 대규모 데이터셋을 배치 단위로 처리할 때
- 진행 중인 결과를 모니터링할 때
- 학습 중 UI에서 업데이트를 확인 가능
- 증가분을 단계별로 확인 가능
다음 섹션에서는 각 모드에 대한 예제 코드 스니펫과, 각 모드를 언제 사용하는 것이 적절한지에 대한 고려 사항을 설명합니다.

MUTABLE 모드

MUTABLE 모드는 기존 테이블을 새로운 테이블로 교체하는 방식으로 업데이트합니다. MUTABLE 모드는 반복 루프 없이(비반복적, non-iterative) 기존 테이블에 새로운 열과 행을 추가하려는 경우에 유용합니다. UI에서는 초기 로깅 이후에 추가된 열과 행을 포함해, 모든 행과 열이 있는 테이블이 렌더링됩니다.
MUTABLE 모드에서는 테이블을 로그할 때마다 테이블 객체가 교체됩니다. 테이블을 새 테이블로 덮어쓰는 작업은 연산 비용이 많이 들며, 테이블이 큰 경우 속도가 느려질 수 있습니다.
다음 예시는 MUTABLE 모드에서 테이블을 생성하고 로깅한 뒤, 새 열을 추가하는 방법을 보여줍니다. 테이블 객체는 총 세 번 로깅됩니다. 처음에는 초기 데이터, 두 번째는 신뢰도 점수(confidence scores), 세 번째는 최종 예측값으로 로깅됩니다.
다음 예시에서는 데이터를 로드하기 위해 load_eval_data()라는 플레이스홀더 함수와, 예측을 수행하기 위해 model.predict()라는 플레이스홀더 함수를 사용합니다. 이 함수들은 여러분의 데이터 로딩 및 예측 함수로 교체해야 합니다.
import wandb
import numpy as np

with wandb.init(project="mutable-table-demo") as run:

    # MUTABLE 로깅 모드로 테이블 객체 생성
    table = wandb.Table(columns=["input", "label", "prediction"],
                        log_mode="MUTABLE")

    # 데이터 로드 및 예측 수행
    inputs, labels = load_eval_data() # 플레이스홀더 함수
    raw_preds = model.predict(inputs) # 플레이스홀더 함수

    for inp, label, pred in zip(inputs, labels, raw_preds):
        table.add_data(inp, label, pred)

    # 1단계: 초기 데이터 기록
    run.log({"eval_table": table})  # 초기 테이블 기록

    # 2단계: 신뢰도 점수 추가 (예: 최대 소프트맥스)
    confidences = np.max(raw_preds, axis=1)
    table.add_column("confidence", confidences)
    run.log({"eval_table": table})  # 신뢰도 정보 추가

    # 3단계: 후처리된 예측값 추가
    # (예: 임계값 적용 또는 평활화된 출력)
    post_preds = (confidences > 0.7).astype(int)
    table.add_column("final_prediction", post_preds)
    run.log({"eval_table": table})  # 새 열을 추가한 최종 업데이트
훈련 루프에서처럼 새로운 행 배치(열은 없음)만 순차적으로 추가하려는 경우에는, 대신 INCREMENTAL 모드를 사용하는 것이 좋습니다.

INCREMENTAL 모드

INCREMENTAL 모드에서는 머신러닝 실험 동안 테이블에 행 배치를 나누어 기록합니다. 이는 실행 시간이 긴 작업을 모니터링하거나, 실행 중에 업데이트용으로 기록하기에는 비효율적인 대용량 테이블을 다룰 때 적합합니다. UI에서 테이블은 새 행이 기록될 때마다 업데이트되므로, 전체 실행이 끝날 때까지 기다리지 않고도 최신 데이터를 확인할 수 있습니다. 또한 각 증분을 단계별로 살펴보며 서로 다른 시점의 테이블 상태를 확인할 수 있습니다.
W&B App의 실행 워크스페이스에는 증분 100개 제한이 있습니다. 100개를 초과하여 기록하면, 실행 워크스페이스에는 가장 최근 100개만 표시됩니다.
다음 예시는 INCREMENTAL 모드에서 테이블을 생성하고, 이를 기록한 뒤 새로운 행을 추가합니다. 테이블은 학습 스텝(step)마다 한 번씩 기록된다는 점에 유의하세요.
다음 예제에서는 데이터를 로드하기 위한 플레이스홀더 함수 get_training_batch(), 모델을 학습하기 위한 플레이스홀더 함수 train_model_on_batch(), 예측을 수행하기 위한 플레이스홀더 함수 predict_on_batch()를 사용합니다. 실제 사용 시에는 여러분의 데이터 로딩, 학습, 예측 함수로 이들을 대체해야 합니다.
import wandb

with wandb.init(project="incremental-table-demo") as run:

    # INCREMENTAL 로깅 모드로 테이블 생성
    table = wandb.Table(columns=["step", "input", "label", "prediction"],
                        log_mode="INCREMENTAL")

    # 학습 루프
    for step in range(get_num_batches()): # 플레이스홀더 함수
        # 배치 데이터 로드
        inputs, labels = get_training_batch(step) # 플레이스홀더 함수

        # 학습 및 예측
        train_model_on_batch(inputs, labels) # 플레이스홀더 함수
        predictions = predict_on_batch(inputs) # 플레이스홀더 함수

        # 테이블에 배치 데이터 추가
        for input_item, label, prediction in zip(inputs, labels, predictions):
            table.add_data(step, input_item, label, prediction)

        # 테이블을 증분 방식으로 로깅
        run.log({"training_table": table}, step=step)
증분 로깅은 일반적으로 매번 새 테이블을 로깅하는 것(log_mode=MUTABLE)보다 계산 비용 면에서 더 효율적입니다. 그러나 증분 로그를 많이 기록하는 경우 W&B App이 테이블의 모든 행을 렌더링하지 못할 수 있습니다. 실행이 진행되는 동안 테이블 데이터를 업데이트해서 확인하고, 동시에 분석을 위해 모든 데이터를 사용할 수 있어야 한다면 두 개의 테이블 사용을 고려하십시오. 하나는 INCREMENTAL 로그 모드, 다른 하나는 IMMUTABLE 로그 모드를 사용합니다. 다음 예제는 이러한 목표를 달성하기 위해 INCREMENTALIMMUTABLE 로깅 모드를 함께 사용하는 방법을 보여줍니다.
import wandb

with wandb.init(project="combined-logging-example") as run:

    # 훈련 중 효율적인 업데이트를 위한 증분 테이블 생성
    incr_table = wandb.Table(columns=["step", "input", "prediction", "label"],
                            log_mode="INCREMENTAL")

    # 훈련 루프
    for step in range(get_num_batches()):
        # 배치 처리
        inputs, labels = get_training_batch(step)
        predictions = model.predict(inputs)

        # 증분 테이블에 데이터 추가
        for inp, pred, label in zip(inputs, predictions, labels):
            incr_table.add_data(step, inp, pred, label)

        # 증분 업데이트 로깅 (최종 테이블과 구분하기 위해 -incr 접미사 사용)
        run.log({"table-incr": incr_table}, step=step)

    # 훈련 종료 시 모든 데이터를 포함한 완전한 불변 테이블 생성
    # 전체 데이터셋을 보존하기 위해 기본 IMMUTABLE 모드 사용
    final_table = wandb.Table(columns=incr_table.columns, data=incr_table.data, log_mode="IMMUTABLE")
    run.log({"table": final_table})
이 예시에서 incr_table은 학습 중에 (log_mode="INCREMENTAL"로) 점진적으로 로깅됩니다. 이를 통해 새로운 데이터가 처리될 때마다 테이블 업데이트를 기록하고 확인할 수 있습니다. 학습이 끝나면, 증분 테이블의 모든 데이터를 포함하는 변경 불가능한 테이블(final_table)이 생성됩니다. 이 변경 불가능한 테이블을 로깅하여 추가 분석을 위한 전체 데이터셋을 보존하고, W&B App에서 모든 행을 조회할 수 있도록 합니다.

예제

MUTABLE로 평가 결과를 풍부하게 만들기

import wandb
import numpy as np

with wandb.init(project="mutable-logging") as run:

    # 1단계: 초기 예측값 기록
    table = wandb.Table(columns=["input", "label", "prediction"], log_mode="MUTABLE")
    inputs, labels = load_eval_data()
    raw_preds = model.predict(inputs)

    for inp, label, pred in zip(inputs, labels, raw_preds):
        table.add_data(inp, label, pred)

    run.log({"eval_table": table})  # 원시 예측값 기록

    # 2단계: 신뢰도 점수 추가 (예: 최대 소프트맥스)
    confidences = np.max(raw_preds, axis=1)
    table.add_column("confidence", confidences)
    run.log({"eval_table": table})  # 신뢰도 정보 추가

    # 3단계: 후처리된 예측값 추가
    # (예: 임계값 적용 또는 평활화된 출력)
    post_preds = (confidences > 0.7).astype(int)
    table.add_column("final_prediction", post_preds)
    run.log({"eval_table": table})

INCREMENTAL 테이블로 실행 재개하기

실행을 재개할 때에도 INCREMENTAL 테이블에 계속 로그를 기록할 수 있습니다:
# 실행을 시작하거나 재개합니다
resumed_run = wandb.init(project="resume-incremental", id="your-run-id", resume="must")

# 증분 테이블을 생성합니다. 이전에 로깅된 테이블의 데이터로 채울 필요가 없습니다.
# 증분 데이터는 계속해서 Table 아티팩트에 추가됩니다.
table = wandb.Table(columns=["step", "metric"], log_mode="INCREMENTAL")

# 로깅을 계속합니다
for step in range(resume_step, final_step):
    metric = compute_metric(step)
    table.add_data(step, metric)
    resumed_run.log({"metrics": table}, step=step)

resumed_run.finish()
wandb.Run.define_metric("<table_key>", summary="none") 또는 wandb.Run.define_metric("*", summary="none")를 사용해 증분 테이블에 사용되는 키에 대한 요약(summary)을 끄면, 증분 데이터는 새 테이블에 기록됩니다.

INCREMENTAL 배치 학습 사용하기


with wandb.init(project="batch-training-incremental") as run:

    # 증분 테이블 생성
    table = wandb.Table(columns=["step", "input", "label", "prediction"], log_mode="INCREMENTAL")

    # 시뮬레이션된 학습 루프
    for step in range(get_num_batches()):
        # 배치 데이터 로드
        inputs, labels = get_training_batch(step)

        # 이 배치로 모델 학습
        train_model_on_batch(inputs, labels)

        # 모델 추론 실행
        predictions = predict_on_batch(inputs)

        # 테이블에 데이터 추가
        for input_item, label, prediction in zip(inputs, labels, predictions):
            table.add_data(step, input_item, label, prediction)

        # 테이블의 현재 상태를 증분 방식으로 기록
        run.log({"training_table": table}, step=step)