Manufacturing-MoE / src /robotics_moe.py
rasitcesur's picture
Sync from rasitcesur/Manufacturing-MoE via hub-sync
547ac30 verified
Raw History Blame Contribute Delete
3.83 kB
"""current sign-aware hierarchical gravity expert; learns robot design response.
Only robot expert is changed. Legacy 11 manufacturing operations untouched.
Features: 13 original joint + 10 signed gravity/topology per joint; 18 original
physical aggregate + 8 signed gravity global; 12 history probes.
"""
import numpy as np
import torch
from torch import nn
from robotics_core import Prepared as PreviousPrepared
class Prepared51(PreviousPrepared):
def __init__(self,data,mean=None,std=None):
super().__init__(data,mean,std)
rawj=np.asarray(data['joint_gravity'],np.float32)
rawg=np.asarray(data['global_gravity'],np.float32)
if mean is None:
active=rawj[data['mask']>0]
self.mean['joint_gravity']=active.mean(axis=0)
self.std['joint_gravity']=np.maximum(active.std(axis=0),.03)
self.mean['global_gravity']=rawg.mean(axis=0)
self.std['global_gravity']=np.maximum(rawg.std(axis=0),.03)
nj=np.clip((rawj-self.mean['joint_gravity'])/self.std['joint_gravity'],-8,8)*data['mask'][:,:,None]
ng=np.clip((rawg-self.mean['global_gravity'])/self.std['global_gravity'],-8,8)
self.norm['joint']=np.concatenate([self.norm['joint'],nj],axis=2).astype(np.float32)
self.norm['global_features']=np.concatenate([self.norm['global_features'],ng],axis=1).astype(np.float32)
class RoboticsMoE51(nn.Module):
"""Version-scaled sign-aware hierarchical robot model; 1-15 axes only."""
def __init__(self,joint_dim=23,global_dim=26,history_dim=12,hidden=None):
super().__init__()
from config import choice
hidden=choice(24,48,72) if hidden is None else hidden
mc1,mc2=choice((24,16),(40,28),(64,40))
co1,co2=choice((48,24),(72,40),(96,64))
gr1,gr2=choice((24,16),(40,24),(64,40))
he1,he2=choice((48,24),(96,48),(128,64))
self.joint_expert=nn.Sequential(nn.Linear(joint_dim,hidden),nn.GELU(),nn.Linear(hidden,hidden),nn.GELU())
self.machine_expert=nn.Sequential(nn.Linear(history_dim,mc1),nn.GELU(),nn.Linear(mc1,mc2),nn.Tanh())
self.coupling_expert=nn.Sequential(nn.Linear(hidden*6+global_dim,co1),nn.GELU(),nn.Linear(co1,co2),nn.GELU())
self.gravity_expert=nn.Sequential(nn.Linear(8+mc2,gr1),nn.GELU(),nn.Linear(gr1,gr2),nn.GELU())
self.motion_energy_head=nn.Sequential(nn.Linear(co2+mc2+gr2+global_dim,he1),nn.GELU(),nn.Linear(he1,he2),nn.GELU(),nn.Linear(he2,2))
def forward(self,joint,mask,global_x,history):
x=self.joint_expert(joint)*mask.unsqueeze(-1)
count=mask.sum(dim=1,keepdim=True).clamp(min=1)
pooled=x.sum(dim=1)/count
mx=x.masked_fill(mask.unsqueeze(-1)==0,-1e4).max(dim=1).values
arm1=(joint[:,:,10]>.5).float()*mask
torso=(joint[:,:,11]>.5).float()*mask
arm0=(1.-arm1)*(1.-torso)*mask
def pool(w):return (x*w.unsqueeze(-1)).sum(dim=1)/w.sum(dim=1,keepdim=True).clamp(min=1)
sum_scale=x.sum(dim=1)/count.sqrt()
coupling=self.coupling_expert(torch.cat([pooled,mx,pool(arm0),pool(arm1),pool(torso),sum_scale,global_x],dim=1))
machine=self.machine_expert(history)
gravity=self.gravity_expert(torch.cat([global_x[:,-8:],machine],dim=1))
return self.motion_energy_head(torch.cat([coupling,machine,gravity,global_x],dim=1))
def prediction(model,ds,batch=512,device=None,use_history=True):
model.eval();device=device or next(model.parameters()).device;j,g,h,mask=ds.tensors(device)
if not use_history:h=torch.zeros_like(h)
parts=[]
with torch.no_grad():
for k in range(0,len(ds.y),batch):
parts.append(model(j[k:k+batch],mask[k:k+batch],g[k:k+batch],h[k:k+batch]).cpu().numpy())
ratio=np.exp(np.clip(np.concatenate(parts),-1.5,1.5))
return ratio*ds.prior