DebasishDhal99 commited on
Commit
ba618db
·
1 Parent(s): 3a74c51

feat: add formla of Q, K matrix calculation

Browse files
Files changed (2) hide show
  1. app.py +42 -0
  2. src/plots.py +13 -10
app.py CHANGED
@@ -77,6 +77,47 @@ Shaw relative attention (learned bias `b_{m-n}` on scores) is a **different**
77
  mechanism and is not computed here.
78
  """
79
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
80
  PLACEHOLDER = go.Figure().update_layout(
81
  title="Run **Compute** on the Setup tab first",
82
  template="plotly_white",
@@ -381,6 +422,7 @@ with gr.Blocks(title="RoPE Explorer") as demo:
381
  head = gr.Slider(minimum=0, maximum=2, step=1, value=0, label="Head index (real models)")
382
 
383
  with gr.Tab("Bulk changes"):
 
384
  which = gr.Radio(["Q", "K"], value="Q", label="Tensor")
385
  mod_2pi = gr.Checkbox(False, label="θ heatmap: wrap mod 2π")
386
  bulk_main = gr.Plot(label="Before / after / delta")
 
77
  mechanism and is not computed here.
78
  """
79
 
80
+ BULK_FORMULAS_MD = r"""
81
+ ### What each Q/K matrix entry means
82
+
83
+ The selected heatmap entry is `X[h, k, j]`, where `X` is either **Q** or **K**, `h` is
84
+ the attention-head index, `k` is the token position, and `j` is the dimension within
85
+ that head.
86
+
87
+ For a real model, the first-layer projections calculate each entry as:
88
+
89
+ $$
90
+ Q^{before}_{k,h,j} = \left(H_k W_Q + b_Q\right)_{h d + j},\qquad
91
+ K^{before}_{k,h,j} = \left(H_k W_K + b_K\right)_{h d + j}
92
+ $$
93
+
94
+ Here `H_k` is the token's hidden vector, `d` is the dimension per head, and `W_Q`,
95
+ `W_K` are the model's query/key projection weights. In random-matrix mode, the initial
96
+ entries are sampled directly: `Q before ~ N(0, 1)` and `K before ~ N(0, 1)` using
97
+ independent seeds.
98
+
99
+ RoPE then transforms either matrix using
100
+
101
+ $$
102
+ \theta(k,i) = k\,base^{-2i/d}
103
+ $$
104
+
105
+ For the real-model Llama layout, the paired dimensions are `(i, i+d/2)`:
106
+
107
+ $$
108
+ X^{after}_{h,k,i} = X^{before}_{h,k,i}\cos\theta -
109
+ X^{before}_{h,k,i+d/2}\sin\theta
110
+ $$
111
+ $$
112
+ X^{after}_{h,k,i+d/2} = X^{before}_{h,k,i}\sin\theta +
113
+ X^{before}_{h,k,i+d/2}\cos\theta
114
+ $$
115
+
116
+ where `X` means either **Q** or **K**. Random-matrix mode uses adjacent pairs
117
+ `(2i, 2i+1)` instead. Therefore, **Before** contains projected or sampled values,
118
+ **After** contains rotated values, and **Delta = After − Before**.
119
+ """
120
+
121
  PLACEHOLDER = go.Figure().update_layout(
122
  title="Run **Compute** on the Setup tab first",
123
  template="plotly_white",
 
422
  head = gr.Slider(minimum=0, maximum=2, step=1, value=0, label="Head index (real models)")
423
 
424
  with gr.Tab("Bulk changes"):
425
+ gr.Markdown(BULK_FORMULAS_MD)
426
  which = gr.Radio(["Q", "K"], value="Q", label="Tensor")
427
  mod_2pi = gr.Checkbox(False, label="θ heatmap: wrap mod 2π")
428
  bulk_main = gr.Plot(label="Before / after / delta")
src/plots.py CHANGED
@@ -59,13 +59,16 @@ def bulk_before_after_delta(before: np.ndarray, after: np.ndarray, tokens=None)
59
  go.Heatmap(
60
  z=mat,
61
  showscale=(i == 3),
62
- hovertemplate="token=%{y}<br>dim=%{x}<br>z=%{z:.4f}<extra></extra>",
 
63
  ),
64
  row=1,
65
  col=i,
66
  )
 
 
67
  fig.update_yaxes(autorange="reversed", row=1, col=i)
68
- fig.update_layout(template="plotly_white", height=400, margin=dict(t=60))
69
  return fig
70
 
71
 
