中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁 > news >正文

網(wǎng)站建設(shè)有免費(fèi)的空間嗎網(wǎng)絡(luò)優(yōu)化的內(nèi)容包括哪些

網(wǎng)站建設(shè)有免費(fèi)的空間嗎,網(wǎng)絡(luò)優(yōu)化的內(nèi)容包括哪些,wordpress用戶角色插件,今日陜西疫情最新消息一.什么是注意力 注意力機(jī)制是一種讓模型學(xué)會(huì)「選擇性關(guān)注重要信息」的特征提取器,就像人類視覺會(huì)自動(dòng)忽略背景,聚焦于圖片中的主體(如貓、汽車) transformer中的叫做自注意力機(jī)制,他是一種自己學(xué)習(xí)自己的機(jī)制&#x…

一.什么是注意力

注意力機(jī)制是一種讓模型學(xué)會(huì)「選擇性關(guān)注重要信息」的特征提取器,就像人類視覺會(huì)自動(dòng)忽略背景,聚焦于圖片中的主體(如貓、汽車)
transformer中的叫做自注意力機(jī)制,他是一種自己學(xué)習(xí)自己的機(jī)制,他可以自動(dòng)學(xué)習(xí)到圖片中的主體,并忽略背景。我們現(xiàn)在說的很多模塊,比如通道注意力、空間注意力、通道注意力等等,都是基于自注意力機(jī)制的

從數(shù)學(xué)角度看,注意力機(jī)制是對(duì)輸入特征進(jìn)行加權(quán)求和,輸出=∑(輸入特征×注意力權(quán)重),其中注意力權(quán)重是學(xué)習(xí)到的。所以他和卷積很像,因?yàn)榫矸e也是一種加權(quán)求和。但是卷積是 “固定權(quán)重” 的特征提取(如 3x3 卷積核)

之所以需要多種注意力模塊是因?yàn)椴煌瑘?chǎng)景下的關(guān)鍵信息分布不同。例如,識(shí)別鳥類和飛機(jī)時(shí),需關(guān)注 “羽毛紋理”“金屬光澤” 等特定通道的特征,通道注意力可強(qiáng)化關(guān)鍵通道;而物體位置不確定時(shí)(如貓出現(xiàn)在圖像不同位置),空間注意力能聚焦物體所在區(qū)域,忽略背景。復(fù)雜場(chǎng)景中,可能需要同時(shí)關(guān)注通道和空間(如混合注意力模塊 CBAM),或處理長距離依賴(如全局注意力模塊 Non-local)

