KenteaKe11 commited on
Commit
9cd4795
·
verified ·
1 Parent(s): bebf90d

Upload 3 files

Browse files
Files changed (3) hide show
  1. README.md +11 -11
  2. config.json +1 -0
  3. model.py +69 -23
README.md CHANGED
@@ -14,26 +14,24 @@ tags:
14
  - custom_code
15
  - fp16
16
  - base
17
- datasets:
18
- - wikimedia/wikipedia
19
- - HuggingFaceFW/fineweb-edu
20
  ---
21
 
22
  # KenT-30M-Base
23
 
24
- KenT is a recurrent language model. This ~30M-parameter version stacks 24 identical layers; each layer expands the
25
- representation stream into `M` resolution positions, mixes them with a fixed DCT-II, transforms the features with a SwiGLU,
26
- and keeps a learned-forgetting memory (EMA) with one decay coefficient per resolution position.
 
27
 
28
  > This repo contains `trust_remote_code` code; weights are stored in **FP16**.
29
 
30
  ## Layer
31
 
32
  ```
33
- Z = ResProj_in(Norm(X)) # n -> M x d
34
  Z = Z + SwiGLU(DCT_M(RMSNorm(Z))) # WNN block: fixed DCT-II over the M axis, SwiGLU over the d axis
35
- H_t = (1 - a) * H_{t-1} + a * Z_t # EMA, a = learned vector of M coefficients per layer
36
- X' = X + ResProj_out(Norm(H_t)) # M x d -> n
37
  ```
38
 
39
  | | value |
@@ -42,7 +40,9 @@ X' = X + ResProj_out(Norm(H_t)) # M x d -> n
42
  | layers | 24 |
43
  | resolution `M` x features `d` | 12 x 96 (M·d = 1152 = 4.5n) |
44
  | SwiGLU hidden | 384 (4d) |
45
- | parameters | ~29.7M (embedding 12.9M + layers 16.9M) |
 
 
46
 
47
  ## Quickstart
48
 
@@ -66,4 +66,4 @@ Long documents: `python infer.py --model ./KenT-30M-Base --prompt-file doc.txt -
66
  ## Notes
67
 
68
  - Research model, trained from scratch; evaluate before real-world use.
69
- - The tokenizer and weights must match `vocab_size` in `config.json`.
 
14
  - custom_code
15
  - fp16
16
  - base
 
 
 
17
  ---
18
 
19
  # KenT-30M-Base
20
 
21
+ KenT is a recurrent language model. This ~30M-parameter version reads **one token per step** and stacks 24 identical layers;
22
+ each layer expands the token vector into `M` resolution positions, mixes them with a fixed DCT-II, transforms the features
23
+ with a SwiGLU, and keeps a learned-forgetting memory (EMA) whose decay is a learned **matrix** (one coefficient per
24
+ resolution position and feature). The memory is read back through a DCT-II and projected to the token dimension.
25
 
26
  > This repo contains `trust_remote_code` code; weights are stored in **FP16**.
27
 
28
  ## Layer
29
 
30
  ```
31
+ Z = ResProj_in(Norm(X)) # 1 -> M: token vector n -> M x d
32
  Z = Z + SwiGLU(DCT_M(RMSNorm(Z))) # WNN block: fixed DCT-II over the M axis, SwiGLU over the d axis
