学习笔记:手动构造线性回归函数

手动构造线性回归函数

线性回归是对维输入的加权,外加偏差
使用平方损失来衡量预测值和真实值的差异
线性回归有显示解
线性回归可以看做是单层神经网络

梯度下降通过不断沿着反梯度方向更新参数求解
小批量随机梯度下降是深度学习默认的求解算法

导入相关包

两个重要的超参数是批量大小和学习率

%matplotlib inline
import random
import torch
from d2l import torch as d2l

构建一个虚拟数据集

根据带有噪声的线性模型构造一个人造数据集。我们使用线性模型参数
w=[2,-3.4]、b=4.2和噪声项生成数据集及其标签:

def synthetic_data(w, b, num_examples):
    #生成 y = Xw + b + 噪声
    X = torch.normal(0, 1, (num_examples, len(w)) )
    #均值为0方差为1随机数,生成(num_examples, len(w)元组
    #num_examples:生成的数量,len:生成的长度
    y = torch.matmul(X, w) + b
    y += torch.normal(0, 0.01, y.shape) #增加难度,添加噪声,使用均值0,方差0.01,与y形状相同
    return X, y.reshape((-1, 1))
#真实值,w和b
true_w = torch.tensor([2, -3.4]) #有两个特征,表示两个权重
true_b = 4.2
features, labels = synthetic_data(true_w, true_b, 1000)

输出:

features: tensor([-1.6097, 0.1451])
label: tensor([0.4820])

打印数据集

print('features:', features[0], '\nlabel:', labels[0])
#features【0】:0号样本内容
#label:标号(标记),为标量

画出数据集分布图

d2l.set_figsize() #set_figsize()用于设置matplotlib图表的默认大小
#plt.scatter(...)调用了matplotlib的散点图绘制功能
d2l.plt.scatter(features[:, 1].detach().numpy(), #选取全部行的第二列,作为x轴
               labels.detach().numpy(), 1);#作为y轴
#.detach()方法用来从当前计算图中“断开”tensor,就不会跟踪其后续的操作
#并转换为numpy()便于画图

读取数据集,设置批量

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].unsqueeze(1)
        yield features[batch_indices], labels[batch_indices]
#https://blog.csdn.net/mieleizhi0522/article/details/82142856
# yield 相当于返回return,但是会记录上一次最后返回的位置,下一次从此继续运行,有此函数相当于生成器


batch_size = 10

for X, y in data_iter(batch_size, features, labels):
    print(X,'\n', y)
    break

输出:

tensor([[ 0.5830, -0.4698],
[-1.3739, 0.6487],
[ 0.0180, -0.0068],
[-0.2491, 0.2345],
[ 1.3643, -0.1198],
[ 0.9106, -1.0124],
[-0.2534, -0.9694],
[ 0.3089, 0.7512],
[ 2.2439, 2.4315],
[ 0.2354, -1.4545]])
tensor([[ 6.9761],
[-0.7486],
[ 4.2614],
[ 2.9004],
[ 7.3393],
[ 9.4687],
[ 7.0110],
[ 2.2447],
[ 0.4337],
[ 9.6244]])

定义初始化模型参数

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

输出:

(tensor([[0.0105],
[0.0304]], requires_grad=True),
tensor([0.], requires_grad=True))

定义线性回归模型

def linreg(X, w, b):
    """调用模型"""
    return torch.matmul(X, w) + b

定义损失函数

def squared_loss(y_hat, y):
    """均方损失"""
    return ( y_hat - y.reshape(y_hat.shape) ) **2 /2 #数量相同,防止维度不同使用reshap

定义优化算法

def sgd(params, lr, batch_size): #params参数,包含一个list
    """小批量随机梯度下降"""
    with torch.no_grad(): #不需要计算梯度时
        for param in params:
            param -= lr * param.grad / batch_size #减去自身梯度下降,并补上除以分之一得均值
            param.grad.zero_() #torch不会自动清除提u,防止下次计算梯度相关,手动清零梯度

训练过程

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']的梯度,数字 1 代表了该张量的第二个维度的大小

        l.sum().backward() #反向传播累积计算w, b梯度(对设置了requires_grad=True计算)
        sgd([w, b], lr, batch_size)  #沿梯度更新
        #.backward()计算了梯度,而SGD或其它优化算法利用这些梯度信息来指导模型参数的更新

    with torch.no_grad():
        train_l = loss(net(features, w, b), labels)  #再将更新后所有预测和真实值做损失,每迭代一次就打印
        #train_l = loss(net(features, w, labels.unsqueeze(1)), labels.unsqueeze(1)) 

        print(f'epoch{epoch + 1}, loss {float(train_l.mean()):f}')  #.mean()对整个批次损失进行平均,:f是为了规范输出格式,减少不必要小数点输出

输出:

epoch1, loss 0.038107
epoch2, loss 0.000146
epoch3, loss 0.000052

求误差

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

print(f'w的估计误差:{true_w - w.reshape(true_w.shape)}')
print(f'b的估计误差:{true_b - b}')

输出:

w的估计误差:tensor([ 0.0003, -0.0005], grad_fn=)
b的估计误差:tensor([0.0007], grad_fn=)

博客内容均系原创,未经允许严禁转载!
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