浅谈Attention UNet

1 理论

浅谈Attention UNet
浅谈Attention UNet
其中,g就是解码部分的矩阵,xl是编码(左边)的矩阵,x经过乘于系数(完成Attention)和g一起concat,进入下一层解码。

数学公式:
浅谈Attention UNet

2 实践

Pytorch Attention Unet:

class Attention_block(nn.Module):
    def __init__(self,F_g,F_l,F_int):
        super(Attention_block,self).__init__()
        self.W_g = nn.Sequential(
            nn.Conv2d(F_g, F_int, kernel_size=1,stride=1,padding=0,bias=True),
            nn.BatchNorm2d(F_int)
            )
        
        self.W_x = nn.Sequential(
            nn.Conv2d(F_l, F_int, kernel_size=1,stride=1,padding=0,bias=True),
            nn.BatchNorm2d(F_int)
        )

        self.psi = nn.Sequential(
            nn.Conv2d(F_int, 1, kernel_size=1,stride=1,padding=0,bias=True),
            nn.BatchNorm2d(1),
            nn.Sigmoid()
        )
        
        self.relu = nn.ReLU(inplace=True)
        
    def forward(self,g,x):
        g1 = self.W_g(g)
        x1 = self.W_x(x)
        psi = self.relu(g1+x1)
        psi = self.psi(psi)

        return x*psi

numpy 版本理解:

import numpy as np
a = np.array([[1,1,0],[0,1,0],[1,1,1]])
b = np.array([[1,0,0],[0,1,0],[1,0,1]])
import torch
#m = nn.Sigmoid()
#print(m(torch.from_numpy(a).float()))
n_dim = 2
w1 = np.random.normal(0, 1, (a.shape[0],n_dim))
w2 = np.random.normal(0, 1, (b.shape[0],n_dim))
w3 = np.random.normal(0, 1, (n_dim,1))
def relu(x):
    return x*(x>0)
def sigmoid(x):
    return 1/(1+ np.exp(-x))
#
res = np.matmul((np.matmul(a,w1) + np.matmul(b,w2)),w3)
resRelu = relu(res)
resSigmoid= sigmoid(resRelu)
final = a*resSigmoid
print('a:\n', a)
print('\nb\n',b)
print('\n final a:\n',final)

输出:

a:
 [[1 1 0]
 [0 1 0]
 [1 1 1]]

b
 [[1 0 0]
 [0 1 0]
 [1 0 1]]

 final a:
 [[0.84840315 0.84840315 0.        ]
 [0.         0.70498539 0.        ]
 [0.58395277 0.58395277 0.58395277]]

这里,可以看出,Attention的作用就是调整权重。

3 疑问与理解

使用两个矩阵相乘,第一次相乘是,g,x之间的权重分配,第二次相乘是,每个像素的权重分配。


参考:
1 GitHub源码:Attention U-Net: Learning Where to Look for the Pancreas
2 Pytorch attention Unet;