33
+ H_t = (1 - A) * H_{t-1} + A * Z_t # EMA Learner Matrix: A = sigmoid(logits), shape M x d, per layer
34
+ X' = X + ResProj_out(DCT_M(Norm(H_t))) # DCT-II Proj, then M -> 1; residual with the layer input
35
  ```
36
 
37
  | | value |
 
40
  | layers | 24 |
41
  | resolution `M` x features `d` | 12 x 96 (M·d = 1152 = 4.5n) |
42
  | SwiGLU hidden | 384 (4d) |
43
+ | EMA decay | learned matrix `(12, 96)` per layer (`ema_per_feature=false` -> vector `(12,)`) |
44
+ | recurrent state | `H`: `(12, 96)` per layer, constant size |
45
+ | parameters | ~29.75M (embedding 12.9M + layers 16.9M) |
46
 
47
  ## Quickstart
48
 
 
66
  ## Notes
67
 
68
  - Research model, trained from scratch; evaluate before real-world use.
69
+ - The tokenizer and weights must match `vocab_size` in `config.json`.
config.json CHANGED
@@ -26,6 +26,7 @@
26
  "dtype": "float16",
27
  "ema_alpha_first": 0.5,
28
  "ema_alpha_last": 0.01,
 
29
  "ema_block_size": 128,
30
  "use_gradient_checkpointing": false
31
  }
 
26
  "dtype": "float16",
27
  "ema_alpha_first": 0.5,
28
  "ema_alpha_last": 0.01,
29
+ "ema_per_feature": true,
30
  "ema_block_size": 128,
31
  "use_gradient_checkpointing": false
32
  }
model.py CHANGED
@@ -1,24 +1,25 @@
1
  # coding=utf-8
2
  """KenT: kiến trúc hồi quy hai luồng (representation X_t / temporal-memory H_t).
3
 
4
- Mỗi KenT layer (hộp "WNN" trong sơ đồ) thực hiện một bước:
 
5
 
6
- Z = ResProj_in(Norm_X(X)) # (…, M, d) n -> M resolution, mỗi resolution d feature
7
  Z = Z + SwiGLU( DCT_M( RMSNorm(Z) ) ) # WNN Block: DCT-II cố định trên trục M, SwiGLU trên trục d, skip quanh cả cụm
8
- H_t = (1 - a) ⊙ H_{t-1} + a ⊙ Z_t # EMA, a = sigmoid(ema_logit) là VECTOR M phần tử học được / layer
9
- X' = X + ResProj_out(Norm_H(H_t)) # M x d -> n (Add với X vào layer, rồi sang layer kế / lm_head)
10
 
11
  Mỗi layer xếp K = `num_wnn_blocks` WNN Block nối tiếp (mặc định K = 1, đúng sơ đồ); độ sâu đến từ việc xếp chồng
12
- nhiều layer ("xN" trong sơ đồ).
13
 
14
- Bộ nhớ H có cơ chế quên: a là một vector M phần tử (mỗi vị trí trên trục resolution/phổ có hệ số quên riêng,
15
- chung cho mọi feature d), học được và riêng từng layer. Khởi tạo: nội suy theo cấp số nhân từ `ema_alpha_first`
16
- (layer đầu, vị trí đầu) tới `ema_alpha_last` (layer cuối, vị trí cuối) theo trung bình của chỉ số layer và chỉ số vị trí.
 
17
 
18
- EMA là một phép hồi quy tuyến tính nên vẫn song song hóa được theo thời gian: trong từng khối
19
- độ dài `ema_block_size` dùng ma trận phân rã tam giác dưới (riêng cho từng vị trí M), các khối được ghép bằng
20
- affine-scan log-depth. Kết quả bằng đúng hồi quy tuần tự. Trạng thái giải mã chỉ là H cho mỗi
21
- layer: O(1) theo độ dài.
22
 
23
  Trọng số được lưu ở FP16; EMA và normalization chạy ở FP32.
24
  """
@@ -55,9 +56,11 @@ class KentConfig(PretrainedConfig):
55
  use_bias: dùng bias trong Resolution Proj (SwiGLU không bias).
56
  initializer_range: độ lệch chuẩn khởi tạo trọng số.
57
  ema_alpha_first: hệ số a khởi tạo của layer đầu, vị trí đầu (quên nhanh).
58
- ema_alpha_last: hệ số a khởi tạo của layer cuối, vị trí cuối (nhớ lâu); phần còn lại nội suy theo cấp số
59
- nhân theo trung bình chỉ số layer và chỉ số vị trí. Vector a vẫn là tham số học được.
60
- ema_block_size: độ dài khối của EMA song song (chỉ ảnh hưởng tốc độ/bộ nhớ).
 
 
61
  use_cache: trả về KentCache khi suy luận.
62
  use_gradient_checkpointing: bật gradient checkpointing theo từng KenT layer khi khởi tạo model
63
  (chỉ có tác dụng ở chế độ train; tương đương gọi `model.gradient_checkpointing_enable()`).
@@ -79,6 +82,7 @@ class KentConfig(PretrainedConfig):
79
  initializer_range: float = 0.02,
80
  ema_alpha_first: float = 0.5,
81
  ema_alpha_last: float = 0.01,
 
82
  ema_block_size: int = 128,
83
  use_cache: bool = True,
84
  use_gradient_checkpointing: bool = False,
@@ -100,6 +104,7 @@ class KentConfig(PretrainedConfig):
100
  self.initializer_range = initializer_range
101
  self.ema_alpha_first = ema_alpha_first
102
  self.ema_alpha_last = ema_alpha_last
 
103
  self.ema_block_size = ema_block_size
104
  self.use_cache = use_cache
105
  self.use_gradient_checkpointing = use_gradient_checkpointing
@@ -119,10 +124,22 @@ class KentConfig(PretrainedConfig):
119
  return [float(self.ema_alpha_first * ratio ** (0.5 * (r_l + (p / (n_p - 1) if n_p > 1 else 0.0))))
120
  for p in range(n_p)]
121
 
 
 
 
 
 
 
 
 
 
122
  def alpha_init(self, layer_idx: int) -> float:
123
- """Trung bình của vector a khởi tạo của layer (để log)."""
124
- v = self.alpha_init_vector(layer_idx)
125
- return float(sum(v) / len(v))
 
 
 
126
 
127
 
128
  # --------------------------------------------------------------------------- #
@@ -164,11 +181,37 @@ def _affine_scan(a: torch.Tensor, b: torch.Tensor):
164
 
165
 
166
  def ema_scan(u: torch.Tensor, mask: torch.Tensor, h0: torch.Tensor, a: torch.Tensor, block: int = 128):
167
- """EMA song song, luôn chạy fp32 (tắt autocast để matmul không bị ép về fp16)."""
 
 
 
168
  with torch.autocast(device_type=u.device.type, enabled=False):
 
 
169
  return _ema_scan_fp32(u.float(), mask, h0.float(), a.float(), block)
170
 
171
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
172
  def _ema_scan_fp32(u: torch.Tensor, mask: torch.Tensor, h0: torch.Tensor, a: torch.Tensor, block: int = 128):
173
  """H_t = (1 - a m_t) ⊙ H_{t-1} + a m_t ⊙ u_t, tính song song cho mọi t.
174
 
@@ -308,12 +351,14 @@ class KentLayer(nn.Module):
308
  self.wnn = nn.ModuleList([KentWNNBlock(config) for _ in range(config.num_wnn_blocks)])
309
  self.norm_h = KentRMSNorm(config.feature_dim, config.rms_norm_eps)
310
  self.res_out = nn.Linear(self.n * self.d, config.hidden_size, bias=config.use_bias) # Resolution Proj M -> 1
311
- a0 = torch.tensor(config.alpha_init_vector(layer_idx), dtype=torch.float32)
 
 
312
  self.ema_logit_init = torch.log(a0 / (1.0 - a0))
313
- self.ema_logit = nn.Parameter(self.ema_logit_init.clone()) # (M,)
314
 
315
  def alpha(self) -> torch.Tensor:
316
- """Vector a (M,) trong (0,1), tính ở fp32."""
317
  return torch.sigmoid(self.ema_logit.float()).clamp_max(0.999)
318
 
319
  def forward(self, x, mask, h0, chunked: bool = False):
@@ -331,7 +376,8 @@ class KentLayer(nn.Module):
331
  h0 = u.new_zeros((u.shape[0], self.n, self.d))
332
  h, h_last = ema_scan(u, m, h0, self.alpha(), self.block_size)
333
  h = h.reshape(b, t, self.n, self.d)
334
- dx = self.res_out(self.norm_h(h).to(x.dtype).reshape(b, t, self.n * self.d))
 
335
  return x + dx, h_last
336
 
337
 
 
1
  # coding=utf-8
2
  """KenT: kiến trúc hồi quy hai luồng (representation X_t / temporal-memory H_t).
3
 
4
+ Mỗi bước nhận ĐÚNG MỘT token (cửa sổ trượt từng token một); lịch sử nằm trong trạng thái H của từng layer.
5
+ Mỗi KenT layer (hộp "WNN" trong sơ đồ) thực hiện:
6
 
7
+ Z = ResProj_in(Norm_X(X)) # 1 -> M: một vector token thành M resolution, mỗi resolution d feature
8
  Z = Z + SwiGLU( DCT_M( RMSNorm(Z) ) ) # WNN Block: DCT-II cố định trên trục M, SwiGLU trên trục d, skip quanh cả cụm
9
+ H_t = (1 - A) ⊙ H_{t-1} + A ⊙ Z_t # "EMA Learner Matrix": A = sigmoid(ema_logit), MA TRẬN M x d học được / layer
10
+ X' = X + ResProj_out( DCT_M( Norm_H(H_t) ) ) # DCT-II Proj rồi M -> 1; Add với X vào layer (residual)
11
 
12
  Mỗi layer xếp K = `num_wnn_blocks` WNN Block nối tiếp (mặc định K = 1, đúng sơ đồ); độ sâu đến từ việc xếp chồng
13
+ nhiều layer ("xN" trong sơ đồ). Layer cuối cho X' -> norm cuối -> lm_head (tied với embedding).
14
 
15
+ Bộ nhớ H có cơ chế quên: A là ma trận M x d (mỗi vị trí resolution VÀ mỗi feature có hệ số quên riêng), học được và
16
+ riêng từng layer. Khởi tạo: nội suy theo cấp số nhân từ `ema_alpha_first` (layer đầu, vị trí đầu, feature đầu) tới
17
+ `ema_alpha_last` (layer cuối, vị trí cuối, feature cuối) theo trung bình của chỉ số layer, vị trí và feature.
18
+ `ema_per_feature=False` quay về vector M phần tử (chung cho mọi feature), dùng scan theo khối.
19
 
20
+ EMA là một phép hồi quy tuyến tính (đường chéo theo từng kênh) nên vẫn song song hóa được theo thời gian bằng
21
+ affine-scan log-depth (Hillis-Steele): kết quả bằng đúng hồi quy tuần tự. Trạng thái giải mã chỉ là H cho mỗi
22
+ layer, shape (M, d): O(1) theo độ dài.
 
23
 
24
  Trọng số được lưu ở FP16; EMA và normalization chạy ở FP32.
25
  """
 
56
  use_bias: dùng bias trong Resolution Proj (SwiGLU không bias).
57
  initializer_range: độ lệch chuẩn khởi tạo trọng số.
58
  ema_alpha_first: hệ số a khởi tạo của layer đầu, vị trí đầu (quên nhanh).
59
+ ema_alpha_last: hệ số a khởi tạo của layer cuối, vị trí cuối, feature cuối (nhớ lâu); phần còn lại nội suy theo
60
+ cấp số nhân theo trung bình các chỉ số (layer, vị trí[, feature]). a vẫn là tham số học được.
61
+ ema_per_feature: True = EMA Learner Matrix (hệ số quên riêng cho mỗi (vị trí M, feature d), ema_logit shape
62
+ (M, d)); False = vector M phần tử, chung cho mọi feature (ema_logit shape (M,)).
63
+ ema_block_size: độ dài khối của EMA song song (chỉ dùng khi ema_per_feature=False; ảnh hưởng tốc độ/bộ nhớ).
64
  use_cache: trả về KentCache khi suy luận.
65
  use_gradient_checkpointing: bật gradient checkpointing theo từng KenT layer khi khởi tạo model
66
  (chỉ có tác dụng ở chế độ train; tương đương gọi `model.gradient_checkpointing_enable()`).
 
82
  initializer_range: float = 0.02,
83
  ema_alpha_first: float = 0.5,
84
  ema_alpha_last: float = 0.01,
85
+ ema_per_feature: bool = True,
86
  ema_block_size: int = 128,
87
  use_cache: bool = True,
88
  use_gradient_checkpointing: bool = False,
 
104
  self.initializer_range = initializer_range
105
  self.ema_alpha_first = ema_alpha_first
106
  self.ema_alpha_last = ema_alpha_last
107
+ self.ema_per_feature = ema_per_feature
108
  self.ema_block_size = ema_block_size
109
  self.use_cache = use_cache
110
  self.use_gradient_checkpointing = use_gradient_checkpointing
 
124
  return [float(self.ema_alpha_first * ratio ** (0.5 * (r_l + (p / (n_p - 1) if n_p > 1 else 0.0))))
125
  for p in range(n_p)]
126
 
127
+ def alpha_init_matrix(self, layer_idx: int):
128
+ """Ma trận a (M x d) khởi tạo của layer: giảm theo cấp số nhân theo độ sâu, vị trí và feature."""
129
+ n_l, n_p, n_d = self.num_hidden_layers, self.resolution_size, self.feature_dim
130
+ r_l = layer_idx / (n_l - 1) if n_l > 1 else 0.0
131
+ ratio = self.ema_alpha_last / self.ema_alpha_first
132
+ return [[float(self.ema_alpha_first * ratio ** ((r_l + (p / (n_p - 1) if n_p > 1 else 0.0)
133
+ + (j / (n_d - 1) if n_d > 1 else 0.0)) / 3.0))
134
+ for j in range(n_d)] for p in range(n_p)]
135
+
136
  def alpha_init(self, layer_idx: int) -> float:
137
+ """Trung bình của a khởi tạo của layer (để log)."""
138
+ if self.ema_per_feature:
139
+ flat = [x for row in self.alpha_init_matrix(layer_idx) for x in row]
140
+ else:
141
+ flat = self.alpha_init_vector(layer_idx)
142
+ return float(sum(flat) / len(flat))
143
 
144
 
145
  # --------------------------------------------------------------------------- #
 
181
 
182
 
183
  def ema_scan(u: torch.Tensor, mask: torch.Tensor, h0: torch.Tensor, a: torch.Tensor, block: int = 128):
184
+ """EMA song song, luôn chạy fp32 (tắt autocast để matmul không bị ép về fp16).
185
+
186
+ a: (M, d) -> hệ số riêng từng kênh (EMA Learner Matrix, scan Hillis-Steele); a: (M,) -> theo khối (chung cho d).
187
+ """
188
  with torch.autocast(device_type=u.device.type, enabled=False):
189
+ if a.dim() == 2:
190
+ return _ema_scan_diag(u.float(), mask, h0.float(), a.float())
191
  return _ema_scan_fp32(u.float(), mask, h0.float(), a.float(), block)
192
 
193
 
194
+ def _ema_scan_diag(u: torch.Tensor, mask: torch.Tensor, h0: torch.Tensor, a: torch.Tensor):
195
+ """H_t = (1 - a m_t) ⊙ H_{t-1} + a m_t ⊙ u_t với a: (M, d) khác nhau theo từng kênh.
196
+
197
+ u: (B,T,M,d) fp32 | mask: (B,T) {0,1} (0 = padding: H giữ nguyên) | h0: (B,M,d) fp32.
198
+ Mỗi bước là ánh xạ affine h -> A_t h + B_t (A_t = 1 - a m_t, B_t = a m_t u_t); inclusive scan log-depth
199
+ (Hillis-Steele) cho trạng thái sau mọi t. Mọi A_t nằm trong (0, 1] nên ổn định.
200
+ Trả về H (B,T,M,d) và h_cuối (B,M,d).
201
+ """
202
+ bsz, t, n, d = u.shape
203
+ am = a.view(1, 1, n, d) * mask.to(u.dtype).view(bsz, t, 1, 1)
204
+ dec = 1.0 - am
205
+ acc = am * u
206
+ off = 1
207
+ while off < t:
208
+ acc = torch.cat([acc[:, :off], dec[:, off:] * acc[:, :-off] + acc[:, off:]], dim=1)
209
+ dec = torch.cat([dec[:, :off], dec[:, off:] * dec[:, :-off]], dim=1)
210
+ off *= 2
211
+ h = dec * h0.unsqueeze(1) + acc
212
+ return h, h[:, -1]
213
+
214
+
215
  def _ema_scan_fp32(u: torch.Tensor, mask: torch.Tensor, h0: torch.Tensor, a: torch.Tensor, block: int = 128):
216
  """H_t = (1 - a m_t) ⊙ H_{t-1} + a m_t ⊙ u_t, tính song song cho mọi t.
217
 
 
351
  self.wnn = nn.ModuleList([KentWNNBlock(config) for _ in range(config.num_wnn_blocks)])
352
  self.norm_h = KentRMSNorm(config.feature_dim, config.rms_norm_eps)
353
  self.res_out = nn.Linear(self.n * self.d, config.hidden_size, bias=config.use_bias) # Resolution Proj M -> 1
354
+ a0 = torch.tensor(
355
+ config.alpha_init_matrix(layer_idx) if config.ema_per_feature else config.alpha_init_vector(layer_idx),
356
+ dtype=torch.float32)
357
  self.ema_logit_init = torch.log(a0 / (1.0 - a0))
358
+ self.ema_logit = nn.Parameter(self.ema_logit_init.clone()) # (M, d) hoặc (M,)
359
 
360
  def alpha(self) -> torch.Tensor:
361
+ """EMA Learner Matrix a (M, d) (hoặc vector (M,)) trong (0,1), tính ở fp32."""
362
  return torch.sigmoid(self.ema_logit.float()).clamp_max(0.999)
363
 
364
  def forward(self, x, mask, h0, chunked: bool = False):
 
376
  h0 = u.new_zeros((u.shape[0], self.n, self.d))
377
  h, h_last = ema_scan(u, m, h0, self.alpha(), self.block_size)
378
  h = h.reshape(b, t, self.n, self.d)
379
+ spec = dct2(self.norm_h(h).to(x.dtype)) # DCT-II Proj trên trục M của H
380
+ dx = self.res_out(spec.reshape(b, t, self.n * self.d))
381
  return x + dx, h_last
382
 
383