Chainer 中加载的神经网络层的梯度
Gradient of the layers of a loaded neural network in Chainer
我正在 Chainer 中加载预训练模型:
net=chainer.links.VGG16Layers(pretrained_model='auto')
然后,我用一些数据进行正向传递并添加一个损失层:
acts = net.predict([image]).array
loss=chainer.Variable(np.array(np.sum(np.square(acts-one_hot))))
现在的问题是,如何进行反向传递并获得不同层的梯度?
典型的向后方法不起作用。
第 1 点。
不要调用 VGGLayers.predict()
,它不用于反向传播计算。
请改用 VGGLayers.extract()
。
第 2 点。
不要将 np.square()
和 np.sum()
直接应用于 chainer.Variable
.
请使用 F.square()
和 F.sum()
代替 chainer.Variable
。
第 3 点
使用 loss.backward()
获取 .grad
可学习参数。 (模式 1)
使用 loss.backward(retain_grad=True)
获取所有变量的 .grad
。 (模式 2)
使用 chainer.grad()
获取特定变量的 .grad
。 (模式 3)
代码:
import chainer
from chainer import functions as F, links as L
from cv2 import imread
net = L.VGG16Layers(pretrained_model='auto')
img = imread("/path/to/img")
prob = net.extract([img], layers=['prob'])['prob'] # NOT predict, which overrides chainer.config['enable_backprop'] as False
intermediate = F.square(prob)
loss = F.sum(intermediate)
# pattern 1:
loss.backward()
print(net.fc8.W.grad) # some ndarray
print(intermediate.grad) # None
###########################################
net.cleargrads()
intermediate.grad = None
prob.grad = None
###########################################
# pattern 2:
loss.backward(retain_grad=True)
print(net.fc8.W.grad) # some ndarray
print(intermediate.grad) # some ndarray
###########################################
net.cleargrads()
intermediate.grad = None
prob.grad = None
###########################################
# pattern 3:
print(chainer.grad([loss], [net.fc8.W])) # some ndarray
print(intermediate.grad) # None
如果你想得到输入图像的.grad
,你必须用chainer.Variable
包裹输入。
然而,VGGLayers.extract()
不支持 Variable
的输入,所以在这种情况下你应该调用 .forward()
或者它的包装函数 __call__()
.
import chainer
from chainer import Variable
from chainer import functions as F
from cv2 import imread
from chainer.links.model.vision import vgg
net = vgg.VGG16Layers(pretrained_model='auto')
# convert raw image (np.ndarray, dtype=uint32) to a batch of Variable(dtype=float32)
img = imread("path/to/image")
img = Variable(vgg.prepare(img))
img = img.reshape((1,) + img.shape) # (channel, width, height) -> (batch, channel, width, height)
# just call VGG16Layers.forward, which is wrapped by __call__()
prob = net(img)['prob']
intermediate = F.square(prob)
loss = F.sum(intermediate)
# calculate grad
img_grad = chainer.grad([loss], [img]) # returns Variable
print(img_grad.array) # some ndarray
我正在 Chainer 中加载预训练模型:
net=chainer.links.VGG16Layers(pretrained_model='auto')
然后,我用一些数据进行正向传递并添加一个损失层:
acts = net.predict([image]).array
loss=chainer.Variable(np.array(np.sum(np.square(acts-one_hot))))
现在的问题是,如何进行反向传递并获得不同层的梯度?
典型的向后方法不起作用。
第 1 点。
不要调用 VGGLayers.predict()
,它不用于反向传播计算。
请改用 VGGLayers.extract()
。
第 2 点。
不要将 np.square()
和 np.sum()
直接应用于 chainer.Variable
.
请使用 F.square()
和 F.sum()
代替 chainer.Variable
。
第 3 点
使用 loss.backward()
获取 .grad
可学习参数。 (模式 1)
使用 loss.backward(retain_grad=True)
获取所有变量的 .grad
。 (模式 2)
使用 chainer.grad()
获取特定变量的 .grad
。 (模式 3)
代码:
import chainer
from chainer import functions as F, links as L
from cv2 import imread
net = L.VGG16Layers(pretrained_model='auto')
img = imread("/path/to/img")
prob = net.extract([img], layers=['prob'])['prob'] # NOT predict, which overrides chainer.config['enable_backprop'] as False
intermediate = F.square(prob)
loss = F.sum(intermediate)
# pattern 1:
loss.backward()
print(net.fc8.W.grad) # some ndarray
print(intermediate.grad) # None
###########################################
net.cleargrads()
intermediate.grad = None
prob.grad = None
###########################################
# pattern 2:
loss.backward(retain_grad=True)
print(net.fc8.W.grad) # some ndarray
print(intermediate.grad) # some ndarray
###########################################
net.cleargrads()
intermediate.grad = None
prob.grad = None
###########################################
# pattern 3:
print(chainer.grad([loss], [net.fc8.W])) # some ndarray
print(intermediate.grad) # None
如果你想得到输入图像的.grad
,你必须用chainer.Variable
包裹输入。
然而,VGGLayers.extract()
不支持 Variable
的输入,所以在这种情况下你应该调用 .forward()
或者它的包装函数 __call__()
.
import chainer
from chainer import Variable
from chainer import functions as F
from cv2 import imread
from chainer.links.model.vision import vgg
net = vgg.VGG16Layers(pretrained_model='auto')
# convert raw image (np.ndarray, dtype=uint32) to a batch of Variable(dtype=float32)
img = imread("path/to/image")
img = Variable(vgg.prepare(img))
img = img.reshape((1,) + img.shape) # (channel, width, height) -> (batch, channel, width, height)
# just call VGG16Layers.forward, which is wrapped by __call__()
prob = net(img)['prob']
intermediate = F.square(prob)
loss = F.sum(intermediate)
# calculate grad
img_grad = chainer.grad([loss], [img]) # returns Variable
print(img_grad.array) # some ndarray