← 文章 / AI技术
东东4050 6小时前 · 2026-09-04 03:09:05 · 2 阅读

AI内部手术:模型如何‘自生长’出新能力?

病灶已定位,但手术刀长度不足。

引子:一次关于AI“内部手术”的实验

近期,我们持续尝试一项看似疯狂的实验:为AI模型进行“内部手术”。

核心问题是:当AI掌握某一任务后,若令其学习新任务,我们能否提前“观测”到其结构中的瓶颈,并精准于该处“生长”出新结构以提供支撑?

这听起来如同科幻——通过手术让AI“长出”新能力。但我们已将其转化为实验室中的真实实验。

实验规模有限(模型仅约54万参数,较主流大模型小数个数量级),却揭示了极为清晰的信号。最新一轮实验更给出了迄今最精确的答案。

一、我们的“手术方案”

1.1 双任务设置:先学A,再测B

我们让模型学习两项数学任务:

· 任务A:给定数字序列,计算累积和(如 1,2,3 → 1,3,6)。

· 任务B:给定数字序列,计算加权累积和(如 1,2,3 → 1, 1×1+2×2, 1×1+2×2+3×3 = 1,5,14)。

两任务表面相似(均属“累加”),但任务B多一关键要求:每个数字需乘以其位置序号。这要求模型掌握“位置加权”概念。

1.2 三步流程:诊断 → 定位 → 生长

第一步:学会任务A。 我们将模型训练至任务A准确率超90%,使其形成稳定的“计算骨架”。

第二步:用“X光”扫描模型。 我们采用三种工具“观察”模型内部:

· 有效秩:度量模型实际利用的“独立方向”数量。若该值下降,表明模型正将知识压缩至更少维度。

· 外部压力:令模型接触任务B数据,计算其“学习方向”中有多少无法由现有结构覆盖。

· 消融测试:删除模型尾部若干“次要方向”,观察任务B表现变化。

第三步:尝试“结构生长”。 我们在诊断出的“最需要生长”位置添加小型新支路(约占模型总参数的1%),随后在任务B上进行训练。

我们比较了五种情形:

· 不生长:原模型直接学习任务B。

· 随机生长:新支路方向随机选取。

· SVD引导生长:新支路方向基于当前权重的几何结构。

· 梯度引导生长:新支路方向基于任务B的“学习信号”指向。

· Oracle(“理想”生长):新支路加入且基座同步进行适应性调整——此为“上限对照”。

若“引导生长”较“随机生长”能获取更多增益,则证明诊断有效。

二、我们看到了什么?

2.1 诊断:教科书级别的成功

为确保结果非偶然,我们运行了三个不同随机种子。诊断部分结果高度一致:

种子 外部压力 有效秩

42 44.5% 36.47

123 63.0% 27.93

2026 71.5% 24.64

更重要的是,三个种子均精确指向同一层——模型最后一层——作为“最需要生长”的位置。

诊断结论极为清晰:

· 模型在学习任务A过程中,确实将知识压缩至更少方向(有效秩下降)。

· 面对任务B时,44%~71%的“学习方向”指向现有结构之外(外部压力显著)。

· 诊断工具能精确定位“病灶”位置。

2.2 三种引导生长:精确为0.0000的“完全无效”

随后我们满怀信心地执行“生长手术”。结果令人震惊:

生长方式 种子42 种子123 种子2026

随机生长 0.0000 0.0000 0.0000

SVD引导生长 0.0000 0.0000 0.0000

梯度引导生长 0.0000 0.0000 0.0000

三种引导生长,在三个独立种子上,增益均精确为0。任务B表现无任何改善。

这并非“效果不佳”——而是完全无效。三种不同引导方向结果如出一辙,宛如新添支路根本不存在。

2.3 Oracle:意外中的意外

但Oracle结果带来强烈反差:

种子 Oracle增益 B损失变化

42 11.86 15.85 → 3.99

123 15.65 19.91 → 4.25

2026 12.64 16.68 → 4.05

Oracle成功实现!且成效显著——损失大幅下降(从15~20降至3.9~4.3)。

然而,一个关键细节浮现:准确率几乎未变(仍维持在6.7%左右,接近随机水平)。

这意味着什么?Oracle能够消除任务A带来的干扰(损失骤降),却无法真正学会任务B(准确率停滞)。

