动手学深度学习 - 手搓线性回归

3.2 线性回归的从零开始实现

超详细注释,代码理解

%matplotlib inline
import torch
from IPython import display
from matplotlib import pyplot as plt
import numpy as np
import random

print(torch.__version__)
2.0.0

3.2.1 生成数据集

数据矩阵的每一行都是一个样本,每一列都是一个特征,labels是一个列向量,每一行都是对应样本的标签。

num_inputs = 2
num_examples = 1000
true_w = [2, -3.4]
true_b = 4.2

features = torch.randn(num_examples, num_inputs,dtype=torch.float32)
# num_example行,特征列的矩阵 ,每一行都是一个样本

labels = true_w[0] * features[:, 0] + true_w[1] * features[:, 1] + true_b
# 造标签

labels += torch.tensor(np.random.normal(0, 0.01, size=labels.size()),dtype=torch.float32)
# 标签加噪声
print(features[0], labels[0])
print(features.size(),labels.size())
tensor([-0.5611,  1.4220]) tensor(-1.7809)
torch.Size([1000, 2]) torch.Size([1000])
def use_svg_display():
    # 用矢量图显示
    display.set_matplotlib_formats('svg')
    # 显示格式为SVG(Scalable Vector Graphics)

def set_figsize(figsize=(3.5, 2.5)):
    use_svg_display()
    # 设置图的尺寸
    plt.rcParams['figure.figsize'] = figsize
    # runtime configuration parameters 运行时参数

# # 在../d2lzh_pytorch里面添加上面两个函数后就可以这样导入
# import sys
# sys.path.append("..")
# from d2lzh_pytorch import * 

set_figsize()
plt.scatter(features[:, 1].numpy(), labels.numpy(), 1)
plt.scatter(features[:, 0].numpy(), labels.numpy(), 1)

3.2.2 读取数据

实现一下迭代器,每次返回一定批量的数据

# 本函数已保存在d2lzh包中方便以后使用
def data_iter(batch_size, features, labels):
    # num_ 样本数量
    num_examples = len(features)
    # 存到一个列表
    indices = list(range(num_examples))
    # 样本的读取顺序是随机的
    random.shuffle(indices)  
    # 循环,从0到num_examples,步长是batch_size
    for i in range(0, num_examples, batch_size):
         # 最后一次可能不足一个batch 列表左闭右开,所以右边是size就是size个样本
        j = torch.LongTensor(indices[i: min(i + batch_size, num_examples)])
        yield  features.index_select(0, j), labels.index_select(0, j)
batch_size = 10

for X, y in data_iter(batch_size, features, labels):
    print(X, '\n', y)
    break
tensor([[ 0.7540, -0.5112],
        [-0.7727, -0.9994],
        [ 0.4473, -1.1965],
        [ 1.8597,  0.9544],
        [ 0.1463, -0.1498],
        [ 1.0885, -0.4189],
        [-1.1626, -0.2331],
        [ 0.5824,  1.5569],
        [-2.2608,  0.1622],
        [ 1.4301,  0.3798]]) 
 tensor([ 7.4268,  6.0439,  9.1675,  4.6993,  5.0116,  7.8275,  2.6682,  0.0571,
        -0.8854,  5.7735])

3.2.3 初始化模型参数

# 大小为num_inputs, 1
w = torch.tensor(np.random.normal(0, 0.01, (num_inputs, 1)), dtype=torch.float32) 
b = torch.zeros(1, dtype=torch.float32)
w.requires_grad_(requires_grad=True)
b.requires_grad_(requires_grad=True) 
tensor([0.], requires_grad=True)

3.2.4 定义模型

def linreg(X, w, b):  # 本函数已保存在d2lzh包中方便以后使用
    return torch.mm(X, w) + b

3.2.5 定义损失函数

def squared_loss(y_hat, y):  # 本函数已保存在pytorch_d2lzh包中方便以后使用
    return (y_hat - y.view(y_hat.size())) ** 2 / 2

3.2.6 定义优化算法

小批量梯度下降

# 本函数已保存在d2lzh_pytorch包中方便以后使用
def sgd(params, lr, batch_size):  
    for param in params:
        # 注意这里更改param时用的param.data
        param.data -= lr * param.grad / batch_size 

3.2.7 训练模型

lr = 0.03
num_epochs = 3
net = linreg
loss = squared_loss

for epoch in range(num_epochs):  # 训练模型一共需要num_epochs个迭代周期
    # 在每一个迭代周期,会使用训练数据集中所有样本一次(假设样本数能够被批量大小整除)。
    # X和y分别是小批量样本的特征和标签
    for X, y in data_iter(batch_size, features, labels):
        l = loss(net(X, w, b), y).sum()  # l是有关小批量X和y的损失
        # 小批量的损失对模型参数求梯度
        l.backward()  
        # 使用小批量随机梯度下降迭代模型参数
        sgd([w, b], lr, batch_size)  
        
        # 不要忘了梯度清零
        w.grad.data.zero_()
        b.grad.data.zero_()
    train_l = loss(net(features, w, b), labels)
    print('epoch %d, loss %f' % (epoch + 1, train_l.mean().item()))
epoch 1, loss 0.040210
epoch 2, loss 0.000155
epoch 3, loss 0.000047
print(true_w, '\n', w)
print(true_b, '\n', b)
[2, -3.4] 
 tensor([[ 1.9997],
        [-3.3985]], requires_grad=True)
4.2 
 tensor([4.1997], requires_grad=True)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

熊熊想读研究生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值