动手学深度学习:线性回归+基础优化算法

一、线性回归

买房的案例:
在这里插入图片描述

线性模型

在这里插入图片描述

线性模型可以看做是单层神经网络

在这里插入图片描述
在这里插入图片描述

衡量预估质量

在这里插入图片描述

训练数据

在这里插入图片描述

参数学习

在这里插入图片描述

找到w,b使得损失函数最小

显示解

在这里插入图片描述

总结

在这里插入图片描述

二、基础优化算法

梯度下降

在这里插入图片描述

选择学习率

在这里插入图片描述

小批量随机梯度下降

在这里插入图片描述

批量大小的选择

在这里插入图片描述

总结

在这里插入图片描述

三、线性回归的从零开始实现

根据带有噪声的线性模型构造一个人造数据集。

我们使用线性模型参数 w = [ 2 , − 3.4 ] ⊤ \mathbf{w} = [2, -3.4]^\top w=[2,3.4] b = 4.2 b = 4.2 b=4.2和噪声项 ϵ \epsilon ϵ生成数据集及其标签:
y = X w + b + ϵ . \mathbf{y}= \mathbf{X} \mathbf{w} + b + \mathbf\epsilon. y=Xw+b+ϵ.

def synthetic_data(w, b, num_examples):  #@save
    """生成 y = Xw + b + 噪声。"""
    X = torch.normal(0, 1, (num_examples, len(w)))
    y = torch.matmul(X, w) + b
    y += torch.normal(0, 0.01, y.shape)
    return X, y.reshape((-1, 1))

true_w = torch.tensor([2, -3.4])
true_b = 4.2
features, labels = synthetic_data(true_w, true_b, 1000)

注意,[features 中的每一行都包含一个二维数据样本,labels 中的每一行都包含一维标签值(一个标量)]。

print('features:', features[0], '\nlabel:', labels[0])
features: tensor([-0.9267, -0.2346]) 
label: tensor([3.1315])

通过生成第二个特征 features[:, 1]labels 的散点图,可以直观地观察到两者之间的线性关系。

d2l.set_figsize()
d2l.plt.scatter(features[:, (1)].detach().numpy(),
                labels.detach().numpy(), 1);

此处不用.detach().numpy()也可以

在这里插入图片描述
定义一个data_iter 函数,该函数接收批量大小、特征矩阵和标签向量作为输入,生成大小为batch_size的小批量

def data_iter(batch_size, features, labels):
    num_examples = len(features)
    indices = list(range(num_examples))
    # 这些样本是随机读取的,没有特定的顺序
    random.shuffle(indices)
    for i in range(0, num_examples, batch_size):
        batch_indices = torch.tensor(indices[i:min(i + batch_size, num_examples)])
        yield features[batch_indices], labels[batch_indices]

batch_size = 10

for X, y in data_iter(batch_size, features, labels):
    print(X, '\n', y)
    break
tensor([[ 0.8127,  0.6865],
        [-0.4427,  0.5321],
        [ 0.1517, -0.1386],
        [-0.9238,  0.7089],
        [ 0.6578, -0.1356],
        [-1.4326,  1.9160],
        [ 1.6796,  0.5500],
        [-1.0313, -0.2434],
        [-0.4650,  1.1109],
        [-0.2465, -0.1693]]) 
 tensor([[ 3.4920],
        [ 1.5161],
        [ 4.9724],
        [-0.0411],
        [ 5.9892],
        [-5.1784],
        [ 5.7042],
        [ 2.9737],
        [-0.4977],
        [ 4.2807]])

初始化模型参数

w = torch.normal(0, 0.01, size=(2, 1), requires_grad=True)
b = torch.zeros(1, requires_grad=True)

定义模型

def linreg(X, w, b):  #@save
    """线性回归模型。"""
    return torch.matmul(X, w) + b

定义损失函数

def squared_loss(y_hat, y):  #@save
    """均方损失。"""
    return (y_hat - y.reshape(y_hat.shape))**2 / 2

定义优化算法

