Python打卡訓練營Day43

DAY 43 復習日

作業:

kaggle找到一個圖像數據集,用cnn網絡進行訓練并且用grad-cam做可視化

數據集地址:Lung Nodule Malignancy?肺結核良惡性判斷?

進階:并拆分成多個文件

import os
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from torch.utils.data import Dataset, DataLoader
from PIL import Image
import torch
from torchvision import transforms
import torch.nn as nn
import torch.optim as optim
import matplotlib.pyplot as plt# 1. 讀標簽并映射 0/1
df = pd.read_csv('archive/malignancy.csv')# 2. 按 patch_id 劃 train/val
ids    = df['NoduleID'].values
labels = df['malignancy'].values
train_ids, val_ids = train_test_split(ids, test_size=0.2, random_state=42, stratify=labels
)
train_df = df[df['NoduleID'].isin(train_ids)].reset_index(drop=True)
val_df   = df[df['NoduleID'].isin(val_ids)].reset_index(drop=True)# 3. Dataset:多頁 TIFF 按頁讀取
class LungTBDataset(Dataset):def __init__(self, tif_path, df, transform=None):self.tif_path = tif_pathself.df = dfself.transform = transformdef __len__(self):return len(self.df)def __getitem__(self, idx):row = self.df.iloc[idx]pid = int(row['NoduleID'])label = int(row['malignancy'])try:with Image.open(self.tif_path) as img:# 檢查 pid 是否超出實際幀數total_pages = sum(1 for _ in ImageSequence.Iterator(img))if pid >= total_pages:pid = total_pages - 1  # 取最后一幀img.seek(pid)img = img.convert('RGB')except Exception as e:# 返回黑色占位圖img = Image.new('RGB', (224, 224), (0, 0, 0))if self.transform:img = self.transform(img)return img, label# 4. 變換 & DataLoader
transform = transforms.Compose([transforms.Resize((224,224)),transforms.ToTensor(),transforms.Normalize(mean=[0.485,0.456,0.406],std =[0.229,0.224,0.225])
])
train_ds = LungTBDataset('archive/ct_tiles.tif', train_df, transform)
val_ds   = LungTBDataset('archive/ct_tiles.tif',   val_df, transform)
train_loader = DataLoader(train_ds, batch_size=16, shuffle=True,  num_workers=0, pin_memory=True)
val_loader   = DataLoader(val_ds,   batch_size=16, shuffle=False, num_workers=0, pin_memory=True)# 5. 定義簡單 CNN(3層卷積 + 全連接)
class SimpleCNN(nn.Module):def __init__(self):super(SimpleCNN, self).__init__()# 卷積層self.conv1 = nn.Sequential(nn.Conv2d(3, 32, kernel_size=3, padding=1),nn.ReLU(inplace=True),nn.MaxPool2d(2)  # 224->112)self.conv2 = nn.Sequential(nn.Conv2d(32, 64, kernel_size=3, padding=1),nn.ReLU(inplace=True),nn.MaxPool2d(2)  # 112->56)# 最后一層卷積,用于 Grad-CAMself.conv3 = nn.Sequential(nn.Conv2d(64, 128, kernel_size=3, padding=1),nn.ReLU(inplace=True),nn.MaxPool2d(2)  # 56->28)# 全連接分類器self.fc = nn.Sequential(nn.Flatten(),nn.Linear(128 * 28 * 28, 256),nn.ReLU(inplace=True),nn.Linear(256, 2))def forward(self, x):x = self.conv1(x)x = self.conv2(x)x = self.conv3(x)      # 保留這一層的輸出作 CAMx = self.fc(x)return xdevice = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model = SimpleCNN().to(device)criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=1e-4)# 6. 訓練 + 驗證循環
num_epochs = 5
for epoch in range(num_epochs):# 訓練model.train()running_loss = 0for imgs, labs in train_loader:imgs, labs = imgs.to(device), labs.to(device)optimizer.zero_grad()outputs = model(imgs)loss    = criterion(outputs, labs)loss.backward()optimizer.step()running_loss += loss.item() * imgs.size(0)epoch_loss = running_loss / len(train_ds)# 驗證model.eval()correct = 0with torch.no_grad():for imgs, labs in val_loader:imgs, labs = imgs.to(device), labs.to(device)preds = model(imgs).argmax(dim=1)correct += (preds == labs).sum().item()val_acc = correct / len(val_ds)print(f'Epoch {epoch+1}/{num_epochs}  Loss={epoch_loss:.4f}  ValAcc={val_acc:.4f}')# 7. 簡易 Grad-CAM
class GradCAM:def __init__(self, model, target_conv):self.model = modelself.target_conv = target_convself.grad    = Noneself.activation = None# 注冊 hooktarget_conv.register_forward_hook(self._forward)target_conv.register_backward_hook(self._backward)def _forward(self, module, inp, outp):self.activation = outp.detach()def _backward(self, module, grad_in, grad_out):self.grad = grad_out[0].detach()def __call__(self, x, class_idx=None):self.model.zero_grad()out = self.model(x)if class_idx is None:class_idx = out.argmax(dim=1).item()loss = out[0, class_idx]loss.backward()# 計算權重weights = self.grad.mean(dim=(2,3))  # (1,C)cam = (weights.view(-1,1,1) * self.activation[0]).sum(dim=0)cam = torch.relu(cam)cam -= cam.min()cam /= cam.max()return cam.cpu().numpy()# 8. 隨機選一張驗證圖做可視化
model.eval()
imgs, labs = next(iter(val_loader))
img, lab = imgs[0:1].to(device), labs[0].item()# 以 conv3 的最后 Conv2d 為 target
# conv3 是 Sequential,取其中的第0層 Conv2d
target_layer = model.conv3[0]
gradcam = GradCAM(model, target_layer)
heatmap = gradcam(img)  # (28,28)# 上采樣到 224×224
heatmap = np.uint8(255 * heatmap)
heatmap = Image.fromarray(heatmap).resize((224,224), resample=Image.BILINEAR)
heatmap = np.array(heatmap) / 255.0# 反歸一化 & 可視化疊加
inv_norm = transforms.Normalize(mean=[-0.485/0.229, -0.456/0.224, -0.406/0.225],std =[1/0.229,       1/0.224,       1/0.225]
)
img_show = inv_norm(img[0]).permute(1,2,0).cpu().numpy()
img_show = np.clip(img_show, 0, 1)plt.figure(figsize=(8,4))
plt.subplot(1,2,1)
plt.imshow(img_show)
plt.title(f'Label={lab}')
plt.axis('off')plt.subplot(1,2,2)
plt.imshow(img_show, alpha=0.6)
plt.imshow(heatmap, cmap='jet', alpha=0.4)
plt.title('Grad-CAM')
plt.axis('off')
plt.tight_layout()
plt.show()

