You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
defmoduleDLM.Treedo@moduledoc""" Recursively maps a function over nested tuples of tensors. """defmap(tuple,func)whenis_tuple(tuple)dotuple|>Tuple.to_list()|>Enum.map(&map(&1,func))|>List.to_tuple()end# The base case: When it hits a tensor (or a compile-time Expr), apply the functiondefmap(tensor,func)dofunc.(tensor)endend
defmoduleBabyLM.CurriculumStreamerdodefbuild_infinite_stream(directory_path,batch_size)dotarget_shards=Path.wildcard(Path.join(directory_path,"*.bin"))iflength(target_shards)==0doraise"CRITICAL: No .bin shards found in directory: #{directory_path}"endStream.iterate(1,&(&1+1))|>Stream.flat_map(fnepoch->:rand.seed(:exsss,{epoch,epoch,epoch})shuffled_shards=Enum.shuffle(target_shards)IO.puts("\n🔄 Epoch #{epoch} Started | Shuffling #{length(target_shards)} shards...")Stream.flat_map(shuffled_shards,fnpath->tensor=File.read!(path)|>:erlang.binary_to_term()total_seqs=Nx.axis_size(tensor,0)num_batches=div(total_seqs,batch_size)# 1. Generate all the slice indices0..(num_batches-1)# 2. Slice the tensor into actual batch tensors|>Enum.map(fni->Nx.slice_along_axis(tensor,i*batch_size,batch_size,axis: 0)end)# 3. Shuffle the list of batches|>Enum.shuffle()end)#|> Enum.shuffle() # shuffle it all together nowend)endend
defmoduleDLM.StatelessMuondoimportNx.Defndefnnewton_schulz(g)dofrobenius_norm=Nx.LinAlg.norm(g)# defaults to frobenius if type not givenx=g/frobenius_norm{final_x,_}=while{curr_x=x,i=0},Nx.less(i,5)dox_t_x=Nx.dot(Nx.transpose(curr_x),curr_x)next_x=1.5*curr_x-0.5*Nx.dot(curr_x,x_t_x){next_x,i+1}endfinal_xenddefnstep(em,grad,lr)dons_grad=newton_schulz(grad)update=Nx.multiply(lr,ns_grad)Nx.subtract(em,update)enddefnstep_decay(em,grad,lr,wd\\1.0e-4)dons_grad=newton_schulz(grad)update=Nx.multiply(lr,ns_grad)em_decayed=Nx.multiply(em,Nx.subtract(1.0,Nx.multiply(lr,wd)))Nx.subtract(em_decayed,update)endend
defmoduleDLM.SvdSSMdoimportNx.Defndefnrms_norm(x,epsilon\\1.0e-6)dovariance=Nx.mean(Nx.pow(x,2),axes: [-1],keep_axes: true)x*Nx.rsqrt(variance+epsilon)enddefnlayer_norm(x,gamma,beta,epsilon\\1.0e-6)donorm=rms_norm(x,epsilon)scaled=norm*gammascaled+betaenddefngelu(x)docdf=Nx.multiply(0.7978845608,Nx.add(x,Nx.multiply(0.044715,Nx.pow(x,3))))Nx.multiply(Nx.multiply(0.5,x),Nx.add(1.0,Nx.tanh(cdf)))enddefnsoftmax(t)domax_val=Nx.reduce_max(t,axes: [-1],keep_axes: true)safe_t=Nx.subtract(t,max_val)exps=Nx.exp(safe_t)sum_exps=Nx.sum(exps,axes: [-1],keep_axes: true)Nx.divide(exps,Nx.add(sum_exps,1.0e-8))enddefnfeed_forward_layer(x,um,dm,bi,sc,ga,be)doup=Nx.dot(x,um)# up projectionact=gelu(up)# gelu activation, tanh also works similarly wellscaled=Nx.multiply(act,sc)# scale projectionbiased=Nx.add(scaled,bi)# add bias to projectionout=Nx.dot(biased,dm)|>Nx.add(x)# down projectionlayer_norm(out,ga,be)# rms norm with scaler and biasenddefnapply_xsa(x,y)do# exclusive 'space' attentiony_norm_sq=Nx.add(Nx.sum(Nx.pow(y,2),axes: [-1],keep_axes: true),1.0e-6)y_unit=Nx.divide(y,Nx.sqrt(y_norm_sq))y_ov=Nx.sum(Nx.multiply(x,y_unit),axes: [-1],keep_axes: true)Nx.subtract(x,Nx.multiply(y_ov,y_unit))enddefnapply_dot_attention(q,em)dor=Nx.axis_size(em,1)scores=Nx.dot(q,Nx.transpose(em))scaled=Nx.divide(scores,Nx.sqrt(r))weights=softmax(scaled)attended=Nx.dot(weights,em)apply_xsa(attended,q)|>Nx.add(q)enddefnapply_attention(q,v)dok=Nx.transpose(v,axes: [0,2,1])r=Nx.axis_size(v,2)qu=Nx.new_axis(q,1)score=Nx.dot(qu,[2],[0],k,[1],[0])scaled_score=Nx.divide(score,Nx.sqrt(r))soft_score=softmax(scaled_score)at=Nx.dot(soft_score,[2],[0],v,[1],[0])|>Nx.squeeze(axes: [1])apply_xsa(at,q)|>Nx.add(q)enddefnforward_step(x_t,h_prev,p)do{a1,a2,ab,aq,ag,ae,b1,b2,bb,bq,bg,be,c1,c2,cb,cq,cg,ce,d1,d2,db,dq,dg,de,emb,gw}=pbatch_size=Nx.axis_size(x_t,0)em=Nx.take(emb,x_t)# process h_prevhp_at=apply_attention(h_prev,em)h_term=feed_forward_layer(hp_at,a1,a2,ab,aq,ag,ae)# process current character batch_indices=Nx.iota({batch_size})coords=Nx.stack([batch_indices,x_t],axis: -1)u_t=Nx.gather(em,coords)u_at=apply_attention(u_t,em)b_term=feed_forward_layer(u_at,b1,b2,bb,bq,bg,be)# update hidden stateh_new=Nx.add(b_term,h_term)# attend 'pieces' of h_new to vocabb_at=apply_attention(b_term,em)h_at=apply_attention(h_term,em)# predictive ffw layersc_term=feed_forward_layer(h_at,c1,c2,cb,cq,cg,ce)d_term=feed_forward_layer(b_at,d1,d2,db,dq,dg,de)# add results for final logitsctxr=Nx.add(c_term,d_term)# Learn a scalar gate per character dimgate=Nx.sigmoid(Nx.dot(h_new,gw))# gate_w is a 128x128 learned matrixlogits=Nx.add(Nx.multiply(gate,u_t),Nx.multiply(Nx.subtract(1.0,gate),ctxr)){logits,h_new}endend
defmoduleDLM.Phase2_EvaldoimportNx.Defndefnstep_cross_entropy(logits,targets)dovocab_size=Nx.axis_size(logits,-1)one_hot=Nx.equal(Nx.iota({vocab_size}),Nx.new_axis(targets,-1))max_logits=Nx.reduce_max(logits,axes: [-1],keep_axes: true)safe_logits=Nx.subtract(logits,max_logits)log_probs=Nx.subtract(safe_logits,Nx.log(Nx.sum(Nx.exp(safe_logits),axes: [-1],keep_axes: true)))Nx.negate(Nx.sum(Nx.multiply(one_hot,log_probs),axes: [-1]))enddefncompute_sentence_loss(input_tokens,target_tokens,h_init,trainable)doseq_len=Nx.axis_size(input_tokens,1)-1batch_size=Nx.axis_size(input_tokens,0)# Explicitly initialize the batch-sized accumulatorszero_batch=Nx.broadcast(0.0,{batch_size})result=while{i=0,total_loss=zero_batch,valid_tokens=zero_batch,h=h_init,inf=input_tokens,tgf=target_tokens,tr=trainable},Nx.less(i,seq_len)do# 1. Grab the single character context and targetx_t=inf[[..,i]]t_t=tgf[[..,i]]# 2. Forward pass through the reservoir{logits,h_new}=DLM.SvdSSM.forward_step(x_t,h,tr)# 3. Calculate 1-step prediction lossstep_loss=step_cross_entropy(logits,t_t)# 4. MASK: 1.0 if valid text, 0.0 if ASCII 1 (SOH / Padding)mask=Nx.not_equal(t_t,1)|>Nx.as_type(:f32)masked_loss=Nx.multiply(step_loss,mask){i+1,Nx.add(total_loss,masked_loss),Nx.add(valid_tokens,mask),h_new,inf,tgf,tr}end{_,acc_loss,val_tokens,_,_,_,_}=resulttotal_loss=Nx.divide(acc_loss,Nx.add(val_tokens,1.0e-8))total_lossendend
defmoduleDLM.Probedodefrun(params)dogpu=Nx.default_backend()muzzle=DLM.Inference.build_muzzle()|>Nx.backend_copy(gpu)IO.puts("\n"<>String.duplicate("=",60))IO.puts("DLM UNIVERSAL SSM INFERENCE PROBE")IO.puts(String.duplicate("=",60))IO.puts("\n📚 IN-DISTRIBUTION")IO.puts(String.duplicate("-",40))probe(params,"[W]happy [T]adj [D]","Definition of 'happy'",muzzle)probe(params,"[W]water [T]noun [D]","Definition of 'water'",muzzle)probe(params,"[W]run [T]verb [D]","Definition of 'run'",muzzle)IO.puts("\n🔄 REVERSE FORMAT")IO.puts(String.duplicate("-",40))probe(params,"[D]A feeling of great pleasure [W]","Word for pleasure",muzzle)probe(params,"[D]To move swiftly on foot [W]","Word for swift",muzzle)IO.puts("\n🔀 NEAR-DISTRIBUTION")IO.puts(String.duplicate("-",40))probe(params,"The word 'happy' means","Prose definition",muzzle)probe(params,"[W]love [R]Related:","Relational format",muzzle)probe(params,"[W]cold [T]adj [D]The opposite","Partial def",muzzle)IO.puts("\n💬 OUT-OF-DISTRIBUTION")IO.puts(String.duplicate("-",40))probe(params,"What is the meaning of life?","Philosophical",muzzle)probe(params,"Hello, how are you?","Greeting",muzzle)probe(params,"Can you define the word","Conversational",muzzle)probe(params,"Do state space models dream of recursive sheep?","Special",muzzle)IO.puts("\n🔤 MORPHOLOGY")IO.puts(String.duplicate("-",40))probe(params,"[W]Electr","Electr-",muzzle)probe(params,"[W]Mecha","Mecha-",muzzle)probe(params,"[W]Inter","Inter-",muzzle)probe(params,"[W]Ortho","Ortho-",muzzle)probe(params,"[W]Trans","Trans-",muzzle)IO.puts("\n"<>String.duplicate("=",60))enddefpprobe(params,prompt,label,muzzle)doIO.puts("\n▶ #{label}")IO.puts(" Prompt: #{inspect(prompt)}")# Call the V17 Inferencesampled=DLM.Inference.top_k(params,prompt,muzzle)IO.puts(" Top-k: #{inspect(String.slice(sampled,String.length(prompt)..-1//1))}"):erlang.garbage_collect(self())endendIO.puts("✅ DLM.Probe loaded")
✅ DLM.Probe loaded
:ok
# --- Inference Probe ---full_state_path="v7667_DLM_512sq_bgbgem1237gw_checkpoint_step_3400.bin"ifFile.exists?(full_state_path)doIO.puts("💾 Loading latest V18 Checkpoint...")%{trainable: t_p}=File.read!(full_state_path)|>:erlang.binary_to_term()params_gpu=DLM.Tree.map(t_p,&Nx.backend_copy(&1,gpu))IO.puts("✅ Model Loaded")# Fire the battery!DLM.Probe.run(params_gpu)elseIO.puts("❌ No checkpoint found at #{full_state_path}")end
💾 Loading latest V18 Checkpoint...
✅ Model Loaded
============================================================
DLM UNIVERSAL SSM INFERENCE PROBE
============================================================
📚 IN-DISTRIBUTION
----------------------------------------
▶ Definition of 'happy'
Prompt: "[W]happy [T]adj [D]"
Top-k: "e shere what we wh ha s ouly se and the aran wan and ancer thoutour the are to sono had and he ther and the the st the sea der ar an are and aid in he tha ain the se hand an the and to to on t and winge songh se she hand and, wand hear t"
▶ Definition of 'water'
Prompt: "[W]water [T]noun [D]"
Top-k: "ind shead the saringingre anging and he hinghin the anong ane te beathe and whorand ofre so hare was and and the athe toferer and ared and the athe ar the ar and han he and and the to fare the thes ass in she and and whe an tore heallly"
▶ Definition of 'run'
Prompt: "[W]run [T]verb [D]"
Top-k: "er aid thas tha d hin ar on w io and thin t the ain the has ong tin the the the wo he d he sorora fin the hand the ar he atorongere to the she me me se the to and sen se the me se so hast it he the wat and are wher he t the sind the ain t"
🔄 REVERSE FORMAT
----------------------------------------
▶ Word for pleasure
Prompt: "[D]A feeling of great pleasure [W]"
Top-k: "andin andoun t he aro t ther whe he the art ane ta dond and an toun har ou he the hou the sould some tomer hond and and ond hing tout the bo s and that and an the and the har the ther ard the an he he arat ther wing the th"
▶ Word for swift
Prompt: "[D]To move swiftly on foot [W]"
Top-k: "\" the mustingan s t and sher arin in and so the thou ase he the thate an to the and we and and and and and the wonond he sase sathe so an a an thing thin tou the sous at that was the ther arand are hin s hathe hate ar and whe "
🔀 NEAR-DISTRIBUTION
----------------------------------------
▶ Prose definition
Prompt: "The word 'happy' means"
Top-k: "an an st toroury hou and ass and ard ang ton and shee har he whin the soute ooure sono the cheris the and and whe ar t at and and the an a d ar at the hes and hed ofor ang and the hast whe her ast hou her asastere to ould aid and she "
▶ Relational format
Prompt: "[W]love [R]Related:"
Top-k: "and ar artonofone mang tit anet the aill sthe some to oute that wes one sonone mas serer and the tar the sould whis the hile sond the she torer to t he ald sould and or and whe has her tore the thes ongere boust ithe sand thing the aid t"
▶ Partial def
Prompt: "[W]cold [T]adj [D]The opposite"
Top-k: "e boof o te t an toone se ster boor ar and aid and, ald, the are to shat his and hereres ofor s the send and oratonofofofred the sorer soof her hand and shie the but he the torer and and and and he storono t the ally and the t"
💬 OUT-OF-DISTRIBUTION
----------------------------------------
▶ Philosophical
Prompt: "What is the meaning of life?"
Top-k: " he as seandourd and she shering inge to of a d he ave bun the and hine and ofre and his wat the the so the chisted and and se and hed are she hat he and the sous ar he sher hene sher the whe llle werer the an the te mo ar hat h"
▶ Greeting
Prompt: "Hello, how are you?"
Top-k: ", aid an or astorend hering t in thing ther ain wing thonond thee wishe hat to ier her ore the when w he mere sond wat tounthingh his we sate wat the soute of he her the hare the healitoro and the hat and as as, s and she somene the wat "
▶ Conversational
Prompt: "Can you define the word"
Top-k: "ed towing st ain wato ar o he has s ato o o the watl and thee withe sand ofere an t an the woring ther and an the an hore and and hat ar ain a hand ar to the sally and ar the the ange and the ait she hes atinghe has and wat the aid a"
▶ Special
Prompt: "Do state space models dream of recursive sheep?"
Top-k: "edin the se tome monthe wate was shen what the the cean t t our st shen and our and hin the hile and and the the to t ang the that the as soule to the and hed har and hed has s ar ald the hea he t torere as an"
🔤 MORPHOLOGY
----------------------------------------
▶ Electr-
Prompt: "[W]Electr"
Top-k: "is as she here hereate hof at teres as oore harar ang to to an tho ond thed his the ther his ofing the heand, the aid the sus the ashas as and the sais so he ce angh was and shar and the ar at s of as and that hous to oul st as in ther hand her an"
▶ Mecha-
Prompt: "[W]Mecha"
Top-k: "in the saste to and whish at an s aid wa the sherore he mo s and aid and, ald, the are to shat his and hereres ofor s the send and oratonofofofred the sorer soof her hand and shie the but he the torer and and and and he storono t the ally and the t"
▶ Inter-
Prompt: "[W]Inter"
Top-k: "in the the he are tone torongo te tan wa and hat out oust hout he mare te t o the are the chand wh ho he denet and the and as the shithe the the aid the sout to and she and whis, and ar and and wat s the sonore sun the ala ald dowat hen hand wit wh"
▶ Ortho-
Prompt: "[W]Ortho"
Top-k: "oror he she sored towa the shoull tis stofof t wa ther wou d and aid and, ald, whe the to f an t ar and the ave the be and to he so tonge and and she shere hare and wat an the torere to the and ont the the s in st in and wat the hand at orer sere a"
▶ Trans-
Prompt: "[W]Trans"
Top-k: "ind and and an to asst to ongat wit, and wand ther sad as at the sust th hen s the she hissered dowand whit we sout he s ond and theride the the as an her are wer ait lll wand as and as and and shain sas so ad dowat to orango as s ing war and serer"
============================================================
:ok
Train
defmoduleDLM.Phase2TrainerdoimportNx.Defndefnstep_cross_entropy(logits,targets)dovocab_size=Nx.axis_size(logits,-1)one_hot=Nx.equal(Nx.iota({vocab_size}),Nx.new_axis(targets,-1))max_logits=Nx.reduce_max(logits,axes: [-1],keep_axes: true)safe_logits=Nx.subtract(logits,max_logits)log_probs=Nx.subtract(safe_logits,Nx.log(Nx.sum(Nx.exp(safe_logits),axes: [-1],keep_axes: true)))# Returns a {batch_size} 1D tensor of individual sequence lossesNx.negate(Nx.sum(Nx.multiply(one_hot,log_probs),axes: [-1]))enddefncompute_sequence_loss(input_tokens,params)dobatch_size=Nx.axis_size(input_tokens,0)h_start=Nx.broadcast(0.0,{batch_size,128})|>Nx.as_type(:f32)zero_scalar=Nx.tensor(0.0,type: :f32)result=while{i=0,total_loss=zero_scalar,valid_tokens=zero_scalar,h=h_start,inf=input_tokens,tp=params},Nx.less(i,Nx.axis_size(inf,1)-1)dox_t=inf[[..,i]]t_t=inf[[..,i+1]]{logits,h_new}=DLM.SvdSSM.forward_step(x_t,h,tp)step_loss=step_cross_entropy(logits,t_t)mask=Nx.not_equal(t_t,1)|>Nx.as_type(:f32)masked_loss_scalar=Nx.sum(Nx.multiply(step_loss,mask))valid_tokens_scalar=Nx.sum(mask){i+1,Nx.add(total_loss,masked_loss_scalar),Nx.add(valid_tokens,valid_tokens_scalar),h_new,inf,tp}end{_,acc_loss,val_tokens,_,_,_}=result# compress and save final hlong for a long term memory context?total_loss=Nx.divide(acc_loss,Nx.add(val_tokens,1.0e-8))total_lossenddefncompute_grad(params,batch_tokens)doseq_len=Nx.axis_size(batch_tokens,1)-1input_tokens=Nx.slice_along_axis(batch_tokens,0,seq_len,axis: 1){loss,raw_grads}=value_and_grad(params,fnp->compute_sequence_loss(input_tokens,p)end){loss,raw_grads}endend
defmoduleDLM.CheckpointManagerdo@moduledoc""" Scans the directory for the latest checkpoint of a specific run prefix. If no checkpoints exist, it triggers a completely fresh initialization. """defget_resume_state(run_prefix)docheckpoints=Path.wildcard("#{run_prefix}_checkpoint_step_*.bin")ifEnum.empty?(checkpoints)doifFile.exists?("#{run_prefix}_final.bin")doIO.puts("Found completed run: #{run_prefix}_final.bin"){"#{run_prefix}_final.bin",:completed}elseIO.puts("No checkpoints found for '#{run_prefix}'. Starting FRESH from Genesis."){:fresh,0}endelse# Extract step numbers using regex and find the maximumlatest_file=Enum.max_by(checkpoints,fnfile->caseRegex.run(~r/_step_(\d+)\.bin$/,file)do[_,step_str]->String.to_integer(step_str)_->-1endend)[_,step_str]=Regex.run(~r/_step_(\d+)\.bin$/,latest_file)step=String.to_integer(step_str)IO.puts("Auto-Resuming '#{run_prefix}' from Step #{step}..."){latest_file,step}endendend
run_prefix="v7667_DLM_512sq_bgbgem1237gw"# frozen_path = "./data/f_semantic_reservoir_128D.bin"total_steps=7500{load_path,start_step}=DLM.CheckpointManager.get_resume_state(run_prefix)ifstart_step==:completeddoIO.puts("This run has already reached #{total_steps} steps. Exiting.")elsebatch_size=128# ./data/bbylm_512_fullmix (256 too) bbylm_lg_wiki_512 # try data with sq len of just one worddata_dir="./data/bbylm_512_strict"#/babylm_high_sanitize(sq 256), /bbylm_512_strict(sq 512)IO.puts("Initializing Lazy Curriculum Data Stream from [#{data_dir}]...")data_stream=BabyLM.CurriculumStreamer.build_infinite_stream(data_dir,batch_size)|>Stream.drop(start_step){starting_trainable,initial_key}=ifload_path==:freshdoIO.puts("Igniting brand new Trainable weights for #{run_prefix}..."){ip,ik}=DLM.PhysicsGenesis.init(Nx.Random.key(System.system_time()))# %{frozen: {r, _m}} = File.read!(frozen_path) |> :erlang.binary_to_term(){ip,ik}elseIO.puts("Loading Trainable Weights from #{load_path}...")# Checkpoints now only contain %{trainable: ...}%{trainable: t_p}=File.read!(load_path)|>:erlang.binary_to_term()# %{frozen: {r, _m}} = File.read!(frozen_path) |> :erlang.binary_to_term(){t_p,Nx.Random.key(System.system_time())}endtrainable_gpu=DLM.Tree.map(starting_trainable,&Nx.backend_copy(&1,gpu))step_count=Nx.tensor(start_step)|>Nx.backend_copy(gpu)# ZIP FROM THE START_STEP{final_p,_key,_step}=Enum.reduce(Stream.zip(start_step..(total_steps-1),data_stream),{trainable_gpu,initial_key,step_count},fn{step,cpu_batch},{cur_tr,cur_key,c_step}->gpu_batch=Nx.backend_copy(cpu_batch,gpu)base_lr=7.0e-4min_lr=7.0e-5warmup_steps=1600cooldown_start=5600current_lr=ifstep<warmup_stepsdobase_lr*(step/warmup_steps)elseifstep<cooldown_startdobase_lrelseprogress=min(max((step-cooldown_start)/(total_steps-cooldown_start),0.0),1.0)min_lr+0.5*(base_lr-min_lr)*(1.0+:math.cos(:math.pi()*progress))endendlr_tensor=Nx.tensor(current_lr,type: :f32)|>Nx.backend_copy(gpu)split_keys=Nx.Random.split(cur_key)next_key=split_keys[1]{loss_tensor,grads}=DLM.Phase2Trainer.compute_grad(cur_tr,gpu_batch)loss_val=Nx.to_number(loss_tensor){up_tr,up_step}=DLM.SvdOptimizer.update(cur_tr,grads,c_step,lr_tensor)# Telemetryifrem(step,100)==0do{a1,a2,ab,aq,ag,ae,b1,b2,bb,bq,bg,be,c1,c2,cb,cq,cg,ce,d1,d2,db,dq,dg,de,em,gw}=up_tra1_norm=a1|>Nx.pow(2)|>Nx.sum()|>Nx.sqrt()|>Nx.to_number()|>Float.round(4)a2_norm=a2|>Nx.pow(2)|>Nx.sum()|>Nx.sqrt()|>Nx.to_number()|>Float.round(4)ab_norm=ab|>Nx.pow(2)|>Nx.sum()|>Nx.sqrt()|>Nx.to_number()|>Float.round(4)aq_norm=aq|>Nx.pow(2)|>Nx.sum()|>Nx.sqrt()|>Nx.to_number()|>Float.round(4)ag_norm=ag|>Nx.pow(2)|>Nx.sum()|>Nx.sqrt()|>Nx.to_number()|>Float.round(4)ae_norm=ae|>Nx.pow(2)|>Nx.sum()|>Nx.sqrt()|>Nx.to_number()|>Float.round(4)b1_norm=b1|>Nx.pow(2)|>Nx.sum()|>Nx.sqrt()|>Nx.to_number()|>Float.round(4)b2_norm=b2|>Nx.pow(2)|>Nx.sum()|>Nx.sqrt()|>Nx.to_number()|>Float.round(4)bb_norm=bb|>Nx.pow(2)|>Nx.sum()|>Nx.sqrt()|>Nx.to_number()|>Float.round(4)bq_norm=bq|>Nx.pow(2)|>Nx.sum()|>Nx.sqrt()|>Nx.to_number()|>Float.round(4)bg_norm=bg|>Nx.pow(2)|>Nx.sum()|>Nx.sqrt()|>Nx.to_number()|>Float.round(4)be_norm=be|>Nx.pow(2)|>Nx.sum()|>Nx.sqrt()|>Nx.to_number()|>Float.round(4)c1_norm=c1|>Nx.pow(2)|>Nx.sum()|>Nx.sqrt()|>Nx.to_number()|>Float.round(4)c2_norm=c2|>Nx.pow(2)|>Nx.sum()|>Nx.sqrt()|>Nx.to_number()|>Float.round(4)cb_norm=cb|>Nx.pow(2)|>Nx.sum()|>Nx.sqrt()|>Nx.to_number()|>Float.round(4)cq_norm=cq|>Nx.pow(2)|>Nx.sum()|>Nx.sqrt()|>Nx.to_number()|>Float.round(4)cg_norm=cg|>Nx.pow(2)|>Nx.sum()|>Nx.sqrt()|>Nx.to_number()|>Float.round(4)ce_norm=ce|>Nx.pow(2)|>Nx.sum()|>Nx.sqrt()|>Nx.to_number()|>Float.round(4)d1_norm=d1|>Nx.pow(2)|>Nx.sum()|>Nx.sqrt()|>Nx.to_number()|>Float.round(4)d2_norm=d2|>Nx.pow(2)|>Nx.sum()|>Nx.sqrt()|>Nx.to_number()|>Float.round(4)db_norm=db|>Nx.pow(2)|>Nx.sum()|>Nx.sqrt()|>Nx.to_number()|>Float.round(4)dq_norm=dq|>Nx.pow(2)|>Nx.sum()|>Nx.sqrt()|>Nx.to_number()|>Float.round(4)dg_norm=dg|>Nx.pow(2)|>Nx.sum()|>Nx.sqrt()|>Nx.to_number()|>Float.round(4)de_norm=de|>Nx.pow(2)|>Nx.sum()|>Nx.sqrt()|>Nx.to_number()|>Float.round(4)em_norm=em|>Nx.pow(2)|>Nx.sum()|>Nx.sqrt()|>Nx.to_number()|>Float.round(4)gw_norm=gw|>Nx.pow(2)|>Nx.sum()|>Nx.sqrt()|>Nx.to_number()|>Float.round(4)IO.puts("➡️ Step #{step} | LR: #{Float.round(current_lr,6)} | Loss: #{Float.round(loss_val,4)} | em #{em_norm} | gw #{gw_norm}")IO.puts("➡️ PN 1: a1 #{a1_norm} | a2 #{a2_norm} | ab #{ab_norm} | aq #{aq_norm} | ae #{ae_norm} | ag #{ag_norm}")IO.puts("➡️ PN 2: b1 #{b1_norm} | b2 #{b2_norm} | bb #{bb_norm} | bq #{bq_norm} | be #{be_norm} | bg #{bg_norm}")IO.puts("➡️ PN 3: c1 #{c1_norm} | c2 #{c2_norm} | cb #{cb_norm} | cq #{cq_norm} | ce #{ce_norm} | cg #{cg_norm}")IO.puts("➡️ PN 4: d1 #{d1_norm} | d2 #{d2_norm} | db #{db_norm} | dq #{dq_norm} | de #{de_norm} | dg #{dg_norm}"):erlang.garbage_collect()end# Checkpoint Saving (Save both structures!) try every 500 for 64bx512sqlnifrem(step,200)==0andstep>0doIO.puts("Checkpoint reached! Saving Step #{step}...")cpu_tr=DLM.Tree.map(up_tr,&Nx.backend_copy(&1,Nx.BinaryBackend))filename="#{run_prefix}_checkpoint_step_#{step}.bin"File.write!(filename,:erlang.term_to_binary(%{trainable: cpu_tr})):erlang.garbage_collect()end{up_tr,next_key,up_step}end)IO.puts("Saving Final Fourier Reservoir Weights...")fin_t=DLM.Tree.map(final_p,&Nx.backend_copy(&1,Nx.BinaryBackend))# You could save frozen here too if desired, but since they are deterministic it's optional.File.write!("#{run_prefix}_final.bin",:erlang.term_to_binary(%{trainable: fin_t}))IO.puts("Training Complete!")end