vision_rs/models/yolo/yolo26/blocks/
c3k2.rs1use teeny_core::{dtype::Float, graph::{Op, SymTensor}, name_scope::name_scope};
19
20use super::bottleneck::{bottleneck_3x3, bottleneck_std};
21use super::c2psa::psa_block;
22use super::conv::conv;
23
24fn channel_chunk(x: SymTensor, c_total: usize, chunk_c: usize, chunk_offset: usize) -> SymTensor {
27 let op = Op::ChannelChunk { c_total, chunk_c, chunk_offset };
28 let shape = vec![x.shape[0], Some(chunk_c), x.shape[2], x.shape[3]];
29 let node_id = x.graph.borrow_mut().add_node(op, vec![x.node_id], x.dtype, shape.clone());
30 SymTensor { node_id, graph: x.graph.clone(), dtype: x.dtype, shape }
31}
32
33fn channel_cat(tensors: Vec<SymTensor>, c_total: usize) -> SymTensor {
34 let first = &tensors[0];
35 let shape = vec![first.shape[0], Some(c_total), first.shape[2], first.shape[3]];
36 let inputs: Vec<usize> = tensors.iter().map(|t| t.node_id).collect();
37 let node_id = first.graph.borrow_mut().add_node(
38 Op::ChannelCat { c_total }, inputs, first.dtype, shape.clone(),
39 );
40 SymTensor { node_id, graph: first.graph.clone(), dtype: first.dtype, shape }
41}
42
43fn c3k_inner<D: Float + 'static>(c: usize, shortcut: bool) -> impl Fn(SymTensor) -> SymTensor {
47 let c_h = ((c as f32) * 0.5) as usize;
48 let cv1 = conv::<D>(c, c_h, 1, 1);
49 let cv2 = conv::<D>(c, c_h, 1, 1);
50 let cv3 = conv::<D>(2 * c_h, c, 1, 1);
51 let m0 = bottleneck_3x3::<D>(c_h, shortcut);
52 let m1 = bottleneck_3x3::<D>(c_h, shortcut);
53 move |x: SymTensor| {
54 let after_cv1 = { let _g = name_scope("cv1"); cv1(x.clone()) };
55 let after_m0 = { let _g = name_scope("m.0"); m0(after_cv1) };
56 let after_m1 = { let _g = name_scope("m.1"); m1(after_m0) };
57 let after_cv2 = { let _g = name_scope("cv2"); cv2(x) };
58 let _g = name_scope("cv3");
59 cv3(channel_cat(vec![after_m1, after_cv2], 2 * c_h))
60 }
61}
62
63fn bottleneck_psa_seq<D: Float + Send + Sync + 'static>(
68 c: usize,
69 shortcut: bool,
70 num_heads: usize,
71 key_dim: usize,
72) -> impl Fn(SymTensor) -> SymTensor {
73 let bneck = bottleneck_std::<D>(c, shortcut);
74 let psa = psa_block::<D>(c, num_heads, key_dim);
75 move |x: SymTensor| {
76 let x = { let _g = name_scope("0"); bneck(x) };
77 { let _g = name_scope("1"); psa(x) }
78 }
79}
80
81pub fn c3k2<D: Float + 'static>(
95 c_in: usize,
96 c_out: usize,
97 n: usize,
98 c3k: bool,
99 shortcut: bool,
100 e: f32,
101) -> impl Fn(SymTensor) -> SymTensor {
102 let c = (c_out as f32 * e) as usize;
103 let cv1 = conv::<D>(c_in, 2 * c, 1, 1);
104 let cv2 = conv::<D>((2 + n) * c, c_out, 1, 1);
105 let bottlenecks: Vec<Box<dyn Fn(SymTensor) -> SymTensor>> = (0..n)
106 .map(|_| -> Box<dyn Fn(SymTensor) -> SymTensor> {
107 if c3k {
108 Box::new(c3k_inner::<D>(c, shortcut))
109 } else {
110 Box::new(bottleneck_std::<D>(c, shortcut))
111 }
112 })
113 .collect();
114 move |x: SymTensor| {
115 let h = { let _g = name_scope("cv1"); cv1(x) };
116 let y0 = channel_chunk(h.clone(), 2 * c, c, 0);
117 let y1 = channel_chunk(h, 2 * c, c, c);
118 let mut last = y1.clone();
119 let mut parts = vec![y0, y1];
120 for (i, b) in bottlenecks.iter().enumerate() {
121 let _g = name_scope(format!("m.{i}"));
122 last = b(last);
123 parts.push(last.clone());
124 }
125 { let _g = name_scope("cv2"); cv2(channel_cat(parts, (2 + n) * c)) }
126 }
127}
128
129pub fn c3k2_psa<D: Float + Send + Sync + 'static>(
135 c_in: usize,
136 c_out: usize,
137 n: usize,
138 shortcut: bool,
139 e: f32,
140) -> impl Fn(SymTensor) -> SymTensor {
141 let c = (c_out as f32 * e) as usize;
142 let num_heads = c / 64;
143 let key_dim = 32;
144 let cv1 = conv::<D>(c_in, 2 * c, 1, 1);
145 let cv2 = conv::<D>((2 + n) * c, c_out, 1, 1);
146 let bottlenecks: Vec<Box<dyn Fn(SymTensor) -> SymTensor>> = (0..n)
147 .map(|_| -> Box<dyn Fn(SymTensor) -> SymTensor> {
148 Box::new(bottleneck_psa_seq::<D>(c, shortcut, num_heads, key_dim))
149 })
150 .collect();
151 move |x: SymTensor| {
152 let h = { let _g = name_scope("cv1"); cv1(x) };
153 let y0 = channel_chunk(h.clone(), 2 * c, c, 0);
154 let y1 = channel_chunk(h, 2 * c, c, c);
155 let mut last = y1.clone();
156 let mut parts = vec![y0, y1];
157 for (i, b) in bottlenecks.iter().enumerate() {
158 let _g = name_scope(format!("m.{i}"));
159 last = b(last);
160 parts.push(last.clone());
161 }
162 { let _g = name_scope("cv2"); cv2(channel_cat(parts, (2 + n) * c)) }
163 }
164}