我是一个学习深度学习三个月的新手,正在使用Pytorch做一些小的NLP项目。
最近我尝试重现一篇论文中介绍的GAN网络,使用我自己的文本数据来生成一些特定的问题句子。
这里有一些背景知识…如果你没有时间或兴趣了解这些,直接阅读下面的问题也可以。
根据那篇论文的描述,生成器首先使用正常的问题数据进行常规训练,以确保输出至少看起来像一个真实的问题。然后通过使用辅助分类器的结果(对输出的分类),再次训练生成器以生成特定的(几个独特类别)问题。
然而,由于论文没有公布其代码,我必须自己编写代码。我有这三种训练思路,但我不知道它们的区别,你能告诉我吗?
如果它们的效果几乎相同,你能告诉我哪一种在Pytorch的语法中更推荐吗?非常感谢!
假设判别器对生成器的损失是loss_G_D,分类器对生成器的损失是loss_G_C,且loss_G_D和loss_G_C具有相同的形状,即[batch_size, 损失值],那么它们的区别是什么?
1.
optimizer.zero_grad()loss_G_D = loss_func1(discriminator(generated_data))loss_G_C = loss_func2(classifier(generated_data))loss = loss_G+loss_Closs.backward()optimizer.step()
optimizer.zero_grad()loss_G_D = loss_func1(discriminator(generated_data))loss_G_D.backward()loss_G_C = loss_func2(classifier(generated_data))loss_G_C.backward()optimizer.step()
optimizer.zero_grad()loss_G_D = loss_func1(discriminator(generated_data))loss_G_D.backward()optimizer.step()optimizer.zero_grad()loss_G_C = loss_func2(classifier(generated_data))loss_G_C.backward()optimizer.step()
附加信息:我观察到分类器的分类损失总是比生成器的损失大很多,比如-300对3。所以也许第三种方法更好?
回答:
首先:
loss.backward()
反向传播错误,并为路径上每个具有 requires_grad=True
的参数分配一个梯度。
optimizer.step()
使用存储的梯度更新模型参数
optimizer.zero_grad()
将梯度设为0,这样你就可以为每个批次反向传播损失并更新模型参数,而不干扰其他批次。
1
和 2
非常相似,但如果你的模型使用批次统计或你使用自适应优化器,它们可能会表现出不同的效果。然而,例如,如果你的模型不使用批次统计,并且你使用的是普通的SGD优化器,它们会产生相同的结果,尽管 1
会更快,因为你只进行一次反向传播。
3
是一个完全不同的情况,因为你在处理和反向传播 loss_G_C
之前,使用 loss_G_D.backward()
和 optimizer.step()
更新了模型参数。
考虑到所有这些,具体选择哪一种取决于你的应用需求。