En este tutorial, diseñamos un proceso de aprendizaje de robótica en streaming de extremo a extremo en torno al conjunto de datos NVIDIA Cosmos3-Droid sin descargar su repositorio de 707 GB de forma local. Primero analizamos la estructura de LeRobotDataset v3.0 y construimos un gráfico de metadatos a partir de info.json, los metadatos de las tareas, las tablas de episodios y las estadísticas de los conjuntos de datos. Después, utilizamos el acceso por rango de bytes HTTP con PyArrow para leer de forma selectiva los grupos de filas y las columnas de Parquet. Convertimos los episodios individuales en trayectorias de acción entre estados y analizamos el movimiento de las articulaciones, los eventos de agarre, las rutas cartesianas de los efectores finales y los espectros de frecuencia de acción antes de decodificar solo las ventanas de vídeo AV1 necesarias mediante el acceso a PyAV/FFMPEG basado en búsquedas. A continuación, normalizamos las observaciones y las acciones mediante estadísticas de conjuntos de datos, construimos un conjunto de datos PyTorch fragmentado al estilo ACT con un acondicionamiento visual opcional y aplicamos una política multimodal de clonación de comportamientos. Por último, evaluamos la política adquirida a través de una implementación en bucle abierto con fragmentos de acción ensamblados temporalmente, elaboramos informes sobre cada MSE y R^2 en función de una línea base de acción media, visualizamos las acciones previstas y las que se basan en la verdad básica y guardamos el punto de control de la política completo para su uso posterior

