ftramer / ensemble-adv-training

Ensemble Adversarial Training on MNIST
MIT License
121 stars 31 forks source link

Tool for loss surfaces? #3

Closed akskuchi closed 5 years ago

akskuchi commented 5 years ago

Hello, Could you disclose the tool you used for visualizing the loss surfaces of models in the publication?

ftramer commented 5 years ago

They are plain matplotlib 3D plots (see https://matplotlib.org/mpl_toolkits/mplot3d/tutorial.html#surface-plots).

akskuchi commented 5 years ago

Got it, thank you! Also, in this expression: image

how do you pick the gradient from modelB that is in the orthogonal adversarial direction to g of modelA_adv? or am I missing something basic?

ftramer commented 5 years ago

The gradient of modelB actually happens to be roughly orthogonal to that of modelA_adv so we don't have to do anything special here.

akskuchi commented 5 years ago

Oh, that's interesting. So what I tried was:

x_star[i] = x + epsilon * (_g + _g_orthogonal)


- run all `x_star` through modelA_adv and collect losses

Now, maybe for some trivial reason, I am stuck on how to plot the loss surfaces?
interpolate `eps1` and `eps2` between `0.0 - 0.3` and [tri-surface plot](https://matplotlib.org/mpl_toolkits/mplot3d/tutorial.html#tri-surface-plots) them? or am I completely lost?
ftramer commented 5 years ago

Yes, the typical workflow would look something like this (I haven't tested this specific code so there might be some small bugs):

import numpy as np
from mpl_toolkits.mplot3d import axes3d, Axes3D
from matplotlib import cm

# bounds for the x and y axis
x1, x2, y1, y2 = [0.0, 0.3, 0.0, 0.3]

# step size
h_x = (x2 - x1) / 100.0
h_y = (y2 - y1) / 100.0

# create a grid (of size 100x100) of (x,y) coordinates 
xx, yy = np.meshgrid(np.arange(x1, x2, h_x), np.arange(y1, x2, h_y))

perturbs = xx.reshape((-1, 1)) * g.reshape((1, -1)) + yy.reshape((-1, 1)) * g_ortho.reshape((1, -1))

X_perturbs[i] = X[i] + perturbs.reshape((-1, X.shape[1], X.shape[2], X.shape[3]))

# evaluate the model on X_perturbs[i]
losses = ...

fig = plt.figure(figsize=(10, 8))
ax = Axes3D(fig, rect=[0.0, 0.0, 0.9, 1.0])
surf = ax.plot_surface(xx, yy, np.asarray(losses).reshape(xx.shape), cmap=cm.coolwarm,
                       linewidth=0, antialiased=False)
fig.colorbar(surf, shrink=0.5, aspect=5)
plt.show()
akskuchi commented 5 years ago

Thank you for clarifying. I tried it:

print(f'min loss: {min(losses)}, max loss: {max(losses)}')
fig = plt.figure(figsize=(10, 8))
ax = Axes3D(fig, rect=[0.0, 0.0, 0.9, 1.0])
surf = ax.plot_surface(xx, yy, np.asarray(losses).reshape(xx.shape),
                       cmap=cm.coolwarm, linewidth=0, antialiased=False)
fig.colorbar(surf, shrink=0.5, aspect=5)
plt.show()

which results in: min loss: 0.0, max loss: 4.505677223205566

image

From the colorbar, I see that the losses need to be normalized or moved to some other scale, but for some reason, it does not give the landscape (like in the publication) :/

akskuchi commented 5 years ago

I get the idea behind and will look further for any mistakes I'm doing. Thanks a lot for all the explanation.