动手学深度学习(二)线性神经网络

这篇具有很好参考价值的文章主要介绍了动手学深度学习(二)线性神经网络。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

推荐课程:跟李沐学AI的个人空间-跟李沐学AI个人主页-哔哩哔哩视频

目录

一、线性回归

1.1 线性模型

1.2 损失函数(衡量预估质量)

二、基础优化算法(梯度下降算法)

2.1 梯度下降公式

2.2 选择学习率

2.3 小批量随机梯度下降

三、线性回归的从零开始实现(代码实现)

3.1 导包

3.2 生成数据集

3.3 读取数据集

3.4 定义初始化模型参数

3.5 定义模型

3.6 定义损失函数

3.7 定义优化算法

3.7 训练过程

四、线性回归的简洁实现

4.1 导包和生成数据集

4.2 读取数据集

4.3 定义模型

4.4 初始化模型参数

4.5 定义损失函数

4.6 定义优化算法

4.7 训练


回归任务是指对连续变量进行预测的任务。

一、线性回归

线性回归模型是一种常用的统计学习方法,用于分析自变量与因变量之间的关系。它通过建立一个关于自变量和因变量的线性方程,来对未知数据进行预测。

1.1 线性模型

举个例子,房价预测模型

  • 假设1︰影响房价的关键因素是卧室个数,卫生间个数和居住面积,记为x1,x2,x3。
  • 假设2:成交价是关键因素的加权和,动手学深度学习(二)线性神经网络,李沐讲深度学习,深度学习,神经网络,梯度下降,线性回归

权重和偏差的实际值在后面决定。

  • 给定n维输入,,向量x对应于单个数据样本的特征
  • 线性模型有一个n维权重和一个标量偏差,,。权重决定了每个特征对预测值的影响。偏置是指当所有的特征都取0时,预测值应为多少。
  • 输出是输入的加权和,动手学深度学习(二)线性神经网络,李沐讲深度学习,深度学习,神经网络,梯度下降,线性回归。我们常用表示预测值

则,该房价预测模型为:动手学深度学习(二)线性神经网络,李沐讲深度学习,深度学习,神经网络,梯度下降,线性回归,这是一个线性预测模型。给定一个数据集(如x),我们的目标就是寻找模型的权重和偏置,使得根据模型做出的预测大体符合数据中真实价格。也是就说最佳的权重和偏置有能力使得预测值逼近真实值,找到最佳的权重和偏置这是我们的最终目的。

1.2 损失函数(衡量预估质量)

用于比较真实值和预估值的差异,即以特定规则计算真实值和预估值的差值,例如房屋售价和估价。

假设是真实值,是预测值,平方差损失为 ,我们以该函数作为损失函数。

设训练集有n个样本,则这n个样本的损失均值

             动手学深度学习(二)线性神经网络,李沐讲深度学习,深度学习,神经网络,梯度下降,线性回归

Q:那么损失函数,对我们找到最优的权重和偏置有什么帮助呢?

我们可以看到,最佳的预测值与真实值之间的损失值一定是尽可能小的,因此我们只要求得最小的损失值,那么得到这个损失值的权重和偏置一定是最优的。

Q:怎么求得最小的损失值呢?

如,平方差损失函数是一个凹函数,那么求解最小的损失值,我们只需要将该函数关于的偏导数设为0,求导即可。求解得到的就是最优的权重。预测出的预估值也就最接近真实值。这类解称为解析解。

动手学深度学习(二)线性神经网络,李沐讲深度学习,深度学习,神经网络,梯度下降,线性回归

二、基础优化算法(梯度下降算法)

在绝大多数的情况下,损失函数是很复杂的(比如逻辑回归),根本无法得到参数估计值的表达式,也就无从获取没有显示解(解析解)

此需要一种对大多数函数都适用的方法,这就引出了“梯度下降算法”,这种方法几乎可以优化所有深度学习模型它通过不断地在损失函数递减的方向上更新参数来降低误差(原理)

