self-attention-cv:用于三维分割的子体积采样训练过程的演示

self-attention-cv:三维分割示例

原文在此: self-attention-cv.

数据集在此: dataset.

from google.colab import drive
drive.mount('/gdrive')
import zipfile
root_path = '/gdrive/My Drive/DATASETS/iSeg-2019-Training.zip' 
!echo "Download and extracting folders..."
zip_ref = zipfile.ZipFile(root_path, 'r')
zip_ref.extractall("./")
zip_ref.close()
!echo "Finished"
!pip install torchio
!pip install self-attention-cv

训练示例

import glob
import torchio as tio
import torch
from torch.utils.data import DataLoader

paths_t1 = sorted(glob.glob('./iSeg-2019-Training/*T1.img'))
paths_t2 = sorted(glob.glob('./iSeg-2019-Training/*T2.img'))
paths_seg = sorted(glob.glob('./iSeg-2019-Training/*label.img'))
assert len(paths_t1) == len(paths_t2) == len(paths_seg)

subject_list = []
for pat in zip(paths_t1, paths_t2, paths_seg):
  path_t1, path_t2, path_seg = pat
  subject = tio.Subject(t1=tio.ScalarImage(path_t1,),
              t2=tio.ScalarImage(path_t2,),
              label=tio.LabelMap(path_seg)) 
  subject_list.append(subject)


transforms = [tio.RescaleIntensity((0, 1)),tio.RandomAffine() ]
transform = tio.Compose(transforms)

subjects_dataset = tio.SubjectsDataset(subject_list, transform=transform)

patch_size = 24
queue_length = 300
samples_per_volume = 50
sampler = tio.data.UniformSampler(patch_size)

patches_queue = tio.Queue(
subjects_dataset,
queue_length,
samples_per_volume,sampler, num_workers=1)

patches_loader = DataLoader(patches_queue, batch_size=16)
from self_attention_cv.Transformer3Dsegmentation import Transformer3dSeg

