1. 生成数据集
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
# 通过 d2l中的函数 来生成features和labels
features,labels = d2l.synthetic_data(true_w,true_b,1000)
2. 调用框架中现有的API来读取数据
def load_array(data_arrays,batch_size,is_train=True):
'''构造一个pytorch数据迭代器'''
# TensorDataset基于一系列张量构建数据集
# 这些张量的形状可以不尽相同,但第一个维度必须具有相同大小。如下,是把features和labels的每一行对应起来
# * :表示对元组拆包解开入参,也可以传入features,labels
# 实例化 TensorDataset 时传入的就是一系列张量:TensorDataset(tensor_1, tensor_2, ..., tensor_n)
dataset = data.TensorDataset(*data_arrays)
# 每次从dataset数据集中随机挑选batch_size个数据
# shuffle=is_train 随机打乱顺序
return data.DataLoader(dataset,batch_size,shuffle=is_train) # 返回的是随机挑选的数据:特征和标签
batch_size=10
# 把真实数据features和labels做成tuple,传入到函数
data_iter = load_array((features,labels),batch_size)
# iter()转成iterator迭代器,通过next()函数得到X和y
next(iter(data_iter))
3. 使用框架与预定义好的层
from torch import nn # 'nn'是神经网络的缩写
# 线性回归就是一个单层的神经网络,但是为了规范引入了Sequential 容器,可以把Sequential理解为list of layers
net = nn.Sequential(nn.Linear(2,1)) # 指定输入维度是2(输入的特征数为2),输出维度是1
在这篇文章中,用到model.parameters:解释
4. 初始化模型参数权重和偏差(w和b)
# 通过net[0]访问到layer,通过weight访问到权重w,data是访问到w中的数据,normal_则是是用正态分布,替换掉data的值
# 正态分布 均值为0 标准差为0.01
net[0].weight.data.normal_(0,0.01) # PyTorch权重初始化
net[0].bias.data.fill_(0) # 对偏差进行初始化
5. 定义损失函数
# 计算均方误差使用的是 MSELoss 类,也称为平方范数
loss = nn.MSELoss() # 可以向loss函数传递两个参数,第一个是预测值,第二个是真实值
6. 随机梯度下降
# 实例化 SGD实例
# 用全部样本梯度的均值更新可学习参数
# net.parameters()包括network中的所有参数,包括w和b
# trainer 优化器
# net.parameters() 括w和b
trainer = torch.optim.SGD(net.parameters(), lr = 0.03)
7. 训练过程
# 训练过程代码与从零开始实现所做的非常相似
num_epochs = 3
for epoch in range(num_epochs):
for X,y in data_iter: # 从data_iter中一次一次拿出mini_batch
l = loss(net(X),y) # 放进net中,因为net本身带了模型参数w和b,传入X,得到预测的y
# 再和真实的y做loss
trainer.zero_grad() # 先把优化器梯度清零,因为每一遍都会得到梯度,如果不清零,会累积梯度
l.backward() # pytorch已经做了l.sum(),这个sum是在nn.MSELoss()中做的
# 就可以直接l.backward()进行反向传播
trainer.step() # 有了梯度之后,可以调用优化器trainer的step函数,来进行模型参数的更新
# 最后每扫完一遍数据,就传入真实的features得到预测的labels,去和真实的labels做loss损失
# 可以看出 预测值和真实值之间的差距
l = loss(net(features),labels)
print(f'epoch{epoch+1},loss{l:f}')