【日积月累】Linear Regression with PyTorch

本文详细介绍了如何从头开始构建线性回归模型,并利用PyTorch进行优化。首先,通过手写代码实现线性回归,包括初始化权重、生成预测、计算损失和梯度下降。随后,展示了如何使用PyTorch内置的线性模型、损失函数和优化器简化这一过程。通过多个epoch的训练,模型逐渐提高了预测苹果和橙子产量的准确性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

import numpy as np
import torch

'''
Training data
'''
# Input (temp, rainfall, humidity)
inputs = np.array([[73, 67, 43], 
                   [91, 88, 64], 
                   [87, 134, 58], 
                   [102, 43, 37], 
                   [69, 96, 70]], dtype='float32')
# Targets (apples, oranges)
targets = np.array([[56, 70], 
                    [81, 101], 
                    [119, 133], 
                    [22, 37], 
                    [103, 119]], dtype='float32')

# Convert inputs and targets to tensors
inputs = torch.from_numpy(inputs)
targets = torch.from_numpy(targets)
print(inputs)
print(targets)

'''
1.Linear regression model from scratch
'''
# Weights and biases
w = torch.randn(2, 3, requires_grad=True)
b = torch.randn(2, requires_grad=True)
print(w)
print(b)

def model(x):
    return x @ w.t() + b
#@ represents matrix multiplication in PyTorch, 
#and the .t method returns the transpose of a tensor.

# Generate predictions
preds = model(inputs)
print(preds)

# Compare with targets
print(targets)

'''
Loss function

计算两个矩阵(preds 和 targets)之间的差异;
求这个差异矩阵的所有元素的平方以消除其中的负值;
计算所得矩阵中元素的平均值。
'''
# MSE loss
def mse(t1, t2):
    diff = t1 - t2
    return torch.sum(diff * diff) / diff.numel()
#torch.sum 返回一个张量中所有元素的和,
#.numel 方法则返回一个张量中元素的数量

# Compute loss
loss = mse(preds, targets)
print(loss)
#平均而言,预测结果中每个元素与实际目标之间的差距大约为 215(46194 的平方根)。
#考虑到我们所要预测的数值的范围本身只有 50-200,所以这个结果实在相当糟糕。
#我们称这个结果为损失(loss),因为它指示了模型在预测目标变量方面的糟糕程度。损失越低,模型越好。

'''
Compute gradients
可以根据权重和偏置自动计算 loss 的梯度和导数,
因为它们已将 requires_grad 设置为 True
'''
# Compute gradients
loss.backward()
#这些梯度存储在各自张量的 .grad 属性中

# Gradients for weights
print(w)
print(w.grad)

#通过调用 .zero() 方法将梯度重置为零。我们需要这么做的原因是 PyTorch 会累积梯度,
#也就是说,我们下一次在损失上调用 .backward 时,新的梯度值会被加到已有的梯度值上,
#这可能会导致意外结果出现
w.grad.zero_()
b.grad.zero_()
print(w.grad)
print(b.grad)

'''
Adjust weights and biases using gradient descent

生成预测
计算损失
根据权重和偏置计算梯度
按比例减去少量梯度来调整权重
将梯度重置为零
'''
# Generate predictions
preds = model(inputs)
print(preds)

# Calculate the loss
loss = mse(preds, targets)
print(loss)

# Compute gradients
loss.backward()
print(w.grad)
print(b.grad)

# Adjust weights & reset gradients
with torch.no_grad():
    w -= w.grad * 1e-5
    b -= b.grad * 1e-5
    w.grad.zero_()
    b.grad.zero_()
#我们使用 torch.no_grad 指示 PyTorch 我们在更新权重和偏置时不应该跟踪、计算或修改梯度。
#我们为梯度乘上了一个非常小的数值(这个案例中为 10^-5),以确保我们不会改变权重太多,因为我们只想在梯度的下降方向上迈出一小步。
#这个数值是这个算法的学习率(learning rate)。
#在更新权重之后,我们将梯度重置为零,以免影响后续计算。

print(w)
print(b)

# Calculate loss
preds = model(inputs)
loss = mse(preds, targets)
print(loss)

'''
Train for multiple epochs
'''
# Train for 100 epochs
for i in range(100):
    preds = model(inputs)
    loss = mse(preds, targets)
    loss.backward()
    with torch.no_grad():
        w -= w.grad * 1e-5
        b -= b.grad * 1e-5
        w.grad.zero_()
        b.grad.zero_()

# Calculate loss
preds = model(inputs)
loss = mse(preds, targets)
print(loss)

# Predictions
preds
# Targets
targets

'''
2.Linear regression using PyTorch built-ins
'''
import torch.nn as nn
# Input (temp, rainfall, humidity)
inputs = np.array([[73, 67, 43], [91, 88, 64], [87, 134, 58], 
                   [102, 43, 37], [69, 96, 70], [73, 67, 43], 
                   [91, 88, 64], [87, 134, 58], [102, 43, 37], 
                   [69, 96, 70], [73, 67, 43], [91, 88, 64], 
                   [87, 134, 58], [102, 43, 37], [69, 96, 70]], 
                  dtype='float32')

# Targets (apples, oranges)
targets = np.array([[56, 70], [81, 101], [119, 133], 
                    [22, 37], [103, 119], [56, 70], 
                    [81, 101], [119, 133], [22, 37], 
                    [103, 119], [56, 70], [81, 101], 
                    [119, 133], [22, 37], [103, 119]], 
                   dtype='float32')

inputs = torch.from_numpy(inputs)
targets = torch.from_numpy(targets)

from torch.utils.data import TensorDataset
# Define dataset
train_ds = TensorDataset(inputs, targets)
train_ds[0:3]
#创建一个 TensorDataset,这让我们可以读取 inputs 和 targets 的行作为元组,
#并提供了 PyTorch 中用于处理许多不同类型的数据集的标准 API

from torch.utils.data import DataLoader
# Define data loader
batch_size = 5
train_dl = DataLoader(train_ds, batch_size, shuffle=True)
#将创建一个 DataLoader,它可以在训练时将数据分成预定义大小的批次。
#它还能提供其它效用程序,如数据的混洗和随机采样。

for xb, yb in train_dl:
    print(xb)
    print(yb)
    break

'''
nn.Linear
'''
# Define model
model = nn.Linear(3, 2)
print(model.weight)
print(model.bias)

# Parameters
list(model.parameters())
#PyTorch 模型还有一个很有用的 .parameters 方法,
#这能返回一个列表,其中包含了模型中所有的权重和偏置矩阵。

# Generate predictions
preds = model(inputs)
preds

'''
Loss Function
'''
# Import nn.functional
import torch.nn.functional as F

# Define loss function
loss_fn = F.mse_loss

loss = loss_fn(model(inputs), targets)
print(loss)

'''
Optimizer
'''
# Define optimizer
opt = torch.optim.SGD(model.parameters(), lr=1e-5)

'''
Train the model
'''
# Utility function to train the model
def fit(num_epochs, model, loss_fn, opt):
    
    # 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. Compute 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()))
#我们使用之前定义的数据加载器来为每个迭代获取数据批次。
#我们没有手动更新参数(权重和偏置),而是使用了 opt.step 来执行更新,并使用了 opt.zero_grad 来将梯度重置为零。
#我们还添加了一个日志语句,能够显示每第 10 个 epoch 的最后一批数据的损失,从而可让我们跟踪训练进程。
#loss.item 会返回存储在损失张量中的实际值。

fit(100, model, loss_fn, opt)
# Generate predictions
preds = model(inputs)
preds

# Compare with targets
targets

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值