.
: sys, os, json, math, time, warnings, random, tempfile
warnings.filterwarnings («ignorar»)
subprocess.run ([sys.executable, «-m», «pip», «install», «-q»,
 «huggingface_hub>=0.34.0", «pyarrow>=15,0", «av>=12.0",
 «pandas», «matplotlib», «tqdm"], check=false)
importe numpy como np, pandas como pd, pyarrow como pa, pyarrow.parquet como pq
importar matplotlib.pyplot como plt
desde huggingface_hub importe HFAPI, HFFileSystem, hf_hub_download, hf_hub_url
importar torch, torch.nn como nn, torch.nn.functional como F
desde torch.utils.data, importe el conjunto de datos, DataLoader
REPO_ID = «NVIDIA/COSMOS3-DROID»
ROOT = «éxito»
VIDEO_KEY = «observation.image.wrist_image_left»
FPS = 15
N EPISODIOS = 48
HORIZONTE = 8
OBS_HISTORY = 2
USE_VISION = Verdadero
N_VIS_EPS = 6
VIS_SIZE = 96
ÉPOCAS = 12
LOTE = 256
SEMILLA = 0
random.seed (SEMILLA); np.random.seed (SEMILLA); torch.manual_seed (SEMILLA)
DEV = «cuda» si torch.cuda.is_available () sino «cpu»
print (f) "[env] torch= {antorcha. __versión__} dispositivo= {DEV}»)
si os.environ.get («HF_TOKEN»):
 desde huggingface_hub importa el inicio de sesión; inicia sesión (os.environ ["HF_TOKEN"])
api = hfaPi ()
fs = hfSistema de archivos ()
HFS = relé lambda: f"datasets/ {REPO_ID}/{rel}»
URL = lambda rel: hf_hub_url (REPO_ID, rel, repo_type="dataset»)
print (»\n"+ «="*78 +"\n1. INTROSPECCIÓN DE REPOSITORIOS (\n"+ «="*78)
all_files = api.list_repo_files (REPO_ID, repo_type="dataset»)
print (f"número total de archivos en el repositorio: {len (all_files):,}»)
para el prefijo en («success/data», «success/videos», «success/meta»,
 «fallo/datos», «fallo/vídeos», «fallo/meta»):
 <18} {sum (f.startswith (prefix) for f in all_files) :>print (f» {prefijo: 6,} archivos»)
data_shards = sorted (f para f en all_files si f.startswith (f "{ROOT} /data/») y f.endwith («.parquet»))
vid_shards = ordenado (f para f en all_files si f.startswith (f "{ROOT} /videos/ {VIDEO_KEY}/»))
meta_files = ordenado (f para f en all_files si f.startswith (f "{ROOT} /meta/»))
print (f»\n[{ROOT}] fragmentos de datos= {len (data_shards)} fragmentos de vídeo ({VIDEO_KEY}) = {len (vid_shards)}»)
print («primer fragmento de datos:», data_shards [0])
print («primer fragmento de vídeo:», vid_shards [0])
imprimir (»\n"+ «="*78 +"\n2. METADATOS\n"+ «="*78)
info = json.load (open (hf_hub_download (REPO_ID, f "{ROOT} /meta/info.json», repo_type="dataset»)))
print (f"episodes= {info.get ('total_episodes'):,} frames= {info.get ('total_frames'):,}»
 f"tasks= {info.get ('total_tasks'):,} fps= {info.get ('fps')}»)
print («plantilla de data_path:», info.get («data_path»))
print («plantilla video_path:», info.get («video_path»))
CARACTERÍSTICAS = info ["características"]
state_keys = clasificado (k para k en FEATURES si k.startswith («observation.state»))
action_keys = clasificado (k para k en FEATURES si k.startswith («action.»))
video_keys = ordenado (k para k en FEATURES si FEATURES [k] ["dtype"] == «video»)
print (»\nstate:», [f "{k.split ('.') [-1]} {tuple (FEATURES [k] ['shape'])}» para k en state_keys])
print («action:», [f "{k.split ('.') [-1]} {tuple (FEATURES [k] ['shape'])}» para k en action_keys])
print («vídeo:», video_keys)
tdf = pd.read_parquet (hf_hub_download (REPO_ID, f "{ROOT} /meta/tasks.parquet», repo_type="dataset»))
tdf = tdf.reset_index ()
tcol = «tarea» si «tarea» está en tdf.columns o tdf.columns [0]
TAREAS = dict (zip (tdf ["task_index"] .astype (int), tdf [tcol] .astype (str))) si «task_index» está en tdf\
 else {i: str (v) para i, v en enumerate (tdf [tcol])}
print (f»\n{len (TASKS):,} cadenas de tareas. Muestra aleatoria:»)
para t en random.sample (list (tasks.values ()), min (8, len (TASKS))): print (» ·», t [:90])
ep_files = [f para f en meta_files si «/episodes/» está en f y f.endwith («.parquet»)]
eps = pd.concat ([pd.read_parquet (hf_hub_download (REPO_ID, f, repo_type="dataset»))
 para f en ep_files [:4]], ignore_index=true)
print (f»\ntabla de episodios: {len (eps):,} filas»)
print («columns:», [c para c en eps.columns si no c. startswith («stats»)] [:14], «...»)
print (eps [[c para c in («episode_index», «length», «data/chunk_index», «data/file_index»)
 si c está en eps.columns]]
.head ())

Inicializamos el entorno de Colab, instalamos las bibliotecas necesarias y configuramos el conjunto de datos, el episodio, el vídeo y los parámetros de entrenamiento de COSMOS3-Droid. Inspeccionamos la estructura del repositorio e identificamos los fragmentos de datos, vídeos y metadatos disponibles sin descargar el conjunto de datos completo. A continuación, cargamos los metadatos principales y las descripciones de las tareas para comprender el esquema del conjunto de datos, las funciones de estado y acción disponibles y la organización de los episodios

.
print (»\n"+ «="*78 +"\n3. LECTOR DE PARQUET BYTE-RANGE\n"+ «="*78)
def open_pf (rel_path):
 devuelve pq.parquetFile (fs.open (HFS (rel_path), «rb»))
defina rowgroup_span (pdf):
 md, comienza, c = pf.metadata, [], 0
 para i en el rango (md.num_row_groups):
 starts.append (c); c += md.row_group (i) .num_rows
 devuelve np.array (comienza), c
def read_rows (pf, lo, hola, columnas):
 comienza, total = rowgroup_span (pf)
 termina = np.append (comienza [1:], total)
 < hi and ends [i] >rgs = [i para i in range (len (starts)) si comienza [i] lo]
 tbl = pf.read_row_groups (rgs, columns=columnas)
 return tbl.slice (lo - comienza [rgs [0]], hola - lo)
def col2np (tbl, nombre):
 ca = tbl.column (nombre) .combine_chunks ()
 si pa.types.is_list (ca.type) o pa.types.is_large_list (ca.type) o pa.types.is_fixed_size_list (ca.type):
 flat = np.asarray (ca.flatten () .to_numpy (ZERO_COPY_ONLY=FALSE))
 devuelve flat.reshape (len (ca), -1) .astype (np.float32)
 devuelve np.asarray (ca.to_numpy (ZERO_COPY_ONLY=false)) .reshape (-1, 1) .astype (np.float32)
FRAGMENTO = fragmentos de datos [0]
pf = open_pf (FRAGMENTO)
md = pf.metadata
imprimir («f"shard: {SHARD}»)
print (f"rows: {md.num_rows:,} row_groups: {md.num_row_groups}»
 f"comprimido: {md.serialized_size/1e6: .1f} Pie de página de MB»)
print (f"columns: {len (pf.schema_arrow.names)}»)
t0 = time.time ()
ep_idx_all = pf.read (columns= ["episode_index"]) .column («episode_index») .to_numpy ()
print (f"columna episode_index extraída ({len (ep_idx_all):,} filas) en {time.time () -t0: .1f} s»)
uniq, first_pos = np.unique (ep_idx_all, return_index=true)
orden = np.argsort (first_pos)
uniq = uniq [pedido]; first_pos = first_pos [pedido]
last_pos = np.append (first_pos [1:], len (ep_idx_all))
EP_BOUNDS = {int (e): (int (a), int (b)) para e, a, b en zip (uniq, first_pos, last_pos)}
Los episodios de print (f) "{len (EP_BOUNDS)} viven en este fragmento»
 f "(ids {uniq.min ()}.. {uniq.max ()}, mean len {np.mean (last_pos-first_pos) :.0f} frames)»)
STATE_USE = ["observation.state.joint_positions», «observation.state.gripper_position»,
 «observation.state.cartesian_position"]
ACTION_USE = ["action.joint_velocity», «action.gripper_position"]
READ_COLS = STATE_USE + ACTION_USE + ["timestamp», «frame_index», «task_index», «episode_index"]
def load_episode (ep):
 lo, hola = EP_BOUNDS [ep]
 tbl = read_rows (pf, lo, hola, READ_COLS)
 out = {k: col2np (tbl, k) para k en STATE_USE + ACTION_USE}
 out ["timestamp"] = col2np (tbl, «timestamp») .ravel ()
 out ["task_index"] = int (col2np (tbl, «task_index») .ravel () [0])
 out ["task"] = tasks.get (out ["task_index"], "«)
 out ["state"] = np.concatenate ([out [k] para k en STATE_USE], axis=1)
 out ["action"] = np.concatenate ([out [k] para k en ACTION_USE], axis=1)
 devolver
EP0 = int (uniq [0]); traj = load_episode (EP0)
print (f»\nepisodio {EP0}: T= {len (traj ['state'])}

                        

¿Tiene un proyecto de software o plataforma SaaS en mente?

Hable directamente con nuestros arquitectos de software en SoftAndino. Le brindamos asesoría técnica y cotización inmediata sin compromiso.