def sgd(params, lr, batch_size):  #@save
    """小批量随机梯度下降。"""
    with torch.no_grad():
        for param in params:
            param -= lr * param.grad / batch_size
            param.grad.zero_()

训练过程

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

for epoch in range(num_epochs):
    for X, y in data_iter(batch_size, features, labels):
        l = loss(net(X, w, b), y)  # `X`和`y`的小批量损失
        # 因为`l`形状是(`batch_size`, 1),而不是一个标量。`l`中的所有元素被加到一起,
        # 并以此计算关于[`w`, `b`]的梯度
        l.sum().backward()
        sgd([w, b], lr, batch_size)  # 使用参数的梯度更新参数
    with torch.no_grad():
        train_l = loss(net(features, w, b), labels)
        print(f'epoch {epoch + 1}, loss {float(train_l.mean()):f}')
epoch 1, loss 0.040376
epoch 2, loss 0.000154
epoch 3, loss 0.000052

比较真实参数和通过训练学到的参数来评估训练的成功程度

print(f'w的估计误差: {true_w - w.reshape(true_w.shape)}')
print(f'b的估计误差: {true_b - b}')
w的估计误差: tensor([ 2.6226e-05, -5.0330e-04], grad_fn=<SubBackward0>)
b的估计误差: tensor([0.0002], grad_fn=<RsubBackward1>)

四、线性回归的简洁实现

通过使用深度学习框架来简洁地实现

import numpy as np
import torch
from torch.utils import data
from d2l import torch as d2l

true_w = torch.tensor([2, -3.4])
true_b = 4.2
features, labels = d2l.synthetic_data(true_w, true_b, 1000)

调用框架中现有的API来读取数据

def load_array(data_arrays, batch_size, is_train=True):  #@save
    """构造一个PyTorch数据迭代器。"""
    dataset = data.TensorDataset(*data_arrays)
    return data.DataLoader(dataset, batch_size, shuffle=is_train)
batch_size = 10
data_iter = load_array((features, labels), batch_size)
next(iter(data_iter))
[tensor([[ 0.3477, -1.3373],
         [-1.4896, -0.8495],
         [-0.0790, -2.7086],
         [-0.5485, -0.4496],
         [-0.7152,  0.8290],
         [ 0.5100,  0.6566],
         [ 0.8817, -1.8366],
         [ 2.3389, -0.3786],
         [-0.4357,  0.8328],
         [-1.8519, -0.4630]]),
 tensor([[ 9.4402],
         [ 4.0956],
         [13.2606],
         [ 4.6372],
         [-0.0446],
         [ 2.9945],
         [12.1993],
         [10.1901],
         [ 0.5035],
         [ 2.0714]])]

使用框架的预定义好的层

# `nn` 是神经网络的缩写
from torch import nn

net = nn.Sequential(nn.Linear(2, 1))

初始化模型参数

net[0].weight.data.normal_(0, 0.01)
net[0].bias.data.fill_(0)

计算均方误差使用的是MSELoss类,也称为平方 L 2 L_2 L2 范数

loss = nn.MSELoss()

实例化 SGD 实例

trainer = torch.optim.SGD(net.parameters(), lr=0.03)

训练过程代码与我们从零开始实现时所做的非常相似

num_epochs = 3
for epoch in range(num_epochs):
    for X, y in data_iter:
        l = loss(net(X), y)
        trainer.zero_grad()
        l.backward()
        trainer.step()
    l = loss(net(features), labels)
    print(f'epoch {epoch + 1}, loss {l:f}')
epoch 1, loss 0.000324
epoch 2, loss 0.000102
epoch 3, loss 0.000102

比较生成数据集的真实参数和通过有限数据训练获得的模型参数

w = net[0].weight.data
print('w的估计误差:', true_w - w.reshape(true_w.shape))
b = net[0].bias.data
print('b的估计误差:', true_b - b)
w的估计误差: tensor([-0.0005,  0.0003])
b的估计误差: tensor([-0.0007])
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

GeniusAng丶

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

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

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

打赏作者

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

抵扣说明:

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

余额充值