三、这是怎么回事?

3.1 我们的“手术刀”并未触及病灶

深入分析后,我们找到问题根源:

模型学会任务A后,其最后一层FFN(前馈网络)的中间层激活(GELU层输出)高度专化于任务A。面对任务B时,该中间层几乎不输出任何信号——它被“门控”关闭。

而我们的growth branch(新支路)恰好接在该中间层之后。若中间层输出≈0,则无论growth branch权重如何设定,其输出均为0×权重=0。

这宛如:我们为患者开刀并找到病灶位置,却发觉手术器械无法伸入——因为通往病灶的通道已被锁死。

三种不同引导方向(随机、SVD、梯度)在“输入为零”时毫无差异——方向再优,乘以0仍为0。

关键升级(对比 v4): 1)多层诊断:计算所有层的外部压力,再选取结构差距最大的一层。 2)在该层实施四种生长干预: - 随机(随机正交矩阵) - SVD(基于权重几何结构) - 梯度(基于投影梯度方向) - Oracle(完整容量:解冻整层 + 大分支) 3)增大生长规模并进行部分基座解冻,以克服"自信错误"的干扰。 4)采用严格因果对比,保持参数量和步数一致。 ```python if torch.cuda.is_available(): torch.cuda.manual_seed_all(s) seed_everything(BASE_SEED) device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') if device.type == 'cuda': torch.backends.cuda.matmul.allow_tf32 = True torch.backends.cudnn.benchmark = True print('PyTorch:', torch.__version__) print('Device:', device) if device.type == 'cuda': print('GPU:', torch.cuda.get_device_name(0)) # --------------------------- # 配置 # --------------------------- @dataclass class CFG: vocab_size: int = 32 seq_len: int = 32 d_model: int = 128 n_heads: int = 4 n_layers: int = 4 d_ff: int = 256 dropout: float = 0.0 batch_size: int = 64 phase_a_max_steps: int = 8000 phase_a_target_acc: float = 0.90 growth_steps: int = 800 eval_batches: int = 16 lr: float = 1e-3 growth_lr: float = 1e-3 # 为增长阶段调高 weight_decay: float = 0.01 svd_rank: int = 16 growth_rank: int = 16 # oracle 使用更大的秩 train_size: int = 12000 eval_size: int = 2000 eps: float = 1e-12 # 增长幅度:初始输出量级 growth_scale: float = 0.3 # 远大于 v4 的 0.01 cfg = CFG() # --------------------------- # 数据工具函数(与 v4 相同) # --------------------------- PAD = 0 BOS = 1 TOKEN_OFFSET = 4 DATA_V = cfg.vocab_size - TOKEN_OFFSET def make_example(task): x = torch.randint(TOKEN_OFFSET, cfg.vocab_size, (cfg.seq_len,)) z = x - TOKEN_OFFSET if task == 'A': y = torch.cumsum(z, 0) % DATA_V elif task == 'B': y = torch.cumsum(z * torch.arange(1, cfg.seq_len + 1), 0) % DATA_V else: raise ValueError(task) return x, (y + TOKEN_OFFSET).long() class ToyTaskDataset(Dataset): def __init__(self, task, n): data = [make_example(task) for _ in range(n)] self.x = torch.stack([d[0] for d in data]) self.y = torch.stack([d[1] for d in data]) def __len__(self): return self.x.size(0) def __getitem__(self, i): return self.x[i], self.y[i] def loaders(): ``` ```python train_A = ToyTaskDataset('A', cfg.train_size) train_B = ToyTaskDataset('B', cfg.train_size) eval_A = ToyTaskDataset('A', cfg.eval_size) eval_B = ToyTaskDataset('B', cfg.eval_size) pin = device.type == 'cuda' return ( DataLoader(train_A, batch_size=cfg.batch_size, shuffle=True, drop_last=True, pin_memory=pin), DataLoader(train_B, batch_size=cfg.batch_size, shuffle=True, drop_last=True, pin_memory=pin), DataLoader(eval_A, batch_size=cfg.batch_size, shuffle=False, drop_last=True, pin_memory=pin), DataLoader(eval_B, batch_size=cfg.batch_size, shuffle=False, drop_last=True, pin_memory=pin) ) # --------------------------- # 模型(与 v4 相同) # --------------------------- class TinyTransformer(nn.Module): def __init__(self): super().__init__() self.tok = nn.Embedding(cfg.vocab_size, cfg.d_model) self.pos = nn.Parameter(torch.randn(1, cfg.seq_len, cfg.d_model) * 0.02) layer = nn.TransformerEncoderLayer( cfg.d_model, cfg.n_heads, cfg.d_ff, cfg.dropout, 'gelu', batch_first=True, norm_first=True ) self.blocks = nn.TransformerEncoder(layer, cfg.n_layers) self.norm = nn.LayerNorm(cfg.d_model) self.head = nn.Linear(cfg.d_model, cfg.vocab_size) mask = torch.full((cfg.seq_len, cfg.seq_len), float('-inf')) mask = torch.triu(mask, 1) self.register_buffer('causal_mask', mask, persistent=False) def forward(self, x, return_hidden=False): h = self.tok(x) + self.pos[:, :x.size(1)] h = self.blocks(h, mask=self.causal_mask[:x.size(1), :x.size(1)]) h = self.norm(h) z = self.head(h) return (z, h) if return_hidden else z # --------------------------- # 辅助函数(与 v4 相同) # --------------------------- def count_params(m, trainable=False): return sum(p.numel() for p in m.parameters() if (p.requires_grad or not trainable)) def batch_to_device(b): return b[0].to(device, non_blocking=True), b[1].to(device, non_blocking=True) def loss_batch(m, b): x, y = batch_to_device(b) logits = m(x) return F.cross_entropy(logits.reshape(-1, cfg.vocab_size), y.reshape(-1)) @torch.no_grad() ```

