Add interactive HTML pages for planning explainer and spectral explainer
Sync to site1 / sync (push) Has been cancelled
Sync to site1 / sync (push) Has been cancelled
- Created planning_explainer.html to demonstrate orthogonal invariance and optimal planning with interactive controls and visualizations. - Created spectral_explainer.html to illustrate spectral decomposition and linear identifiability, featuring adjustable spectral weights and real-time correlation calculations.
This commit is contained in:
@@ -0,0 +1,193 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>OU 过程与 Mehler 公式 — 交互式探索</title>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link href="https://fonts.googleapis.com/css2?family=Spectral:ital,wght@0,400;0,600;1,400&family=Sora:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;700&display=swap" rel="stylesheet" />
|
||||
<style>
|
||||
:root{
|
||||
--bg:#0e1116; --panel:#161b22; --panel-2:#1b222c; --line:#232b36;
|
||||
--txt:#e6edf3; --txt-2:#8b949e; --txt-3:#5c6672;
|
||||
--linear:#4cc9f0; --linear-soft:rgba(76,201,240,.16);
|
||||
--nl:#f4a261; --nl-soft:rgba(244,162,97,.16); --r:14px;
|
||||
}
|
||||
*{box-sizing:border-box;}
|
||||
html,body{margin:0;height:100%;}
|
||||
body{background:radial-gradient(1200px 700px at 78% -8%, rgba(76,201,240,.06), transparent 60%),var(--bg);color:var(--txt);font-family:'Sora',system-ui,sans-serif;-webkit-font-smoothing:antialiased;overflow:hidden;}
|
||||
.app{height:100vh;display:grid;grid-template-columns:300px 1fr 320px;grid-template-rows:auto 1fr;grid-template-areas:"head head head" "ctrl stage read";gap:18px;padding:22px 26px;}
|
||||
header{grid-area:head;display:flex;align-items:baseline;gap:18px;flex-wrap:wrap;}
|
||||
header .kicker{font:500 12px/1 'JetBrains Mono',monospace;letter-spacing:.32em;color:var(--linear);text-transform:uppercase;}
|
||||
header h1{margin:0;font-family:'Spectral',serif;font-weight:600;font-size:30px;}
|
||||
header h1 em{color:var(--txt-2);font-style:italic;font-weight:400;}
|
||||
header .sub{font-size:13px;color:var(--txt-2);max-width:560px;line-height:1.5;}
|
||||
.card{background:var(--panel);border:1px solid var(--line);border-radius:var(--r);}
|
||||
.controls{grid-area:ctrl;padding:20px;display:flex;flex-direction:column;gap:22px;overflow-y:auto;}
|
||||
.block .label{font:600 11px/1 'JetBrains Mono',monospace;letter-spacing:.18em;color:var(--txt-3);text-transform:uppercase;margin-bottom:12px;}
|
||||
.rho-val{font:700 40px/1 'JetBrains Mono',monospace;color:var(--linear);}
|
||||
.rho-val small{font-size:14px;color:var(--txt-2);font-weight:400;}
|
||||
input[type=range]{-webkit-appearance:none;width:100%;height:4px;border-radius:4px;background:linear-gradient(90deg,var(--linear) 0%,var(--linear) var(--fill,70%),#2a323d var(--fill,70%));margin-top:14px;cursor:pointer;}
|
||||
input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;width:18px;height:18px;border-radius:50%;background:#eaf6fb;border:3px solid var(--linear);box-shadow:0 0 0 4px var(--linear-soft);}
|
||||
input[type=range]::-moz-range-thumb{width:18px;height:18px;border-radius:50%;background:#eaf6fb;border:3px solid var(--linear);}
|
||||
.hint{font-size:12px;color:var(--txt-3);line-height:1.55;margin-top:10px;}
|
||||
.play{margin-top:4px;display:flex;gap:8px;}
|
||||
.play button{flex:1;padding:10px;border-radius:10px;border:1px solid var(--line);background:var(--panel-2);color:var(--txt);font:500 13px 'Sora';cursor:pointer;transition:.16s;}
|
||||
.play button:hover{border-color:var(--linear);color:var(--linear);}
|
||||
.play button.live{background:var(--linear-soft);border-color:var(--linear);color:var(--linear);}
|
||||
.stat{display:flex;justify-content:space-between;align-items:baseline;padding:8px 0;border-bottom:1px solid var(--line);font:400 13px 'JetBrains Mono',monospace;}
|
||||
.stat b{color:var(--linear);font-weight:700;}
|
||||
.stage{grid-area:stage;padding:18px 20px 16px;display:flex;flex-direction:column;gap:14px;min-height:0;}
|
||||
.stage .ttl{display:flex;align-items:baseline;justify-content:space-between;}
|
||||
.stage .ttl h2{margin:0;font-family:'Spectral',serif;font-weight:600;font-size:18px;}
|
||||
.stage .ttl span{font:400 12px 'JetBrains Mono',monospace;color:var(--txt-3);}
|
||||
.canvas-wrap{position:relative;flex:1;min-height:0;border-radius:10px;overflow:hidden;background:#0b0e13;border:1px solid var(--line);}
|
||||
canvas{display:block;width:100%;height:100%;}
|
||||
.corr-wrap{height:150px;flex:none;border-radius:10px;overflow:hidden;background:#0b0e13;border:1px solid var(--line);position:relative;}
|
||||
.corr-cap{position:absolute;top:10px;left:14px;font:400 12px 'JetBrains Mono',monospace;color:var(--txt-3);}
|
||||
.reading{grid-area:read;padding:22px;display:flex;flex-direction:column;gap:18px;overflow-y:auto;}
|
||||
.reading h3{margin:0;font-family:'Spectral',serif;font-weight:600;font-size:17px;}
|
||||
.takeaway{background:var(--panel-2);border:1px solid var(--line);border-radius:10px;padding:16px;font-size:13.5px;line-height:1.62;}
|
||||
.takeaway .big{font-family:'JetBrains Mono',monospace;color:var(--linear);font-weight:700;}
|
||||
.formula{font:500 14px 'JetBrains Mono',monospace;color:var(--txt);background:#0b0e13;border:1px solid var(--line);border-radius:8px;padding:14px 16px;line-height:1.7;}
|
||||
.formula .hi{color:var(--linear);}.formula .hl{color:var(--nl);}
|
||||
.verdict{margin-top:auto;padding:16px;border-radius:10px;background:linear-gradient(135deg,var(--linear-soft),transparent 70%);border:1px solid color-mix(in oklch,var(--linear) 40%,var(--line));font-family:'Spectral',serif;font-size:14px;line-height:1.6;}
|
||||
.verdict b{color:var(--linear);}
|
||||
.src{font:400 11px 'JetBrains Mono',monospace;color:var(--txt-3);}
|
||||
.navbar{position:fixed;bottom:14px;left:50%;transform:translateX(-50%);display:flex;gap:6px;background:rgba(22,27,34,.9);border:1px solid var(--line);border-radius:30px;padding:6px 10px;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);z-index:20;}
|
||||
.navbar a{font:500 12px 'JetBrains Mono',monospace;color:var(--txt-2);text-decoration:none;padding:5px 11px;border-radius:20px;}
|
||||
.navbar a:hover{color:var(--linear);}
|
||||
.navbar a.on{background:var(--linear-soft);color:var(--linear);}
|
||||
::-webkit-scrollbar{width:8px;height:8px;}::-webkit-scrollbar-thumb{background:#2a323d;border-radius:8px;}
|
||||
@media (max-width:1080px){.app{grid-template-columns:1fr;grid-template-rows:auto auto auto auto;grid-template-areas:"head" "ctrl" "stage" "read";overflow:auto;height:auto;}body{overflow:auto;}.canvas-wrap{height:340px;flex:none;}}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="app">
|
||||
<header>
|
||||
<div style="display:flex;flex-direction:column;gap:6px;">
|
||||
<span class="kicker">LeJEPA · Topic 2</span>
|
||||
<h1>OU 过程 <em>与 Mehler 公式</em></h1>
|
||||
</div>
|
||||
<p class="sub">正样本对 <b style="color:var(--linear)">(z, z′)</b> 由 OU 过程 <b>z′ = ρz + √(1−ρ²)·η</b> 生成。拖动 ρ 观察散点相关性与 ρᵈ 衰减——这正是「高阶成分被更强惩罚」的来源。</p>
|
||||
</header>
|
||||
|
||||
<section class="card controls">
|
||||
<div class="block">
|
||||
<div class="label">相关性 ρ</div>
|
||||
<div class="rho-val"><span id="rhoTxt">0.90</span><small> ∈ (0,1)</small></div>
|
||||
<input id="rho" type="range" min="0.05" max="0.97" step="0.01" value="0.90" aria-label="相关性 ρ" title="相关性 ρ" />
|
||||
<div class="hint">物理图像:弹簧拴住的粒子(均值回归 ρz)+ 随机扰动(√(1−ρ²)η)。ρ→1 视图几乎相同,ρ→0 趋于独立。</div>
|
||||
</div>
|
||||
<div class="block">
|
||||
<div class="label">平稳性 & 相关性(实时统计)</div>
|
||||
<div class="stat"><span>样本数 N</span><b id="sN">1500</b></div>
|
||||
<div class="stat"><span>Var(z)</span><b id="sVz">1.00</b></div>
|
||||
<div class="stat"><span>Var(z′)</span><b id="sVzp">1.00</b></div>
|
||||
<div class="stat"><span>Cov(z,z′)</span><b id="sCov">0.90</b></div>
|
||||
<div class="hint">无论 ρ 多少,z 与 z′ 都保持单位方差(平稳性);协方差 ≈ ρ。</div>
|
||||
</div>
|
||||
<div class="block">
|
||||
<div class="label">演示</div>
|
||||
<div class="play">
|
||||
<button id="autoBtn" class="live">⏸ 自动扫描 ρ</button>
|
||||
<button id="reseedBtn">⟲ 重采样</button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="card stage">
|
||||
<div class="ttl"><h2>正样本对联合散点 (z, z′)</h2><span>每点一个样本;越靠对角线 = 越相关</span></div>
|
||||
<div class="canvas-wrap"><canvas id="scatter"></canvas></div>
|
||||
<div class="corr-wrap">
|
||||
<div class="corr-cap">第 d 阶 Hermite 成分的相关性 = ρᵈ(线性 d=1 最大)</div>
|
||||
<canvas id="bars"></canvas>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="card reading">
|
||||
<h3>Mehler 公式</h3>
|
||||
<div class="formula">E[h(z′)·h(z)]<br> = Σ<sub>d≥1</sub> w<sub>d</sub>·<span class="hi">ρ</span><sup>d</sup> ≤ <span class="hi">ρ</span></div>
|
||||
<div class="takeaway" id="takeaway"></div>
|
||||
<h3 style="margin-top:4px;">对齐损失下界</h3>
|
||||
<div class="formula">L<sub>align</sub> = 2n − 2Σ corr<sub>i</sub><br> ≥ <span class="hi">2(1−ρ)n</span></div>
|
||||
<div class="verdict" id="verdict"></div>
|
||||
<div class="src">来源:JEPA/math/02_ou_process_mehler.md</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<nav class="navbar" id="nav"></nav>
|
||||
|
||||
<script>
|
||||
const NAV=[["01","Hermite","hermite_explainer.html"],["02","OU·Mehler","ou_mehler_explainer.html"],["03","谱分解","spectral_explainer.html"],["04","高斯唯一","gaussian_uniqueness_explainer.html"],["05","近似界","approx_bound_explainer.html"],["06","规划等价","planning_explainer.html"]];
|
||||
const nav=document.getElementById('nav');
|
||||
NAV.forEach(([n,t,f])=>{const a=document.createElement('a');a.href=f;a.textContent=n+' '+t;if(f==='ou_mehler_explainer.html')a.className='on';nav.appendChild(a);});
|
||||
|
||||
let rho=0.90, auto=true, autoDir=-1, lastTick=performance.now();
|
||||
const N=1500;
|
||||
let zSamples=null, etaSamples=null;
|
||||
function randn(){let u=0,v=0;while(!u)u=Math.random();while(!v)v=Math.random();return Math.sqrt(-2*Math.log(u))*Math.cos(2*Math.PI*v);}
|
||||
function reseed(){zSamples=new Float32Array(N);etaSamples=new Float32Array(N);for(let i=0;i<N;i++){zSamples[i]=randn();etaSamples[i]=randn();}}
|
||||
reseed();
|
||||
|
||||
const rhoEl=document.getElementById('rho'),rhoTxt=document.getElementById('rhoTxt');
|
||||
function setRho(v,fromUser){rho=Math.max(0.05,Math.min(0.97,v));rhoEl.value=rho;rhoTxt.textContent=rho.toFixed(2);rhoEl.style.setProperty('--fill',((rho-0.05)/(0.97-0.05)*100).toFixed(1)+'%');if(fromUser){auto=false;const b=document.getElementById('autoBtn');b.classList.remove('live');b.textContent='▶ 自动扫描 ρ';}draw();}
|
||||
rhoEl.addEventListener('input',e=>setRho(+e.target.value,true));
|
||||
document.getElementById('autoBtn').addEventListener('click',e=>{auto=!auto;e.target.classList.toggle('live',auto);e.target.textContent=auto?'⏸ 自动扫描 ρ':'▶ 自动扫描 ρ';lastTick=performance.now();});
|
||||
document.getElementById('reseedBtn').addEventListener('click',()=>{reseed();draw();});
|
||||
|
||||
const scatter=document.getElementById('scatter'),sctx=scatter.getContext('2d');
|
||||
const bars=document.getElementById('bars'),bctx=bars.getContext('2d');
|
||||
function fit(cv){const r=cv.getBoundingClientRect(),dpr=devicePixelRatio||1;cv.width=r.width*dpr;cv.height=r.height*dpr;return{w:r.width,h:r.height,dpr};}
|
||||
|
||||
function drawScatter(){
|
||||
const {w,h,dpr}=fit(scatter);sctx.setTransform(dpr,0,0,dpr,0,0);sctx.clearRect(0,0,w,h);
|
||||
const pad=40,x0=pad,x1=w-pad,y0=pad,y1=h-pad,lim=3.4;
|
||||
const sx=z=>x0+(z+lim)/(2*lim)*(x1-x0), sy=z=>y1-(z+lim)/(2*lim)*(y1-y0);
|
||||
// grid
|
||||
sctx.strokeStyle='#1c2530';sctx.lineWidth=1;sctx.font="11px 'JetBrains Mono',monospace";sctx.fillStyle='#5c6672';
|
||||
for(let g=-3;g<=3;g++){sctx.beginPath();sctx.moveTo(sx(g),y0);sctx.lineTo(sx(g),y1);sctx.stroke();sctx.beginPath();sctx.moveTo(x0,sy(g));sctx.lineTo(x1,sy(g));sctx.stroke();}
|
||||
// 对角线 z'=z
|
||||
sctx.strokeStyle='rgba(76,201,240,.4)';sctx.setLineDash([6,5]);sctx.beginPath();sctx.moveTo(sx(-lim),sy(-lim));sctx.lineTo(sx(lim),sy(lim));sctx.stroke();sctx.setLineDash([]);
|
||||
sctx.fillStyle='#5c6672';sctx.fillText('z',x1-12,sy(0)-6);sctx.fillText("z′",sx(0)+6,y0+14);
|
||||
// 回归线 z'=ρz
|
||||
sctx.strokeStyle='var(--nl)';sctx.strokeStyle='#f4a261';sctx.lineWidth=2;sctx.beginPath();sctx.moveTo(sx(-lim),sy(-rho*lim));sctx.lineTo(sx(lim),sy(rho*lim));sctx.stroke();
|
||||
// points
|
||||
const fac=Math.sqrt(1-rho*rho);
|
||||
let sz=0,szp=0,scov=0;
|
||||
for(let i=0;i<N;i++){const z=zSamples[i],zp=rho*z+fac*etaSamples[i];sz+=z*z;szp+=zp*zp;scov+=z*zp;
|
||||
sctx.fillStyle='rgba(76,201,240,.5)';sctx.beginPath();sctx.arc(sx(z),sy(zp),2,0,7);sctx.fill();}
|
||||
document.getElementById('sVz').textContent=(sz/N).toFixed(2);
|
||||
document.getElementById('sVzp').textContent=(szp/N).toFixed(2);
|
||||
document.getElementById('sCov').textContent=(scov/N).toFixed(2);
|
||||
}
|
||||
|
||||
const DEG=[1,2,3,4,5];
|
||||
function drawBars(){
|
||||
const {w,h,dpr}=fit(bars);bctx.setTransform(dpr,0,0,dpr,0,0);bctx.clearRect(0,0,w,h);
|
||||
const padT=34,padB=24,padL=18,padR=18,y0=padT,y1=h-padB,n=DEG.length;
|
||||
const gap=18,bw=Math.min(72,(w-padL-padR-gap*(n-1))/n),groupW=bw*n+gap*(n-1),startX=(w-groupW)/2;
|
||||
const refY=y1-rho*(y1-y0);
|
||||
bctx.strokeStyle='rgba(76,201,240,.45)';bctx.setLineDash([5,4]);bctx.lineWidth=1.5;bctx.beginPath();bctx.moveTo(padL,refY);bctx.lineTo(w-padR,refY);bctx.stroke();bctx.setLineDash([]);
|
||||
bctx.fillStyle='rgba(76,201,240,.8)';bctx.font="500 11px 'JetBrains Mono',monospace";bctx.fillText('ρ¹='+rho.toFixed(2),w-padR-66,refY-6);
|
||||
DEG.forEach((d,i)=>{const val=Math.pow(rho,d),x=startX+i*(bw+gap),bh=val*(y1-y0),yTop=y1-bh;
|
||||
bctx.fillStyle=d===1?'#4cc9f0':'#f4a261';bctx.globalAlpha=d===1?1:0.82;bctx.fillRect(x,yTop,bw,bh);bctx.globalAlpha=1;
|
||||
bctx.fillStyle=d===1?'#4cc9f0':'#f4a261';bctx.font="700 12px 'JetBrains Mono',monospace";bctx.textAlign='center';bctx.fillText(val.toFixed(3),x+bw/2,yTop-7);
|
||||
bctx.fillStyle='#8b949e';bctx.font="400 11px 'JetBrains Mono',monospace";bctx.fillText('d='+d,x+bw/2,y1+15);bctx.textAlign='left';});
|
||||
}
|
||||
|
||||
function updateText(){
|
||||
const r=rho;
|
||||
document.getElementById('takeaway').innerHTML=`当前 ρ = <span class="big">${r.toFixed(2)}</span>:线性成分 corr = ρ¹ = <b style="color:var(--linear)">${r.toFixed(3)}</b>,二次仅 ρ² = <b style="color:var(--nl)">${(r*r).toFixed(3)}</b>,五次 ρ⁵ = <b style="color:var(--nl)">${Math.pow(r,5).toFixed(3)}</b>。<br><br>任意混合的相关性是 ρᵈ 的<strong>加权平均</strong>,因 ρᵈ≤ρ,总和必 ≤ ρ,等号仅当 <b style="color:var(--linear)">w₁=1(纯线性)</b>。`;
|
||||
document.getElementById('verdict').innerHTML=`最小化 L<sub>align</sub> ⟺ 最大化 Σ corr<sub>i</sub>。下界 <b>2(1−ρ)n</b> 当前 = <b>${(2*(1-r)).toFixed(3)}·n</b>,仅当每个 h<sub>i</sub> 线性时取到。<br>→ <b>最优编码器必须是线性的</b>。`;
|
||||
}
|
||||
|
||||
function draw(){drawScatter();drawBars();updateText();}
|
||||
function loop(now){if(auto){const dt=(now-lastTick)/1000;lastTick=now;let v=rho+autoDir*dt*0.18;if(v<=0.05){v=0.05;autoDir=1;}if(v>=0.97){v=0.97;autoDir=-1;}setRho(v,false);}else lastTick=now;requestAnimationFrame(loop);}
|
||||
document.addEventListener('keydown',e=>{if(e.code==='Space'){e.preventDefault();document.getElementById('autoBtn').click();}else if(e.key==='ArrowLeft')setRho(rho-0.03,true);else if(e.key==='ArrowRight')setRho(rho+0.03,true);});
|
||||
window.addEventListener('resize',draw);
|
||||
setRho(0.90,false);draw();requestAnimationFrame(loop);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user