动手学深度学习(二)线性神经网络,李沐讲深度学习,深度学习,神经网络,梯度下降,线性回归

2.1 梯度下降公式

首先,我们需要确定初始化模型的参数,接下来重复迭代更新参数t=1、2、3、....、n,更新权重的公式为:

动手学深度学习(二)线性神经网络,李沐讲深度学习,深度学习,神经网络,梯度下降,线性回归

其中,为上一次更新权重的结果,为学习率(这是一个超参数,决定了每次参数更新的步长),为损失函数递增的方向(注意公式中为负)。

2.2 选择学习率

梯度下降的过程宛如一个人在走下山路,一步一步地接近谷底,学习率相当于这个人的步长

动手学深度学习(二)线性神经网络,李沐讲深度学习,深度学习,神经网络,梯度下降,线性回归

学习率的选取不易过大,也不宜过小。学习率选取过大会使得权重更新的过程一直在震荡,而不是真正的在下降。学习率选取过小,会使得权重更新的过程十分缓慢,影响效率。

2.3 小批量随机梯度下降

一个神经网络模型的训练可能需要几分钟至数个小时,我们可以采用小批量随机梯度下降的方式来加快这一过程。

在整个训练集上计算梯度太昂贵了,因此可以随机采用 个样本来求取整个训练集的近似损失(原理)。求近似损失公式为:

动手学深度学习(二)线性神经网络,李沐讲深度学习,深度学习,神经网络,梯度下降,线性回归

 其中, 是批量大小,另一个重要的超参数。

Q:如何选择批量大小?

选择批量大小不能太小,也不能太大。批量大小选择过小,则每次计算量太小,不适合并行来最大利用计算资源。批量大小选择过大,内存消耗增加浪费计算,例如如果所有样本都是相同的。

三、线性回归的从零开始实现(代码实现)

3.1 导包

import random # 用于随机梯度下降
import torch
from d2l.torch import d2l # 这是动手学深度学习这本书中,李沐大神封装的一些方法

  

3.2 生成数据集

首先,我们根据带有噪声的线性模型构造一个人造数据集,我们的目的是通过这个数据集来还原线性模型中正确的参数。

我们使用线性模型参数 ,​ 和噪声项 生成数据集及其标签。

动手学深度学习(二)线性神经网络,李沐讲深度学习,深度学习,神经网络,梯度下降,线性回归

# 生成数据集
def synthetic_data(w, b, num_examples):
    """生成 y=Xw + b + 噪声"""
    X = torch.normal(0, 1, (num_examples, len(w))) # 正态分布(均值为0,标准差为1)
    y = torch.matmul(X, w) + b # 矩阵相乘
    y += torch.normal(0, 0.01, y.shape) # 加入噪声项
    # 得到的y为行向量的形式,为了使其变为一列的形式需要进行reshape
    return X, y.reshape((-1, 1))

true_w = torch.tensor([2, -3.4])
true_b = 4.2
features, labels = synthetic_data(true_w, true_b, 1000)

补充

torch.normal(mean,std,size,out)是PyTorch中用于生成服从正态分布的随机数的函数。

  • mean:正态分布的均值。可以是一个数值或一个张量。
  • std:正态分布的标准差。可以是一个数值或一个张量。
  • size:输出随机数的形状。可以是一个整数,用于生成一个大小为(size,)的一维张量;也可以是一个元组,用于生成相应形状的多维张量。
  • out:可选参数,用于指定一个输出张量。

绘图查看生成的数据集:

d2l.set_figsize()
d2l.plt.scatter(features[:, 1].detach().numpy(), labels.detach().numpy(), 1);
d2l.plt.show()

动手学深度学习(二)线性神经网络,李沐讲深度学习,深度学习,神经网络,梯度下降,线性回归

因为带有噪声原本的线性模型,变成了离散的点,但依然可以看出它是围绕着线性模型生成的。