代碼沒問題但跑的很慢不知道啥原因。

浙大疏錦行-CSDN博客

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

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

相關文章

悲觀鎖與樂觀鎖:并發編程中的兩種核心控制策略詳解

在并發編程中,悲觀鎖和樂觀鎖是兩種不同的并發控制策略,用于解決多個線程或進程對共享資源的并發訪問問題。下面將詳細介紹它們的概念、實現方式以及優缺點。 悲觀鎖 概念 悲觀鎖認為在并發環境下,多個線程或進程對共享資源的訪問大概率會發…

python 如何寫4或5的表達式

python寫4或5的表達式的方法: python中和是用“and”語句,或是用“or”語句。那么4或5的表達式為“4 or 5” 具體示例如下: 執行結果:

麻省理工新突破:家庭場景下機器人實現精準控制,real-to-sim-to-real學習助力

麻省理工學院電氣工程與計算機科學系Pulkit Agrawal教授,介紹了一種新方法,可以讓機器人在掃描的家庭環境模擬中接受訓練,為任何人都可以實現定制的家庭自動化鋪平了道路。 本文將探討通過Franka機器人在虛擬環境中訓練的特點,研…

Linux程序管理練習題

Linux程序管理100題 一、Linux程序與進程(1-15) 程序、進程、線程的本質區別是什么? 答案:程序是靜態指令集,進程是運行中的程序實例,線程是進程內的執行單元 進程的并發性和交往性體現在哪些方面&#xf…

虛幻基礎:模型

能幫到你的話,就給個贊吧 😘 文章目錄 資源模型:骨架/骨骼模型動畫:一系列姿勢補幀:只需設定關鍵姿勢,則系統在關鍵幀姿勢之間自動生成動畫。姿勢的變換:即骨骼的變換 動畫藍圖:執行…

《Discuz! X3.5開發從入門到生態共建》第1章 Discuz! 的前世今生-優雅草卓伊凡

《Discuz! X3.5開發從入門到生態共建》第1章 Discuz! 的前世今生-優雅草卓伊凡 第一節 從康盛創想到騰訊收購:PC時代的輝煌 1.1 Discuz! 的誕生:康盛創想的開源夢想 2001年,中國互聯網正處于萌芽階段,個人網站和論壇開始興起。…

如何打包conda環境從一臺電腦到另外一臺電腦

在 Ubuntu 系統下,使用的是 VSCode 和 Conda 環境開發項目,想要將整個 Conda 環境從一臺電腦遷移到另一臺電腦,可以通過以下步驟來實現打包和導入: ? 一、在原電腦上導出 Conda 環境 1. 激活你要導出的環境 conda activate you…

2025GDCPC廣東省賽游記(附賽時代碼)

我覺得算是給swan的自證之旅畫上一個句號吧...說實話HDU給我帶來的不止是排位上的壓力,更多的是對自己能力的懷疑,特別是pluto不明說但是我很清楚的看不起(沒有責備本人的意思),evil和jxj之類的總感覺看到我就是看小丑…

MySQL 修改數據的全鏈路流程

