Python PyTorch:定义的层不参与正向传播,但影响损耗值

Python PyTorch:定义的层不参与正向传播,但影响损耗值,python,deep-learning,pytorch,Python,Deep Learning,Pytorch,最近,当我使用Pytork做逻辑回归的简单实验时,我遇到了一个令人困惑的现象 问题是当我修复随机种子时,如下所示: def set_seed(seed, cuda=True): np.random.seed(seed) torch.manual_seed(seed) if cuda: torch.cuda.manual_seed(seed) class net(nn.Module): def __init__(self): sup

最近,当我使用Pytork做逻辑回归的简单实验时,我遇到了一个令人困惑的现象

问题是当我修复随机种子时,如下所示:

def set_seed(seed, cuda=True):
    np.random.seed(seed)
    torch.manual_seed(seed)
    if cuda:
        torch.cuda.manual_seed(seed)
class net(nn.Module):
    def __init__(self):
        super(net, self).__init__()
        self.hidden = nn.Linear(784, 100)
        self.output = nn.Linear(100, 10)
        self.add = nn.Linear(10,10)

    def forward(self, x):
        x = self.hidden(x)
        x = self.output(x)
        return x

并定义了以下具有2层的模型:

class net(nn.Module):
    def __init__(self):
        super(net, self).__init__()
        self.hidden = nn.Linear(784, 100)
        self.output = nn.Linear(100, 10)

    def forward(self, x):
        x = self.hidden(x)
        x = self.output(x)
        return x
对网络进行以下培训:

criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(net.parameters(), lr=0.1)
原始损失值为0.6422,可重复

但是,当我添加一个在转发过程中未涉及的附加层时,如下所示:

def set_seed(seed, cuda=True):
    np.random.seed(seed)
    torch.manual_seed(seed)
    if cuda:
        torch.cuda.manual_seed(seed)
class net(nn.Module):
    def __init__(self):
        super(net, self).__init__()
        self.hidden = nn.Linear(784, 100)
        self.output = nn.Linear(100, 10)
        self.add = nn.Linear(10,10)

    def forward(self, x):
        x = self.hidden(x)
        x = self.output(x)
        return x

原始损失值更改为0.7431,与前一个值不相等,同时模型性能下降


我真想知道为什么会这样。谢谢大家!

如果在计算损失之前存在其他随机性来源(消耗RNG的东西),则这是完全可以预料的。由于您没有提供,我猜您使用的是带有
shuffle=True的
DataLoader
。在这种情况下,即使您不使用
self.add
层,当您初始化它时,它也会消耗RNG;因此导致样品的顺序不同。如果随机性来自具有
shuffle=True
的数据加载器,则可以通过向数据加载器提供不同的RNG来控制随机性。大概是这样的:

def set_seed(seed, cuda=True):
    np.random.seed(seed)
    torch.manual_seed(seed)
    if cuda:
        torch.cuda.manual_seed(seed)
class net(nn.Module):
    def __init__(self):
        super(net, self).__init__()
        self.hidden = nn.Linear(784, 100)
        self.output = nn.Linear(100, 10)
        self.add = nn.Linear(10,10)

    def forward(self, x):
        x = self.hidden(x)
        x = self.output(x)
        return x

将numpy导入为np
进口火炬
从火炬进口
进口火炬视觉
从torchvision.com导入传感器
def set_seed(seed,cuda=True):
np.随机种子(种子)
手电筒.手动种子(种子)
如果cuda:
火炬。cuda。手动种子(种子)
类别网络(nn.模块):
定义初始化(自):
超级(网络,自我)。\uuuu初始化
自隐藏=nn.线性(784100)
自输出=nn.线性(100,10)
#self.add=nn.Linear(10,10)#尝试使用和不使用
def前进(自身,x):
x=自隐藏(x)
x=自输出(x)
返回x
设置种子(0)
m=净()
bs=4
ds=torchvision.datasets.MNIST(root=“.”,train=True,transform=ToTensor(),download=True)
rng_dl=火炬发生器()
dl=torch.utils.data.DataLoader(ds,批处理大小=bs,洗牌=True,工作者数=0,生成器=rng\u dl)
标准=nn.CrossEntropyLoss()
optimizer=torch.optim.SGD(m.parameters(),lr=0.1)
对于dl中的x,y:
y_hat=m(x视图(bs,-1))
l=标准(y_hat,y)
印刷品(l)
退出()
请记住,可能还有其他一些事情,例如数据扩充和对依赖于随机操作的函数的其他调用。如果你能提供MRE,我可以试着给出一个更具体的答案