【深度学习-pytorch】线性回归从0开始实现

#从零开始实现整个方法,包括数据流水线、模型、损失函数和小批量随机梯度下降优化器
from matplotlib import pyplot as plt
import random#随机化,初始化权重
import torch
import torchvision
from d2l import torch as d2l
#构造人造数据集
#指定w和b,y=Xw+b+c X随机数 w权重 b偏差 c随机噪音
def synthetic_data(w,b,num_examples):
    x=torch.normal(0,1,(num_examples,len(w)))#均值0,方差1,大小为n个样本,列数为w的长度
    y=torch.matmul(x,w)+b#两个张量矩阵相乘
    y+=torch.normal(0,0.01,y.shape)#加入噪音
    return x,y.reshape((-1,1))#做成列向量返回,-1表示自动计算,未指定,1固定,列向量为1
true_w=torch.tensor((2,-3.4))
true_b=4.2
features,labels=synthetic_data(true_w,true_b,1000)#特征为x,标签为y
#features中每一行都包含一个二维数据样本,labels中每一行都包含一维标签值(一个标量)
print('features:',features[0],'\nlabels',labels[0])
d2l.set_figsize()#画板
d2l.plt.scatter(features[:,(1)].detach().numpy()#detach分离出来才能转到numpy中
                ,labels.detach().numpy(),1);
plt.show()
#实现一个函数,读取小批量,定义一个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
#以上给出样本标号,随机选取样本返回出来
#定义初始化模型参数
w=torch.normal(0,0.01,size=(2,1),requires_grad=True)
b=torch.zeros(1,requires_grad=True)
#定义模型
def linreg(x,w,b):
#线性回归模型
    return torch.matmul(x,w)+b
#定义损失函数
def squares_loss(y_hat,y):
 #均方损失
    return (y_hat-y.reshape(y_hat.shape))**2/2
#定义优化算法
def sgd(params,lr,batch_size):#参数,学习率,
    with torch.no_grad():#更新的时候不参与梯度计算
        for param in params:#参数可能是w,可能是b
            param-=lr*param.grad/batch_size#除了均值
            param.grad.zero_()
#把所有模块儿定义好后,接下来是训练的过程
lr=0.03#学习率
num_epochs=3#三个回合
net=linreg#模型
loss=squares_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}')
print(f'w的估计误差:{true_w-w.reshape(true_w.shape)}')
print(f'b的估计误差:{true_b-b}')








你可能感兴趣的:(pytorch,深度学习,线性回归,python,算法)