easylearning's picture
Add files using upload-large-folder tool
64b9802 verified
Raw History Blame Contribute Delete
4.4 kB
"""Four disjoint beam groups, with unmodified policy scores for the RL surrogate.
Search penalties only affect proposal selection. Deterministic proposals do not
have on-policy sampling probabilities; the beam RL objective remains biased.
"""
import torch
from .memory import make_prefix
@torch.no_grad()
def rollout_group_beam(model, context, anchor, actions, horizon, penalty,
groups=4, beams=2, visual=4375, width=80):
model.eval()
device=context.device; count=groups*beams
history={1:anchor.expand(count,-1)}; frames=[]; traces=[]
scores=torch.full((count,),float('-inf'),device=device,dtype=torch.float64)
scores[::beams]=0
raw=torch.zeros(count,device=device,dtype=torch.float64)
for target in range(2,horizon+2):
original,kept=make_prefix(context.expand(count,-1),history,actions,target)
ancestors=torch.arange(count,device=device)
codes=torch.empty((count,0),device=device,dtype=torch.long)
logs=torch.empty((count,0),device=device)
pending=original; cache=None
for token in range(width):
out=model(input_ids=pending,past_key_values=cache,use_cache=True)
lp=out.logits[:,-1,:visual].float().log_softmax(-1)
parents=[]; choices=[]; next_scores=[]
for g in range(groups):
start=g*beams
if g:
frequency=torch.bincount(torch.cat(choices),minlength=visual).double()/(g*beams)
else:
frequency=torch.zeros(visual,device=device,dtype=torch.float64)
totals=scores[start:start+beams,None]+lp[start:start+beams].double()-penalty*frequency
score,flat=totals.flatten().topk(beams,sorted=True)
parents.append(start+flat//visual);choices.append(flat%visual);next_scores.append(score)
parent=torch.cat(parents);chosen=torch.cat(choices)
assert torch.equal(parent//beams,torch.arange(count,device=device)//beams)
raw=raw[parent]+lp[parent,chosen].double()
scores=torch.cat(next_scores)
codes=torch.cat([codes[parent],chosen[:,None]],1)
logs=torch.cat([logs[parent],lp[parent,chosen,None]],1)
ancestors=ancestors[parent]
cache=out.past_key_values;cache.reorder_cache(parent)
pending=chosen[:,None]
for f in frames:
for key in ['prefix','response','model_logp']:f[key]=f[key][ancestors]
history={t:x[ancestors] for t,x in history.items()}
history[target]=codes
frames.append(dict(target=target,prefix=original[ancestors],response=codes,model_logp=logs))
traces.append(dict(target=target,retained=kept,prefix_length=original.shape[1],
frame_parent_indices=ancestors.tolist(),positions_reset=True,kv_reset=True,
future_observations=False,random_sampling=False))
selected=torch.arange(0,count,beams,device=device)
frames=[{k:(v[selected] if torch.is_tensor(v) else v) for k,v in f.items()} for f in frames]
history={t:x[selected] for t,x in history.items()}
for f in frames:
rebuilt,_=make_prefix(context.expand(groups,-1),history,actions,f['target'])
assert torch.equal(rebuilt,f['prefix'])
rebuilt=sum(f['model_logp'].double().sum(-1) for f in frames)
assert torch.allclose(rebuilt,raw[selected],atol=1e-7,rtol=0)
codes=torch.stack([f['response'] for f in frames],1)
pair=[float((codes[i]!=codes[j]).float().mean()) for i in range(groups) for j in range(i+1,groups)]
perframe=(codes!=codes[:1]).any(0).sum(-1).tolist()
return frames,dict(strategy='grouped_diverse_full_video_beam',groups=groups,beams_per_group=beams,
active_paths=count,returned_trajectories=groups,penalty=penalty,
unique_trajectories=len({tuple(c.flatten().tolist()) for c in codes}),
mean_pairwise_token_difference_fraction=sum(pair)/len(pair),
pairwise_token_difference_fraction=pair,different_token_positions=sum(perframe),
different_positions_per_frame=perframe,model_log_scores=raw[selected].tolist(),
search_scores=scores[selected].tolist(),score_is_behavior_logprob=False,
on_policy_grpo=False,frames=traces)