深度学习之线性回归模型的实现(原理+pytorch代码实现)

目录

引言

1、原理

2、实战

2.1、生成样本数据集

2.2、加载数据集

2.3、创建模型

2.4、定义损失函数

2.5、定义优化算法

2.6、训练模型

引言

线性模型我觉得可以看作是深度学习中的开篇之作,通过该模型我们可以深入的理解深度学习是如何来训练模型的,以及深度学习训练一个模型的大概流程是什么样的,掌握了套路,我们就可以照猫画虎,按照自己的想法去构建模型。

1、原理

所谓线性回归,就是我们假设自变量x和因变量y之间的关系是线性的,y可以由x中的元素加权和得来。比如我们假设x是一个包含(x1, x2, …,xn)的一个n*1维的向量,每一个元素xi都对应一个权值wi,那么我们的y可以表示成:y=x1 x w1 + x2 x w2 + … + xn x wn +b, 这个b我们可以理解为线性模型的截距,我们称之为偏置,只是简单的平移作用。这里的xi的一个样本的若干个属性,加入我们有多个样本比如n个样本,每个样本有m个特征,那么可以将每个样本按照行进行拜访,形成一个n行m列的矩阵X,矩阵的每一行都对应一个样本。

深度学习之线性回归模型的实现(原理+pytorch代码实现)

上式的X的列数和w的行数是对应的,不明白的可以补一下矩阵相乘的知识哈。b在这里可以通过广播机制,自动变换成和w相同的行数。

那么由上式,我们就可以联系到深度学习神经网络中,输入有x1-xn组成, 输出只有一个y,每一个xi与y相连,相连的神经元之间再添加一个权重wi,由此就可以构造我们的神经网络线性回归模型了。

我们知道,神经网络做的工作就是预测,即我们给定样本输入,他进行预测样本标签。通过预测值与样本的真实值之间的差距,这个差距我们可以用损失来替代,通过损失值,我们可以来优化我们的参数,这个参数指的是我们的wi和b,因为我们的输出预测值是由一系列的wi和b经过计算得到的,所以我们的损失值中也包含着这些参数。那么我们希望的是这个损失值要足够的小,也就是我们的预测值和样本的真实值之间的差距很小,表示我们的预测值更精确更准确。那么如何让这个损失值足够小呢,我们常用的方法是梯度下降,也就是我们对损失值进行方向传播求导,计算参数的梯度也就是我们所说的对参数进行求导,然后对我们的参数进行更新,使得我们的线性模型能够更加准确的拟合我们的样本的真实值。

2、实战

在理清楚上面的思想之后我们就可以动手动过敲代码来实现我们上面的思路,以验证它的合理性。实践是检验真理的唯一标准,理论和实践并用,才能真正的明白。话不多说,下面我们分步骤,分行的来实现。

2.1、生成样本数据集

在后面的学习中,我们会用一些现成的数据,比如Minist,fashion-Minist,CIAFAR-10等数据集。这里的线性回归模型,我们自己定义一些数据集。

我们定义的简单一点,假如权值w只有两个值,true_w=[4.0, 5.0],偏置 true_b=[3.0],我们只有定义了这个w和b我们才能生成我们的样本标签,这里我们可以将ture_w和true_b看作是我们的真实的权值和偏置,在后面我们会通过神经网络来拟合出这些参数的近似值。有了权值和偏置,我们就可以生成我们的样本标签了。

通过torch.normal()函数来随机初始化我们的若干个样本,这个函数的功能是,通过我们给定均值和标准差,以及返回的张量的形状。可以参考这篇博客: torch.normal()小清新嘻嘻无敌的博客-CSDN博客torch.normal()

我们得到的预测值是通过矩阵相乘,需要用到torch.matmul()函数,这个函数可以实现tensor类型的数据的矩阵相乘。可以参考这篇博客: torch.matmul()用法介绍明日何其多的博客-CSDN博客_torch.matmul

对应的代码如下:

