PyTorch model sensitivity analysis

rcalix: <p>Hello,</p>
<p>I want to do a sensitivity analysis of a torch nn regression model. I understand how it works like this:</p>
<p>x1 = torch.randn(1, requires_grad=True)<br>
x2 = torch.randn(1, requires_grad=True)</p>
<h2>
<a name="u-ux1x2-1" class="anchor" href="#u-ux1x2-1"></a>u = u(x1,x2)</h2>
<p>u = 3 * x1 ** 3 - x2 ** 2<br>
print(u)</p>
<h1>
<a name="h-1st-derivatives-2" class="anchor" href="#h-1st-derivatives-2"></a>1st derivatives</h1>
<p>dx1 = torch.autograd.grad(u, x1)[0]<br>
dx2 = torch.autograd.grad(u, x2)[0]<br>
print(dx1)<br>
print(dx2)<br>
print(dx1 &gt; dx2)</p>
<p>But how do I reference the input features (x1, x2) and the u (model), if I am using an NN module like this:</p>
<h2>
<a name="linear-regression-3" class="anchor" href="#linear-regression-3"></a>Linear Regression</h2>
<p>class LinRegNet_SIO(nn.Module):<br>
## initialize the layers<br>
def <strong>init</strong>(self, x_means, x_deviations, y_means, y_deviations):<br>
super().<strong>init</strong>()<br>
self.x_means      = x_means<br>
self.x_deviations = x_deviations<br>
self.y_means      = y_means<br>
self.y_deviations = y_deviations<br>
self.linear1 = nn.Linear(4, 2)</p>
<pre><code>## perform inference
def forward(self, x):
    x = (x - self.x_means) / self.x_deviations
    y_scaled = self.linear1(x)
    y_descaled = y_scaled * self.y_deviations + self.y_means
    return y_descaled, y_scaled
</code></pre>
<p>is it something like this?</p>
<p>u = model()</p>
<h1>
<a name="h-1st-derivatives-4" class="anchor" href="#h-1st-derivatives-4"></a>1st derivatives</h1>
<p>dx1 = torch.autograd.grad(u, u.layers.input.x1)[0]<br>
dx2 = torch.autograd.grad(u, u.layers.inout.x2)[0]<br>
print(dx1)</p>
<p>Thanks!</p>

rcalix: <p>Hello,</p>
<p>Can someone help me with this?</p>
<p>Thanks</p>

ptrblck: <p>PyTorch modules do not store an <code>.input</code> attribute and I assume <code>x1</code> and <code>x2</code> are treated as trainable parameters in the first example? If so, they would correspond to e.g. <code>u.linear1.weight</code>.</p>

rcalix: <p>Thanks for your reply. I need the derivatives in terms of each feature such as:</p>
<p>du/dx1    and    du/x2</p>
<p>so I need to access the input tensor from the computational graph. Is there another way to do that?</p>
<p>u.linear1.weight is a reference to the weights but I need the layer before that (i.e. the input)</p>
<p>Thanks</p>

ptrblck: <p>I’m unsure what your exact use case is, but maybe <a href="https://pytorch.org/docs/stable/generated/torch.autograd.grad.html#torch.autograd.grad"><code>torch.autograd.grad</code></a> is what you are looking for.</p>

rcalix: <p>Thank you. Yes, torch.autograd is what I have been using. The use case is feature ranking. In theory, you can use the derivatives of the function with respect to each input. In a classic linear regression it is called sensitivity analysis. I just have not seen this done for neural nets and PyTorch.</p>
<p>The goal is to know which features are most important for the regression model prediction.</p>
<p>Thank you.</p>

ptrblck: <p>Would <a href="https://discuss.pytorch.org/t/derivative-of-model-outputs-w-r-t-input-features/95814/2">this approach</a> of looping through the inputs to calculate the gradients (or using <code>jacobian</code>) work for your use case?</p>