Pytorch - 这是使用 pytorch.data.Dataset 加载大数据集并对其进行线性回归训练的正确方法吗
Posted
技术标签:
【中文标题】Pytorch - 这是使用 pytorch.data.Dataset 加载大数据集并对其进行线性回归训练的正确方法吗【英文标题】:Pytorch - is this the right way to load a big dataset using pytorch.data.Dataset and train it for Linear Regression 【发布时间】:2019-05-23 13:17:29 【问题描述】:我是 PyTorch 的新手,目前正在使用 historical weather dataset,并且已经构建了 PyTorch DataLoader 迭代器并将数据成功拆分到训练集和测试集。
我想对此数据运行一个简单的线性回归模型来预测列["Temperature (C)"]
。我没有做任何特征工程,而只是使用所有浮点 dtypes 作为特征。
在运行模型时(只是一个带有偏差 True-Linear Regression 的全连接层),我发现前 2 批左右的损失有所减少,然后损失在 (100 +- 25)
附近波动。当我对特征进行归一化时,第一批的损失减少了,但波动在200 +- 25
左右。
据我所知,我知道一旦对特征进行归一化,SGD 就有更高的机会更快地收敛。但是基础损失存在差异,即。没有特征归一化 ~ 100,有特征归一化/缩放 ~ 200.
我觉得我在某处实现了一些错误,但没有任何线索可以弄清楚我搞砸了什么或者这是否是正常行为。
[更新] 这就是我的 loss function plot 在下降过程中的样子。但我注意到损失的变化太大了。我错了吗 ? Loss vs number of iterations plot x 轴 - 100 个批量大小的迭代次数; y 轴 - 损失
这是我的代码
import pandas as pd
import numpy as np
import torch
from torch.utils.data import DataLoader, Dataset, random_split
from sklearn.preprocessing import StandardScaler
import torch
import torch.nn as nn
from torch.autograd import Variable
from torch.optim import SGD
class LinearRegression(nn.Module):
def __init__(self, input_dim, output_dim):
super(LinearRegression, self).__init__()
self.fc1 = nn.Linear(input_dim, output_dim)
def forward(self, x):
output = self.fc1(x)
return output
class LoaderWeather(Dataset):
def __init__(self, file_path, transform=None):
self.file_path = file_path
self.transform = transform
# self.scaler = StandardScaler()
self.data = pd.read_csv(self.file_path)
self.data = self.data.loc[:, self.data.dtypes == np.float64]
self.outputs = self.data["Temperature (C)"]
self.inputs = self.data.drop(["Apparent Temperature (C)", "Temperature (C)"], axis=1)
self.outputs = np.array(self.outputs).reshape(-1,1)
self.inputs = np.array(self.inputs)
# self.inputs = self.scaler.fit_transform(np.array(self.inputs))
#Normalize data
# self.means = self.inputs.mean(axis=1).reshape(-1,1)
# self.stds = self.inputs.std(axis=1).reshape(-1,1)
# self.inputs = (self.inputs - self.means)/self.stds
def __getitem__(self, idx):
return self.inputs[idx], self.outputs[idx]
def __len__(self):
return len(self.inputs)
def train_epoch(epoch, train_loader, regression_model, criterion, optimizer):
print(epoch)
train_loader = iter(train_loader)
#Convert to tensors
for iteration, (inputs, outputs) in enumerate(train_loader):
# inputs,outputs = train_loader.next()
inputs = Variable(torch.tensor(inputs).type(torch.FloatTensor))
outputs = Variable(torch.tensor(outputs).type(torch.FloatTensor))
#Clear the gradients w.r.t the parameters
optimizer.zero_grad()
#Forward pass
predicted = regression_model(inputs)
#Calculate loss
loss = criterion(predicted, outputs)
#Backpropogate gradient of loss
loss.backward()
#Perform one step of gradient descent
optimizer.step()
#Verbosity
if iteration % 100 == 0:
print("epochs :, loss : , iteration: ,".format(epoch, loss, iteration))
return regression_model, loss
def main():
############################################
#Hyper parameters
batch_size=100
n_iters = 20000
learning_rate=0.0000001
#############################################
weather_data = LoaderWeather("data/weatherHistory.csv")
n = len(weather_data)
n_train = int(0.8 * len(weather_data))
n_test = n - n_train
train, test = random_split(weather_data, lengths=[n_train, n_test])
train_loader = DataLoader(train, batch_size=batch_size, shuffle=True, num_workers=4)
test_loader = DataLoader(test, batch_size=batch_size, num_workers=4)
input_dim = 6
output_dim = 1
regression_model = LinearRegression(input_dim, output_dim)
criterion = nn.MSELoss()
optimizer = SGD(regression_model.parameters(), lr=learning_rate)
no_of_batches = np.floor(n/batch_size)
print(no_of_batches)
epochs = int(n_iters/no_of_batches)
print("Total epochs : ".format(epochs))
for epoch in range(epochs):
regression_model, loss = train_epoch(epoch, train_loader, regression_model, criterion, optimizer)
print(regression_model, loss)
print(regression_model.parameters())
if __name__ == '__main__':
main()
任何帮助将不胜感激。另外,请让我知道我的训练方式是否良好或这里有什么根本错误。
谢谢
【问题讨论】:
【参考方案1】:绘制梯度的范数可能很有用(使用线性 reg 这应该不会太难)。如果梯度很小,那么误差的方差是由于随机效应造成的,而如果范数不小,则可能存在一些编程错误。一旦达到收敛区域,一些减少方差的常见技巧是降低学习率(参见https://www.tensorflow.org/api_docs/python/tf/train/exponential_decay),或增加批量大小。这完全取决于您想要达到的准确度。
【讨论】:
以上是关于Pytorch - 这是使用 pytorch.data.Dataset 加载大数据集并对其进行线性回归训练的正确方法吗的主要内容,如果未能解决你的问题,请参考以下文章