def evaluate(m, loader, n=None):

m.eval()

total_loss = 0.0

count = 0

for i, b in enumerate(loader):

if n is not None and i >= n:

break

total_loss += float(loss_batch(m, b))

count += 1

return total_loss / max(count, 1)

@torch.no_grad()

def accuracy(m, loader, n=None):

m.eval()

correct = total = 0

for i, b in enumerate(loader):

if n is not None and i >= n:

break

x, y = batch_to_device(b)

pred = m(x).argmax(-1)

correct += int((pred == y).sum())

total += y.numel()

return correct / max(total, 1)

# ---------------------------

# SVD 工具函数(扩展支持多层)

# ---------------------------

def effrank(S):

q = S.float().pow(2)

p = q / (q.sum() + cfg.eps)

return float(torch.exp(-(p * (p + cfg.eps).log()).sum()))

def get_linear_layers(m):

"""返回所有 FFN 输出投影层的 (layer_idx, linear_module) 列表。

"""

layers = []

for i, block in enumerate(m.blocks.layers):

# 每个 block 包含 linear2(即 FFN 输出投影)

layers.append((i, block.linear2))

return layers

def svd_diag(linear_layer, rank=16):

W = linear_layer.weight.detach().float().cpu()

U, S, Vh = torch.linalg.svd(W, full_matrices=False)

k = min(rank, U.shape[1])

return {

'U': U[:, :k].to(device),

'S': S,

'effective_rank': effrank(S),

'topk_energy': float((S[:k]**2).sum() / (S.pow(2).sum() + cfg.eps))

}

def grad_geometry(linear_layer, U, batch):

"""计算给定层和 U 的外部梯度压力。

"""

linear_layer.zero_grad(set_to_none=True)

L = loss_batch_for_layer(linear_layer, batch) # 需要通过整个模型计算 loss

L.backward()

G = linear_layer.weight.grad.detach().float()

GGt = G @ G.T

total = torch.trace(GGt).clamp_min(cfg.eps)

P = U @ U.T

inside = torch.trace(P @ GGt).clamp_min(0)

outside = (total - inside).clamp_min(0)

linear_layer.zero_grad(set_to_none=True)