3.3 读取数据集

定义一个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]

补充

range(start, stop, step),三个参数分别为起始,终止,步长。

random.shuffle(),调用后会直接打乱原来的列表。

3.4 定义初始化模型参数

# 初始化模型参数
w = torch.normal(0,0.01,(2,1),requires_grad=True)
b = torch.zeros(1,requires_grad=True)

3.5 定义模型

def linear(X,w,b):
    """定义模型"""
    return torch.matmul(X,w)+b

3.6 定义损失函数

采用平方损失函数。

def squared_loss(y_hat,y):
    # reshape为同一形状,再求平方差损失
    return (y_hat-y.reshape(y_hat.shape))**2/2

3.7 定义优化算法

小批量随机梯度下降。

# 小批量随机梯度下降
def sgd(params, lr, batch_size):
    with torch.no_grad(): # 以下不会生成计算图
        for param in params:  # 参数b和w
            param -= lr*param.grad/batch_size
            # 梯度归零
            param.grad.zero_()

补充:

在每一步中使用从数据集中随机抽取的一个小批量,然后根据参数计算损失的梯度。因为我们定义的损失函数是一个批量的总和,所以我们使用batch_size归一化步长,这样使得步长大小不会取决于我们对批量大小的选择。

3.7 训练过程

(1)初始化参数。

(2)重复以下训练,直到轮次结束:

  • 计算梯度
  • 更新参数
lr = 0.03  # 学习率
num_epochs = 3  # 迭代周期
batch_size = 10 # 批量大小
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中的所有元素被加到一起,backward的对象只能是标量
        # 并以此计算关于[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}')

补充

backward()函数是反向求导,使用链式法则求导。

如:l.sum().backward(),是指根据计算图,从标量l.sum()开始向后反向传播梯度(即,通过链式法则,从后往前计算每个参与得到 的tensor的梯度),并将得到的每个梯度存入对应tensor的grad元素中。

深度学习框架通过自动计算导数,即自动微分(automatic differentiation))来加快求导。实践中,根据设计好的模型,系统会构建一个计算图(computational graph),来跟踪计算是哪些数据通过哪些操作组合起来产生输出。自动微分使系统能够随后反向传播梯度。这里,反向传播(backpropagate) 意味着跟踪整个计算图,填充关于每个参数的偏导数。

深度学习之反向传播算法(backward())

四、线性回归的简洁实现

所谓的简洁实现是指使用pytorch的nn模组中到的一些数据预处理方法,来简洁地实现线性回归模型以及生成数据集。

4.1 导包和生成数据集

import numpy as np
import torch
from torch.utils import data
from torch import nn # nn是神经网络的缩写
from d2l import torch as d2l # 这是动手学深度学习这本书中,李沐大神封装的一些方法

true_w = torch.tensor([2,-3.4])
true_b = 4.2
features, labels = d2l.synthetic_data(true_w, true_b, 1000) # 直接生成

4.2 读取数据集

 调用torch.utils框架中现有的API来读取数据。

# 读取数据集
def load_array(data_arrays, batch_size, is_train=True):
    """构造一个PyTorch数据迭代器"""
    dataset = data.TensorDataset(*data_arrays) # 创建dataset对象
    return data.DataLoader(dataset, batch_size, shuffle=is_train) # 数据加载器,每一次随机返回batch_size个样本

batch_size = 10
data_iter = load_array((features, labels), batch_size)

我们读取并打印第一个小批量的样本查看。 

print(next(iter(data_iter))) # iter构造迭代器,next函数从迭代器中读取第一项

动手学深度学习(二)线性神经网络,李沐讲深度学习,深度学习,神经网络,梯度下降,线性回归

补充

data.TensorDataset(data_tensor, target_tensor),可以将给定的 tensor 数据(样本和标签),将它们包装成 dataset 。这些 tensor 数据的形状可以不尽相同,但第一个维度必须具有相同大小。

  • data_tensor (Tensor) – 样本数据
  • target_tensor (Tensor) – 样本目标(标签)

