手动实现线性回归

1.构造数据集

1.1导入相对应的包

%matplotlib inline     
import torch
import numpy as np
import matplotlib.pyplot as plt

1.2加载数据集

首先设置真实权重true_w=[2,-3.4],偏置为4.2,以此来生成线性回归的数据集,当然我们可以自己构造数据集,但为了在简单和方便理解的基础上,我们自己构造了一个线性的数据集,不仅可以帮助大家更好的理解,也可以更加方便的训练,更加方便入门。

true_w=torch.tensor([2,-3.4])  # 真实权重
true_b=4.2                     # 真实偏置
num_samples = 1000             # 样本数

再接着书写获取数据集的函数

def datasets(w,b,num_samples):
    features = torch.normal(0,1,(num_samples,len(w)))# 创建x值
    labels = torch.matmul(features,w) + b            # 生成y值
    labels += torch.normal(0,0.01,labels.shape)      # 加上噪音
    labels = labels.unsqueeze(1)                     # 将一维转换为2维
    return features,labels                           # 返回相应的值

定义本文所需要的数据集

features,labels = datasets(true_w,true_b,num_samples)
features.shape,labels.shape     # 打印一下输入和输出的维度

2.加载数据集

接下来就是读取数据,我们设置小批量读取数据,即并不是以此把所有的数据喂给机器直接进行训练,而是小批次的为机器提供数据。

def data_iter(batch_size,features,labels):
    index = np.arange(num_samples)    # 设置一个新的索引
    np.random.shuffle(index)          # 打乱索引
    for i in range(0,num_samples,batch_size):
        batch_index = torch.LongTensor(index[i:min(i+batch_size,num_samples)])  
#         yield features.index_select(0,batch_index),labels.index_select(0,batch_index)  注意此处的"0"指的是第0维,pytorch中的dim和numpy中的axes一致
        yield features[batch_index],labels[batch_index]

上面给出了两种返回数据的方式,都可以返回数据,尤其需要注意一下labels.index_select(0,batch_size)为第0维的数据,并不是从0开始索引,如果你之前熟悉numpy的话,其实本质上就和axes一个道理。

3.初始化模型的参数

接下来就是随机初始化模型的参数,采用normal函数来随机初始化权重。

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

注意一下,需要设置梯度,为了利用pytorch的反向传播。

4. 构建模型

def LinReg(X,w,b):
    return torch.mm(X,w) + b

主要利用了torch.mm函数实现矩阵的相乘,当然也可以采用torch.matmul,都是可以的,但要注意二者的区别。

5.损失函数

def loss_fun(y_hat,y):
    return (y_hat-y.reshape(y_hat.shape))**2/2

此处采用最小二乘损失

6.优化函数

def SGD(params,lr,batch_size):
    for param in params:
        with torch.no_grad():
            param.data -=lr*param.grad/batch_size
            param.grad.zero_()    # 设置梯度清零,注意此处也可以不进行梯度清零,可以写在训练函数中,其实是一致的

注意一下,后面的梯度清零,可以在此处设置,也可以在训练函数处设置,基本上没有什么差别。

7.训练模型

epoches = 3    # 设置训练轮次
batch_size=10  # 设置一个批次训练的样本数
lr=0.01        # 学习率的设置

for epoch in range(epoches):
    for X,y in data_iter(batch_size,features,labels):
        loss=loss_fun(LinReg(X,w,b),y)  # 计算损失
        loss.sum().backward()           # 反向传播
        SGD([w,b],lr,batch_size)        # 更新参数
    with torch.no_grad():
        train_1 = loss_fun(LinReg(X,w,b),y)
        print("epoch:%d,loss:%.8f"%(epoch+1,train_1.mean().item()))

这里需要注意的就是loss需要求和转化为标量,如果没有此步骤的话,loss还是一个二维向量,pytorch里面设置的大部分都是标量的求导。

计算的结果如下:

以上就是今天的全部分享了,有问题的话可以在评论区留言哦,看到了就是及时回复大家的,希望哦我们可以一起进步呦。

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