def crop_target(img, target_size):
  dim = img.shape[-1]
  center = dim//2
  start_dim = center - (target_size//2) - 1
  end_dim = center + (target_size//2)
  return img[:,0,start_dim:end_dim,start_dim:end_dim,start_dim:end_dim].long()

target_size = 3 # as in the paper 
patch_dim = 8
num_epochs = 50
num_classes = 4
model = Transformer3dSeg(subvol_dim=patch_size, patch_dim=patch_dim,
                         in_channels=2, blocks=2, num_classes=num_classes).cuda()

criterion = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(model.parameters(), lr=0.001, momentum=0.9)
print(len(patches_loader))
for epoch_index in range(num_epochs):
  epoch_loss = 0
  for c,patches_batch in enumerate(patches_loader):
    optimizer.zero_grad()
    
    input_t1 = patches_batch['t1'][tio.DATA]  
    input_t2 = patches_batch['t2'][tio.DATA]

    input_tensor = torch.cat([input_t1, input_t2], dim=1).cuda()
    
    
    logits = model(input_tensor) # 8x8x8 the 3d transformer-based approach

    # for the 3d transformer-based approach the target must be cropped again to the desired size
    targets = patches_batch['label'][tio.DATA]  
    
    cropped_target = crop_target(targets, target_size).cuda()

    loss = criterion(logits, cropped_target)
    loss.backward()
    optimizer.step()
    epoch_loss = epoch_loss+loss.cpu().item()

  print(f'epoch {epoch_index} loss {epoch_loss/c}')

结果

import torch
import torch.nn as nn
import torchio as tio
patch_overlap = 0
patch_size = 24, 24, 24
target_patch_size = 3

#input sampling
grid_sampler = tio.inference.GridSampler(subject_list[0], patch_size, patch_overlap)
patch_loader = torch.utils.data.DataLoader(grid_sampler, batch_size=4)
# target vol sampling
grid_sampler_target = tio.inference.GridSampler(subject_list[0], target_patch_size, patch_overlap)
aggregator = tio.inference.GridAggregator(grid_sampler_target)
target_loader = torch.utils.data.DataLoader(grid_sampler_target, batch_size=4)

model.eval()

with torch.no_grad():
  for patches_batch,target_patches in zip(patch_loader,target_loader):

    input_t1 = patches_batch['t1'][tio.DATA]  
    input_t2 = patches_batch['t2'][tio.DATA]
    input_tensor = torch.cat([input_t1, input_t2], dim=1).float().cuda()

    locations = target_patches[tio.LOCATION]
    logits = model(input_tensor)
    labels = logits.argmax(dim=tio.CHANNELS_DIMENSION, keepdim=True)
    outputs = labels
    aggregator.add_batch(outputs.type(torch.int32), locations)

  print('output tensor shape:',outputs.shape)
  output_tensor = aggregator.get_output_tensor()
  print(output_tensor.shape)
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 以下是一个 Python 代码示例,用于实现 multi-head self-attention: ```python import torch import torch.nn as nn class MultiHeadAttention(nn.Module): def __init__(self, d_model, num_heads): super(MultiHeadAttention, self).__init__() self.num_heads = num_heads self.d_model = d_model self.depth = d_model // num_heads self.query_linear = nn.Linear(d_model, d_model) self.key_linear = nn.Linear(d_model, d_model) self.value_linear = nn.Linear(d_model, d_model) self.output_linear = nn.Linear(d_model, d_model) def forward(self, query, key, value, mask=None): batch_size = query.size() # Linear transformations query = self.query_linear(query) key = self.key_linear(key) value = self.value_linear(value) # Split into heads query = query.view(batch_size * self.num_heads, -1, self.depth) key = key.view(batch_size * self.num_heads, -1, self.depth) value = value.view(batch_size * self.num_heads, -1, self.depth) # Transpose for matrix multiplication query = query.transpose(1, 2) key = key.transpose(1, 2) value = value.transpose(1, 2) # Calculate scores scores = torch.matmul(query, key.transpose(-2, -1)) scores = scores / torch.sqrt(torch.tensor(self.depth).float()) # Apply mask (if provided) if mask is not None: mask = mask.unsqueeze(1) scores = scores.masked_fill(mask == , -1e9) # Softmax attention_weights = nn.Softmax(dim=-1)(scores) # Dropout attention_weights = nn.Dropout(p=.1)(attention_weights) # Multiply by values context = torch.matmul(attention_weights, value) # Reshape and concatenate context = context.transpose(1, 2).contiguous().view(batch_size, -1, self.num_heads * self.depth) # Linear transformation output = self.output_linear(context) return output ``` 希望对你有所帮助! ### 回答2: 下面是使用Python语言实现multi-head self-attention的一个示例代码: ``` import torch import torch.nn as nn import torch.nn.functional as F class MultiHeadSelfAttention(nn.Module): def __init__(self, d_model, num_heads): super(MultiHeadSelfAttention, self).__init__() self.num_heads = num_heads self.d_head = d_model // num_heads self.fc_query = nn.Linear(d_model, d_model) self.fc_key = nn.Linear(d_model, d_model) self.fc_value = nn.Linear(d_model, d_model) self.fc_concat = nn.Linear(d_model, d_model) def forward(self, x): batch_size, seq_len, d_model = x.size() h = self.num_heads # Split input into multiple heads query = self.fc_query(x).view(batch_size, seq_len, h, self.d_head) key = self.fc_key(x).view(batch_size, seq_len, h, self.d_head) value = self.fc_value(x).view(batch_size, seq_len, h, self.d_head) # Compute attention scores scores = torch.matmul(query, key.transpose(-2, -1)) / (self.d_head ** 0.5) attn_weights = F.softmax(scores, dim=-1) # Apply attention weights to value vectors attended_values = torch.matmul(attn_weights, value) attended_values = attended_values.transpose(1, 2).contiguous().view(batch_size, seq_len, -1) # Concatenate and linearly transform attended values output = self.fc_concat(attended_values) return output # 使用示例 d_model = 128 num_heads = 8 seq_len = 10 batch_size = 4 input_tensor = torch.randn(batch_size, seq_len, d_model) attention = MultiHeadSelfAttention(d_model, num_heads) output = attention(input_tensor) print("Input Shape: ", input_tensor.shape) print("Output Shape: ", output.shape) ``` 上述代码定义了一个`MultiHeadSelfAttention`的类,其中`forward`函数实现了multi-head self-attention的计算过程。在使用示例中,我们输入一个大小为`(batch_size, seq_len, d_model)`的张量,经过multi-head self-attention计算后输出一个大小为`(batch_size, seq_len, d_model)`的张量。其中`d_model`表示输入的特征维度,`num_heads`表示attention头的数量。 ### 回答3: 下面是使用Python实现multi-head self-attention示例的代码: ```python import torch import torch.nn as nn class MultiHeadSelfAttention(nn.Module): def __init__(self, embed_size, num_heads): super(MultiHeadSelfAttention, self).__init__() self.embed_size = embed_size self.num_heads = num_heads self.head_size = embed_size // num_heads self.query = nn.Linear(embed_size, embed_size) self.key = nn.Linear(embed_size, embed_size) self.value = nn.Linear(embed_size, embed_size) self.out = nn.Linear(embed_size, embed_size) def forward(self, x): batch_size, seq_len, embed_size = x.size() # Split the embedding into num_heads and reshape x = x.view(batch_size, seq_len, self.num_heads, self.head_size) x = x.permute(0, 2, 1, 3) # Apply linear transformations to obtain query, key, and value query = self.query(x) key = self.key(x) value = self.value(x) # Compute scaled dot product attention scores scores = torch.matmul(query, key.permute(0, 1, 3, 2)) scores = scores / self.head_size**0.5 # Apply softmax to obtain attention probabilities attn_probs = nn.Softmax(dim=-1)(scores) # Apply attention weights to value and sum across heads attended = torch.matmul(attn_probs, value) attended = attended.permute(0, 2, 1, 3) attended = attended.contiguous().view(batch_size, seq_len, self.embed_size) # Apply output linear transformation output = self.out(attended) return output ``` 上述代码中定义了一个名为MultiHeadSelfAttention的类,继承自nn.Module,可以通过指定嵌入大小(embed_size)和头部数量(num_heads)来创建多头自注意力层。在前向传播方法forward中,先通过线性变换将输入张量分别变换为查询(query)、键(key)和值(value)张量。然后计算缩放点积注意力得分,将其作为注意力概率经过softmax函数进行归一化。通过注意力概率权重对值进行加权求和,并应用线性变换得到最终的输出张量。最后返回输出张量。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值