1use burn::nn::{Linear, LinearConfig};
16use burn::prelude::*;
17
18#[inline]
26pub fn pool_v_to_bd<B: Backend>(x: &Tensor<B, 3>) -> Tensor<B, 2> {
27 let pooled = x.clone().mean_dim(2);
30
31 let pooled: Tensor<B, 2> = pooled.squeeze::<2>(2);
37 pooled
38}
39
40#[inline]
42pub fn pool_d_to_bv<B: Backend>(x: &Tensor<B, 3>) -> Tensor<B, 2> {
43 let pooled = x.clone().mean_dim(1);
44 let pooled: Tensor<B, 2> = pooled.squeeze::<2>(1);
45 pooled
46}
47
48#[inline]
50pub fn l2_normalize_bd<B: Backend>(x: Tensor<B, 2>, eps: f32) -> Tensor<B, 2> {
51 let norm: Tensor<B, 2> = x.clone().powf_scalar(2.0).sum_dim(1).sqrt().add_scalar(eps);
53 let norm: Tensor<B, 2> = norm.unsqueeze::<2>();
55 x.div(norm)
56}
57
58#[derive(Config, Debug)]
63pub struct KBranchConfig {
64 pub d_model: usize,
65 pub d_hidden: usize,
66 #[config(default = "1e-8")]
67 pub eps: f32,
68}
69
70#[derive(Module, Debug)]
74pub struct KBranch<B: Backend> {
75 linear1: Linear<B>,
76 linear2: Linear<B>,
77 eps: f32,
78}
79
80impl KBranchConfig {
81 pub fn init<B: Backend>(&self, device: &B::Device) -> KBranch<B> {
82 KBranch {
83 linear1: LinearConfig::new(self.d_model, self.d_hidden).init(device),
84 linear2: LinearConfig::new(self.d_hidden, self.d_model).init(device),
85 eps: self.eps,
86 }
87 }
88}
89
90impl<B: Backend> KBranch<B> {
91 pub fn forward(&self, x: &Tensor<B, 3>) -> Tensor<B, 2> {
93 let pooled: Tensor<B, 2> = pool_v_to_bd(x); let h: Tensor<B, 2> = self.linear1.forward(pooled);
95 let h: Tensor<B, 2> = burn::tensor::activation::gelu(h);
96 let k: Tensor<B, 2> = self.linear2.forward(h);
97 l2_normalize_bd(k, self.eps)
98 }
99}
100
101#[derive(Config, Debug)]
106pub struct BetaBranchConfig {
107 pub d_model: usize,
108 pub d_hidden: usize,
109}
110
111#[derive(Module, Debug)]
115pub struct BetaBranch<B: Backend> {
116 w_in: Linear<B>,
117 w_out: Linear<B>,
118}
119
120impl BetaBranchConfig {
121 pub fn init<B: Backend>(&self, device: &B::Device) -> BetaBranch<B> {
122 BetaBranch {
123 w_in: LinearConfig::new(self.d_model, self.d_hidden).init(device),
124 w_out: LinearConfig::new(self.d_hidden, 1).init(device),
125 }
126 }
127}
128
129impl<B: Backend> BetaBranch<B> {
130 pub fn forward(&self, x: &Tensor<B, 3>) -> Tensor<B, 2> {
132 use burn::tensor::activation::sigmoid;
133 let pooled: Tensor<B, 2> = pool_v_to_bd(x); let h: Tensor<B, 2> = self.w_in.forward(pooled).tanh();
135 let logit: Tensor<B, 2> = self.w_out.forward(h); sigmoid(logit).mul_scalar(2.0)
137 }
138}
139
140#[derive(Config, Debug)]
145pub struct VBranchConfig {
146 pub d_model: usize,
147 pub dv: usize,
148 pub d_hidden: usize,
149}
150
151#[derive(Module, Debug)]
159pub struct VBranch<B: Backend> {
160 linear1: Linear<B>,
161 linear2: Linear<B>,
162}
163
164impl VBranchConfig {
165 pub fn init<B: Backend>(&self, device: &B::Device) -> VBranch<B> {
166 VBranch {
167 linear1: LinearConfig::new(self.d_model, self.d_hidden).init(device),
168 linear2: LinearConfig::new(self.d_hidden, self.dv).init(device),
169 }
170 }
171}
172
173impl<B: Backend> VBranch<B> {
174 pub fn forward(&self, x: &Tensor<B, 3>) -> Tensor<B, 2> {
176 let pooled: Tensor<B, 2> = pool_v_to_bd(x); let h: Tensor<B, 2> = self.linear1.forward(pooled);
178 let h: Tensor<B, 2> = burn::tensor::activation::gelu(h);
179 let v: Tensor<B, 2> = self.linear2.forward(h);
180 v
181 }
182}
183
184#[derive(Config, Debug)]
189pub struct DeltaBranchesConfig {
190 pub d_model: usize,
191 pub dv: usize,
192 pub d_hidden: usize,
193 #[config(default = "1e-8")]
194 pub eps: f32,
195}
196
197#[derive(Module, Debug)]
198pub struct DeltaBranches<B: Backend> {
199 pub k_branch: KBranch<B>,
200 pub beta_branch: BetaBranch<B>,
201 pub v_branch: VBranch<B>,
202}
203
204impl DeltaBranchesConfig {
205 pub fn init<B: Backend>(&self, device: &B::Device) -> DeltaBranches<B> {
206 DeltaBranches {
207 k_branch: KBranchConfig::new(self.d_model, self.d_hidden)
208 .with_eps(self.eps)
209 .init(device),
210 beta_branch: BetaBranchConfig::new(self.d_model, self.d_hidden).init(device),
211 v_branch: VBranchConfig::new(self.d_model, self.dv, self.d_hidden).init(device),
212 }
213 }
214}
215
216impl<B: Backend> DeltaBranches<B> {
217 pub fn forward(&self, x: &Tensor<B, 3>) -> (Tensor<B, 2>, Tensor<B, 2>, Tensor<B, 2>) {
219 let k = self.k_branch.forward(x);
220 let beta = self.beta_branch.forward(x);
221 let v = self.v_branch.forward(x);
222 (k, beta, v)
223 }
224}
225
226#[cfg(test)]
227mod tests {
228 use super::*;
229
230 use crate::backend::AutoBackend;
231 type TestBackend = AutoBackend;
232 use burn::tensor::Distribution;
233
234 #[test]
235 fn test_pool_v_to_bd_shape() {
236 let device = Default::default();
237 let x =
238 Tensor::<TestBackend, 3>::random([2, 8, 4], Distribution::Uniform(-1.0, 1.0), &device);
239 let pooled = pool_v_to_bd(&x);
240 assert_eq!(pooled.dims(), [2, 8]);
241 }
242
243 #[test]
244 fn test_k_branch_shape_and_norm() {
245 let device = Default::default();
246 let cfg = KBranchConfig::new(8, 16);
247 let branch = cfg.init::<TestBackend>(&device);
248
249 let x =
250 Tensor::<TestBackend, 3>::random([2, 8, 4], Distribution::Uniform(-1.0, 1.0), &device);
251 let k = branch.forward(&x);
252 assert_eq!(k.dims(), [2, 8]);
253
254 let norms: Tensor<TestBackend, 2> = k.clone().powf_scalar(2.0).sum_dim(1).sqrt();
255 let norms: Vec<f32> = norms.into_data().to_vec().unwrap();
256 for n in norms {
257 assert!((n - 1.0).abs() < 0.05);
258 }
259 }
260
261 #[test]
262 fn test_beta_branch_range() {
263 let device = Default::default();
264 let cfg = BetaBranchConfig::new(8, 16);
265 let branch = cfg.init::<TestBackend>(&device);
266
267 let x =
268 Tensor::<TestBackend, 3>::random([2, 8, 4], Distribution::Uniform(-1.0, 1.0), &device);
269 let beta = branch.forward(&x);
270 assert_eq!(beta.dims(), [2, 1]);
271
272 let vals: Vec<f32> = beta.into_data().to_vec().unwrap();
273 for b in vals {
274 assert!(b >= 0.0 && b <= 2.0);
275 }
276 }
277
278 #[test]
279 fn test_v_branch_shape() {
280 let device = Default::default();
281 let cfg = VBranchConfig::new(8, 4, 16);
282 let branch = cfg.init::<TestBackend>(&device);
283
284 let x =
285 Tensor::<TestBackend, 3>::random([2, 8, 4], Distribution::Uniform(-1.0, 1.0), &device);
286 let v = branch.forward(&x);
287 assert_eq!(v.dims(), [2, 4]);
288 }
289
290 #[test]
291 fn test_bundle_shapes() {
292 let device = Default::default();
293 let cfg = DeltaBranchesConfig::new(8, 4, 16);
294 let branches = cfg.init::<TestBackend>(&device);
295
296 let x =
297 Tensor::<TestBackend, 3>::random([2, 8, 4], Distribution::Uniform(-1.0, 1.0), &device);
298 let (k, beta, v) = branches.forward(&x);
299
300 assert_eq!(k.dims(), [2, 8]);
301 assert_eq!(beta.dims(), [2, 1]);
302 assert_eq!(v.dims(), [2, 4]);
303 }
304}