【问题标题】:what is the pytorch equivalent of a tensorflow linear regression?什么是 tensorflow 线性回归的 pytorch 等价物?
【发布时间】:2020-12-28 23:54:17
【问题描述】:

我正在学习 pytorch,要对这里以这种方式创建的数据进行基本的线性回归:

from sklearn.datasets import make_regression

x, y = make_regression(n_samples=100, n_features=1, noise=15, random_state=42)
y = y.reshape(-1, 1)
print(x.shape, y.shape)

plt.scatter(x, y)

我知道使用te​​nsorflow这段代码可以解决:

model = tf.keras.models.Sequential()
model.add(tf.keras.layers.Dense(units=1, activation='linear', input_shape=(x.shape[1], )))

model.compile(optimizer=tf.keras.optimizers.SGD(lr=0.05), loss='mse')

hist = model.fit(x, y, epochs=15, verbose=0)

但我需要知道 pytorch 等价物是什么样的,我试图做的是:

# Model Class
class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.linear = nn.Linear(1,1)
        
    def forward(self, x):
        x = self.linear(x)
        return x
    
    def predict(self, x):
        return self.forward(x)
    
model = Net()

loss_fn = F.mse_loss
opt = torch.optim.SGD(modelo.parameters(), lr=0.05)

# Funcao para treinar
def fit(num_epochs, model, loss_fn, opt, train_dl):
    
    
    # Repeat for given number of epochs
    for epoch in range(num_epochs):
        
        # Train with batches of data
        for xb, yb in train_dl:
            
            # 1. Generate predictions
            pred = model(xb)
            
            # 2. Calculate Loss
            loss = loss_fn(pred, yb)
            
            # 3. Campute gradients
            loss.backward()
            
            # 4. Update parameters using gradients
            opt.step()
            
            # 5. Reset the gradients to zero
            opt.zero_grad()
            
        # Print the progress
        if (epoch+1) % 10 == 0:
            print('Epoch [{}/{}], Loss: {:.4f}'.format(epoch+1, num_epochs, loss.item()))

# Training
fit(200, model, loss_fn, opt, data_loader)

但是模型什么都没学到,我不知道我还能做什么。

输入/输出维度为(1/1)

【问题讨论】:

    标签: python tensorflow machine-learning pytorch regression


    【解决方案1】:

    数据集

    首先,你应该定义torch.utils.data.Dataset

    import torch
    from sklearn.datasets import make_regression
    
    
    class RegressionDataset(torch.utils.data.Dataset):
        def __init__(self):
            data = make_regression(n_samples=100, n_features=1, noise=0.1, random_state=42)
            self.x = torch.from_numpy(data[0]).float()
            self.y = torch.from_numpy(data[1]).float()
    
        def __len__(self):
            return len(self.x)
    
        def __getitem__(self, index):
            return self.x[index], self.y[index]
    

    它将numpy 数据转换为__init__ 内的PyTorch 的tensor 并将数据转换为float(numpy 默认为double,而PyTorch 的默认为float,以便使用更少的内存)。

    除此之外,它只会返回 tuple 的特征和相应的回归目标。

    适合

    差不多了,但是您必须展平模型的输出(如下所述)。 torch.nn.Linear 将返回形状为 (batch, 1) 的张量,而您的目标的形状为 (batch,)。 flatten() 将删除不必要的 1 维度。

    # 2. Calculate Loss
    loss = criterion(pred.flatten(), yb)
    

    型号

    这就是你真正需要的:

    model = torch.nn.Linear(1, 1)
    

    任何层都可以直接调用,不需要forward和简单模型的继承。

    调用

    其余的几乎没问题,您只需要创建torch.utils.data.DataLoader 并传递我们数据集的实例。 DataLoader 的作用是多次发出 __getitem__ 或 dataset 并创建一批指定大小(还有一些其他有趣的事情,但就是这样):

    dataset = RegressionDataset()
    dataloader = torch.utils.data.DataLoader(dataset, batch_size=32)
    model = torch.nn.Linear(1, 1)
    criterion = torch.nn.MSELoss()
    optimizer = torch.optim.SGD(model.parameters(), lr=3e-4)
    
    fit(5000, model, criterion, optimizer, dataloader)
    

    另外请注意,我使用了torch.nn.MSELoss(),因为我们正在传递对象,在这种情况下它看起来比函数更好。

    完整代码

    为了更容易:

    import torch
    from sklearn.datasets import make_regression
    
    
    class RegressionDataset(torch.utils.data.Dataset):
        def __init__(self):
            data = make_regression(n_samples=100, n_features=1, noise=0.1, random_state=42)
            self.x = torch.from_numpy(data[0]).float()
            self.y = torch.from_numpy(data[1]).float()
    
        def __len__(self):
            return len(self.x)
    
        def __getitem__(self, index):
            return self.x[index], self.y[index]
    
    
    # Funcao para treinar
    def fit(num_epochs, model, criterion, optimizer, train_dl):
        # Repeat for given number of epochs
        for epoch in range(num_epochs):
    
            # Train with batches of data
            for xb, yb in train_dl:
    
                # 1. Generate predictions
                pred = model(xb)
    
                # 2. Calculate Loss
                loss = criterion(pred.flatten(), yb)
    
                # 3. Compute gradients
                loss.backward()
    
                # 4. Update parameters using gradients
                optimizer.step()
    
                # 5. Reset the gradients to zero
                optimizer.zero_grad()
    
            # Print the progress
            if (epoch + 1) % 10 == 0:
                print(
                    "Epoch [{}/{}], Loss: {:.4f}".format(epoch + 1, num_epochs, loss.item())
                )
    
    
    dataset = RegressionDataset()
    dataloader = torch.utils.data.DataLoader(dataset, batch_size=32)
    model = torch.nn.Linear(1, 1)
    criterion = torch.nn.MSELoss()
    optimizer = torch.optim.SGD(model.parameters(), lr=3e-4)
    
    fit(5000, model, criterion, optimizer, dataloader)
    

    您应该绕过0.053 损失左右,改变noise 或其他参数以获得更难/更容易的回归任务。

    【讨论】:

    • @manynothing 虽然感谢你是很自然的,但在这里我们感谢你的支持并接受你已经做过的回答(这样的 cmets 会产生不必要的噪音)。很高兴我能提供帮助,欢迎来到 StackOverflow! :)
    猜你喜欢
    • 2019-11-11
    • 2022-06-22
    • 1970-01-01
    • 2019-08-29
    • 1970-01-01
    • 2022-08-21
    • 2017-01-14
    • 1970-01-01
    • 2019-03-24
    相关资源
    最近更新 更多