data.DataLoader(dataset, batch_size=1, shuffle=False, sampler=None,num_workers=0, collate_fn=<function default_collate>, pin_memory=False, drop_last=False)数据加载器,可以结合数据集和取样器,并在数据集上提供单线程或多线程迭代器。实际上,DataLoader是按指定规则在指定的数据集上生成了批量大小固定的可供迭代的数据

  • dataset (Dataset) – 加载数据的数据集。
  • batch_size (int, optional) – 每个batch加载多少个样本(默认: 1)。
  • shuffle (bool, optional) – 设置为True时,会在每个epoch重新打乱数据(默认: False).
  • sampler (Sampler, optional) – 定义从数据集中提取样本的策略。如果指定,则忽略shuffle参数。
  • num_workers (int, optional) – 用多少个子进程加载数据。0表示数据将在主进程中加载(默认: 0)
  • pin_memory (bool, optional) – 内存寄存,默认为False。在数据返回前,是否将数据复制到CUDA内存中。
  • drop_last (bool, optional) – 如果数据集大小不能被batch size整除,则设置为True后可删除最后一个不完整的batch。如果设为False并且数据集的大小不能被batch size整除,则最后一个batch将更小。(默认: False)

4.3 定义模型

使用nn框架的预定义好的层(线性层或全连接层)。

net = nn.Sequential(nn.Linear(2, 1)) # 输入大小为2、输出大小为1

第一个参数指定输入特征的形状大小,即2。

第二个参数指定输出特征形状,输出特征形状为单个标量,因此为1。

4.4 初始化模型参数

# 初始化模型参数
net[0].weight.data.normal_(0, 0.01)
net[0].bias.data.fill_(0)

net[0]是指网络的第一层。weight.data是指权重参数值,采用normal_()从均值为0,方差为1的正态分布区间随机选取bias.data是偏置参数值,采用fill_()填充为0。

4.5 定义损失函数

计算均方误差使用的是MSELoss类,也称为平方L2范数。默认情况下,它返回所有样本损失的平均值。

# 定义损失函数
loss = nn.MSELoss()

4.6 定义优化算法

小批量随机梯度下降算法,PyTorch在optim模块中实现了该算法的许多不同版本,其中之一,如torch.optim.SGD()。

trainer = torch.optim.SGD(net.parameters(), lr=0.03)

第一个参数是模型中所有的待优化的参数,第二个参数是学习率文章来源地址https://www.toymoban.com/news/detail-626035.html

4.7 训练

# 训练
num_epochs = 3
for epoch in range(num_epochs):
    for X, y in data_iter:              # 迭代已读取的数据
        l = loss(net(X) ,y)             # 计算一个批量数据的损失
        trainer.zero_grad()             # 清空梯度
        l.backward()                    # 反向传播,求导
        trainer.step()                  # 更新模型参数
    l = loss(net(features), labels)     # 计算总的平均损失
    print(f'epoch {epoch + 1}, loss {l:f}')

w = net[0].weight.data
print('w的估计误差:', true_w - w.reshape(true_w.shape))
b = net[0].bias.data
print('b的估计误差:', true_b - b)

