in sparseconvnet/networkArchitectures.py [0:0]
def UNet(dimension, reps, nPlanes, residual_blocks=False, downsample=[2, 2], leakiness=0, n_input_planes=-1):
"""
U-Net style network with VGG or ResNet-style blocks.
For voxel level prediction:
import sparseconvnet as scn
import torch.nn
class Model(nn.Module):
def __init__(self):
nn.Module.__init__(self)
self.sparseModel = scn.Sequential().add(
scn.SubmanifoldConvolution(3, nInputFeatures, 64, 3, False)).add(
scn.UNet(3, 2, [64, 128, 192, 256], residual_blocks=True, downsample=[2, 2]))
self.linear = nn.Linear(64, nClasses)
def forward(self,x):
x=self.sparseModel(x).features
x=self.linear(x)
return x
"""
def block(m, a, b):
if residual_blocks: #ResNet style blocks
m.add(scn.ConcatTable()
.add(scn.Identity() if a == b else scn.NetworkInNetwork(a, b, False))
.add(scn.Sequential()
.add(scn.BatchNormLeakyReLU(a,leakiness=leakiness))
.add(scn.SubmanifoldConvolution(dimension, a, b, 3, False))
.add(scn.BatchNormLeakyReLU(b,leakiness=leakiness))
.add(scn.SubmanifoldConvolution(dimension, b, b, 3, False)))
).add(scn.AddTable())
else: #VGG style blocks
m.add(scn.Sequential()
.add(scn.BatchNormLeakyReLU(a,leakiness=leakiness))
.add(scn.SubmanifoldConvolution(dimension, a, b, 3, False)))
def U(nPlanes,n_input_planes=-1): #Recursive function
m = scn.Sequential()
for i in range(reps):
block(m, n_input_planes if n_input_planes!=-1 else nPlanes[0], nPlanes[0])
n_input_planes=-1
if len(nPlanes) > 1:
m.add(
scn.ConcatTable().add(
scn.Identity()).add(
scn.Sequential().add(
scn.BatchNormLeakyReLU(nPlanes[0],leakiness=leakiness)).add(
scn.Convolution(dimension, nPlanes[0], nPlanes[1],
downsample[0], downsample[1], False)).add(
U(nPlanes[1:])).add(
scn.BatchNormLeakyReLU(nPlanes[1],leakiness=leakiness)).add(
scn.Deconvolution(dimension, nPlanes[1], nPlanes[0],
downsample[0], downsample[1], False))))
m.add(scn.JoinTable())
for i in range(reps):
block(m, nPlanes[0] * (2 if i == 0 else 1), nPlanes[0])
return m
m = U(nPlanes,n_input_planes)
return m