Robot Dataset 분석과 VLA 입출력 · 학습

실행 조건

작은 데이터 분석에는 requests·pandas·pyarrow·scikit-learn이 필요합니다. 공개 Parquet 한 개만 읽으며 인터넷 연결이 필요합니다.

VLA 모델 추론·학습은 별도의 장비와 모델별 환경을 사용합니다.

필요한 패키지가 없으면 Colab·Jupyter 코드 셀에서 %pip install pyarrow==23.0.1를 실행하세요.

이번에 배울 내용

공개 시연 데이터를 직접 읽고 평가 기준을 만든 뒤, 시각·언어·행동 모델에 연결할 입력과 출력의 의미를 확인합니다.

시연 데이터와 평가

연속 Frame은 강하게 연관되므로 Frame 무작위 분할과 Episode 단위 분할의 결과가 다를 수 있습니다. 기록된 Action 예측 오차와 실제 Task 성공률도 구분합니다.

VLA의 인터페이스

카메라·현재 로봇 상태·언어 지시가 Action chunk로 이어집니다. 로봇별 Action 표현·Normalization·시간 기준을 알아야 사전학습 정책을 사용할 수 있습니다.

VLM·VLA·서빙

VLM의 장면 해석과 VLA의 행동 출력은 역할이 다릅니다. vLLM은 지원하는 모델의 추론·서빙에 활용할 수 있으며, 그 출력이 로봇의 유효한 Action인지는 별도로 검증해야 합니다.

풀이 예제

LeRobot svla_so100_pickplace의 첫 Parquet shard를 읽습니다. 영상·모델 가중치는 내려받지 않습니다.

"""Read one public LeRobot data shard, without downloading videos or model weights."""
import io,json
import numpy as np
import pandas as pd
import requests
repo='lerobot/svla_so100_pickplace'
def read_json(url):
    response=requests.get(url,timeout=30);response.raise_for_status();return response.json()
manifest=read_json('https://huggingface.co/api/datasets/'+repo)
revision=manifest['sha']
base='https://huggingface.co/datasets/'+repo+'/resolve/'+revision+'/'
metadata=read_json(base+'meta/info.json')
shards=sorted(x['rfilename'] for x in manifest['siblings'] if x['rfilename'].startswith('data/') and x['rfilename'].endswith('.parquet'))
assert shards,'Dataset layout changed; inspect the repository data tree.'
response=requests.get(base+shards[0],timeout=60);response.raise_for_status()
frame=pd.read_parquet(io.BytesIO(response.content))
print('Repository / revision / shard:',repo,revision,shards[0])
print('Format / FPS / episodes:',metadata.get('codebase_version'),metadata['fps'],metadata['total_episodes'])
print('Features:',metadata['features'])
print('Loaded rows / episodes:',len(frame),frame['episode_index'].nunique())
state=np.stack(frame['observation.state'].to_numpy())
action=np.stack(frame['action'].to_numpy())
print('State / action shape:',state.shape,action.shape)
# Task text and video paths are described in the repository metadata.
# No robot commands, model execution, remote uploads, or video downloads occur here.
Repository / revision / shard: lerobot/svla_so100_pickplace 728583b5eaf9e739a7f119e2def466fa1d552402 data/chunk-000/file-000.parquet
Format / FPS / episodes: v3.0 30 50
Features: {'action': {'dtype': 'float32', 'shape': [6], 'names': ['main_shoulder_pan', 'main_shoulder_lift', 'main_elbow_flex', 'main_wrist_flex', 'main_wrist_roll', 'main_gripper'], 'fps': 30.0}, 'observation.state': {'dtype': 'float32', 'shape': [6], 'names': ['main_shoulder_pan', 'main_shoulder_lift', 'main_elbow_flex', 'main_wrist_flex', 'main_wrist_roll', 'main_gripper'], 'fps': 30.0}, 'observation.images.top': {'dtype': 'video', 'shape': [480, 640, 3], 'names': ['height', 'width', 'channels'], 'info': {'video.fps': 30.0, 'video.height': 480, 'video.width': 640, 'video.channels': 3, 'video.codec': 'av1', 'video.pix_fmt': 'yuv420p', 'video.is_depth_map': False, 'has_audio': False}}, 'observation.images.wrist': {'dtype': 'video', 'shape': [480, 640, 3], 'names': ['height', 'width', 'channels'], 'info': {'video.fps': 30.0, 'video.height': 480, 'video.width': 640, 'video.channels': 3, 'video.codec': 'av1', 'video.pix_fmt': 'yuv420p', 'video.is_depth_map': False, 'has_audio': False}}, 'timestamp': {'dtype': 'float32', 'shape': [1], 'names': None, 'fps': 30.0}, 'frame_index': {'dtype': 'int64', 'shape': [1], 'names': None, 'fps': 30.0}, 'episode_index': {'dtype': 'int64', 'shape': [1], 'names': None, 'fps': 30.0}, 'index': {'dtype': 'int64', 'shape': [1], 'names': None, 'fps': 30.0}, 'task_index': {'dtype': 'int64', 'shape': [1], 'names': None, 'fps': 30.0}}
Loaded rows / episodes: 19631 50
State / action shape: (19631, 6) (19631, 6)

공식 문서·데이터