Tensorflow 如何两次得到损失函数的梯度
以下是我试图实现的目标: 我们通常根据Tensorflow 如何两次得到损失函数的梯度,tensorflow,pytorch,Tensorflow,Pytorch,以下是我试图实现的目标: 我们通常根据F(X)计算损失。但我们也定义了“对抗性损失”,即基于F(X+e)的损失e定义为dF(X)/dX乘以某个常数。损失和对抗性损失都是总损失的反向传播 在tensorflow中,此部分(获取dF(X)/dX)可按如下方式编码: grad, = tf.gradients( loss, X ) grad = tf.stop_gradient(grad) e = constant * grad 下面是我的pytorch代码: class DocReade
F(X)
计算损失。但我们也定义了“对抗性损失”,即基于F(X+e)
的损失e
定义为dF(X)/dX
乘以某个常数。损失和对抗性损失都是总损失的反向传播
在tensorflow中,此部分(获取dF(X)/dX
)可按如下方式编码:
grad, = tf.gradients( loss, X )
grad = tf.stop_gradient(grad)
e = constant * grad
下面是我的pytorch代码:
class DocReaderModel(object):
def __init__(self, embedding=None, state_dict=None):
self.train_loss = AverageMeter()
self.embedding = embedding
self.network = DNetwork(opt, embedding)
self.optimizer = optim.SGD(parameters)
def adversarial_loss(self, batch, loss, embedding, y):
self.optimizer.zero_grad()
loss.backward(retain_graph=True)
grad = embedding.grad
grad.detach_()
perturb = F.normalize(grad, p=2)* 0.5
self.optimizer.zero_grad()
adv_embedding = embedding + perturb
network_temp = DNetwork(self.opt, adv_embedding) # This is how to get F(X)
network_temp.training = False
network_temp.cuda()
start, end, _ = network_temp(batch) # This is how to get F(X)
del network_temp # I even deleted this instance.
return F.cross_entropy(start, y[0]) + F.cross_entropy(end, y[1])
def update(self, batch):
self.network.train()
start, end, pred = self.network(batch)
loss = F.cross_entropy(start, y[0]) + F.cross_entropy(end, y[1])
loss_adv = self.adversarial_loss(batch, loss, self.network.lexicon_encoder.embedding.weight, y)
loss_total = loss + loss_adv
self.optimizer.zero_grad()
loss_total.backward()
self.optimizer.step()
我有几个问题:
1) 我将tf.stop_梯度替换为grad.detach_u()。这是正确的吗
2) 我得到了“RuntimeError:第二次尝试通过图形反向运行,但缓冲区已被释放。第一次调用backward时指定retain\u graph=True。”
因此我在loss.backward
处添加了retain\u graph=True
。那个具体的错误消失了。
然而,现在我在经历了几个时代之后出现了一个内存错误(RuntimeError:cuda运行时错误(2):在/opt/conda/conda bld/pytorch_1525909934016/work/aten/src/THC/generic/THCStorage.cu:58处内存不足
).我怀疑我没有必要保留图表
有人能告诉我pytorch在这方面的最佳实践吗?任何提示/即使是简短的评论都将受到高度赞赏。我认为您正在尝试实现生成性对抗网络(GAN),但从代码来看,我不理解,也无法理解您试图实现的目标,因为GAN缺少一些功能。我可以看到有一个鉴别器网络模块,DNetwork
,但缺少发电机网络模块
如果要猜的话,当你说“损失函数两次”时,我假设你的意思是,你有一个用于鉴别器网络的损失函数,另一个用于发生器网络。如果是这样的话,让我来分享一下我将如何实现一个基本的GAN模型
作为一个例子,让我们来看看这个
我将跳过不太重要的部分,在这里放大重要的部分:
首先,导入PyTorch库并设置
# Set up batch size, image size, and size of noise vector:
bs, sz, nz = 64, 64, 100 # nz is the size of the latent z vector for creating some random noise later
构建鉴别器模块
class DCGAN_D(nn.Module):
def __init__(self):
... truncated, the usual neural nets stuffs, layers, etc ...
def forward(self, input):
... truncated, the usual neural nets stuffs, layers, etc ...
class DCGAN_G(nn.Module):
def __init__(self):
... truncated, the usual neural nets stuffs, layers, etc ...
def forward(self, input):
... truncated, the usual neural nets stuffs, layers, etc ...
构建一个生成器模块
class DCGAN_D(nn.Module):
def __init__(self):
... truncated, the usual neural nets stuffs, layers, etc ...
def forward(self, input):
... truncated, the usual neural nets stuffs, layers, etc ...
class DCGAN_G(nn.Module):
def __init__(self):
... truncated, the usual neural nets stuffs, layers, etc ...
def forward(self, input):
... truncated, the usual neural nets stuffs, layers, etc ...
把它们放在一起
netG = DCGAN_G().cuda()
netD = DCGAN_D().cuda()
优化器需要被告知要优化哪些变量。模块自动跟踪其变量
optimizerD = optim.RMSprop(netD.parameters(), lr = 1e-4)
optimizerG = optim.RMSprop(netG.parameters(), lr = 1e-4)
鉴别器的一个前进步和一个后退步
在这里,网络可以计算反向过程中的梯度,这取决于此函数的输入。因此,在我的情况下,我有3种类型的损失;发生器损失,分色器真实图像损失,分色器假图像损失。我可以得到三次不同净传递的损失函数梯度
def step_D(input, init_grad):
# input can be from generator's generated image data or input image from dataset
err = netD(input)
err.backward(init_grad) # backward pass net to calculate gradient
return err # loss
控制可训练参数[重要信息]
模型中的可训练参数是那些需要梯度的参数
def make_trainable(net, val):
for p in net.parameters():
p.requires_grad = val # note, i.e, this is later set to False below in netG update in the train loop.
在TensorFlow中,该部分可按如下方式编码:
梯度=tf.梯度(损失,X)
梯度=tf.停止梯度(梯度)
所以,我想这将回答你的第一个问题,“我用grad.detach_u()替换了tf.stop_u梯度。这是正确的吗?”
列车环路
你可以在这里看到3个不同的损失函数是如何被调用的
def train(niter, first=True):
for epoch in range(niter):
# Make iterable from PyTorch DataLoader
data_iter = iter(dataloader)
i = 0
while i < n:
###########################
# (1) Update D network
###########################
make_trainable(netD, True)
# train the discriminator d_iters times
d_iters = 100
j = 0
while j < d_iters and i < n:
j += 1
i += 1
# clamp parameters to a cube
for p in netD.parameters():
p.data.clamp_(-0.01, 0.01)
data = next(data_iter)
##### train with real #####
real_cpu, _ = data
real_cpu = real_cpu.cuda()
real = Variable( data[0].cuda() )
netD.zero_grad()
# Real image discriminator loss
errD_real = step_D(real, one)
##### train with fake #####
fake = netG(create_noise(real.size()[0]))
input.data.resize_(real.size()).copy_(fake.data)
# Fake image discriminator loss
errD_fake = step_D(input, mone)
# Discriminator loss
errD = errD_real - errD_fake
optimizerD.step()
###########################
# (2) Update G network
###########################
make_trainable(netD, False)
netG.zero_grad()
# Generator loss
errG = step_D(netG(create_noise(bs)), one)
optimizerG.step()
print('[%d/%d][%d/%d] Loss_D: %f Loss_G: %f Loss_D_real: %f Loss_D_fake %f'
% (epoch, niter, i, n,
errD.data[0], errG.data[0], errD_real.data[0], errD_fake.data[0]))
def序列(niter,first=True):
对于范围内的历元(niter):
#从PyTorch数据加载器使其可用
数据_iter=iter(数据加载器)
i=0
而i
“我得到了”RuntimeError:第二次尝试通过图形反向
PyTorch具有这种行为;为了减少GPU内存使用,在调用.backward()
期间,所有中间结果(如果您有保存的激活等)都会在不再需要时被删除。因此,如果您尝试调用.backward())
同样,中间结果不存在,无法执行反向传递(并且您会看到错误)
这取决于您尝试执行的操作。您可以调用.backward(retain\u graph=True)
进行向后传递,该传递不会删除中间结果,因此您可以