@@ -78,10 +81,10 @@ def norms_and_cosine(before: np.ndarray, after: np.ndarray, tokens=None) -> go.F
78
  fig.add_trace(go.Scatter(x=xs, y=nb, name="before", mode="lines+markers"), row=1, col=1)
79
  fig.add_trace(go.Scatter(x=xs, y=na, name="after", mode="lines+markers"), row=1, col=1)
80
  fig.add_trace(go.Bar(x=xs, y=cos, name="cosine", showlegend=False), row=1, col=2)
81
- fig.update_xaxes(title_text="token", row=1, col=1)
82
- fig.update_xaxes(title_text="token", row=1, col=2)
83
- fig.update_yaxes(title_text="L2", row=1, col=1)
84
- fig.update_yaxes(title_text="cosine", range=[min(0.0, float(np.min(cos)) - 0.05), 1.02], row=1, col=2)
85
  fig.update_layout(template="plotly_white", height=380, barmode="group")
86
  return fig
87
 
@@ -97,13 +100,13 @@ def theta_heatmap(seq_len: int, dim: int, base: float, mod_2pi: bool = False) ->
97
  fig = go.Figure(
98
  data=go.Heatmap(
99
  z=z,
100
- colorbar=dict(title="radians"),
101
  hovertemplate="token k=%{y}<br>pair i=%{x}<br>θ=%{z:.4f}<extra></extra>",
102
  )
103
  )
104
  fig.update_layout(
105
  title=title,
106
- xaxis_title="pair index i",
107
  yaxis_title="token position k",
108
  yaxis=dict(autorange="reversed"),
109
  template="plotly_white",
@@ -117,8 +120,8 @@ def frequency_strip(dim: int, base: float) -> go.Figure:
117
  fig = go.Figure(data=go.Bar(x=list(range(len(omega))), y=omega, name="ω_i"))
118
  fig.update_layout(
119
  title="Pair frequencies ω_i (pair 0 is fastest)",
120
- xaxis_title="pair index i",
121
- yaxis_title="ω",
122
  yaxis_type="log",
123
  template="plotly_white",
124
  height=280,
 
59
  go.Heatmap(
60
  z=mat,
61
  showscale=(i == 3),
62
+ colorbar=dict(title="matrix value") if i == 3 else None,
63
+ hovertemplate="token position k=%{y}<br>dimension index j=%{x}<br>value=%{z:.4f}<extra></extra>",
64
  ),
65
  row=1,
66
  col=i,
67
  )
68
+ fig.update_xaxes(title_text="dimension index j (within selected head)", row=1, col=i)
69
+ fig.update_yaxes(title_text="token position k", row=1, col=i)
70
  fig.update_yaxes(autorange="reversed", row=1, col=i)
71
+ fig.update_layout(template="plotly_white", height=430, margin=dict(t=60, b=65))
72
  return fig
73
 
74
 
 
81
  fig.add_trace(go.Scatter(x=xs, y=nb, name="before", mode="lines+markers"), row=1, col=1)
82
  fig.add_trace(go.Scatter(x=xs, y=na, name="after", mode="lines+markers"), row=1, col=1)
83
  fig.add_trace(go.Bar(x=xs, y=cos, name="cosine", showlegend=False), row=1, col=2)
84
+ fig.update_xaxes(title_text="token position k", row=1, col=1)
85
+ fig.update_xaxes(title_text="token position k", row=1, col=2)
86
+ fig.update_yaxes(title_text="L2 norm of Q/K vector", row=1, col=1)
87
+ fig.update_yaxes(title_text="cosine similarity (before, after)", range=[min(0.0, float(np.min(cos)) - 0.05), 1.02], row=1, col=2)
88
  fig.update_layout(template="plotly_white", height=380, barmode="group")
89
  return fig
90
 
 
100
  fig = go.Figure(
101
  data=go.Heatmap(
102
  z=z,
103
+ colorbar=dict(title="rotation angle θ (radians)"),
104
  hovertemplate="token k=%{y}<br>pair i=%{x}<br>θ=%{z:.4f}<extra></extra>",
105
  )
106
  )
107
  fig.update_layout(
108
  title=title,
109
+ xaxis_title="pair index i (dimension pair)",
110
  yaxis_title="token position k",
111
  yaxis=dict(autorange="reversed"),
112
  template="plotly_white",
 
120
  fig = go.Figure(data=go.Bar(x=list(range(len(omega))), y=omega, name="ω_i"))
121
  fig.update_layout(
122
  title="Pair frequencies ω_i (pair 0 is fastest)",
123
+ xaxis_title="pair index i (dimension pair)",
124
+ yaxis_title="frequency ω_i (radians per position)",
125
  yaxis_type="log",
126
  template="plotly_white",
127
  height=280,