網(wǎng)站改版后seo該怎么做做廢鐵在哪個(gè)網(wǎng)站推廣
鶴壁市浩天電氣有限公司
2026/01/24 13:04:19
網(wǎng)站改版后seo該怎么做,做廢鐵在哪個(gè)網(wǎng)站推廣,臺(tái)州網(wǎng)站設(shè)計(jì),網(wǎng)站開發(fā)流程知乎簡(jiǎn)介
本文詳細(xì)解析了Transformer架構(gòu)的核心原理#xff0c;包括位置編碼、多頭注意力和殘差連接等。通過時(shí)間序列預(yù)測(cè)實(shí)戰(zhàn)案例#xff0c;展示了Encoder-Decoder結(jié)構(gòu)的應(yīng)用#xff0c;并提供完整代碼實(shí)現(xiàn)和可視化分析。文章解釋了Transformer如何解決序列建模中的長(zhǎng)依賴問題…簡(jiǎn)介本文詳細(xì)解析了Transformer架構(gòu)的核心原理包括位置編碼、多頭注意力和殘差連接等。通過時(shí)間序列預(yù)測(cè)實(shí)戰(zhàn)案例展示了Encoder-Decoder結(jié)構(gòu)的應(yīng)用并提供完整代碼實(shí)現(xiàn)和可視化分析。文章解釋了Transformer如何解決序列建模中的長(zhǎng)依賴問題使其成為大模型的關(guān)鍵架構(gòu)。首先咱們先大概解釋一下什么事Transformer以及優(yōu)勢(shì)~如果把機(jī)器學(xué)習(xí)比作讓機(jī)器讀書學(xué)習(xí)的過程傳統(tǒng) RNN/LSTM 就像是從頭到尾一頁(yè)頁(yè)地讀書讀過的內(nèi)容記在腦子里但越往后前面看的內(nèi)容就模糊了長(zhǎng)依賴很難記住。那么Transformer 則像是配備了一個(gè)全書搜索多焦點(diǎn)注意力的讀書系統(tǒng)每當(dāng)它要理解當(dāng)前位置的內(nèi)容時(shí)它可以同時(shí)翻全書聚焦到最相關(guān)的段落并且可以開多個(gè)注意力焦點(diǎn)多頭注意力從不同視角理解內(nèi)容結(jié)合多層堆疊它就像一個(gè)推理深度不斷加深的閱讀者。它好在哪里省事不必一頁(yè)頁(yè)串行回憶直接在全局范圍檢索相關(guān)信息并行訓(xùn)練效率高。能力強(qiáng)多頭注意力像多個(gè)專家能同時(shí)從不同的關(guān)系維度建模??煞夯瘡恼Z(yǔ)言到圖像、語(yǔ)音、時(shí)間序列它都能工作已成為 AI 時(shí)代的通用基座模型方法論??傊蠹铱梢赃@么理解Transformer 是注意力機(jī)制驅(qū)動(dòng)的并行神經(jīng)網(wǎng)絡(luò)架構(gòu)通過全局對(duì)齊與多頭注意力解決了序列建模中長(zhǎng)依賴難、并行效率低的問題。老規(guī)矩如果大家覺得對(duì)你有所啟發(fā)不要忘記點(diǎn)贊或者轉(zhuǎn)發(fā)你們的支持是我持續(xù)的動(dòng)力~下面會(huì)進(jìn)行一個(gè)詳細(xì)的闡述~一、核心原理模型的宏觀結(jié)構(gòu)經(jīng)典的 Transformer 由 Encoder-Decoder 兩部分組成也可只用 Encoder 或 DecoderEncoder輸入序列經(jīng)過多層自注意力 前饋網(wǎng)絡(luò)的堆疊得到上下文表示。Decoder在預(yù)測(cè)時(shí)逐步看已預(yù)測(cè)的部分并做未來信息屏蔽對(duì)每個(gè)位置再次做自注意力同時(shí)通過交叉注意力看 Encoder 的輸出從而生成輸出序列。最后實(shí)戰(zhàn)會(huì)使用一個(gè)小型的 Encoder-Decoder 結(jié)構(gòu)進(jìn)行時(shí)間序列多步預(yù)測(cè)。位置編碼Positional Encoding由于注意力本身對(duì)位置不敏感需要注入位置信息。經(jīng)典位置編碼使用固定的正弦-余弦函數(shù)其中 是序列位置 是通道維度索引。不同頻率的正弦、余弦組合使模型可以通過線性變換學(xué)習(xí)相對(duì)位置關(guān)系。也可用可學(xué)習(xí)的位置嵌入但正弦-余弦簡(jiǎn)單穩(wěn)定跨長(zhǎng)度泛化好??s放點(diǎn)積注意力Scaled Dot-Product Attention給定查詢向量 、鍵向量 、值向量 注意力本質(zhì)是用 與 的相似度對(duì) 加權(quán)求和的形狀通常是 是鍵向量維度。用于縮放避免點(diǎn)積過大導(dǎo)致梯度不穩(wěn)定。是可選的 mask如解碼器中的未來信息屏蔽把不該看的位置賦值為 。多頭注意力Multi-Head Attention不是只用一組 而是把通道分成多個(gè)子空間頭每個(gè)頭做一次注意力再把各頭結(jié)果拼接起來多頭像多個(gè)專家從不同子空間看問題增強(qiáng)表達(dá)能力。殘差連接與層歸一化每個(gè)子層都有殘差連接 層歸一化殘差幫助深層梯度流動(dòng)LayerNorm 穩(wěn)定訓(xùn)練。實(shí)現(xiàn)上可分Pre-Norm和Post-Norm現(xiàn)代實(shí)踐多用 Pre-Norm收斂更穩(wěn)。前饋網(wǎng)絡(luò)Position-wise FFN對(duì)每個(gè)位置獨(dú)立的兩層全連接網(wǎng)絡(luò)一般包含非線性激活ReLU/GELU或使用 GELU 激活效果更佳。編碼器與解碼器編碼器層自注意力 FFN。解碼器層自注意力帶未來信息屏蔽 交叉注意力看編碼器輸出 FFN。在序列預(yù)測(cè)如時(shí)間序列多步預(yù)測(cè)中常用教師強(qiáng)制即訓(xùn)練時(shí)把真實(shí)前綴喂給解碼器測(cè)試時(shí)自回歸生成。損失函數(shù)與優(yōu)化本文實(shí)戰(zhàn)使用多任務(wù)回歸預(yù)測(cè)未來值MSE分類輔助識(shí)別序列的生成類型正弦/方波/鋸齒波用交叉熵總損失優(yōu)化器AdamW學(xué)習(xí)率策略NoamTransformer 原版熱身策略其中 是步數(shù)。二、完整案例我們構(gòu)造一個(gè)數(shù)據(jù)集包含三種模式正弦、方波、鋸齒波長(zhǎng)度為 60 的歷史序列預(yù)測(cè)未來 20 個(gè)點(diǎn)同時(shí)預(yù)測(cè)該序列屬于哪一種生成模式輔助分類。模型小型 Encoder-Decoder Transformer數(shù)值輸入經(jīng)線性投影至 d_model并疊加正弦位置編碼。訓(xùn)練使用 AdamW Noam 學(xué)習(xí)率計(jì)劃損失 MSE λ·CE。import mathimport osimport randomfrom dataclasses import dataclassimport numpy as npimport torchimport torch.nn as nnfrom torch.utils.data import Dataset, DataLoaderfrom sklearn.manifold import TSNEimport matplotlib.pyplot as pltSEED 42random.seed(SEED)np.random.seed(SEED)torch.manual_seed(SEED)device torch.device(cudaif torch.cuda.is_available() elsecpu)# 數(shù)據(jù)集構(gòu)造def gen_sine(length, freq, amp, phase, noise_std0.05): t np.arange(length) y amp * np.sin(2 * np.pi * freq * t / length phase) y np.random.normal(0, noise_std, sizelength) return ydef gen_square(length, freq, amp, noise_std0.05): t np.arange(length) s np.sign(np.sin(2 * np.pi * freq * t / length)) y amp * s np.random.normal(0, noise_std, sizelength) return ydef gen_sawtooth(length, freq, amp, noise_std0.05): t np.arange(length) # sawtooth: 線性上升、驟降 frac (t * freq / length) % 1.0 y amp * (2 * frac - 1) y np.random.normal(0, noise_std, sizelength) return ydef gen_mixed_sequence(src_len60, tgt_len20): # 隨機(jī)選擇一種模式 mode np.random.choice([0, 1, 2]) # 0: sine, 1: square, 2: sawtooth amp np.random.uniform(0.5, 1.5) freq np.random.uniform(1.0, 6.0) phase np.random.uniform(0, np.pi) total_len src_len tgt_len if mode 0: seq gen_sine(total_len, freq, amp, phase, noise_std0.06) elif mode 1: seq gen_square(total_len, freq, amp, noise_std0.06) else: seq gen_sawtooth(total_len, freq, amp, noise_std0.06) # 疊加緩慢趨勢(shì)項(xiàng)增強(qiáng)難度 trend np.linspace(0, np.random.uniform(-0.5, 0.5), total_len) seq seq trend src seq[:src_len] tgt seq[src_len:] return src.astype(np.float32), tgt.astype(np.float32), modeclass TimeSeriesDataset(Dataset): def __init__(self, n_samples20000, src_len60, tgt_len20): self.src, self.tgt, self.mode [], [], [] for _ in range(n_samples): s, t, m gen_mixed_sequence(src_len, tgt_len) self.src.append(s) self.tgt.append(t) self.mode.append(m) self.src np.array(self.src) # [N, src_len] self.tgt np.array(self.tgt) # [N, tgt_len] self.mode np.array(self.mode) # [N] def __len__(self): return len(self.src) def __getitem__(self, idx): # 返回輸入序列、目標(biāo)序列、類別 return self.src[idx], self.tgt[idx], self.mode[idx]dataclassclass HParams: src_len: int 60 tgt_len: int 20 d_model: int 64 nhead: int 4 num_layers: int 2 dim_ff: int 128 dropout: float 0.1 cls_weight: float 0.2# 分類損失權(quán)重 batch_size: int 128 epochs: int 8 warmup_steps: int 400 lr: float 1.0# 初始lr將由Noam調(diào)節(jié) weight_decay: float 1e-4 grad_clip: float 1.0hp HParams()# 位置編碼class PositionalEncoding(nn.Module): def __init__(self, d_model, max_len1000): super().__init__() pe torch.zeros(max_len, d_model) position torch.arange(0, max_len).unsqueeze(1) div_term torch.exp( torch.arange(0, d_model, 2) * (-math.log(10000.0) / d_model) ) pe[:, 0::2] torch.sin(position.float() * div_term) pe[:, 1::2] torch.cos(position.float() * div_term) self.register_buffer(pe, pe.unsqueeze(0)) # [1, max_len, d_model] def forward(self, x): # x: [B, L, d_model] L x.size(1) return x self.pe[:, :L, :]# 自定義 Transformer暴露注意力權(quán)重class TransformerBlock(nn.Module): def __init__(self, d_model, nhead, dim_ff, dropout0.1): super().__init__() self.self_attn nn.MultiheadAttention(d_model, nhead, dropoutdropout, batch_firstTrue) self.linear1 nn.Linear(d_model, dim_ff) self.dropout nn.Dropout(dropout) self.linear2 nn.Linear(dim_ff, d_model) self.norm1 nn.LayerNorm(d_model) self.norm2 nn.LayerNorm(d_model) self.act nn.GELU() self.dropout1 nn.Dropout(dropout) self.dropout2 nn.Dropout(dropout) # 緩存注意力僅最后一次前向的 self.last_self_attn_weights None def forward(self, x, attn_maskNone, key_padding_maskNone): # Pre-Norm x_norm self.norm1(x) attn_out, attn_weights self.self_attn( x_norm, x_norm, x_norm, attn_maskattn_mask, key_padding_maskkey_padding_mask, need_weightsTrue, average_attn_weightsFalse# 返回 [B, num_heads, L, L] ) self.last_self_attn_weights attn_weights.detach() x x self.dropout1(attn_out) x_norm2 self.norm2(x) ff self.linear2(self.dropout(self.act(self.linear1(x_norm2)))) x x self.dropout2(ff) return xclass TransformerEncoder(nn.Module): def __init__(self, d_model, nhead, dim_ff, num_layers, dropout0.1): super().__init__() self.layers nn.ModuleList([ TransformerBlock(d_model, nhead, dim_ff, dropout) for _ in range(num_layers) ]) def forward(self, x, attn_maskNone, key_padding_maskNone): last_attn None for layer in self.layers: x layer(x, attn_maskattn_mask, key_padding_maskkey_padding_mask) last_attn layer.last_self_attn_weights return x, last_attn # 返回最后一層的注意力權(quán)重class TransformerDecoderBlock(nn.Module): def __init__(self, d_model, nhead, dim_ff, dropout0.1): super().__init__() self.self_attn nn.MultiheadAttention(d_model, nhead, dropoutdropout, batch_firstTrue) self.cross_attn nn.MultiheadAttention(d_model, nhead, dropoutdropout, batch_firstTrue) self.norm1 nn.LayerNorm(d_model) self.norm2 nn.LayerNorm(d_model) self.norm3 nn.LayerNorm(d_model) self.linear1 nn.Linear(d_model, dim_ff) self.linear2 nn.Linear(dim_ff, d_model) self.dropout nn.Dropout(dropout) self.dropout1 nn.Dropout(dropout) self.dropout2 nn.Dropout(dropout) self.dropout3 nn.Dropout(dropout) self.act nn.GELU() self.last_self_attn_weights None self.last_cross_attn_weights None def forward(self, x, mem, tgt_maskNone, tgt_key_padding_maskNone, mem_key_padding_maskNone): x_norm self.norm1(x) self_attn_out, self_attn_w self.self_attn( x_norm, x_norm, x_norm, attn_masktgt_mask, key_padding_masktgt_key_padding_mask, need_weightsTrue, average_attn_weightsFalse ) self.last_self_attn_weights self_attn_w.detach() x x self.dropout1(self_attn_out) x_norm2 self.norm2(x) cross_attn_out, cross_attn_w self.cross_attn( x_norm2, mem, mem, key_padding_maskmem_key_padding_mask, need_weightsTrue, average_attn_weightsFalse ) self.last_cross_attn_weights cross_attn_w.detach() x x self.dropout2(cross_attn_out) x_norm3 self.norm3(x) ff self.linear2(self.dropout(self.act(self.linear1(x_norm3)))) x x self.dropout3(ff) return xclass TransformerDecoder(nn.Module): def __init__(self, d_model, nhead, dim_ff, num_layers, dropout0.1): super().__init__() self.layers nn.ModuleList([ TransformerDecoderBlock(d_model, nhead, dim_ff, dropout) for _ in range(num_layers) ]) def forward(self, x, mem, tgt_maskNone, tgt_key_padding_maskNone, mem_key_padding_maskNone): last_self, last_cross None, None for layer in self.layers: x layer(x, mem, tgt_mask, tgt_key_padding_mask, mem_key_padding_mask) last_self layer.last_self_attn_weights last_cross layer.last_cross_attn_weights return x, last_self, last_crossclass TimeSeriesTransformer(nn.Module): def __init__(self, hp: HParams, n_classes3): super().__init__() self.hp hp self.src_proj nn.Linear(1, hp.d_model) self.tgt_proj nn.Linear(1, hp.d_model) self.pe PositionalEncoding(hp.d_model, max_len2000) self.encoder TransformerEncoder(hp.d_model, hp.nhead, hp.dim_ff, hp.num_layers, hp.dropout) self.decoder TransformerDecoder(hp.d_model, hp.nhead, hp.dim_ff, hp.num_layers, hp.dropout) self.out nn.Linear(hp.d_model, 1) # 預(yù)測(cè)數(shù)值 # 輔助分類頭對(duì) encoder 輸出進(jìn)行池化 self.cls_head nn.Sequential( nn.LayerNorm(hp.d_model), nn.Linear(hp.d_model, hp.d_model), nn.GELU(), nn.Linear(hp.d_model, n_classes) ) def generate_square_subsequent_mask(self, L): # 上三角為 -inf阻止看未來 mask torch.triu(torch.ones(L, L, devicedevice), diagonal1) mask mask.masked_fill(mask 1, float(-inf)) return mask def forward(self, src, tgt_in): # src: [B, src_len], tgt_in: [B, tgt_len]解碼器輸入訓(xùn)練時(shí)為已知前綴的真實(shí)值 B, S src.shape T tgt_in.shape[1] src src.unsqueeze(-1) # [B, S, 1] tgt_in tgt_in.unsqueeze(-1) # [B, T, 1] src self.src_proj(src) tgt self.tgt_proj(tgt_in) src self.pe(src) tgt self.pe(tgt) mem, enc_attn self.encoder(src) tgt_mask self.generate_square_subsequent_mask(T) dec_out, dec_self_attn, cross_attn self.decoder(tgt, mem, tgt_masktgt_mask) pred self.out(dec_out).squeeze(-1) # [B, T] # 分類對(duì) encoder 輸出做平均池化也可用 CLS token pooled mem.mean(dim1) # [B, d_model] logits self.cls_head(pooled) # [B, n_classes] # 暴露注意力權(quán)重便于可視化 self.last_enc_self_attn enc_attn # [B, H, S, S] self.last_dec_self_attn dec_self_attn # [B, H, T, T] self.last_cross_attn cross_attn # [B, H, T, S] return pred, logits# 訓(xùn)練工具class NoamLR: def __init__(self, optimizer, d_model, warmup_steps): self.optimizer optimizer self.d_model d_model self.warmup_steps warmup_steps self.step_num 0 self.lrs [] def step(self): self.step_num 1 lr (self.d_model ** -0.5) * min(self.step_num ** -0.5, self.step_num * (self.warmup_steps ** -1.5)) for pg in self.optimizer.param_groups: pg[lr] lr self.lrs.append(lr) def get_last_lr(self): return self.lrs[-1] if self.lrs else0.0def collate_fn(batch): # batch: list of (src, tgt, mode) src torch.tensor([b[0] for b in batch], dtypetorch.float32) tgt torch.tensor([b[1] for b in batch], dtypetorch.float32) mode torch.tensor([b[2] for b in batch], dtypetorch.long) return src, tgt, modedef train_one_epoch(model, loader, optimizer, scheduler, hp): model.train() mse_loss_fn nn.MSELoss() ce_loss_fn nn.CrossEntropyLoss() total_loss, total_mse, total_ce 0.0, 0.0, 0.0 for src, tgt, mode in loader: src, tgt, mode src.to(device), tgt.to(device), mode.to(device) # 教師強(qiáng)制tgt_in 右移一位的真實(shí)序列這里簡(jiǎn)化用全部真實(shí)序列做輸入預(yù)測(cè)對(duì)應(yīng)步 tgt_in torch.zeros_like(tgt) tgt_in[:, 1:] tgt[:, :-1] # 右移一位第一位為0或可用最后一個(gè)src的值 # 也可嘗試把第一位設(shè)為 src 的最后一個(gè)點(diǎn) tgt_in[:, 0] src[:, -1] pred, logits model(src, tgt_in) mse_loss mse_loss_fn(pred, tgt) ce_loss ce_loss_fn(logits, mode) loss mse_loss hp.cls_weight * ce_loss optimizer.zero_grad() loss.backward() torch.nn.utils.clip_grad_norm_(model.parameters(), hp.grad_clip) optimizer.step() scheduler.step() total_loss loss.item() * src.size(0) total_mse mse_loss.item() * src.size(0) total_ce ce_loss.item() * src.size(0) n len(loader.dataset) return total_loss / n, total_mse / n, total_ce / ntorch.no_grad()def evaluate(model, loader, hp): model.eval() mse_loss_fn nn.MSELoss() ce_loss_fn nn.CrossEntropyLoss() total_loss, total_mse, total_ce 0.0, 0.0, 0.0 correct, total 0, 0 for src, tgt, mode in loader: src, tgt, mode src.to(device), tgt.to(device), mode.to(device) # 驗(yàn)證也用教師強(qiáng)制方式 tgt_in torch.zeros_like(tgt) tgt_in[:, 1:] tgt[:, :-1] tgt_in[:, 0] src[:, -1] pred, logits model(src, tgt_in) mse_loss mse_loss_fn(pred, tgt) ce_loss ce_loss_fn(logits, mode) loss mse_loss hp.cls_weight * ce_loss total_loss loss.item() * src.size(0) total_mse mse_loss.item() * src.size(0) total_ce ce_loss.item() * src.size(0) preds_cls logits.argmax(dim-1) correct (preds_cls mode).sum().item() total mode.numel() n len(loader.dataset) return total_loss / n, total_mse / n, total_ce / n, correct / totaldef build_dataloaders(): # 較大虛擬數(shù)據(jù)集可根據(jù)硬件調(diào)參 train_set TimeSeriesDataset(n_samples18000, src_lenhp.src_len, tgt_lenhp.tgt_len) val_set TimeSeriesDataset(n_samples3000, src_lenhp.src_len, tgt_lenhp.tgt_len) test_set TimeSeriesDataset(n_samples3000, src_lenhp.src_len, tgt_lenhp.tgt_len) train_loader DataLoader(train_set, batch_sizehp.batch_size, shuffleTrue, num_workers0, collate_fncollate_fn) val_loader DataLoader(val_set, batch_sizehp.batch_size, shuffleFalse, num_workers0, collate_fncollate_fn) test_loader DataLoader(test_set, batch_sizehp.batch_size, shuffleFalse, num_workers0, collate_fncollate_fn) return train_loader, val_loader, test_loader# 主訓(xùn)練流程def main_train_and_analyze(): train_loader, val_loader, test_loader build_dataloaders() model TimeSeriesTransformer(hp).to(device) optimizer torch.optim.AdamW(model.parameters(), lrhp.lr, weight_decayhp.weight_decay) scheduler NoamLR(optimizer, d_modelhp.d_model, warmup_stepshp.warmup_steps) history {train_loss: [], val_loss: [], train_mse: [], val_mse: [], train_ce: [], val_ce: [], val_acc: [], lr: []} print(Start training...) global_step 0 for epoch in range(1, hp.epochs 1): tr_loss, tr_mse, tr_ce train_one_epoch(model, train_loader, optimizer, scheduler, hp) val_loss, val_mse, val_ce, val_acc evaluate(model, val_loader, hp) history[train_loss].append(tr_loss) history[val_loss].append(val_loss) history[train_mse].append(tr_mse) history[val_mse].append(val_mse) history[train_ce].append(tr_ce) history[val_ce].append(val_ce) history[val_acc].append(val_acc) history[lr].append(scheduler.get_last_lr()) print(fEpoch {epoch:02d}: ftrain_loss{tr_loss:.4f}, val_loss{val_loss:.4f}, ftrain_mse{tr_mse:.4f}, val_mse{val_mse:.4f}, ftrain_ce{tr_ce:.4f}, val_ce{val_ce:.4f}, val_acc{val_acc:.3f}, flr{scheduler.get_last_lr():.6f}) # 圖1訓(xùn)練/驗(yàn)證損失曲線線圖 plt.figure() epochs np.arange(1, hp.epochs 1) plt.plot(epochs, history[train_loss], markero, linewidth2.5, labelTrain Loss) plt.plot(epochs, history[val_loss], markers, linewidth2.5, labelVal Loss) plt.title(Training vs Validation Loss, fontsize14) plt.xlabel(Epoch) plt.ylabel(Loss) plt.legend() plt.grid(alpha0.3) plt.tight_layout() plt.show() # 圖2學(xué)習(xí)率隨步數(shù)變化線圖 plt.figure() # 展示 Noam 曲線history[lr] 是每個(gè) epoch 最后一步的lr另繪制scheduler.lrs為步級(jí)曲線 plt.plot(np.arange(1, len(scheduler.lrs) 1), scheduler.lrs, linewidth2.0, labelNoam LR per step) plt.title(Learning Rate Schedule (Noam), fontsize14) plt.xlabel(Training Step) plt.ylabel(LR) plt.legend() plt.grid(alpha0.3) plt.tight_layout() plt.show() # 用測(cè)試集做多角度可視化分析 # 抽取一個(gè)batch做注意力熱力圖 src_batch, tgt_batch, mode_batch next(iter(test_loader)) src_batch, tgt_batch src_batch.to(device), tgt_batch.to(device) # 驗(yàn)證/測(cè)試階段用教師強(qiáng)制來產(chǎn)生注意力權(quán)重也可改為自回歸采樣 tgt_in torch.zeros_like(tgt_batch) tgt_in[:, 1:] tgt_batch[:, :-1] tgt_in[:, 0] src_batch[:, -1] with torch.no_grad(): pred, logits model(src_batch, tgt_in) # 圖3編碼器自注意力熱力圖 # 選取第一條樣本、第一個(gè)頭 enc_attn model.last_enc_self_attn # [B, H, S, S] if enc_attn isnotNone: attn_map enc_attn[0, 0].detach().cpu().numpy() # [S, S] plt.figure() plt.imshow(attn_map, cmapmagma, aspectauto) plt.colorbar() plt.title(Encoder Self-Attention Heatmap (Head 1, Sample 1), fontsize13) plt.xlabel(Key Position) plt.ylabel(Query Position) plt.tight_layout() plt.show() # 圖4注意力相對(duì)距離分布 # 統(tǒng)計(jì) |i - j| 的加權(quán)分布聚合 batch 后按 head 展示 if enc_attn isnotNone: attn enc_attn.detach().cpu().numpy() # [B, H, S, S] B, H, S, _ attn.shape distances np.arange(S) head_distributions [] for h in range(H): # 聚合 batch 和 query 維度 w attn[:, h, :, :] # [B, S, S] # 計(jì)算距離權(quán)重 dist_weight np.zeros(S, dtypenp.float64) total 0.0 for i in range(S): for j in range(S): d abs(i - j) val w[:, i, j].sum() dist_weight[d] val total val dist_weight / (total 1e-8) head_distributions.append(dist_weight) # 繪制條形 平滑曲線 plt.figure() for h in range(H): color plt.rcParams[axes.prop_cycle].by_key()[color][h % 10] plt.plot(distances, head_distributions[h], -, linewidth2.5, labelfHead {h1}, colorcolor) # 添加點(diǎn)標(biāo)記 plt.scatter(distances, head_distributions[h], s12, colorcolor, alpha0.7) plt.title(Encoder Attention Distance Distribution by Head, fontsize13) plt.xlabel(Absolute Distance |i - j|) plt.ylabel(Weighted Probability) plt.legend() plt.grid(alpha0.3) plt.tight_layout() plt.show() # 圖5編碼器嵌入的 t-SNE 可視化 # 取測(cè)試集一部分樣本取 encoder 輸出做平均池化然后做 t-SNE顏色映射到類別 model.eval() embeds [] labels [] with torch.no_grad(): cnt 0 for src, tgt, mode in test_loader: src, tgt src.to(device), tgt.to(device) tgt_in torch.zeros_like(tgt) tgt_in[:, 1:] tgt[:, :-1] tgt_in[:, 0] src[:, -1] # 前向但我們只想拿編碼器表示 src_ model.src_proj(src.unsqueeze(-1)) src_ model.pe(src_) mem, _ model.encoder(src_) pooled mem.mean(dim1) # [B, d_model] embeds.append(pooled.cpu().numpy()) labels.append(mode.numpy()) cnt src.size(0) if cnt 2000: # 限制樣本數(shù)量t-SNE更快 break embeds np.concatenate(embeds, axis0) labels np.concatenate(labels, axis0) tsne TSNE(n_components2, learning_rateauto, initpca, perplexity30, random_stateSEED) emb2d tsne.fit_transform(embeds) plt.figure() colors [#FF1493, #00CED1, #FFA500] # 亮粉、青色、橙色 for c in [0, 1, 2]: idx labels c plt.scatter(emb2d[idx, 0], emb2d[idx, 1], s16, ccolors[c], alpha0.8, labelfClass {c}) plt.title(t-SNE of Encoder Pooled Embeddings, fontsize13) plt.xlabel(Dim 1) plt.ylabel(Dim 2) plt.legend() plt.grid(alpha0.2) plt.tight_layout() plt.show() # 圖6多步預(yù)測(cè)的誤差分布 # 在測(cè)試集上進(jìn)行一次前向并統(tǒng)計(jì)每個(gè)預(yù)測(cè)步的絕對(duì)誤差 abs_err_by_step [] with torch.no_grad(): for src, tgt, mode in test_loader: src, tgt src.to(device), tgt.to(device) tgt_in torch.zeros_like(tgt) tgt_in[:, 1:] tgt[:, :-1] tgt_in[:, 0] src[:, -1] pred, _ model(src, tgt_in) abs_err (pred - tgt).abs().cpu().numpy() # [B, T] abs_err_by_step.append(abs_err) abs_err_by_step np.concatenate(abs_err_by_step, axis0) # [N, T] # 繪制小提琴圖 plt.figure() parts plt.violinplot([abs_err_by_step[:, t] for t in range(hp.tgt_len)], showmeansTrue, showextremaFalse) # 調(diào)整顏色鮮艷 for pc in parts[bodies]: pc.set_facecolor(#1E90FF) pc.set_edgecolor(#FF4500) pc.set_alpha(0.6) ifcmeansin parts: parts[cmeans].set_color(#FF4500) parts[cmeans].set_linewidth(2.0) plt.title(Absolute Error Distribution per Forecast Horizon, fontsize13) plt.xlabel(Horizon Step) plt.ylabel(Absolute Error) plt.grid(alpha0.3) plt.tight_layout() plt.show() return historyif __name__ __main__: history main_train_and_analyze()訓(xùn)練/驗(yàn)證損失曲線觀察模型是否過擬合或欠擬合。兩條曲線在后期收斂并接近說明泛化尚可若驗(yàn)證損失大幅上升需加強(qiáng)正則或早停。學(xué)習(xí)率隨步數(shù)變化Noam 策略先升后降前期熱身避免過早陷入壞局部后期降低學(xué)習(xí)率穩(wěn)定收斂。曲線形狀與論文一致有助于穩(wěn)定訓(xùn)練。編碼器注意力熱力圖行表示 Query 位置列表示 Key 位置顏色越亮表示越關(guān)注??芍庇^看出模型在對(duì)某一時(shí)刻進(jìn)行編碼時(shí)更傾向于關(guān)注哪些歷史時(shí)刻。對(duì)于周期性序列可能出現(xiàn)對(duì)固定相位差位置的高關(guān)注。注意力相對(duì)距離分布橫軸是相對(duì)距離 |i-j|縱軸為按注意力概率加權(quán)后的分布。不同頭的分布形態(tài)可不同有的頭偏好短距離建模局部平滑/短期相關(guān)有的頭偏好較長(zhǎng)距離建模周期/長(zhǎng)期依賴這是多頭多視角的一個(gè)外在證據(jù)。t-SNE 編碼器嵌入二維可視化對(duì)編碼器輸出的平均池化向量做 t-SNE 可視化按生成模式著色。若不同顏色簇較明顯說明編碼器已學(xué)到區(qū)分不同動(dòng)力學(xué)模態(tài)的表征。多步預(yù)測(cè)誤差分布橫軸是預(yù)測(cè)步1 到 20 步縱軸是絕對(duì)誤差。通常越遠(yuǎn)的步誤差越大小提琴的形狀反映分布的離散程度??梢詭椭闩袛嗄P驮诙嗖筋A(yù)測(cè)上的退化速度與穩(wěn)定性。大家如果在后面想要擴(kuò)展的方向可以考慮如下的幾點(diǎn)增加解碼策略從教師強(qiáng)制改為自回歸生成或蒸餾scheduled sampling。引入更復(fù)雜的數(shù)據(jù)生成機(jī)制多頻率混合、突變點(diǎn)、異常注入評(píng)估魯棒性。模型層面加深層數(shù)/維度引入相對(duì)位置編碼、因果卷積、分塊注意力或 FlashAttention。評(píng)估指標(biāo)MAE、SMAPE、DTW距離等繪制校準(zhǔn)圖、殘差自相關(guān)圖。三、常見問題其實(shí)對(duì)于Transformer大家過去的一些問題進(jìn)行了簡(jiǎn)單整理大家結(jié)合上面的內(nèi)容進(jìn)一步理解問為什么要縮放點(diǎn)積注意力答點(diǎn)積隨著維度增大方差會(huì)變大未經(jīng)縮放的 softmax 可能進(jìn)入梯度飽和區(qū)訓(xùn)練不穩(wěn)定。除以 可顯著緩解。問多頭越多越好嗎答頭數(shù)多可增強(qiáng)表達(dá)但會(huì)增加計(jì)算和顯存且頭之間可能冗余。一般和 d_model 成比例比如 d_model64 用 4~8 頭較常見需調(diào)參。問位置編碼用正弦還是可學(xué)習(xí)的答正弦-余弦便宜且對(duì)超長(zhǎng)泛化友好可學(xué)習(xí)位置編碼在固定長(zhǎng)度范圍內(nèi)表現(xiàn)也好。對(duì)于時(shí)間序列許多實(shí)踐仍偏好正弦或選相對(duì)位置編碼T5/DeBERTa 風(fēng)格。問時(shí)間序列強(qiáng)因果的場(chǎng)景如何保證未來不泄漏答解碼器自注意力中使用未來屏蔽上三角置 -inf或在encoder-only場(chǎng)景用因果注意力。四、總結(jié)Transformer 的核心法術(shù)是注意力全局檢索 多頭多視角讓模型能并行學(xué)習(xí)長(zhǎng)依賴。通過位置編碼、殘差歸一化、前饋網(wǎng)絡(luò)、深層堆疊等模塊構(gòu)成了一個(gè)穩(wěn)定且強(qiáng)大的通用序列建模器。后面幾天的文章會(huì)圍繞更多關(guān)于Transformer的細(xì)節(jié)內(nèi)容給大家分享出來~五、如何系統(tǒng)的學(xué)習(xí)大模型 AI 由于新崗位的生產(chǎn)效率要優(yōu)于被取代崗位的生產(chǎn)效率所以實(shí)際上整個(gè)社會(huì)的生產(chǎn)效率是提升的。但是具體到個(gè)人只能說是“最先掌握AI的人將會(huì)比較晚掌握AI的人有競(jìng)爭(zhēng)優(yōu)勢(shì)”。這句話放在計(jì)算機(jī)、互聯(lián)網(wǎng)、移動(dòng)互聯(lián)網(wǎng)的開局時(shí)期都是一樣的道理。我在一線互聯(lián)網(wǎng)企業(yè)工作十余年里指導(dǎo)過不少同行后輩。幫助很多人得到了學(xué)習(xí)和成長(zhǎng)。我意識(shí)到有很多經(jīng)驗(yàn)和知識(shí)值得分享給大家也可以通過我們的能力和經(jīng)驗(yàn)解答大家在人工智能學(xué)習(xí)中的很多困惑所以在工作繁忙的情況下還是堅(jiān)持各種整理和分享。但苦于知識(shí)傳播途徑有限很多互聯(lián)網(wǎng)行業(yè)朋友無法獲得正確的資料得到學(xué)習(xí)提升故此將并將重要的AI大模型資料包括AI大模型入門學(xué)習(xí)思維導(dǎo)圖、精品AI大模型學(xué)習(xí)書籍手冊(cè)、視頻教程、實(shí)戰(zhàn)學(xué)習(xí)等錄播視頻免費(fèi)分享出來。一直在更新更多的大模型學(xué)習(xí)和面試資料已經(jīng)上傳帶到CSDN的官方了有需要的朋友可以掃描下方二維碼免費(fèi)領(lǐng)取【保證100%免費(fèi)】01.大模型風(fēng)口已至月薪30K的AI崗正在批量誕生2025年大模型應(yīng)用呈現(xiàn)爆發(fā)式增長(zhǎng)根據(jù)工信部最新數(shù)據(jù)國(guó)內(nèi)大模型相關(guān)崗位缺口達(dá)47萬初級(jí)工程師平均薪資28K數(shù)據(jù)來源BOSS直聘報(bào)告70%企業(yè)存在能用模型不會(huì)調(diào)優(yōu)的痛點(diǎn)真實(shí)案例某二本機(jī)械專業(yè)學(xué)員通過4個(gè)月系統(tǒng)學(xué)習(xí)成功拿到某AI醫(yī)療公司大模型優(yōu)化崗offer薪資直接翻3倍02.大模型 AI 學(xué)習(xí)和面試資料1?? 提示詞工程把ChatGPT從玩具變成生產(chǎn)工具2?? RAG系統(tǒng)讓大模型精準(zhǔn)輸出行業(yè)知識(shí)3?? 智能體開發(fā)用AutoGPT打造24小時(shí)數(shù)字員工熬了三個(gè)大夜整理的《AI進(jìn)化工具包》送你?? 大廠內(nèi)部LLM落地手冊(cè)含58個(gè)真實(shí)案例?? 提示詞設(shè)計(jì)模板庫(kù)覆蓋12大應(yīng)用場(chǎng)景?? 私藏學(xué)習(xí)路徑圖0基礎(chǔ)到項(xiàng)目實(shí)戰(zhàn)僅需90天第一階段10天初階應(yīng)用該階段讓大家對(duì)大模型 AI有一個(gè)最前沿的認(rèn)識(shí)對(duì)大模型 AI 的理解超過 95% 的人可以在相關(guān)討論時(shí)發(fā)表高級(jí)、不跟風(fēng)、又接地氣的見解別人只會(huì)和 AI 聊天而你能調(diào)教 AI并能用代碼將大模型和業(yè)務(wù)銜接。大模型 AI 能干什么大模型是怎樣獲得「智能」的用好 AI 的核心心法大模型應(yīng)用業(yè)務(wù)架構(gòu)大模型應(yīng)用技術(shù)架構(gòu)代碼示例向 GPT-3.5 灌入新知識(shí)提示工程的意義和核心思想Prompt 典型構(gòu)成指令調(diào)優(yōu)方法論思維鏈和思維樹Prompt 攻擊和防范…第二階段30天高階應(yīng)用該階段我們正式進(jìn)入大模型 AI 進(jìn)階實(shí)戰(zhàn)學(xué)習(xí)學(xué)會(huì)構(gòu)造私有知識(shí)庫(kù)擴(kuò)展 AI 的能力??焖匍_發(fā)一個(gè)完整的基于 agent 對(duì)話機(jī)器人。掌握功能最強(qiáng)的大模型開發(fā)框架抓住最新的技術(shù)進(jìn)展適合 Python 和 JavaScript 程序員。為什么要做 RAG搭建一個(gè)簡(jiǎn)單的 ChatPDF檢索的基礎(chǔ)概念什么是向量表示Embeddings向量數(shù)據(jù)庫(kù)與向量檢索基于向量檢索的 RAG搭建 RAG 系統(tǒng)的擴(kuò)展知識(shí)混合檢索與 RAG-Fusion 簡(jiǎn)介向量模型本地部署…第三階段30天模型訓(xùn)練恭喜你如果學(xué)到這里你基本可以找到一份大模型 AI相關(guān)的工作自己也能訓(xùn)練 GPT 了通過微調(diào)訓(xùn)練自己的垂直大模型能獨(dú)立訓(xùn)練開源多模態(tài)大模型掌握更多技術(shù)方案。到此為止大概2個(gè)月的時(shí)間。你已經(jīng)成為了一名“AI小子”。那么你還想往下探索嗎為什么要做 RAG什么是模型什么是模型訓(xùn)練求解器 損失函數(shù)簡(jiǎn)介小實(shí)驗(yàn)2手寫一個(gè)簡(jiǎn)單的神經(jīng)網(wǎng)絡(luò)并訓(xùn)練它什么是訓(xùn)練/預(yù)訓(xùn)練/微調(diào)/輕量化微調(diào)Transformer結(jié)構(gòu)簡(jiǎn)介輕量化微調(diào)實(shí)驗(yàn)數(shù)據(jù)集的構(gòu)建…第四階段20天商業(yè)閉環(huán)對(duì)全球大模型從性能、吞吐量、成本等方面有一定的認(rèn)知可以在云端和本地等多種環(huán)境下部署大模型找到適合自己的項(xiàng)目/創(chuàng)業(yè)方向做一名被 AI 武裝的產(chǎn)品經(jīng)理。硬件選型帶你了解全球大模型使用國(guó)產(chǎn)大模型服務(wù)搭建 OpenAI 代理熱身基于阿里云 PAI 部署 Stable Diffusion在本地計(jì)算機(jī)運(yùn)行大模型大模型的私有化部署基于 vLLM 部署大模型案例如何優(yōu)雅地在阿里云私有部署開源大模型部署一套開源 LLM 項(xiàng)目?jī)?nèi)容安全互聯(lián)網(wǎng)信息服務(wù)算法備案…學(xué)習(xí)是一個(gè)過程只要學(xué)習(xí)就會(huì)有挑戰(zhàn)。天道酬勤你越努力就會(huì)成為越優(yōu)秀的自己。如果你能在15天內(nèi)完成所有的任務(wù)那你堪稱天才。然而如果你能完成 60-70% 的內(nèi)容你就已經(jīng)開始具備成為一名大模型 AI 的正確特征了。這份完整版的大模型 AI 學(xué)習(xí)資料已經(jīng)上傳CSDN朋友們?nèi)绻枰梢晕⑿艗呙柘路紺SDN官方認(rèn)證二維碼免費(fèi)領(lǐng)取【保證100%免費(fèi)】