Python訓練打卡DAY46

DAY46:通道注意力(SE注意力)

恩師@浙大疏錦行

知識點:

  1. 不同CNN層的特征圖:不同通道的特征圖
  2. 什么是注意力:注意力家族,類似于動物園,都是不同的模塊,好不好試了才知道。
  3. 通道注意力:模型的定義和插入的位置
  4. 通道注意力后的特征圖和熱力圖

內容參考

一、特征圖的提取


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

二、特征圖可視化

def visualize_feature_maps(model, test_loader, device, layer_names, num_images=3, num_channels=9):"""可視化指定層的特征圖(修復循環冗余問題)參數:model: 模型test_loader: 測試數據加載器layer_names: 要可視化的層名稱(如['conv1', 'conv2', 'conv3'])num_images: 可視化的圖像總數num_channels: 每個圖像顯示的通道數(取前num_channels個通道)"""model.eval()  # 設置為評估模式class_names = ['飛機', '汽車', '鳥', '貓', '鹿', '狗', '青蛙', '馬', '船', '卡車']# 從測試集加載器中提取指定數量的圖像(避免嵌套循環)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# 拼接并截取到目標數量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():# 存儲各層特征圖feature_maps = {}# 保存鉤子句柄hooks = []# 定義鉤子函數,捕獲指定層的輸出def hook(module, input, output, name):feature_maps[name] = output.cpu()  # 保存特征圖到字典# 為每個目標層注冊鉤子,并保存鉤子句柄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)# 前向傳播觸發鉤子_ = model(images)# 正確移除鉤子for hook_handle in hooks:hook_handle.remove()# 可視化每個圖像的各層特征圖(僅一層循環)for img_idx in range(num_images):img = images[img_idx].cpu().permute(1, 2, 0).numpy()# 反標準化處理(恢復原始像素值)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]范圍內# 創建子圖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個通道num_rows = int(np.sqrt(num_channels))num_cols = num_channels // num_rows if num_rows != 0 else 1# 創建子圖網格layer_ax = axes[layer_idx + 1]layer_ax.set_title(f'{layer_name}特征圖 \n')# 加個換行讓文字分離上去layer_ax.axis('off')  # 關閉大子圖的坐標軸# 在大子圖內創建小網格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()# 調用示例(按需修改參數)
layer_names = ['conv1', 'conv2', 'conv3']
visualize_feature_maps(model=model,test_loader=test_loader,device=device,layer_names=layer_names,num_images=5,  # 可視化5張測試圖像 → 輸出5張大圖num_channels=9   # 每張圖像顯示前9個通道的特征圖
)

三、通道注意力的定義