import random
import torch
第一步:构造一个自定义数据集
true_w = torch.tensor([4.0, 5])                 #定义我们的真实的权值
true_b = torch.tensor([3.0])                    #定义我们的真实的偏置
data_num = 1000                                 #假设我们生成1000个样本
def data_create(w, b, data_num):                #定义一个函数,用于生成我们的样本
    X = torch.normal(0, 1, (data_num, len(w)))  #注意数据集X的形状,行数就是我们的样本数,列数是权值的行数
    Y = torch.matmul(X, w) + b                  #注意数据集标签的形状,它和X的行数保持一致
    Y += torch.normal(0, 0.01, Y.shape)         #给标签向量Y添加一个噪声,均值为0,标准差为0.01,这个并无大碍
    return X, torch.reshape(Y, (-1, 1))         #将我们得到的数据集的特征和标签返回。
X, Y = data_create(true_w, true_b, data_num)    #调用一下我们的函数
for i in range(5):                              #查看X,Y的前五个数据
    print(f'X[{i}]={X[i]}, Y[{i}]={Y[i]}')      #打印输出

结果如下:

深度学习之线性回归模型的实现(原理+pytorch代码实现)

2.2、加载数据集

我们创建好数据集之后,我们可以按照批量的加载我们生成的数据集,也就是我们一次从数据集中取出若干个样本,假如我们取样本的顺序是无序的。

这里用到的函数有random.shuffle(),其实现的主要功能是将列表中的元素随机打乱。

yield相当于一个可迭代的对象,每一次读取都是从当前位置开始往下执行。可以参考这篇博客: python中yield的用法详解——最简单,最清晰的解释冯爽朗的博客-CSDN博客python yield

对应的代码如下:

第二步:按批次从我们创造的数据集中随机的产生一个小批次的数据集
def data_loader(X, Y, batch_size):            #定义函数,参数为样本数据集,样本标签集Y, 每次取数据的数量batch_size
    data_length = len(X)                      #首先获得我们的数据集的大小
    print('数据长度data_length=', data_length)
    data_list = list(range(data_length))      #生成每一个数据的编号列表,范围从0—数据集的长度
    print('数据列表data_list=',data_list)
    random.shuffle(data_list)                 #打乱我们的这个编号,以保证编号是无序的,我们按照顺序从列表中取出的编号是无序的。
    print('打乱后的数据列表data_list=', data_list)
    for i in range(0, data_length, batch_size): #遍历数据集的长度,步长为batch_size
        data_index = torch.tensor(data_list[i:min(i+batch_size, data_length)])#用min是保证我们最后一次如何数据集中的数据没有batch_size这么多的话则取到数据集的最大长度即可,得到了一个batch_size大小的列表。
        yield X[data_index], Y[data_index]      #可迭代对象,每次只返回一个batch_size大小的数据集样本和标签
    for X, Y in data_loader(X, Y, 2):           #打印结果
        print('X=', X)
        print('Y=', Y)

输出结果如下:

深度学习之线性回归模型的实现(原理+pytorch代码实现)

2.3、创建模型

我们有了数据,就可以创建我们的模型了,模型就是用来根据样本的输入特征,经过计算,预测出结果y。由于我们每一次是按照批次batch_size读取的样本数据,所以我们每一次也是往模型中输入这么多样本,得出的y也是有这么多样本组成的一个向量。

在这里我们需要初始化我们的模型参数权值和偏置,后面的任务就是来优化我们的这些参数。在pytorch中提供了记录参数的梯度的办法,即我们这个参数在进行运算的时候,系统会自动的记录这些参数的计算图,为后来的梯度计算分配内存,直到得出运算结果。我们只需要在初始化参数的时候显示声明requires_grad=True即可。可以参考这篇文章: Pytorch之requires_grad_ Zed的博客-CSDN博客requires_grad

对应的代码如下:

