MCPcopy Create free account
hub / github.com/M-Nauta/ProtoTree / forward

Method forward

util/l2conv.py:26–64  ·  view source on GitHub ↗

Perform convolution over the input using the squared L2 distance for all prototypes in the layer :param xs: A batch of input images obtained as output from some convolutional neural network F. Following the notation from the paper, let the shape of xs be (batch

(self, xs)

Source from the content-addressed store, hash-verified

24 self.prototype_vectors = nn.Parameter(torch.randn(prototype_shape), requires_grad=True)
25
26 def forward(self, xs):
27 """
28 Perform convolution over the input using the squared L2 distance for all prototypes in the layer
29 :param xs: A batch of input images obtained as output from some convolutional neural network F. Following the
30 notation from the paper, let the shape of xs be (batch_size, D, W, H), where
31 - D is the number of output channels of the conv net F
32 - W is the width of the convolutional output of F
33 - H is the height of the convolutional output of F
34 :return: a tensor of shape (batch_size, num_prototypes, W, H) obtained from computing the squared L2 distances
35 for patches of the input using all prototypes
36 """
37 # Adapted from ProtoPNet
38 # Computing ||xs - ps ||^2 is equivalent to ||xs||^2 + ||ps||^2 - 2 * xs * ps
39 # where ps is some prototype image
40
41 # So first we compute ||xs||^2 (for all patches in the input image that is. We can do this by using convolution
42 # with weights set to 1 so each patch just has its values summed)
43 ones = torch.ones_like(self.prototype_vectors,
44 device=xs.device) # Shape: (num_prototypes, num_features, w_1, h_1)
45 xs_squared_l2 = F.conv2d(xs ** 2, weight=ones) # Shape: (bs, num_prototypes, w_in, h_in)
46
47 # Now compute ||ps||^2
48 # We can just use a sum here since ||ps||^2 is the same for each patch in the input image when computing the
49 # squared L2 distance
50 ps_squared_l2 = torch.sum(self.prototype_vectors ** 2,
51 dim=(1, 2, 3)) # Shape: (num_prototypes,)
52 # Reshape the tensor so the dimensions match when computing ||xs||^2 + ||ps||^2
53 ps_squared_l2 = ps_squared_l2.view(-1, 1, 1)
54
55 # Compute xs * ps (for all patches in the input image)
56 xs_conv = F.conv2d(xs, weight=self.prototype_vectors) # Shape: (bs, num_prototypes, w_in, h_in)
57
58 # Use the values to compute the squared L2 distance
59 distance = xs_squared_l2 + ps_squared_l2 - 2 * xs_conv
60 distance = torch.sqrt(torch.abs(distance)+1e-14) #L2 distance (not squared). Small epsilon added for numerical stability
61
62 if torch.isnan(distance).any():
63 raise Exception('Error: NaN values! Using the --log_probabilities flag might fix this issue')
64 return distance # Shape: (bs, num_prototypes, w_in, h_in)

Callers 1

gen_pred_visFunction · 0.45

Calls

no outgoing calls

Tested by

no test coverage detected