此外之所以不設(shè)計(jì)一個(gè)“萬能”注意力模塊是因?yàn)橹饕苄屎挽`活性限制。專用模塊針對(duì)特定需求優(yōu)化計(jì)算,成本更低(如通道注意力僅需處理通道維度,無需全局位置計(jì)算);不同任務(wù)的核心需求差異大(如醫(yī)學(xué)圖像側(cè)重空間定位,自然語言處理側(cè)重語義長距離依賴),通用模塊可能冗余或低效。每個(gè)模塊新增的權(quán)重會(huì)增加模型參數(shù)量,若訓(xùn)練數(shù)據(jù)不足或優(yōu)化不當(dāng),可能引發(fā)過擬合。因此實(shí)際應(yīng)用中需結(jié)合輕量化設(shè)計(jì)(如減少全連接層參數(shù))、正則化(如 Dropout)或結(jié)構(gòu)約束(如共享注意力權(quán)重)來平衡性能與復(fù)雜度

通道注意力(Channel Attention)屬于注意力機(jī)制(Attention Mechanism)的變體,而非自注意力(Self-Attention)的直接變體??梢岳斫鉃樽⒁饬κ且粋€(gè)動(dòng)物園算法,里面很多個(gè)物種,自注意力只是一個(gè)分支,因?yàn)殚_創(chuàng)了transformer所以備受矚目。我們今天的內(nèi)容用通道注意力舉例

常見注意力模塊的歸類:

注意力模塊所屬類別核心功能
自注意力(Self-Attention)自注意力變體建模同一輸入內(nèi)部元素的依賴(如序列位置、圖像塊)
通道注意力(Channel Attention)普通注意力變體(全局上下文)建模特征圖通道間的重要性,通過全局池化壓縮空間信息
空間注意力(Spatial Attention)普通注意力變體(全局上下文)建模特征圖空間位置的重要性,關(guān)注 “哪里” 更重要
多頭注意力(Multi-Head Attention)自注意力 / 普通注意力的增強(qiáng)版將 query/key/value 投影到多個(gè)子空間,捕捉多維度依賴
編碼器 - 解碼器注意力(Encoder-Decoder Attention)普通注意力變體建模編碼器輸出與解碼器輸入的跨模態(tài)交互(如機(jī)器翻譯中句子與譯文的對(duì)齊)

二.特征圖的提取

2.1 簡單CNN的訓(xùn)練

import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms
from torch.utils.data import DataLoader
import matplotlib.pyplot as plt
import numpy as np# 設(shè)置中文字體支持
plt.rcParams["font.family"] = ["SimHei"]
plt.rcParams['axes.unicode_minus'] = False  # 解決負(fù)號(hào)顯示問題# 檢查GPU是否可用
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
print(f"使用設(shè)備: {device}")# 1. 數(shù)據(jù)預(yù)處理
# 訓(xùn)練集:使用多種數(shù)據(jù)增強(qiáng)方法提高模型泛化能力
train_transform = transforms.Compose([# 隨機(jī)裁剪圖像,從原圖中隨機(jī)截取32x32大小的區(qū)域transforms.RandomCrop(32, padding=4),# 隨機(jī)水平翻轉(zhuǎn)圖像(概率0.5)transforms.RandomHorizontalFlip(),# 隨機(jī)顏色抖動(dòng):亮度、對(duì)比度、飽和度和色調(diào)隨機(jī)變化transforms.ColorJitter(brightness=0.2, contrast=0.2, saturation=0.2, hue=0.1),# 隨機(jī)旋轉(zhuǎn)圖像(最大角度15度)transforms.RandomRotation(15),# 將PIL圖像或numpy數(shù)組轉(zhuǎn)換為張量transforms.ToTensor(),# 標(biāo)準(zhǔn)化處理:每個(gè)通道的均值和標(biāo)準(zhǔn)差,使數(shù)據(jù)分布更合理transforms.Normalize((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010))
])# 測(cè)試集:僅進(jìn)行必要的標(biāo)準(zhǔn)化,保持?jǐn)?shù)據(jù)原始特性,標(biāo)準(zhǔn)化不損失數(shù)據(jù)信息,可還原
test_transform = transforms.Compose([transforms.ToTensor(),transforms.Normalize((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010))
])# 2. 加載CIFAR-10數(shù)據(jù)集
train_dataset = datasets.CIFAR10(root='./data',train=True,download=True,transform=train_transform  # 使用增強(qiáng)后的預(yù)處理
)test_dataset = datasets.CIFAR10(root='./data',train=False,transform=test_transform  # 測(cè)試集不使用增強(qiáng)
)# 3. 創(chuàng)建數(shù)據(jù)加載器
batch_size = 64
train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False)
# 4. 定義CNN模型的定義(替代原MLP)
class CNN(nn.Module):def __init__(self):super(CNN, self).__init__()  # 繼承父類初始化# ---------------------- 第一個(gè)卷積塊 ----------------------# 卷積層1:輸入3通道(RGB),輸出32個(gè)特征圖,卷積核3x3,邊緣填充1像素self.conv1 = nn.Conv2d(in_channels=3,       # 輸入通道數(shù)(圖像的RGB通道)out_channels=32,     # 輸出通道數(shù)(生成32個(gè)新特征圖)kernel_size=3,       # 卷積核尺寸(3x3像素)padding=1            # 邊緣填充1像素,保持輸出尺寸與輸入相同)# 批量歸一化層:對(duì)32個(gè)輸出通道進(jìn)行歸一化,加速訓(xùn)練self.bn1 = nn.BatchNorm2d(num_features=32)# ReLU激活函數(shù):引入非線性,公式:max(0, x)self.relu1 = nn.ReLU()# 最大池化層:窗口2x2,步長2,特征圖尺寸減半(32x32→16x16)self.pool1 = nn.MaxPool2d(kernel_size=2, stride=2)  # stride默認(rèn)等于kernel_size# ---------------------- 第二個(gè)卷積塊 ----------------------# 卷積層2:輸入32通道(來自conv1的輸出),輸出64通道self.conv2 = nn.Conv2d(in_channels=32,      # 輸入通道數(shù)(前一層的輸出通道數(shù))out_channels=64,     # 輸出通道數(shù)(特征圖數(shù)量翻倍)kernel_size=3,       # 卷積核尺寸不變padding=1            # 保持尺寸:16x16→16x16(卷積后)→8x8(池化后))self.bn2 = nn.BatchNorm2d(num_features=64)self.relu2 = nn.ReLU()self.pool2 = nn.MaxPool2d(kernel_size=2)  # 尺寸減半:16x16→8x8# ---------------------- 第三個(gè)卷積塊 ----------------------# 卷積層3:輸入64通道,輸出128通道self.conv3 = nn.Conv2d(in_channels=64,      # 輸入通道數(shù)(前一層的輸出通道數(shù))out_channels=128,    # 輸出通道數(shù)(特征圖數(shù)量再次翻倍)kernel_size=3,padding=1            # 保持尺寸:8x8→8x8(卷積后)→4x4(池化后))self.bn3 = nn.BatchNorm2d(num_features=128)self.relu3 = nn.ReLU()  # 復(fù)用激活函數(shù)對(duì)象(節(jié)省內(nèi)存)self.pool3 = nn.MaxPool2d(kernel_size=2)  # 尺寸減半:8x8→4x4# ---------------------- 全連接層(分類器) ----------------------# 計(jì)算展平后的特征維度:128通道 × 4x4尺寸 = 128×16=2048維self.fc1 = nn.Linear(in_features=128 * 4 * 4,  # 輸入維度(卷積層輸出的特征數(shù))out_features=512          # 輸出維度(隱藏層神經(jīng)元數(shù)))# Dropout層:訓(xùn)練時(shí)隨機(jī)丟棄50%神經(jīng)元,防止過擬合self.dropout = nn.Dropout(p=0.5)# 輸出層:將512維特征映射到10個(gè)類別(CIFAR-10的類別數(shù))self.fc2 = nn.Linear(in_features=512, out_features=10)def forward(self, x):# 輸入尺寸:[batch_size, 3, 32, 32](batch_size=批量大小,3=通道數(shù),32x32=圖像尺寸)# ---------- 卷積塊1處理 ----------x = self.conv1(x)       # 卷積后尺寸:[batch_size, 32, 32, 32](padding=1保持尺寸)x = self.bn1(x)         # 批量歸一化,不改變尺寸x = self.relu1(x)       # 激活函數(shù),不改變尺寸x = self.pool1(x)       # 池化后尺寸:[batch_size, 32, 16, 16](32→16是因?yàn)槌鼗翱?x2)# ---------- 卷積塊2處理 ----------x = self.conv2(x)       # 卷積后尺寸:[batch_size, 64, 16, 16](padding=1保持尺寸)x = self.bn2(x)x = self.relu2(x)x = self.pool2(x)       # 池化后尺寸:[batch_size, 64, 8, 8]# ---------- 卷積塊3處理 ----------x = self.conv3(x)       # 卷積后尺寸:[batch_size, 128, 8, 8](padding=1保持尺寸)x = self.bn3(x)x = self.relu3(x)x = self.pool3(x)       # 池化后尺寸:[batch_size, 128, 4, 4]# ---------- 展平與全連接層 ----------# 將多維特征圖展平為一維向量:[batch_size, 128*4*4] = [batch_size, 2048]x = x.view(-1, 128 * 4 * 4)  # -1自動(dòng)計(jì)算批量維度,保持批量大小不變x = self.fc1(x)           # 全連接層:2048→512,尺寸變?yōu)閇batch_size, 512]x = self.relu3(x)         # 激活函數(shù)(復(fù)用relu3,與卷積塊3共用)x = self.dropout(x)       # Dropout隨機(jī)丟棄神經(jīng)元,不改變尺寸x = self.fc2(x)           # 全連接層:512→10,尺寸變?yōu)閇batch_size, 10](未激活,直接輸出logits)return x  # 輸出未經(jīng)過Softmax的logits,適用于交叉熵?fù)p失函數(shù)# 初始化模型
model = CNN()
model = model.to(device)  # 將模型移至GPU(如果可用)criterion = nn.CrossEntropyLoss()  # 交叉熵?fù)p失函數(shù)
optimizer = optim.Adam(model.parameters(), lr=0.001)  # Adam優(yōu)化器# 引入學(xué)習(xí)率調(diào)度器,在訓(xùn)練過程中動(dòng)態(tài)調(diào)整學(xué)習(xí)率--訓(xùn)練初期使用較大的 LR 快速降低損失,訓(xùn)練后期使用較小的 LR 更精細(xì)地逼近全局最優(yōu)解。
# 在每個(gè) epoch 結(jié)束后,需要手動(dòng)調(diào)用調(diào)度器來更新學(xué)習(xí)率,可以在訓(xùn)練過程中調(diào)用 scheduler.step()
scheduler = optim.lr_scheduler.ReduceLROnPlateau(optimizer,        # 指定要控制的優(yōu)化器(這里是Adam)mode='min',       # 監(jiān)測(cè)的指標(biāo)是"最小化"(如損失函數(shù))patience=3,       # 如果連續(xù)3個(gè)epoch指標(biāo)沒有改善,才降低LRfactor=0.5        # 降低LR的比例(新LR = 舊LR × 0.5)
)
# 5. 訓(xùn)練模型(記錄每個(gè) iteration 的損失)
def train(model, train_loader, test_loader, criterion, optimizer, scheduler, device, epochs):model.train()  # 設(shè)置為訓(xùn)練模式# 記錄每個(gè) iteration 的損失all_iter_losses = []  # 存儲(chǔ)所有 batch 的損失iter_indices = []     # 存儲(chǔ) iteration 序號(hào)# 記錄每個(gè) epoch 的準(zhǔn)確率和損失train_acc_history = []test_acc_history = []train_loss_history = []test_loss_history = []for epoch in range(epochs):running_loss = 0.0correct = 0total = 0for batch_idx, (data, target) in enumerate(train_loader):data, target = data.to(device), target.to(device)  # 移至GPUoptimizer.zero_grad()  # 梯度清零output = model(data)  # 前向傳播loss = criterion(output, target)  # 計(jì)算損失loss.backward()  # 反向傳播optimizer.step()  # 更新參數(shù)# 記錄當(dāng)前 iteration 的損失iter_loss = loss.item()all_iter_losses.append(iter_loss)iter_indices.append(epoch * len(train_loader) + batch_idx + 1)# 統(tǒng)計(jì)準(zhǔn)確率和損失running_loss += iter_loss_, predicted = output.max(1)total += target.size(0)correct += predicted.eq(target).sum().item()# 每100個(gè)批次打印一次訓(xùn)練信息if (batch_idx + 1) % 100 == 0:print(f'Epoch: {epoch+1}/{epochs} | Batch: {batch_idx+1}/{len(train_loader)} 'f'| 單Batch損失: {iter_loss:.4f} | 累計(jì)平均損失: {running_loss/(batch_idx+1):.4f}')# 計(jì)算當(dāng)前epoch的平均訓(xùn)練損失和準(zhǔn)確率epoch_train_loss = running_loss / len(train_loader)epoch_train_acc = 100. * correct / totaltrain_acc_history.append(epoch_train_acc)train_loss_history.append(epoch_train_loss)# 測(cè)試階段model.eval()  # 設(shè)置為評(píng)估模式test_loss = 0correct_test = 0total_test = 0with torch.no_grad():for data, target in test_loader:data, target = data.to(device), target.to(device)output = model(data)test_loss += criterion(output, target).item()_, predicted = output.max(1)total_test += target.size(0)correct_test += predicted.eq(target).sum().item()epoch_test_loss = test_loss / len(test_loader)epoch_test_acc = 100. * correct_test / total_testtest_acc_history.append(epoch_test_acc)test_loss_history.append(epoch_test_loss)# 更新學(xué)習(xí)率調(diào)度器scheduler.step(epoch_test_loss)print(f'Epoch {epoch+1}/{epochs} 完成 | 訓(xùn)練準(zhǔn)確率: {epoch_train_acc:.2f}% | 測(cè)試準(zhǔn)確率: {epoch_test_acc:.2f}%')# 繪制所有 iteration 的損失曲線plot_iter_losses(all_iter_losses, iter_indices)# 繪制每個(gè) epoch 的準(zhǔn)確率和損失曲線plot_epoch_metrics(train_acc_history, test_acc_history, train_loss_history, test_loss_history)return epoch_test_acc  # 返回最終測(cè)試準(zhǔn)確率# 6. 繪制每個(gè) iteration 的損失曲線
def plot_iter_losses(losses, indices):plt.figure(figsize=(10, 4))plt.plot(indices, losses, 'b-', alpha=0.7, label='Iteration Loss')plt.xlabel('Iteration(Batch序號(hào))')plt.ylabel('損失值')plt.title('每個(gè) Iteration 的訓(xùn)練損失')plt.legend()plt.grid(True)plt.tight_layout()plt.show()# 7. 繪制每個(gè) epoch 的準(zhǔn)確率和損失曲線
def plot_epoch_metrics(train_acc, test_acc, train_loss, test_loss):epochs = range(1, len(train_acc) + 1)plt.figure(figsize=(12, 4))# 繪制準(zhǔn)確率曲線plt.subplot(1, 2, 1)plt.plot(epochs, train_acc, 'b-', label='訓(xùn)練準(zhǔn)確率')plt.plot(epochs, test_acc, 'r-', label='測(cè)試準(zhǔn)確率')plt.xlabel('Epoch')plt.ylabel('準(zhǔn)確率 (%)')plt.title('訓(xùn)練和測(cè)試準(zhǔn)確率')plt.legend()plt.grid(True)# 繪制損失曲線plt.subplot(1, 2, 2)plt.plot(epochs, train_loss, 'b-', label='訓(xùn)練損失')plt.plot(epochs, test_loss, 'r-', label='測(cè)試損失')plt.xlabel('Epoch')plt.ylabel('損失值')plt.title('訓(xùn)練和測(cè)試損失')plt.legend()plt.grid(True)plt.tight_layout()plt.show()# 8. 執(zhí)行訓(xùn)練和測(cè)試
epochs = 50  # 增加訓(xùn)練輪次為了確保收斂
print("開始使用CNN訓(xùn)練模型...")
final_accuracy = train(model, train_loader, test_loader, criterion, optimizer, scheduler, device, epochs)
print(f"訓(xùn)練完成!最終測(cè)試準(zhǔn)確率: {final_accuracy:.2f}%")# # 保存模型
# torch.save(model.state_dict(), 'cifar10_cnn_model.pth')
# print("模型已保存為: cifar10_cnn_model.pth")

2.2 特征圖可視化

特征圖本質(zhì)就是不同的卷積核的輸出,淺層指的是離輸入圖近的卷積層,淺層卷積層的特征圖通常較大,而深層特征圖會(huì)經(jīng)過多次下采樣,尺寸顯著縮小,尺寸差異過大時(shí),小尺寸特征圖在視覺上會(huì)顯得模糊或丟失細(xì)節(jié)。步驟邏輯如下:

1.初始化設(shè)置:
將模型設(shè)為評(píng)估模式,準(zhǔn)備類別名稱列表(如飛機(jī)、汽車等)

2.數(shù)據(jù)加載與處理:
從測(cè)試數(shù)據(jù)加載器中獲取圖像和標(biāo)簽
僅處理前 `num_images` 張圖像(如2張)

3.注冊(cè)鉤子捕獲特征圖:
為指定層(如 `conv1`, `conv2`, `conv3`)注冊(cè)前向鉤子
鉤子函數(shù)將這些層的輸出(特征圖)保存到字典中

4.前向傳播與特征提取:
模型處理圖像,觸發(fā)鉤子函數(shù),獲取并保存特征圖
移除鉤子,避免后續(xù)干擾

5.可視化特征圖:
對(duì)每張圖像:

  • 恢復(fù)原始像素值并顯示
  • 為每個(gè)目標(biāo)層創(chuàng)建子圖,展示前 `num_channels` 個(gè)通道的特征圖(如9個(gè)通道)
  • 每個(gè)通道的特征圖以網(wǎng)格形式排列,顯示通道編號(hào)

關(guān)鍵細(xì)節(jié):
特征圖布局:原始圖像在左側(cè),各層特征圖按順序排列在右側(cè)
通道選擇:默認(rèn)顯示前9個(gè)通道(按重要性或索引排序)
顯示優(yōu)化:

  • 使用 `inset_axes` 在大圖中嵌入小網(wǎng)格,清晰展示每個(gè)通道
  • 層標(biāo)題與通道標(biāo)題分開,避免重疊
  • 反標(biāo)準(zhǔn)化處理恢復(fù)圖像原始色彩
def visualize_feature_maps(model, test_loader, device, layer_names, num_images=3, num_channels=9):"""可視化指定層的特征圖(修復(fù)循環(huán)冗余問題)參數(shù):model: 模型test_loader: 測(cè)試數(shù)據(jù)加載器layer_names: 要可視化的層名稱(如['conv1', 'conv2', 'conv3'])num_images: 可視化的圖像總數(shù)num_channels: 每個(gè)圖像顯示的通道數(shù)(取前num_channels個(gè)通道)"""model.eval()  # 設(shè)置為評(píng)估模式class_names = [    '飛機(jī)', '汽車', '鳥', '貓', '鹿', '狗', '青蛙', '馬', '船', '卡車']# 從測(cè)試集加載器中提取指定數(shù)量的圖像(避免嵌套循環(huán))images_list, labels_list = [], []for images, labels in test_loader:images_list.append(images)labels_list.append(labels)if len(images_list) * test_loader.batch_size >= num_images:break# 拼接并截取到目標(biāo)數(shù)量images = torch.cat(images_list, dim=0)[:num_images].to(device)labels = torch.cat(labels_list, dim=0)[:num_images].to(device)with torch.no_grad():# 存儲(chǔ)各層特征圖feature_maps = {}# 保存鉤子句柄hooks = []# 定義鉤子函數(shù),捕獲指定層的輸出def hook(module, input, output, name):feature_maps[name] = output.cpu()  # 保存特征圖到字典# 為每個(gè)目標(biāo)層注冊(cè)鉤子,并保存鉤子句柄for name in layer_names:module = getattr(model, name)hook_handle = module.register_forward_hook(lambda m, i, o, n=name: hook(m, i, o, n))hooks.append(hook_handle)# 前向傳播觸發(fā)鉤子_ = model(images)# 正確移除鉤子for hook_handle in hooks:hook_handle.remove()# 可視化每個(gè)圖像的各層特征圖(僅一層循環(huán))for img_idx in range(num_images):img = images[img_idx].cpu().permute(1, 2, 0).numpy()# 反標(biāo)準(zhǔn)化處理(恢復(fù)原始像素值)img = img * np.array([0.2023, 0.1994, 0.2010]).reshape(1, 1, 3) + np.array([0.4914, 0.4822, 0.4465]).reshape(1, 1, 3)img = np.clip(img, 0, 1)  # 確保像素值在[0,1]范圍內(nèi)# 創(chuàng)建子圖num_layers = len(layer_names)fig, axes = plt.subplots(1, num_layers + 1, figsize=(4 * (num_layers + 1), 4))# 顯示原始圖像axes[0].imshow(img)axes[0].set_title(f'原始圖像\n類別: {class_names[labels[img_idx]]}')axes[0].axis('off')# 顯示各層特征圖for layer_idx, layer_name in enumerate(layer_names):fm = feature_maps[layer_name][img_idx]  # 取第img_idx張圖像的特征圖fm = fm[:num_channels]  # 僅取前num_channels個(gè)通道num_rows = int(np.sqrt(num_channels))num_cols = num_channels // num_rows if num_rows != 0 else 1# 創(chuàng)建子圖網(wǎng)格layer_ax = axes[layer_idx + 1]layer_ax.set_title(f'{layer_name}特征圖 \n')# 加個(gè)換行讓文字分離上去layer_ax.axis('off')  # 關(guān)閉大子圖的坐標(biāo)軸# 在大子圖內(nèi)創(chuàng)建小網(wǎng)格for ch_idx, channel in enumerate(fm):ax = layer_ax.inset_axes([ch_idx % num_cols / num_cols, (num_rows - 1 - ch_idx // num_cols) / num_rows, 1/num_cols, 1/num_rows])ax.imshow(channel.numpy(), cmap='viridis')ax.set_title(f'通道 {ch_idx + 1}')ax.axis('off')plt.tight_layout()plt.show()# 調(diào)用示例(按需修改參數(shù))
layer_names = ['conv1', 'conv2', 'conv3']
visualize_feature_maps(model=model,test_loader=test_loader,device=device,layer_names=layer_names,num_images=5,  # 可視化5張測(cè)試圖像 → 輸出5張大圖num_channels=9   # 每張圖像顯示前9個(gè)通道的特征圖
)

上面的圖為提取CNN不同卷積層輸出的特征圖,我們以第五張圖片-青蛙 進(jìn)行解讀
由于經(jīng)過了不斷的下采樣,特征變得越來越抽象,人類已經(jīng)無法理解

?核心作用 通過可視化特征圖,可直觀觀察:

  • 淺層卷積層(如 `conv1`)如何捕獲邊緣、紋理等低級(jí)特征
  • 深層卷積層(如 `conv3`)如何組合低級(jí)特征形成語義概念(如物體部件)
  • 模型對(duì)不同類別的關(guān)注區(qū)域差異(如鳥類的羽毛紋理 vs. 飛機(jī)的金屬光澤)
conv1特征圖(淺層卷積)
特點(diǎn):
  • 保留較多原始圖像的細(xì)節(jié)紋理(如植物葉片、青蛙身體的邊緣輪廓)
  • 通道間差異相對(duì)小,每個(gè)通道都能看到類似原始圖像的基礎(chǔ)結(jié)構(gòu)(如通道 1 - 9 都能識(shí)別邊緣、紋理)
意義:
  • 提取低級(jí)特征(邊緣、顏色塊、簡單紋理),是后續(xù)高層特征的“原材料”
  • 類似人眼初步識(shí)別圖像的輪廓和基礎(chǔ)結(jié)構(gòu)
conv2特征圖(中層卷積)
特點(diǎn):
  • 空間尺寸(高、寬)比 conv1 更小(因卷積/池化下采樣),但語義信息更抽象
  • 通道間差異更明顯:部分通道開始聚焦局部關(guān)鍵特征(如通道 5、8 中黃色高亮區(qū)域,可能對(duì)應(yīng)青蛙身體或植物的關(guān)鍵紋理)
意義:
  • 對(duì) conv1 的低級(jí)特征進(jìn)行組合與篩選,提取**中級(jí)特征**(如局部形狀、紋理組合)
  • 類似人眼從“邊緣輪廓”過渡到“識(shí)別局部結(jié)構(gòu)”(如青蛙的身體塊、植物的葉片簇)
conv3特征圖(深層卷積)
特點(diǎn):
  • 空間尺寸進(jìn)一步縮小,抽象程度最高,肉眼難直接對(duì)應(yīng)原始圖像細(xì)節(jié)
  • 通道間差異極大,部分通道聚焦全局語義特征(如通道 4、7 中黃色區(qū)域,可能對(duì)應(yīng)模型判斷“青蛙”類別的關(guān)鍵特征)

意義:

  • 對(duì) conv2 的中級(jí)特征進(jìn)行全局整合,提取高級(jí)語義特征(如物體類別相關(guān)的抽象模式)
  • 類似人眼最終“識(shí)別出這是青蛙”的關(guān)鍵依據(jù),模型通過這些特征判斷類別
逐層對(duì)比總結(jié)
層級(jí)特征圖特點(diǎn)對(duì)應(yīng)模型能力類比人類視覺流程
原始圖像細(xì)節(jié)豐富但無抽象語義無(純輸入)視網(wǎng)膜接收原始光信號(hào)
conv1保留基礎(chǔ)細(xì)節(jié),提取低級(jí)特征識(shí)別邊緣、紋理視覺皮層初步解析輪廓
conv2抽象化,提取局部關(guān)鍵特征識(shí)別局部結(jié)構(gòu)(如身體塊、葉片簇)大腦進(jìn)一步組合特征識(shí)別局部模式
conv3高度抽象,聚焦全局語義特征識(shí)別類別相關(guān)核心模式大腦最終整合信息判斷 “這是青蛙”
  • 特征逐層抽象:從“看得見的細(xì)節(jié)”(conv1)→ “局部結(jié)構(gòu)”(conv2)→ “類別相關(guān)的抽象模式”(conv3),模型通過這種方式實(shí)現(xiàn)從“看圖像”到“理解語義”的跨越
  • 通道分工明確:不同通道在各層聚焦不同特征(如有的通道負(fù)責(zé)邊緣,有的負(fù)責(zé)顏色,有的負(fù)責(zé)全局語義),共同協(xié)作完成分類任務(wù)
  • 下采樣的作用:通過縮小空間尺寸,換取更高的語義抽象能力(“犧牲細(xì)節(jié),換取理解”)

三.通道注意力

現(xiàn)在我們引入通道注意力,來觀察精度是否有變化,并且進(jìn)一步可視化想要把通道注意力插入到模型中,關(guān)鍵步驟如下:
1. 定義注意力模塊
2. 重寫之前的模型定義部分,確定好模塊插入的位置

# ===================== 新增:通道注意力模塊(SE模塊) =====================
class ChannelAttention(nn.Module):"""通道注意力模塊(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_ratio=16):"""參數(shù):in_channels: 輸入特征圖的通道數(shù)reduction_ratio: 降維比例,用于減少參數(shù)量"""super(ChannelAttention, self).__init__()# 全局平均池化 - 將空間維度壓縮為1x1,保留通道信息self.avg_pool = nn.AdaptiveAvgPool2d(1)# 全連接層 + 激活函數(shù),用于學(xué)習(xí)通道間的依賴關(guān)系self.fc = nn.Sequential(# 降維:壓縮通道數(shù),減少計(jì)算量nn.Linear(in_channels, in_channels // reduction_ratio, bias=False),nn.ReLU(inplace=True),# 升維:恢復(fù)原始通道數(shù)nn.Linear(in_channels // reduction_ratio, in_channels, bias=False),# Sigmoid將輸出值歸一化到[0,1],表示通道重要性權(quán)重nn.Sigmoid())def forward(self, x):"""參數(shù):x: 輸入特征圖,形狀為 [batch_size, channels, height, width]返回:加權(quán)后的特征圖,形狀不變"""batch_size, channels, height, width = x.size()# 1. 全局平均池化:[batch_size, channels, height, width] → [batch_size, channels, 1, 1]avg_pool_output = self.avg_pool(x)# 2. 展平為一維向量:[batch_size, channels, 1, 1] → [batch_size, channels]avg_pool_output = avg_pool_output.view(batch_size, channels)# 3. 通過全連接層學(xué)習(xí)通道權(quán)重:[batch_size, channels] → [batch_size, channels]channel_weights = self.fc(avg_pool_output)# 4. 重塑為二維張量:[batch_size, channels] → [batch_size, channels, 1, 1]channel_weights = channel_weights.view(batch_size, channels, 1, 1)# 5. 將權(quán)重應(yīng)用到原始特征圖上(逐通道相乘)return x * channel_weights  # 輸出形狀:[batch_size, channels, height, width]

3.1 通道注意力模塊的核心原理

1.Squeeze(壓縮):

  • 通過全局平均池化將每個(gè)通道的二維特征圖(H×W)壓縮為一個(gè)標(biāo)量,保留通道的全局信息
  • 物理意義:計(jì)算每個(gè)通道在整個(gè)圖像中的 “平均響應(yīng)強(qiáng)度”,例如,“邊緣檢測(cè)通道” 在有物體邊緣的圖像中響應(yīng)值會(huì)更高

2.Excitation(激發(fā)):

  • 通過全連接層 + Sigmoid 激活,學(xué)習(xí)通道間的依賴關(guān)系,輸出 0-1 之間的權(quán)重值
  • 物理意義:讓模型自動(dòng)判斷哪些通道更重要(權(quán)重接近 1),哪些通道可忽略(權(quán)重接近 0)

3.Reweight(重加權(quán)):

  • 將學(xué)習(xí)到的通道權(quán)重與原始特征圖逐通道相乘,增強(qiáng)重要通道,抑制不重要通道
  • 物理意義:類似人類視覺系統(tǒng)聚焦于關(guān)鍵特征(如貓的輪廓),忽略無關(guān)特征(如背景顏色)

3.2 模型的重新定義

class CNN(nn.Module):def __init__(self):super(CNN, self).__init__()  # ---------------------- 第一個(gè)卷積塊 ----------------------self.conv1 = nn.Conv2d(3, 32, 3, padding=1)self.bn1 = nn.BatchNorm2d(32)self.relu1 = nn.ReLU()# 新增:插入通道注意力模塊(SE模塊)self.ca1 = ChannelAttention(in_channels=32, reduction_ratio=16)  self.pool1 = nn.MaxPool2d(2, 2)  # ---------------------- 第二個(gè)卷積塊 ----------------------self.conv2 = nn.Conv2d(32, 64, 3, padding=1)self.bn2 = nn.BatchNorm2d(64)self.relu2 = nn.ReLU()# 新增:插入通道注意力模塊(SE模塊)self.ca2 = ChannelAttention(in_channels=64, reduction_ratio=16)  self.pool2 = nn.MaxPool2d(2)  # ---------------------- 第三個(gè)卷積塊 ----------------------self.conv3 = nn.Conv2d(64, 128, 3, padding=1)self.bn3 = nn.BatchNorm2d(128)self.relu3 = nn.ReLU()# 新增:插入通道注意力模塊(SE模塊)self.ca3 = ChannelAttention(in_channels=128, reduction_ratio=16)  self.pool3 = nn.MaxPool2d(2)  # ---------------------- 全連接層(分類器) ----------------------self.fc1 = nn.Linear(128 * 4 * 4, 512)self.dropout = nn.Dropout(p=0.5)self.fc2 = nn.Linear(512, 10)def forward(self, x):# ---------- 卷積塊1處理 ----------x = self.conv1(x)       x = self.bn1(x)         x = self.relu1(x)       x = self.ca1(x)  # 應(yīng)用通道注意力x = self.pool1(x)       # ---------- 卷積塊2處理 ----------x = self.conv2(x)       x = self.bn2(x)         x = self.relu2(x)       x = self.ca2(x)  # 應(yīng)用通道注意力x = self.pool2(x)       # ---------- 卷積塊3處理 ----------x = self.conv3(x)       x = self.bn3(x)         x = self.relu3(x)       x = self.ca3(x)  # 應(yīng)用通道注意力x = self.pool3(x)       # ---------- 展平與全連接層 ----------x = x.view(-1, 128 * 4 * 4)  x = self.fc1(x)           x = self.relu3(x)         x = self.dropout(x)       x = self.fc2(x)           return x  # 重新初始化模型,包含通道注意力模塊
model = CNN()
model = model.to(device)  # 將模型移至GPU(如果可用)criterion = nn.CrossEntropyLoss()  # 交叉熵?fù)p失函數(shù)
optimizer = optim.Adam(model.parameters(), lr=0.001)  # Adam優(yōu)化器# 引入學(xué)習(xí)率調(diào)度器,在訓(xùn)練過程中動(dòng)態(tài)調(diào)整學(xué)習(xí)率--訓(xùn)練初期使用較大的 LR 快速降低損失,訓(xùn)練后期使用較小的 LR 更精細(xì)地逼近全局最優(yōu)解。
# 在每個(gè) epoch 結(jié)束后,需要手動(dòng)調(diào)用調(diào)度器來更新學(xué)習(xí)率,可以在訓(xùn)練過程中調(diào)用 scheduler.step()
scheduler = optim.lr_scheduler.ReduceLROnPlateau(optimizer,        # 指定要控制的優(yōu)化器(這里是Adam)mode='min',       # 監(jiān)測(cè)的指標(biāo)是"最小化"(如損失函數(shù))patience=3,       # 如果連續(xù)3個(gè)epoch指標(biāo)沒有改善,才降低LRfactor=0.5        # 降低LR的比例(新LR = 舊LR × 0.5)
)# 訓(xùn)練模型(復(fù)用原有的train函數(shù))
print("開始訓(xùn)練帶通道注意力的CNN模型...")
final_accuracy = train(model, train_loader, test_loader, criterion, optimizer, scheduler, device, epochs=50)
print(f"訓(xùn)練完成!最終測(cè)試準(zhǔn)確率: {final_accuracy:.2f}%")
開始訓(xùn)練帶通道注意力的CNN模型...
Epoch: 1/50 | Batch: 100/782 | 單Batch損失: 1.8910 | 累計(jì)平均損失: 1.9942
Epoch: 1/50 | Batch: 200/782 | 單Batch損失: 1.6923 | 累計(jì)平均損失: 1.8823
Epoch: 1/50 | Batch: 300/782 | 單Batch損失: 1.6001 | 累計(jì)平均損失: 1.8048
Epoch: 1/50 | Batch: 400/782 | 單Batch損失: 1.2822 | 累計(jì)平均損失: 1.7508
Epoch: 1/50 | Batch: 500/782 | 單Batch損失: 1.5353 | 累計(jì)平均損失: 1.7110
Epoch: 1/50 | Batch: 600/782 | 單Batch損失: 1.4252 | 累計(jì)平均損失: 1.6772
Epoch: 1/50 | Batch: 700/782 | 單Batch損失: 1.5700 | 累計(jì)平均損失: 1.6480
Epoch 1/50 完成 | 訓(xùn)練準(zhǔn)確率: 40.15% | 測(cè)試準(zhǔn)確率: 54.47%
Epoch: 2/50 | Batch: 100/782 | 單Batch損失: 1.1785 | 累計(jì)平均損失: 1.3923
Epoch: 2/50 | Batch: 200/782 | 單Batch損失: 1.1950 | 累計(jì)平均損失: 1.3703
Epoch: 2/50 | Batch: 300/782 | 單Batch損失: 1.5047 | 累計(jì)平均損失: 1.3450
Epoch: 2/50 | Batch: 400/782 | 單Batch損失: 0.9452 | 累計(jì)平均損失: 1.3163
Epoch: 2/50 | Batch: 500/782 | 單Batch損失: 1.4187 | 累計(jì)平均損失: 1.2955
Epoch: 2/50 | Batch: 600/782 | 單Batch損失: 1.2744 | 累計(jì)平均損失: 1.2757
Epoch: 2/50 | Batch: 700/782 | 單Batch損失: 0.8026 | 累計(jì)平均損失: 1.2576
Epoch 2/50 完成 | 訓(xùn)練準(zhǔn)確率: 55.18% | 測(cè)試準(zhǔn)確率: 64.94%
Epoch: 3/50 | Batch: 100/782 | 單Batch損失: 1.1973 | 累計(jì)平均損失: 1.1252
Epoch: 3/50 | Batch: 200/782 | 單Batch損失: 1.0419 | 累計(jì)平均損失: 1.1164
Epoch: 3/50 | Batch: 300/782 | 單Batch損失: 1.1677 | 累計(jì)平均損失: 1.1095
Epoch: 3/50 | Batch: 400/782 | 單Batch損失: 0.8185 | 累計(jì)平均損失: 1.1021
Epoch: 3/50 | Batch: 500/782 | 單Batch損失: 0.9481 | 累計(jì)平均損失: 1.0917
Epoch: 3/50 | Batch: 600/782 | 單Batch損失: 0.9860 | 累計(jì)平均損失: 1.0812
Epoch: 3/50 | Batch: 700/782 | 單Batch損失: 1.1787 | 累計(jì)平均損失: 1.0746
Epoch 3/50 完成 | 訓(xùn)練準(zhǔn)確率: 61.74% | 測(cè)試準(zhǔn)確率: 68.80%
...
Epoch: 50/50 | Batch: 500/782 | 單Batch損失: 0.3202 | 累計(jì)平均損失: 0.3893
Epoch: 50/50 | Batch: 600/782 | 單Batch損失: 0.4020 | 累計(jì)平均損失: 0.3885
Epoch: 50/50 | Batch: 700/782 | 單Batch損失: 0.4807 | 累計(jì)平均損失: 0.3894
Epoch 50/50 完成 | 訓(xùn)練準(zhǔn)確率: 86.14% | 測(cè)試準(zhǔn)確率: 85.38%

@浙大疏錦行

http://www.risenshineclean.com/news/1923.html

相關(guān)文章:

  • 互聯(lián)網(wǎng)推廣加盟搜索引擎優(yōu)化工具
  • 福州營銷網(wǎng)站建設(shè)模板如何制作網(wǎng)站和網(wǎng)頁
  • 網(wǎng)站開發(fā)語言入門瀏覽器直接進(jìn)入網(wǎng)站的注意事項(xiàng)
  • 嘉興秀洲區(qū)全網(wǎng)seo優(yōu)化優(yōu)惠廈門seo關(guān)鍵詞
  • 聯(lián)系昆明網(wǎng)站建設(shè)推廣app用什么平臺(tái)比較好
  • wordpress菜單外觀樣式seo推廣優(yōu)化排名軟件
  • 開發(fā)網(wǎng)站要注意什么問題推廣計(jì)劃書范文
  • 做數(shù)學(xué)的網(wǎng)站視頻外鏈平臺(tái)
  • 建個(gè)網(wǎng)站的電話廣東seo網(wǎng)絡(luò)培訓(xùn)
  • java eclipse做網(wǎng)站網(wǎng)頁制作在線生成
  • 如果是創(chuàng)建的網(wǎng)站網(wǎng)站快速排名優(yōu)化價(jià)格
  • 百度做網(wǎng)站找誰智能建站系統(tǒng)
  • 煙臺(tái)優(yōu)化網(wǎng)站建設(shè)網(wǎng)絡(luò)營銷好不好
  • 前端做視頻直播網(wǎng)站怎么做線上推廣
  • vs中可以用新建項(xiàng)目來做網(wǎng)站嗎如何快速推廣自己的產(chǎn)品
  • 網(wǎng)站開發(fā)php廣州網(wǎng)站seo公司
  • 個(gè)人網(wǎng)站備案可以做項(xiàng)目網(wǎng)站關(guān)鍵詞排名優(yōu)化易下拉排名
  • 自定義網(wǎng)站建站公司seo提升排名
  • 關(guān)于政府網(wǎng)站建設(shè)的調(diào)研報(bào)告百度關(guān)鍵詞查詢排名
  • html網(wǎng)頁模板網(wǎng)站模板下載廈門網(wǎng)站建設(shè)平臺(tái)
  • 深圳自適應(yīng)網(wǎng)站建設(shè)價(jià)格網(wǎng)絡(luò)推廣外包一年多少錢
  • 攝影網(wǎng)站開發(fā)的背景企業(yè)網(wǎng)站建設(shè)哪家好
  • 做網(wǎng)站域名的成本廣州網(wǎng)站建設(shè)公司
  • 音樂做音基題網(wǎng)站seo外鏈推廣工具
  • 免費(fèi)網(wǎng)站空間可訪問第三方推廣平臺(tái)
  • 政府網(wǎng)站建設(shè)項(xiàng)目背景seo網(wǎng)站優(yōu)化推薦
  • 做網(wǎng)站工作室找客戶難廣州谷歌優(yōu)化
  • 裝修公司做網(wǎng)站有用嗎友情鏈接的網(wǎng)站圖片
  • 自助建站系統(tǒng)微信管理系統(tǒng)登錄入口
  • 做技術(shù)開發(fā)的網(wǎng)站如何制作一個(gè)網(wǎng)站