return {

'grad_inside': float(inside / total),

```python 'grad_outside': float(outside / total), 'G': G, 'loss': float(L) } # 需要一个包装器来为给定的线性层修改计算损失。 # 我们会临时克隆模型来实现?为了提高效率,我们计算整个模型的梯度并提取目标层的梯度。 # 这样更简单且更正确。 def compute_layer_gradients(m, batch, target_layers): """计算指定线性层的梯度并返回外部压力。""" m.zero_grad(set_to_none=True) L = loss_batch(m, batch) L.backward() results = {} for idx, lin in target_layers: if lin.weight.grad is None: results[idx] = None continue G = lin.weight.grad.detach().float() # 对权重进行SVD分解以获取U W = lin.weight.detach().float().cpu() U_full, S_full, _ = torch.linalg.svd(W, full_matrices=False) k = min(cfg.svd_rank, U_full.shape[1]) U = U_full[:, :k].to(device) GGt = G @ G.T total = torch.trace(GGt).clamp_min(cfg.eps) P = U @ U.T inside = torch.trace(P @ GGt).clamp_min(0) outside = (total - inside).clamp_min(0) results[idx] = { 'outside_pressure': float(outside / total), 'G': G, 'U': U, 'effective_rank': effrank(S_full), } m.zero_grad(set_to_none=True) return results # --------------------------- # 增长模块(增强版) # --------------------------- class LowRankGrowth(nn.Module): def __init__(self, in_dim, out_dim, rank, U_init=None, scale=0.3): super().__init__() self.down = nn.Linear(in_dim, rank, bias=False) self.up = nn.Linear(rank, out_dim, bias=False) nn.init.normal_(self.down.weight, std=0.02) with torch.no_grad(): if U_init is None: Q = torch.linalg.qr(torch.randn(out_dim, rank, device=device))[0] self.up.weight.data = Q * scale else: Q, _ = torch.linalg.qr(U_init, mode='reduced') self.up.weight.data = Q * scale def forward(self, x): ``` ```python return self.up(self.down(x)) class GrowingLinear(nn.Module): def __init__(self, base, growth): super().__init__() self.base = base self.growth = growth @property def weight(self): return self.base.weight @property def bias(self): return self.base.bias def forward(self, x): return self.base(x) + self.growth(x) def make_growth_at_layer(m, layer_idx, growth_type, U_init=None, rank=16, scale=0.3): """ 将指定层的 linear2 替换为 GrowingLinear。 growth_type:'random'、'svd'、'gradient'、'oracle' 对于 'oracle' 类型,我们还会解冻基础层(允许完全微调)。 """ block = m.blocks.layers[layer_idx] old = block.linear2 if growth_type == 'oracle': # Oracle:稍后我们将解冻整个基础层,但目前仅创建一个大的增长分支 growth = LowRankGrowth(cfg.d_ff, cfg.d_model, rank=rank, U_init=None, scale=scale) else: growth = LowRankGrowth(cfg.d_ff, cfg.d_model, rank=rank, U_init=U_init, scale=scale) block.linear2 = GrowingLinear(old, growth).to(device) return m def freeze_all_except_growth(m, layer_idx, growth_type): """冻结所有参数,仅保留增长分支(oracle 类型可选保留基础层)。""" for p in m.parameters(): p.requires_grad = False # 始终解冻增长分支 growth = m.blocks.layers[layer_idx].linear2.growth growth.down.weight.requires_grad = True growth.up.weight.requires_grad = True if growth_type == 'oracle': # 同时解冻基础的线性层 base = m.blocks.layers[layer_idx].linear2.base base.weight.requires_grad = True if base.bias is not None: base.bias.requires_grad = True # 也解冻层归一化和其他可能相关的组件?先保持简单处理。 # --------------------------- # 训练流程 # --------------------------- def train_until_convergence(m, loader, eval_loader, max_steps, target_acc, lr, weight_decay=0.0): m.train() opt = torch.optim.AdamW([p for p in m.parameters() if p.requires_grad], lr=lr, weight_decay=weight_decay) ``` ```python it = iter(loader) step = 0 while step < max_steps: try: b = next(it) except StopIteration: it = iter(loader) b = next(it) opt.zero_grad(set_to_none=True) L = loss_batch(m, b) L.backward() torch.nn.utils.clip_grad_norm_([p for p in m.parameters() if p.requires_grad and p.grad is not None], 1.0) opt.step() step += 1 if step % 200 == 0 or step == max_steps: acc = accuracy(m, eval_loader, cfg.eval_batches) if acc >= target_acc: print(f"收敛于 step {step}, acc={acc:.4f}") return step print(f"达到最大步数 {max_steps}, acc={accuracy(m, eval_loader, cfg.eval_batches):.4f}") return step def train_growth(m, loader, steps, lr): m.train() params = [p for p in m.parameters() if p.requires_grad] if not params: print("警告:无可训练参数!") return m opt = torch.optim.AdamW(params, lr=lr, weight_decay=0.0) it = iter(loader) for _ in range(steps): try: b = next(it) except StopIteration: it = iter(loader) b = next(it) opt.zero_grad(set_to_none=True) L = loss_batch(m, b) L.backward() torch.nn.utils.clip_grad_norm_(params, 1.0) opt.step() return m # --------------------------- # 单次种子实验 # --------------------------- def run(seed): print(f"\n{'='*70}\nSEED {seed}\n{'='*70}") seed_everything(seed) A, B, eA, eB = loaders() m = TinyTransformer().to(device) # Phase A 训练 steps_taken = train_until_convergence( m, A, eA, max_steps=cfg.phase_a_max_steps, target_acc=cfg.phase_a_target_acc, lr=cfg.lr, weight_decay=cfg.weight_decay ) state = copy.deepcopy(m.state_dict()) # 基线评估 base = { 'A_loss': evaluate(m, eA, cfg.eval_batches), 'A_acc': accuracy(m, eA, cfg.eval_batches), 'B_loss': evaluate(m, eB, cfg.eval_batches), ``` ```python 'B_acc': accuracy(m, eB, cfg.eval_batches) } print("阶段A已收敛:", base) # 多层诊断 batch_B = next(iter(B)) layer_info = [(i, block.linear2) for i, block in enumerate(m.blocks.layers)] grad_info = compute_layer_gradients(m, batch_B, layer_info) # 找出外部压力最大的层 best_layer = max(grad_info.items(), key=lambda x: x[1]['outside_pressure'] if x[1] is not None else -1) layer_idx = best_layer[0] outside_pressure = best_layer[1]['outside_pressure'] G = best_layer[1]['G'] U_old = best_layer[1]['U'] eff_rank = best_layer[1]['effective_rank'] print(f"最优层: {layer_idx}, outside_pressure: {outside_pressure:.4f}, eff_rank: {eff_rank:.2f}") # 准备生长方向 # SVD引导:直接使用 U_old(前k个左奇异向量) # 梯度引导:使用投影后的梯度方向 P_perp = torch.eye(U_old.shape[0], device=device) - U_old @ U_old.T G_proj = P_perp @ G U_grad, S_grad, _ = torch.linalg.svd(G_proj, full_matrices=False) rank_g = min(cfg.growth_rank, U_grad.shape[1]) U_grad_init = U_grad[:, :rank_g] # 构建模型 # 不生长 ng = TinyTransformer().to(device) ng.load_state_dict(state) # 随机生长 rg = TinyTransformer().to(device) rg.load_state_dict(state) rg = make_growth_at_layer(rg, layer_idx, 'random', U_init=None, rank=cfg.growth_rank, scale=cfg.growth_scale) freeze_all_except_growth(rg, layer_idx, 'random') # SVD引导生长 sg = TinyTransformer().to(device) sg.load_state_dict(state) sg = make_growth_at_layer(sg, layer_idx, 'svd', U_init=U_old[:, :cfg.growth_rank], rank=cfg.growth_rank, scale=cfg.growth_scale) freeze_all_except_growth(sg, layer_idx, 'svd') # 梯度引导生长 gg = TinyTransformer().to(device) gg.load_state_dict(state) gg = make_growth_at_layer(gg, layer_idx, 'gradient', U_init=U_grad_init, rank=cfg.growth_rank, scale=cfg.growth_scale) freeze_all_except_growth(gg, layer_idx, 'gradient') # Oracle生长:解冻基座 + 大尺度生长 og = TinyTransformer().to(device) og.load_state_dict(state) ``` ```python og = make_growth_at_layer(og, layer_idx, 'oracle', U_init=None, rank=cfg.growth_rank*2, scale=cfg.growth_scale) freeze_all_except_growth(og, layer_idx, 'oracle') added_params = count_params(rg) - count_params(ng) print(f"每次生长新增参数量: {added_params}") # 在任务B上训练所有生长模型 print("训练无生长(基线)...") # 无生长模型已在A上训练过,不在B上继续训练 print("训练随机生长...") rg = train_growth(rg, B, cfg.growth_steps, cfg.growth_lr) print("训练SVD引导的生长...") sg = train_growth(sg, B, cfg.growth_steps, cfg.growth_lr) print("训练梯度引导的生长...") gg = train_growth(gg, B, cfg.growth_steps, cfg.growth_lr) print("训练oracle生长...") og = train_growth(og, B, cfg.growth_steps, cfg.growth_lr) # 最终评估 results = {} models = [('no_growth', ng), ('random_growth', rg), ('svd_growth', sg), ('gradient_growth', gg), ('oracle_growth', og)] for name, model in models: results[name] = { 'A_loss': evaluate(model, eA, cfg.eval_batches), 'A_acc': accuracy(model, eA, cfg.eval_batches), 'B_loss': evaluate(model, eB, cfg.eval_batches), 'B_acc': accuracy(model, eB, cfg.eval_batches), } print("结果:") for name, res in results.items(): print(f" {name}: B_loss={res['B_loss']:.4f}, B_acc={res['B_acc']:.4f}") baseB = results['no_growth']['B_loss'] gains = { 'random_gain': baseB - results['random_growth']['B_loss'], 'svd_gain': baseB - results['svd_growth']['B_loss'], 'gradient_gain': baseB - results['gradient_growth']['B_loss'], 'oracle_gain': baseB - results['oracle_growth']['B_loss'], } print(f"增益: {gains}") return { 'seed': seed, 'phase_A_steps': steps_taken, 'phase_A': base, 'best_layer': layer_idx, 'outside_pressure': outside_pressure, 'effective_rank': eff_rank, 'results': results, 'gains': gains, 'added_params': added_params, } ``` ```python # ============================================================ # 主程序 # ============================================================ runs = [run(s) for s in SEEDS] print("\n" + "="*70) print("多种子汇总") print("="*70) # 提取指标 rg = [r['gains']['random_gain'] for r in runs] sg = [r['gains']['svd_gain'] for r in runs] gg = [r['gains']['gradient_gain'] for r in runs] og = [r['gains']['oracle_gain'] for r in runs] op = [r['outside_pressure'] for r in runs] for name, arr in [('Random gain', rg), ('SVD gain', sg), ('Gradient gain', gg), ('Oracle gain', og), ('Outside pressure', op)]: mean = np.mean(arr) std = np.std(arr, ddof=1) print(f"{name:20s} mean={mean:.6f} std={std:.6f}") print(f"Oracle > gradient: {sum(o > g for o, g in zip(og, gg))} / {len(runs)}") print(f"Gradient > random: {sum(g > r for g, r in zip(gg, rg))} / {len(runs)}") if len(runs) > 1: corr = np.corrcoef(op, gg)[0, 1] print(f"corr(outside_pressure, gradient_gain): {corr:.4f}") # 保存结果 out_dir = './smart_density_v5' os.makedirs(out_dir, exist_ok=True) summary = { 'config': asdict(cfg), 'seeds': SEEDS, 'device': str(device), 'runs': runs, } with open(os.path.join(out_dir, 'results.json'), 'w') as f: json.dump(summary, f, indent=2) print(f"已保存到 {os.path.abspath(out_dir)}/results.json") try: import matplotlib.pyplot as plt x = np.arange(len(SEEDS)) w = 0.15 plt.figure(figsize=(10,5)) plt.bar(x - 1.5*w, rg, w, label='Random') plt.bar(x - 0.5*w, sg, w, label='SVD') plt.bar(x + 0.5*w, gg, w, label='Gradient') plt.bar(x + 1.5*w, og, w, label='Oracle') plt.xticks(x, [str(s) for s in SEEDS]) plt.ylabel('任务B损失降低值') plt.title('结构增长对比 (v5)') plt.legend() plt.tight_layout() plt.show() except Exception as e: print('绘图已跳过:', repr(e)) PyTorch: 2.11.0+cu128 设备: cuda GPU: Tesla T4 ====================================================================== 种子 42 ====================================================================== ```

/tmp/ipykernel_1842/2151775399.py:132: 用户警告:enable_nested_tensor 为 True,但由于 encoder_layer.norm_first 为 True,self.use_nested_tensor 为 False

self.blocks = nn.TransformerEncoder(layer, cfg.n_layers)

第 3400 步收敛,准确率=0.9017

阶段 A 收敛完成:{'A_loss': 0.3280856553465128, 'A_acc': 0.9017333984375, 'B_loss': 15.854797780513763, 'B_acc': 0.0667724609375}

最优层:3,外部压力:0.4445,有效秩:36.47

/tmp/ipykernel_1842/2151775399.py:132: 用户警告:enable_nested_tensor 为 True,但由于 encoder_layer.norm_first 为 True,self.use_nested_tensor 为 False

self.blocks = nn.TransformerEncoder(layer, cfg.n_layers)

每次增长新增参数量:6144

训练无增长(基线)...

训练随机增长...

训练 SVD 引导增长...

训练梯度引导增长...

训练oracle增长...

结果:

无增长:B_loss=15.8548,B_acc=0.0668

随机增长:B_loss=15.8548,B_acc=0.0668

SVD增长:B_loss=15.8548,B_acc=0.0668

梯度增长:B_loss=15.8548,B_acc=0.0668

oracle增长:B_loss=3.9925,B_acc=0.0672

增益:{'random_gain': 0.0, 'svd_gain': 0.0, 'gradient_gain': 0.0, 'oracle_gain': 11.862322941422462}

======================================================================

种子 123

======================================================================

第 6800 步收敛,准确率=0.9725

阶段 A 收敛完成:{'A_loss': 0.10075912298634648, 'A_acc': 0.97247314453125, 'B_loss': 19.90610122680664, 'B_acc': 0.066925048828125}

最优层:3,外部压力:0.6300,有效秩:27.93

每次增长新增参数量:6144

训练无增长(基线)...

训练随机增长...

训练 SVD 引导增长...

训练梯度引导增长...

训练oracle增长...

结果:

无增长:B_loss=19.9061,B_acc=0.0669

随机增长:B_loss=19.9061,B_acc=0.0669

SVD增长:B_loss=19.9061,B_acc=0.0669

梯度增长:B_loss=19.9061,B_acc=0.0669

oracle增长:B_loss=4.2520,B_acc=0.0675

增益:{'random_gain': 0.0, 'svd_gain': 0.0, 'gradient_gain': 0.0, 'oracle_gain': 15.654108047485352}

======================================================================

种子 2026

======================================================================

第6400步收敛,acc=0.9207

阶段A收敛:{'A_loss': 0.20898992102593184, 'A_acc': 0.920654296875, 'B_loss': 16.68497395515442, 'B_acc': 0.06683349609375}

最优层:3,外部压力:0.7145,有效秩:24.64

每次增长新增参数:6144

训练无增长(基线)...

训练随机增长...

训练SVD引导增长...

训练梯度引导增长...

训练oracle增长...

结果:

无增长:B_loss=16.6850, B_acc=0.0668

随机增长:B_loss=16.6850, B_acc=0.0668

SVD引导增长:B_loss=16.6850, B_acc=0.0668

梯度引导增长:B_loss=16.6850, B_acc=0.0668

oracle增长:B_loss=4.0462, B_acc=0.0674

增益:{'random_gain': 0.0, 'svd_gain': 0.0, 'gradient_gain': 0.0, 'oracle_gain': 12.638744369149208}

======================================================================

多种子汇总

======================================================================

随机增益 均值=0.000000 标准差=0.000000

SVD增益 均值=0.000000 标准差=0.000000

梯度增益 均值=0.000000 标准差=0.000000

Oracle增益 均值=13.385058 标准差=2.003034

外部压力 均值=0.596325 标准差=0.138112

Oracle > 梯度:3 / 3

梯度 > 随机:0 / 3

corr(外部压力, 梯度增益):nan

已保存至 /content/smart_density_v5/results.json

/usr/local/lib/python3.13/dist-packages/numpy/lib/_function_base_impl.py:2999: RuntimeWarning: invalid value encountered in divide

c /= stddev[:, None]

/usr/local/lib/python3.13/dist-packages/numpy/lib/_function_base_impl.py:3000: RuntimeWarning: invalid value encountered in divide

c /= stddev[None, :]

原始来源: 东东4050

评论 (0)