# ===================== 新增:通道注意力模塊(SE模塊) =====================
class ChannelAttention(nn.Module):"""通道注意力模塊(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_ratio=16):"""參數:in_channels: 輸入特征圖的通道數reduction_ratio: 降維比例,用于減少參數量"""super(ChannelAttention, self).__init__()# 全局平均池化 - 將空間維度壓縮為1x1,保留通道信息self.avg_pool = nn.AdaptiveAvgPool2d(1)# 全連接層 + 激活函數,用于學習通道間的依賴關系self.fc = nn.Sequential(# 降維:壓縮通道數,減少計算量nn.Linear(in_channels, in_channels // reduction_ratio, bias=False),nn.ReLU(inplace=True),# 升維:恢復原始通道數nn.Linear(in_channels // reduction_ratio, in_channels, bias=False),# Sigmoid將輸出值歸一化到[0,1],表示通道重要性權重nn.Sigmoid())def forward(self, x):"""參數:x: 輸入特征圖,形狀為 [batch_size, channels, height, width]返回:加權后的特征圖,形狀不變"""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. 通過全連接層學習通道權重:[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. 將權重應用到原始特征圖上(逐通道相乘)return x * channel_weights  # 輸出形狀:[batch_size, channels, height, width]

四、通道注意力的插入

class CNN(nn.Module):def __init__(self):super(CNN, self).__init__()  # ---------------------- 第一個卷積塊 ----------------------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)  # ---------------------- 第二個卷積塊 ----------------------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)  # ---------------------- 第三個卷積塊 ----------------------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)  # 應用通道注意力x = self.pool1(x)       # ---------- 卷積塊2處理 ----------x = self.conv2(x)       x = self.bn2(x)         x = self.relu2(x)       x = self.ca2(x)  # 應用通道注意力x = self.pool2(x)       # ---------- 卷積塊3處理 ----------x = self.conv3(x)       x = self.bn3(x)         x = self.relu3(x)       x = self.ca3(x)  # 應用通道注意力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()  # 交叉熵損失函數
optimizer = optim.Adam(model.parameters(), lr=0.001)  # Adam優化器# 引入學習率調度器,在訓練過程中動態調整學習率--訓練初期使用較大的 LR 快速降低損失,訓練后期使用較小的 LR 更精細地逼近全局最優解。
# 在每個 epoch 結束后,需要手動調用調度器來更新學習率,可以在訓練過程中調用 scheduler.step()
scheduler = optim.lr_scheduler.ReduceLROnPlateau(optimizer,        # 指定要控制的優化器(這里是Adam)mode='min',       # 監測的指標是"最小化"(如損失函數)patience=3,       # 如果連續3個epoch指標沒有改善,才降低LRfactor=0.5        # 降低LR的比例(新LR = 舊LR × 0.5)
)

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/88363.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/88363.shtml
英文地址,請注明出處:http://en.pswp.cn/web/88363.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

fastadmin_php專項

1.時間的判斷,還有就是在php這邊如何去拿前端html元素上面的值input($row.borrowtime);// 創建兩個 DateTime 對象$row_expecttime new \DateTime(input($row.borrowtime));$par_expecttime new \DateTime( $params[expecttime]); // // 計算兩個日期之間的差異 // …

如何在MySQL中選擇使用InnoDB還是MyISAM引擎?

在 MySQL 中選擇 InnoDB 還是 MyISAM 存儲引擎時,需根據應用場景的需求權衡功能、性能和數據完整性。以下是具體的選擇指南: 1. 優先考慮事務和外鍵需求必須使用 InnoDB: 若應用需要 事務支持(如金融轉賬、訂單處理)或…

邀請函 | 知從科技邀您共赴2025 RISC-V 中國峰會

第五屆RISC-V中國峰會將于2025年7月16至19日在上海張江科學會堂隆重舉辦,本屆峰會由上海開放處理器產業創新中心(SOPIC)主辦,RISC-V國際開源實驗室(RIOS實驗室)和上海張江高科技園區開發股份有限公司聯合主…

企業數字化轉型規劃和建設方案(管理架構、應用架構、技術架構)PPT

一、戰略定位與核心目標以 “技術賦能業務,數據驅動創新” 為核心思路,構建 “三步走” 戰略演進路徑,實現 IT 從 “基礎支撐” 到 “戰略引擎” 的升級:IT1.0(1-2 年):夯實基礎能力定位 “穩健…

基于Uniapp+MySQL+PHP的景區多商戶小程序源碼系統 帶完整的搭建指南

溫馨提示:文末有資源獲取方式該系統采用 PHP MySQL 的經典開發組合。PHP 作為一種廣泛使用的開源腳本語言,具有簡單易學、運行速度快、跨平臺性強等優點,能夠快速開發出功能強大的 Web 應用程序。MySQL 則是一款穩定可靠的關系型數據庫管理系…

阿里云和騰訊云RocketMQ 發消息和消費消息客戶端JAVA接口

一、RocketMQ 概述RocketMQ 是阿里巴巴開源的一款分布式消息中間件,后捐贈給 Apache 基金會成為頂級項目。它具有低延遲、高并發、高可用、高可靠等特點,廣泛應用于訂單交易、消息推送、流計算、日志收集等場景。核心特點分布式架構:支持集群…

Vue響應式原理六:Vue3響應式原理

1. 多個對象響應式當前存在的問題:當前實現僅針對某個固定對象(obj)進行依賴收集,實際開發中需要處理多個不同對象將對象響應式處理邏輯抽取為通用函數,支持任意對象代碼如下: // 方案一:Obje…

【算法筆記 day three】滑動窗口(其他類型)

hello大家好!這份筆記包含的題目類型主要包括求子數組已經一些比較‘小眾’的題目。和之前一樣,筆記中的代碼和思路要么是我手搓要么是我借鑒一些大佬的想法轉化成自己的話復現。所以方法不一定是最好的,但一定是經過我理解的產物&#xff0c…

docker-鏡像管理指南

在本節中,我們將詳細介紹 Docker 鏡像的常用命令,幫助您更好地管理和操作鏡像。以下是核心命令及其功能說明:1.使用"ls"查看鏡像列表#查看現有的鏡像列表[rootdocker01 ~]# docker images [rootdocker01 ~]# docker image ls#僅查看…

Mac 電腦無法讀取硬盤的解決方案

引言近年來,選擇使用 Mac 電腦的用戶越來越多,尤其是在設計、開發、剪輯、文檔處理等領域,macOS 憑借其優秀的系統生態與硬件體驗吸引了大量擁躉。與此同時,對于攝影師、剪輯師、程序員、學生等用戶來說,一塊移動硬盤往…

25春期末考

web 瘋狂星期四 先來看一下源碼 分析代碼的黑名單后得知 我們可以用的字符就只剩下 字母a-z(大小寫均可) 數字2 空格 這里的限制太多了 這里比較常用的getallheaders被ban掉了 這里就是用session來做 session_start()開啟session session_id()獲取session 這里我們要構造一…

時間顯示 藍橋云課Java

目錄 題目鏈接 題目 解題思路 代碼 題目鏈接 競賽中心 - 藍橋云課 題目 解題思路 通過%天數,得到一天內的時間,然后/小時單位(換算成毫秒的)得到小時,然后總數減去該小時,得到分鐘數,秒數同理 代碼 import java.util.Scanner; // 1:無需package // 2: 類名必須Main, 不…

STM32F1控制步進電機

一、基礎知識1. 步進電機控制方式脈沖方向控制(最常見)控制信號:DIR方向:高低電平決定正轉或反轉;STEP脈沖:每個脈沖電機前進一步(可通過端口拉高拉低來模擬脈沖,或使用pwm來生成脈沖…

Docker 容器部署腳本

#!/bin/bash# # Author: ldj # Date: 2025-07-08 15:37:11 # Description: 首先刪除舊的容器和鏡像,然后登錄到 Harbor 并拉取最新的鏡像進行部署 # # 顯示每條命令執行情況,便于調試 set -x harbor_addr$1 harbor_repo$2 project_name$3 version$4 po…

OpenCV 4.10.0 移植 - Android

前文: Ubuntu 編譯 OpenCV SDK for Android Linux OpenCV 4.10.0 移植 概述 在移動應用開發領域,Android平臺與OpenCV庫的結合為開發者提供了強大的圖像處理和計算機視覺能力。OpenCV(Open Source Computer Vision Library)是一個開源的計算機視覺和機器學習軟件…

go go go 出發咯 - go web開發入門系列(二) Gin 框架實戰指南

go go go 出發咯 - go web開發入門系列(二) Gin 框架實戰指南 往期回顧 go go go 出發咯 - go web開發入門系列(一) helloworld 前言 前一節我們使用了go語言簡單的通過net/http搭建了go web服務,但是僅使用 Go 的標…

編譯OpenHarmony-4.0-Release RK3566 報錯

編譯OpenHarmony-4.0-Release RK3566 報錯1. 報錯問題2.問題解決3.解決方案4.?調試技巧?subsystem name config incorrect in ‘/home/openharmony/OpenHarmony/vendor/kaihong/khdvk_356b/bundle.json’, build file subsystem name is kaihong_products,configured subsy1.…

【PTA數據結構 | C語言版】線性表循環右移

本專欄持續輸出數據結構題目集,歡迎訂閱。 文章目錄題目代碼題目 給定順序表 A(a1?,a2?,?,an?),請設計一個時間和空間上盡可能高效的算法將該線性表循環右移指定的 m 位。例如,(1,2,5,7,3,4,6,8) 循環右移 3 位(m3) 后的結果…

c++-內部類

概念如果一個類定義在另一個類的內部,這個內部類就叫做內部類。內部類是一個獨立的類, 它不屬于外部類。特性1.不能通過外部類的對象去訪問內部類的成員。外部類對內部類沒有任何優越的訪問權限。 2.內部類就是外部類的友元類,參見友元類的定…

.golangci.yml文件配置

version: “2” run: timeout: 5m concurrency: 10 modules-download-mode: readonly linters: default: standard enable: - revive - cyclop settings: staticcheck: initialisms: [ “ACL”, “API”, “ASCII”, “CPU”, “CSS”, “DNS”, “EOF”, “GUID”, “HTML”, …