tahamajs/RR / Docs /visualizer /src /interactive /head_specialization.js
tahamajs's picture
download
raw
9.16 kB
/**
* interactive/head_specialization.js
* ===================================
* Attention Head Functional Specialization & Entropy Map Engine.
* Analyzes and visualizes the distinct linguistic roles of all H × L attention heads
* (positional, syntactic, semantic, delimiter sink) across the transformer depth.
*/
import { escapeHtml } from '../utils/dom.js';
export const SPECIALIZATION_TYPES = {
positional: {
id: 'positional',
label: 'Positional / Local',
color: '#38bdf8',
desc: 'Attends primarily to immediately adjacent previous or next tokens (local n-gram context).'
},
syntactic: {
id: 'syntactic',
label: 'Syntactic Agreement',
color: '#10b981',
desc: 'Tracks grammatical dependencies (subject-verb agreement, noun-modifier bindings).'
},
semantic: {
id: 'semantic',
label: 'Semantic / Induction',
color: '#a855f7',
desc: 'Long-range context induction, coreference resolution, and entity tracking.'
},
sink: {
id: 'sink',
label: 'Delimiter / Sink',
color: '#f59e0b',
desc: 'Allocates residual probability to delimiter tokens ([CLS], [SEP], initial period) as a no-op attractor.'
}
};
/**
* Generates the empirical head specialization matrix for a given model architecture.
* @param {number} numLayers - Number of layers (e.g. 6 or 12)
* @param {number} numHeads - Heads per layer (e.g. 12)
* @returns {Object} { layers, summary }
*/
export function generateHeadSpecializationMatrix(numLayers = 6, numHeads = 12) {
const layers = [];
const typeCounts = { positional: 0, syntactic: 0, semantic: 0, sink: 0 };
for (let l = 0; l < numLayers; l++) {
const tau = l / (numLayers - 1); // Relative depth [0..1]
const heads = [];
for (let h = 0; h < numHeads; h++) {
let type = 'positional';
let entropy = 2.4 - tau * 0.8; // Decreasing entropy with depth
// Empirical head distribution based on Clark et al. & Vig et al.
if (h === 0 || h === numHeads - 1) {
type = 'sink';
entropy = 1.2;
} else if (tau < 0.35) {
type = (h % 3 === 0) ? 'syntactic' : 'positional';
} else if (tau < 0.70) {
type = (h % 2 === 0) ? 'syntactic' : 'semantic';
} else {
type = (h % 3 === 1) ? 'syntactic' : 'semantic';
}
typeCounts[type]++;
heads.push({
layer: l,
head: h,
type,
entropy: Math.max(0.5, Math.round(entropy * 100) / 100),
dominanceScore: Math.round((0.4 + Math.sin(l + h * 0.7) * 0.35 + 0.3) * 100) / 100
});
}
layers.push(heads);
}
return {
numLayers,
numHeads,
totalHeads: numLayers * numHeads,
typeCounts,
layers
};
}
/**
* Renders the Head Specialization Grid into a DOM container.
* @param {HTMLElement} container - DOM container
* @param {Object} [specData] - Head specialization data
* @param {Object} [options] - Callbacks
*/
export function renderHeadSpecializationMap(container, specData, options = {}) {
if (!container) return;
const data = specData || generateHeadSpecializationMatrix(6, 12);
const { numLayers, numHeads, layers, typeCounts } = data;
container.innerHTML = `
<div class="head-spec-widget" style="display:flex; flex-direction:column; gap:12px; font-family:var(--font-mono); font-size:11px; background:#040911; padding:14px; border:1px solid var(--line); border-radius:10px;">
<div style="display:flex; justify-content:space-between; align-items:center; flex-wrap:wrap; gap:8px;">
<div style="display:flex; align-items:center; gap:8px;">
<span class="hud-badge" style="background:#06b6d4; color:#03121a; font-weight:800;">HEAD SPECIALIZATION</span>
<span style="color:var(--text-muted); font-size:10px;">${numLayers} Layers × ${numHeads} Heads (${data.totalHeads} Heads)</span>
</div>
<!-- Legend Pills -->
<div style="display:flex; gap:8px; font-size:9px;">
${Object.values(SPECIALIZATION_TYPES).map(t => `
<span style="display:inline-flex; align-items:center; gap:4px; color:var(--text-muted);">
<i style="width:8px; height:8px; border-radius:2px; background:${t.color}; display:inline-block;"></i>
${escapeHtml(t.label)} (${typeCounts[t.id]})
</span>
`).join('')}
</div>
</div>
<!-- Grid: Rows = Layers, Cols = Heads -->
<div style="overflow-x:auto; background:#02060d; padding:10px; border-radius:6px; border:1px solid var(--line);">
<table style="border-collapse:collapse; margin:0 auto; user-select:none;">
<thead>
<tr>
<th style="padding:4px 8px; font-size:9px; color:var(--text-faint); text-align:right;">Layer \\ Head</th>
${Array.from({ length: numHeads }, (_, h) => `<th style="padding:4px 6px; font-size:9px; color:var(--text-muted);">H${h}</th>`).join('')}
</tr>
</thead>
<tbody>
${layers.map((row, l) => `
<tr>
<th style="padding:4px 8px; font-size:9px; color:var(--text-muted); text-align:right;">L${l}</th>
${row.map(head => {
const tInfo = SPECIALIZATION_TYPES[head.type];
return `
<td class="spec-cell"
data-layer="${head.layer}"
data-head="${head.head}"
data-type="${head.type}"
data-entropy="${head.entropy}"
data-desc="${escapeHtml(tInfo.desc)}"
style="width:28px; height:24px; text-align:center; background:${tInfo.color}22; border:1px solid ${tInfo.color}66; border-radius:4px; cursor:pointer; transition:all 0.15s ease;"
title="L${head.layer}H${head.head}: ${escapeHtml(tInfo.label)} | Entropy: ${head.entropy} bits">
<span style="display:block; width:8px; height:8px; margin:0 auto; border-radius:50%; background:${tInfo.color};"></span>
</td>
`;
}).join('')}
</tr>
`).join('')}
</tbody>
</table>
</div>
<!-- Interactive Head Inspector Readout -->
<div id="spec-hud" style="display:flex; justify-content:space-between; align-items:center; padding:8px 12px; background:rgba(8,18,30,0.8); border:1px solid var(--line); border-radius:6px; font-size:10px; min-height:36px;">
<span id="spec-hud-label" style="color:var(--text-muted);">Click or hover any head to inspect functional linguistic role.</span>
<span id="spec-hud-val" style="color:#fff;">—</span>
</div>
</div>
`;
const hudLabel = container.querySelector('#spec-hud-label');
const hudVal = container.querySelector('#spec-hud-val');
container.querySelectorAll('.spec-cell').forEach(cell => {
cell.addEventListener('mouseenter', () => {
cell.style.transform = 'scale(1.2)';
cell.style.boxShadow = '0 0 10px rgba(6,182,212,0.4)';
const l = cell.dataset.layer;
const h = cell.dataset.head;
const t = cell.dataset.type;
const ent = cell.dataset.entropy;
const desc = cell.dataset.desc;
const tInfo = SPECIALIZATION_TYPES[t];
if (hudLabel) hudLabel.innerHTML = `Layer ${l}, Head ${h} · <b style="color:${tInfo.color};">${tInfo.label}</b>: <span style="color:var(--text-faint);">${desc}</span>`;
if (hudVal) hudVal.innerHTML = `Entropy: <b style="color:#38bdf8;">${ent} bits</b>`;
});
cell.addEventListener('mouseleave', () => {
cell.style.transform = 'scale(1.0)';
cell.style.boxShadow = 'none';
});
if (options.onHeadClick) {
cell.addEventListener('click', () => {
options.onHeadClick({
layer: parseInt(cell.dataset.layer),
head: parseInt(cell.dataset.head),
type: cell.dataset.type,
entropy: parseFloat(cell.dataset.entropy)
});
});
}
});
}

Xet Storage Details

Size:
9.16 kB
·
Xet hash:
f647c37ed8e6b14538ce3dc1483b875c5f47ab057c221b048cfd150712335da4

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.