MySQL 修改數據的全鏈路流程(InnoDB) 全鏈路流程圖關鍵步驟詳解1. 建立連接階段2.SQL解析與優化3. InnoDB內存操作4. 日志記錄過程5. 二階段提交(2PC) 磁盤同步機制1. Redo Log刷盤策略(innodb_flush_log_at_trx_commi…

蘭亭妙微十六年高水準交互設計公司

北京蘭亭妙微(藍藍設計)成立于 2008 年(前身為設計工作室,2011 年正式注冊),由清華團隊主創,專注軟件和互聯網 UI/UE 設計開發 16 年。我們提供從需求調研、界面設計到開發落地的全流程服務&…

【腳本 完全參數化的通用 APT 源配置方案-Debian/Ubuntu】

通過腳本在 Debian/Ubuntu 系統上一鍵切換 APT 源 如Dockerfile中 使用某個源(比如 aliyun) 假設你的目錄結構是: . ├── Dockerfile └── switch-apt-source.shFROM ubuntu:22.04# 把腳本拷貝到鏡像中 COPY switch-apt-source.sh /us…

學習日記-day20-6.1

完成目標&#xff1a; 知識點&#xff1a; 1.集合_Collections集合工具類 方法:static <T> boolean addAll(Collection<? super T> c, T... elements)->批量添加元素 static void shuffle(List<?> list) ->將集合中的元素順序打亂static <T>…

個人總結八股文之-基礎篇(持續更新)

一、集合的分類有哪些&#xff1f; Java集合框架主要分為兩大類&#xff1a;Collection和Map Collection主要分為以下三類&#xff1a; List&#xff1a;有序集合&#xff0c;允許重復元素。常見的實現類有ArrayList、LinkedList和Vector。 Set&#xff1a;無序集合&#xf…

leetcode hot100刷題日記——35.子集

解答&#xff1a; 方法一&#xff1a;選or不選的dfs&#xff08;輸入視角&#xff09; 思路&#xff1a;[1,2,3]的全部子集可以看成是對數組的每一位數字做選擇。 eg.空集就是一個數字都不選&#xff0c;[1,2]就是1&#xff0c;2選&#xff0c;3不選。 class Solution { pub…

華為OD機試真題——生成哈夫曼樹(2025A卷:100分)Java/python/JavaScript/C/C++/GO六種最佳實現

2025 A卷 100分 題型 本文涵蓋詳細的問題分析、解題思路、代碼實現、代碼詳解、測試用例以及綜合分析; 并提供Java、python、JavaScript、C++、C語言、GO六種語言的最佳實現方式! 本文收錄于專欄:《2025華為OD真題目錄+全流程解析/備考攻略/經驗分享》 華為OD機試真題《生成…

房屋租賃系統 Java+Vue.js+SpringBoot,包括房屋類型、房屋信息、預約看房、合同信息、房屋報修、房屋評價、房主管理模塊

房屋租賃系統 JavaVue.jsSpringBoot&#xff0c;包括房屋類型、房屋信息、預約看房、合同信息、房屋報修、房屋評價、房主管理模塊 百度云盤鏈接&#xff1a;https://pan.baidu.com/s/1KmwOFzN9qogyaLQei3b6qw 密碼&#xff1a;l2yn 摘 要 社會的發展和科學技術的進步&#xf…

Unity 中 Update、FixedUpdate 和 LateUpdate 的區別及使用場景

在Unity開發中,Update、FixedUpdate 和 LateUpdate 是生命周期函數中最常見也最容易混淆的一組。 一、調用時機 方法名調用頻率調用時機說明Update()每幀調用一次跟隨幀率(幀率高則調用頻率高)FixedUpdate()固定時間間隔調用默認每 0.02 秒執行一次LateUpdate()每幀調用一次…

Docker鏡像之windows系統

https://github.com/dockur/windows 在 Docker 容器中運行 Windows 功能 ISO 下載器KVM 加速基于網頁的查看器 使用方法 啟動容器并通過瀏覽器連接到端口 8006。整個安裝過程將全自動完成&#xff0c;無需手動干預。當桌面界面出現時&#xff0c;表示 Windows 安裝已完成&a…

C# 用戶控件(User Control)詳解:創建、使用與最佳實踐

在C#應用程序開發中&#xff0c;用戶控件&#xff08;User Control&#xff09;是一種強大的工具&#xff0c;它允許開發者將多個標準控件組合成一個可復用的自定義組件。無論是Windows Forms還是WPF&#xff0c;用戶控件都能顯著提高UI開發的效率&#xff0c;減少重復代碼&…

pikachu靶場通關筆記09 XSS關卡05-DOM型XSS-X

目錄 一、XSS 二、DOM型XSS 三、源碼分析 1、打開DOM-X型XSS關卡 2、XSS探測 3、源碼分析 四、滲透實戰 1、Payload1 2、Payload2 3、Payload3 五、DOM型XSS與DOM-X型XSS區別 本系列為通過《pikachu靶場通關筆記》的XSS攻擊關卡(共10關&#xff09;滲透集合&#xf…