第三步:定义模型(线性模型)
w = torch.normal(0, 0.1, (2, 1), requires_grad=True)  # 随机的初始化我们的权值
b = torch.zeros(1, requires_grad=True)                # 初始化b为0
def model(X, w, b):                                   # 定义我们的神经网络模型
    return torch.matmul(X, w) + b                    # 返回值是我们经过计算之后输出的预测值Y向量

2.4、定义损失函数

计算损失函数有多种,这里我们计算损失函数用平方差损失,也就是预测值y_hat与真实值y作差然后平方。除以2这个不用担心,这个只是为了求导方便,并不会影响什么。

对应代码如下:

第四步:定义损失函数
def squre_loss(y_hat, Y):                                  #函数传入预测值和真实值
    return (y_hat - torch.reshape(Y, y_hat.shape))**2 / 2  #返回的是平方损失,这里我们没有除以样本数,返回的是一个向量,向量中的元素由每个样本的平方损失组成。

2.5、定义优化算法

所谓优化算法就是我们根据当前的损失值,怎么去更新我们的参数w和b,以使得我们能够更好的去优化我们的模型,输出预测值更加准确。这里我们运用的是梯度下降法来优化我们的参数w和b,也就是求导数。关于torch.no_grad()的使用,可以参考这篇文章: 【pytorch系列】 with torch.no_grad():用法详解大黑山修道的博客-CSDN博客no_grad ,说白了就是反向传播的时候不用记录计算图。

对应代码如下:

第五步:定义优化算法  (即如何更新我们的参数)
这里我们需要着重理解,我们在进行参数更新的时候,不需要记录参数的梯度,更新完之后我们还需把当前的梯度设置为0
def sgd(params, lr, batch_size):                    #传入我们需要更新的参数,学习率lr也就是我们更新的步长,批量大小batch_size
    with torch.no_grad():                           #反向传播不需要梯度。
        for param in params:
            param -= lr * param.grad / batch_size   #进行参数w和b的更新
            param.grad.zero_()                      #将当前参数的梯度设置为0,以防止后面的梯度更显时造成梯度的累加

2.6、训练模型

训练模型是我们的核心工作,前面各个模块声明定义好之后,就需要在这里进行使用了。

mean()函数用于求和,可以查看这篇文章: numpy mean()函数 详解Vic_Hao的博客-CSDN博客mean

第六步:训练我们的模型
定义我们的超参数lr,数据集循环次数epoc,每批量大小batch_size
lr = 0.01
epoc = 5
batch_size = 10
for i in range(epoc):
    for trains, targets in data_loader(X, Y, batch_size=batch_size): #获得每一批量的训练数据和标签
        loss = squre_loss(model(trains, w, b), targets).sum()       #送入网络模型计算损失值,损失值这里我们进行了求和,即计算的是一个批量的整体损失。
        loss.backward()                                             #根据损失进行反向传播,求参数梯度
        sgd([w, b], lr, batch_size)                                 #根据梯度更新我们的参数w和b
    with torch.no_grad():                                           #循环一轮数据集之后,我们测试当前的模型在整个数据集上的整体损失
        global_loss = squre_loss(model(X, w, b), Y)
        print(f'第{i}轮训练,整体损失为:{global_loss.mean()}')
    print(f'第{i}轮循环之后,w和真实值之间的误差为:{w.reshape(true_w.shape) - true_w}')
    print(f'第{i}每一轮循环之后,b和真实值之间的误差为:{float(b - true_b)}')

结果为:

深度学习之线性回归模型的实现(原理+pytorch代码实现)

可以看出我们的损失非常的小,并且我们优化出来的w和b与我们文章开头定义的true_w和True_b的误差非常小。

以上就是线性回归模型的创建。真正弄明白以上程序,需要先把理论给弄懂才能更好的明白程序。

Original: https://blog.csdn.net/BaoITcore/article/details/124752745
Author: AI学习的我
Title: 深度学习之线性回归模型的实现(原理+pytorch代码实现)

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/709873/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球