Pytorch 训练和评估不同的样本大小

Posted

技术标签:

【中文标题】Pytorch 训练和评估不同的样本大小【英文标题】:Pytorch Train & Eval Different Sample Sizes 【发布时间】:2019-12-20 18:57:07 【问题描述】:

我正在学习 pytorch,并且有以下(缩写)代码来设置建模:

# define the model class for a neural net with 1 hidden layer
class myNN(nn.Module):
    def __init__(self, D_in, H, D_out):
        super(myNN, self).__init__()
        self.lin1 = nn.Linear(D_in,H)
        self.lin2 = nn.Linear(H,D_out)
    def forward(self,X):
        return torch.sigmoid(self.lin2(torch.sigmoid(self.lin1(x))))

# now make the datasets & dataloaders
batchSize = 5
# Create the data class
class Data(Dataset):
    def __init__(self, x, y):
        self.x = torch.FloatTensor(x)
        self.y = torch.Tensor(y.astype(int))
        self.len = self.x.shape[0]
        self.p = self.x.shape[1]
    def __getitem__(self, index):      
        return self.x[index], self.y[index]
    def __len__(self):
        return self.len
trainData = Data(trnX, trnY)
trainLoad = DataLoader(dataset = trainData, batch_size = batchSize)
testData = Data(tstX, tstY)
testLoad = DataLoader(dataset = testData, batch_size = len(testData))

# define the modeling objects
hiddenLayers = 30
learningRate = 0.1
model = myNN(p,hiddenLayers,1)
print(model)
optimizer = torch.optim.SGD(model.parameters(), lr = learningRate)
loss = nn.BCELoss()

trnX.shape=(70, 2)trnY.shape=(70,)tstX.shape=(30,2)tstY.shape=(30,)。训练代码为:

# train!
epochs = 1000
talkFreq = 0.2
trnLoss = [np.inf]*epochs
tstLoss = [np.inf]*epochs
for i in range(epochs):
    # train with minibatch gradient descent
    for x, y in trainLoad:
        # forward step
        yhat = model(x)
        # compute loss (not storing for now, will do after minibatching)
        l = loss(yhat, y)
        # backward step
        optimizer.zero_grad()
        l.backward()
        optimizer.step()
    # evaluate loss on training set
    yhat = model(trainData.x)
    trnLoss[i] = loss(yhat, trainData.y)
    # evaluate loss on testing set
    yhat = model(testData.x)
    tstLoss[i] = loss(yhat, testData.y)

数据集 trainDatatestData 分别有 70 和 30 个观测值。这可能只是一个新手问题,但是当我运行训练单元时,它会在 trnLoss[i] = loss(yhat, trainData.y) 行出现错误并显示错误

ValueError: Target and input must have the same number of elements. target nelement (70) != input nelement (5)

当我检查yhat=model(trainData.x) 行的输出时,我看到yhat 是一个带有batchSize 元素的张量,尽管事实上trainData.x.shape = torch.Size([70, 2])

如何使用小批量梯度下降迭代训练模型,然后使用该模型计算完整训练集和测试集的损失和准确率?我尝试在小批量迭代之前设置model.train(),然后在评估代码之前设置model.eval(),但无济于事。

【问题讨论】:

model = myNN(p,hiddenLayers,1) 中的p 是什么?还要保留model.eval() 之前的yhat = model(trainData.x)model.train() 之前的for x, y 我有p=2。我目前在您建议的地方有model.train()model.eval() 电话。 (通过“当前”,我的意思是我已经添加了这些行,但仍然出现错误......) 【参考方案1】:

myNN.forward() 中,您将小写x 作为输入传递给self.lin1,而函数的输入参数命名为大写X。小写 x 是一种在 for 循环中为 trainload 定义的全局变量,因此您没有收到任何语法错误,但您打算传递的值并未传递给 self.lin1

我是否还建议您考虑使用model.eval()with torch.no_grad() 作为您的测试代码。这里不是绝对必要的,但它会更有意义。

【讨论】:

谢谢,将X 更正为x 解决了问题。模型的forward() 评估将x 的最新值读取为“全局”变量这一事实解释了为什么yhat 的长度为batchSize,尽管有输入。关于你的最后一点,我应该把我所有的评估代码(从model.eval() 到循环的结尾)放在with torch.no_grade() 中,对吧?最后一个问题,我应该写model.eval(),还是model = model.eval(),就像我在网上一些地方看到的那样。谢谢! 1:是的,在with torch.no_grad() 块中编写所有评估代码通常是一个好习惯,因为我们不希望在评估期间计算梯度。 2:拨打model.eval()就够了。确保您还在“epoch for loop”开始时调用model.train(),以便在循环trainLoad之前将模型设置为训练模式。

以上是关于Pytorch 训练和评估不同的样本大小的主要内容,如果未能解决你的问题,请参考以下文章

pytorch epoch, batch, iteration

模型评估之过拟合和欠拟合

PyTorch 中的高效指标评估

如何在 Pytorch 中检查模型是处于训练模式还是评估模式?

交叉验证

交叉验证