""" Sequence of operations """
mixture_w , mixture_ws = self.encoder(mixture)
est_mask = self.separator(mixture_w)
est_source = self.decoder(mixture_ws, est_mask)
class Encoder(nn.Module):
"""Estimation of the nonnegative mixture weight by a 1-D conv layer.
"""
def __init__(self, L, N):
super(Encoder, self).__init__()
# Hyper-parameter
self.L, self.N = L, N
# Components
# 50% overlap
self.conv1d_U = nn.Conv1d(1, N, kernel_size=L, stride=L // 2, bias=False)
def forward(self, mixture):
"""
Args:
mixture: [M, T], M is batch size, T is #samples
Returns:
mixture_w: [M, N, K], where K = (T-L)/(L/2)+1 = 2T/L-1
"""
mixture = torch.unsqueeze(mixture, 1) # [M, 1, T]
mixture_w = F.relu(self.conv1d_U(mixture)) # [M, N, K]
mixture_ws = F.sigmoid(self.conv1d_U(mixture))
return mixture_w
From the above code in the model, I am able to retrieve weights of conv1d_U shown below:
by using model.encoder.con1d_U.weight
self.conv1d_U = nn.Conv1d(1, N, kernel_size=L, stride=L // 2, bias=False)
When I tried to retrieve weights of bottleneck_conv1x1 shown in the code below. I couldn’t find bottleneck_conv1x1 in the model.seperator.network.
Can you explain me how to retrieve weights of individual layers? when they are sequentially coded in a .network, like the one in my case?
class TemporalConvNet(nn.Module):
def __init__(self, N, B, H, P, X, R, C, norm_type="gLN", causal=False,
mask_nonlinear='relu'):
"""
Args:
N: Number of filters in autoencoder
B: Number of channels in bottleneck 1 × 1-conv block
H: Number of channels in convolutional blocks
P: Kernel size in convolutional blocks
X: Number of convolutional blocks in each repeat
R: Number of repeats
C: Number of speakers
norm_type: BN, gLN, cLN
causal: causal or non-causal
mask_nonlinear: use which non-linear function to generate mask
"""
super(TemporalConvNet, self).__init__()
# Hyper-parameter
self.C = C
self.mask_nonlinear = mask_nonlinear
# Components
# [M, N, K] -> [M, N, K]
# chomp = Chomp1d(padding)
layer_norm = ChannelwiseLayerNorm(N)
# [M, N, K] -> [M, B, K]
bottleneck_conv1x1 = nn.Conv1d(N, B, 1, bias=False)
# [M, B, K] -> [M, B, K]
repeats = []
for self.r in range(R):
blocks = []
for self.x in range(X):
dilation = 2**self.x
padding = (P - 1) * dilation if causal else (P - 1) * dilation // 2
blocks += [TemporalBlock(B, H, P, stride=1,
padding=padding,
dilation=dilation,
norm_type=norm_type,
causal=causal)]
repeats += [nn.Sequential(*blocks)]
temporal_conv_net = nn.Sequential(*repeats)
# [M, B, K] -> [M, C*N, K]
mask_conv1x1 = nn.Conv1d(B, C*N, 1, bias=False)
# Put together
self.network = nn.Sequential(layer_norm,
bottleneck_conv1x1,
temporal_conv_net,
mask_conv1x1)
def forward(self, mixture_w):
"""
Keep this API same with TasNet
Args:
mixture_w: [M, N, K], M is batch size
returns:
est_mask: [M, C, N, K]
"""
M, N, K = mixture_w.size()
score = self.network(mixture_w) # [M, N, K] -> [M, C*N, K]
score = score.view(M, self.C, N, K) # [M, C*N, K] -> [M, C, N, K]
if self.mask_nonlinear == 'softmax':
est_mask = F.softmax(score, dim=1)
elif self.mask_nonlinear == 'relu':
est_mask = F.relu(score)
elif self.mask_nonlinear == 'sigmoid':
est_mask = F.sigmoid(score)
elif self.mask_nonlinear == 'softsign':
est_mask = self.softsign(score)
else:
raise ValueError("Unsupported mask non-linear function")
return est_mask