facebookresearch / odin

A simple and effective method for detecting out-of-distribution images in neural networks.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

About Input Processing code

chagmgang opened this issue · comments

In the paper, the equation of input preprocessing( eq(2) in paper) is x˜ = x − εsign(−∇x log Syˆ(x; T)).

This equation is introduced in your repository, https://github.com/facebookresearch/odin/blob/master/code/calData.py#L72

tempInputs = torch.add(inputs.data,  -noiseMagnitude1, gradient)

However, the gradient = torch.ge(inputs.grad.data, 0) in your line 65 represents sign(∇x log Syˆ(x; T))
In fact, I think that your code is to implement x˜ = x − εsign(∇x log Syˆ(x; T)) not x˜ = x − εsign(-∇x log Syˆ(x; T))

What's your opinion?

Thank you for answering.

Furthermore, in the paper, the perturbated input is decreasing the maximum softmax score. In literally,

small perturbations are added to decrease the softmax
score for the true label and force the neural network to make a wrong prediction.

However, with your code, softmax score increases not decreasing.

Below is code printing the softmax score of both with perturbation input and without perburbation input.

Also, in my case,

noiseMagnitude1 = 0.0014
temper = 1000
images, _ = data

inputs = Variable(images.cuda(CUDA_DEVICE), requires_grad = True)
outputs = net1(inputs)

### printing softmax
printing_indices = torch.argmax(outputs, axis=1)[0]
printing_softmax = F.softmax(outputs, dim=-1)[0][printing_indices]
print('original outputs: ', printing_softmax)

# Calculating the confidence of the output, no perturbation added here, no temperature scaling used
nnOutputs = outputs.data.cpu()
nnOutputs = nnOutputs.numpy()
nnOutputs = nnOutputs[0]
nnOutputs = nnOutputs - np.max(nnOutputs)
nnOutputs = np.exp(nnOutputs)/np.sum(np.exp(nnOutputs))
f1.write("{}, {}, {}\n".format(temper, noiseMagnitude1, np.max(nnOutputs)))

# Using temperature scaling
outputs = outputs / temper

# Calculating the perturbation we need to add, that is,
# the sign of gradient of cross entropy loss w.r.t. input
maxIndexTemp = np.argmax(nnOutputs)
labels = Variable(torch.LongTensor([maxIndexTemp]).cuda(CUDA_DEVICE))
loss = criterion(outputs, labels)
loss.backward()

# Normalizing the gradient to binary in {0, 1}
gradient =  torch.ge(inputs.grad.data, 0)
gradient = (gradient.float() - 0.5) * 2
# Normalizing the gradient to the same space of image
gradient[0][0] = (gradient[0][0])/(0.2023)
gradient[0][1] = (gradient[0][1])/(0.1994)
gradient[0][2] = (gradient[0][2])/(0.2010)
# Adding small perturbations to images
tempInputs = torch.add(inputs.data,  -noiseMagnitude1, gradient)
outputs = net1(Variable(tempInputs))

### printing softmax
printing_indices = torch.argmax(outputs, axis=1)[0]
printing_softmax = F.softmax(outputs, dim=-1)[0][printing_indices]
print('perturbated outputs: ', printing_softmax)
print('------------')

outputs = outputs / temper
# Calculating the confidence after adding perturbations
nnOutputs = outputs.data.cpu()
nnOutputs = nnOutputs.numpy()
nnOutputs = nnOutputs[0]
nnOutputs = nnOutputs - np.max(nnOutputs)
nnOutputs = np.exp(nnOutputs)/np.sum(np.exp(nnOutputs))
g1.write("{}, {}, {}\n".format(temper, noiseMagnitude1, np.max(nnOutputs)))

Below is the some result of printed softmax score

original outputs:  tensor(0.5309, device='cuda:0', grad_fn=<SelectBackward>)
perturbated outputs:  tensor(0.9331, device='cuda:0', grad_fn=<SelectBackward>)
------------
original outputs:  tensor(1.0000, device='cuda:0', grad_fn=<SelectBackward>)
perturbated outputs:  tensor(1., device='cuda:0', grad_fn=<SelectBackward>)
------------
original outputs:  tensor(0.9995, device='cuda:0', grad_fn=<SelectBackward>)
perturbated outputs:  tensor(1.0000, device='cuda:0', grad_fn=<SelectBackward>)
------------
original outputs:  tensor(0.9942, device='cuda:0', grad_fn=<SelectBackward>)
perturbated outputs:  tensor(0.9996, device='cuda:0', grad_fn=<SelectBackward>)
------------
original outputs:  tensor(0.7618, device='cuda:0', grad_fn=<SelectBackward>)
perturbated outputs:  tensor(0.9521, device='cuda:0', grad_fn=<SelectBackward>)
------------
original outputs:  tensor(0.9991, device='cuda:0', grad_fn=<SelectBackward>)
perturbated outputs:  tensor(1.0000, device='cuda:0', grad_fn=<SelectBackward>)
------------
original outputs:  tensor(0.9775, device='cuda:0', grad_fn=<SelectBackward>)
perturbated outputs:  tensor(0.9994, device='cuda:0', grad_fn=<SelectBackward>)
------------
original outputs:  tensor(0.9907, device='cuda:0', grad_fn=<SelectBackward>)
perturbated outputs:  tensor(0.9997, device='cuda:0', grad_fn=<SelectBackward>)
------------
original outputs:  tensor(0.7449, device='cuda:0', grad_fn=<SelectBackward>)
perturbated outputs:  tensor(0.9994, device='cuda:0', grad_fn=<SelectBackward>)
------------

I can't understand this phenomenon What do you think?

Thanks for answering.
All questions are solved.