到了这里,关于动手学深度学习(二)线性神经网络的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 动手学深度学习-pytorch版本(二):线性神经网络

    参考引用 动手学深度学习 神经网络的整个训练过程,包括: 定义简单的神经网络架构、数据处理、指定损失函数和如何训练模型 。经典统计学习技术中的 线性回归 和 softmax 回归 可以视为线性神经网络 1.1 线性回归 回归 (regression) 是能为一个或多个自变量与因变量之间关系建

    2024年02月12日
    浏览(47)
  • 1、动手学深度学习——线性神经网络:线性回归的实现(从零实现+内置函数实现)

    回归(regression)是能为一个或多个自变量与因变量之间关系建模的一类方法。 在自然科学和社会科学领域, 回归经常用来表示输入和输出之间的关系 。 给定一个数据集,我们的目标是 寻找模型的权重和偏置 , 使得根据模型做出的预测大体符合数据里的真实价格。 输出的

    2024年02月11日
    浏览(49)
  • 【动手学深度学习】现代卷积神经网络汇总

    本文为作者阅读学习李沐老师《动手学深度学习》一书的阶段性读书总结,原书地址为:Dive into Deep Learning。 网络结构 实现代码 网络特征 最早发布的卷积神经网络之一。 每个卷积块中的基本单元是一个卷积层、一个sigmoid激活函数和平均汇聚层。 网络结构 实现代码 网络特

    2024年02月07日
    浏览(47)
  • 自己动手实现一个深度学习算法——三、神经网络的学习

    这里所说的“学习”是指从训练数据中自动获取最优权重参数的过程 。为了使神经网络能进行学习,将导入 损失函数 这一指标。而学习的目的就是以该损失函数为基准,找出能使它的值达到最小的权重参数。为了找出尽可能小的损失函数的值,利用了 函数斜率的梯度法 。

    2024年02月05日
    浏览(48)
  • 动手学深度学习—卷积神经网络(原理解释+代码详解)

    多层感知机对图像处理是百万维度,模型不可实现。 如果要在图片中找到某个物体,寻找方法应该和物体位置无关。 适合 计算机视觉 的神经网络架构: 平移不变性 :不管检测对象出现在图像中的哪个位置,神经网络前几层应该对相同图像区域有相似的反应。 局部性 :神

    2024年02月14日
    浏览(50)
  • 《动手学深度学习》学习笔记 第9章 现代循环神经网络

    书籍链接: 动手学深度学习 笔记是从第四章开始,前面三章为基础知识,有需要的可以自己去看看 关于本系列笔记: 书里为了让读者更好的理解,有大篇幅的描述性的文字,内容很多,笔记只保留主要内容,同时也是对之前知识的查漏补缺 《动手学深度学习》学习笔记 第

    2024年01月18日
    浏览(51)
  • 《动手学深度学习 Pytorch版》 9.4 双向循环神经网络

    之前的序列学习中假设的目标是在给定观测的情况下对下一个输出进行建模,然而也存在需要后文预测前文的情况。 数学推导太复杂了,略。 双向循环神经网络(bidirectional RNNs)添加了反向传递信息的隐藏层,以便更灵活地处理此类信息。 前向和反向隐状态的更新如下:

    2024年02月07日
    浏览(43)
  • 深度学习——第7章 项目实战:自己动手写一个神经网络模型

    7.1 导入数据集 7.2 定义神经网络输入层、隐藏层、输出层神经元个数 7.3 网络参数W和b初始化 7.4 正向传播过程 7.5 损失函数 7.6 反向传播过程 7.7 网络参数更新 7.8 搭建整个神经网络模型 7.9 模型训练 7.10 模型预测 7.11 隐藏层神经元个数对分类效果的影响 上一课主要介绍了最简

    2024年01月16日
    浏览(37)
  • 十 动手学深度学习v2 ——卷积神经网络之NiN + GoogLeNet

    NiN块使用卷积层加两个1x1卷积层 后者对每个像素增加了非线性性 NiN使用全局平均池化层来替代VGG和AlexNet中的全连接层 不容易过拟合,更少的参数个数 Inception块由四条并行路径组成。 前三条路径使用窗口大小为1x1、3x3和5x5的卷积层,从不同空间大小中提取信息。 中间的两条

    2024年02月09日
    浏览(59)
  • 【AI】《动手学-深度学习-PyTorch版》笔记(十八):卷积神经网络模型

    发布时间:1989年 模型目的:识别手写数字 1.3.1 相关函数原型 1)nn.Conv2d:卷积层

    2024年02月13日
    浏览(73)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包