大家好,我是Sonhhxg_柒,希望你看完之后,能对你有所帮助,不足请指正!共同学习交流
个人主页-Sonhhxg_柒的博客_CSDN博客
欢迎各位→点赞 + 收藏⭐️ + 留言
系列专栏 - 机器学习【ML】 自然语言处理【NLP】 深度学习【DL】
foreword
✔说明⇢本人讲解主要包括Python、机器学习(ML)、深度学习(DL)、自然语言处理(NLP)等内容。
如果你对这个系列感兴趣的话,可以关注订阅哟
文章目录
介绍
为什么深度学习?
深度学习的应用
PyTorch 简介
PyTorch 中的 GPU
什么是张量?
练习 1.01:使用 PyTorch 创建不同秩的张量
使用 PyTorch 的优势
使用 PyTorch 的缺点
PyTorch 的关键要素
PyTorch autograd 库
PyTorch nn 模块
练习 1.02:定义单层架构
PyTorch 优化包
练习 1.03:训练神经网络
活动 1.01:创建单层神经网络
概括
本章介绍了这两大主题:深度学习和PyTorch。在这里,您将能够探索深度学习的一些最流行的应用,了解 PyTorch 是什么,并使用 PyTorch 构建单层网络,这将是您将所学应用于现实生活的起点数据问题。到本章结束时,您将能够使用 PyTorch 的语法构建神经网络,这在后续章节中必不可少。
深度学习是机器学习的一个子集,专注于使用神经网络解决复杂的数据问题。由于软件和硬件的进步使我们能够收集和处理大量数据(我们谈论的是数百万和数十亿的条目),它现在变得越来越流行。考虑到深度神经网络需要大量数据才能正常运行,这一点很重要。
一些最著名的深度学习应用是自动驾驶汽车、流行的聊天机器人和各种各样的声控助手,本章将进一步解释这些应用。
PyTorch 于 2017 年推出,其主要特点是使用图形处理单元( GPU ) 使用“张量”处理数据。这允许算法以高速运行,同时,它为用户提供了灵活性和标准语法,以获得许多数据问题的最佳结果。此外,PyTorch 使用动态计算图,让您可以随时随地对网络进行更改。本书使用 PyTorch 揭开神经网络的神秘面纱,帮助您了解神经网络架构的复杂性。
在本节中,我们将介绍深度学习的重要性及其流行的原因。
深度学习是机器学习的一个子集,它使用多层神经网络(大型神经网络),受人脑生物结构的启发,其中一层中的神经元接收一些输入数据,对其进行处理,并将输出发送到下层。这些神经网络可以由数千个相互连接的节点(神经元)组成,大部分组织在不同的层中,其中一个节点连接到前一层中的几个节点,从那里接收输入数据,以及连接到下一层中的多个节点。下一层,它在处理后将输出数据发送到该层。
深度学习的流行是由于它的准确性。对于诸如自然语言处理( NLP )之类的复杂数据问题,它实现了比以往其他算法更高的准确度水平。深度学习的出色表现能力已经达到机器可以超越人类的水平,例如在欺诈检测方面。深度学习模型不仅可以优化流程,还可以提高其质量。这意味着革命性领域的进步,在这些领域中,出于安全原因,准确性至关重要,例如自动驾驶汽车。
尽管神经网络在几十年前就已被理论化,但它们最近变得流行的主要原因有两个:
笔记
标记数据是指包含一组特征(描述实例的特征)和目标值(要达到的值)的数据;例如,一个包含人口统计和财务信息的数据集,其目标特征决定了一个人的工资。
下图显示了深度学习在数据量方面相对于其他算法的性能:
图 1.1:深度学习与其他算法的性能对比
如今,由于软件和硬件的进步使我们能够收集和处理这种粒度,这在今天是可能的。
如今,这可以通过使用 GPU 来实现,GPU 可以将神经网络的训练时间从几周缩短到几小时。
笔记
为了加速深度学习以便能够利用大量训练数据并构建最先进的模型,现场可编程门阵列( FPGA ) 和张量处理单元( TPU ) 正在开发中主要云计算提供商,如 AWS、微软 Azure 和谷歌。
深度学习正在革新技术,并且已经在影响我们的生活。深度学习可以应用于各种各样的情况,从医疗和安全(例如欺诈检测)目的到更琐碎的任务,例如为黑白图像着色或实时翻译文本。
目前正在开发或使用的一些深度学习应用包括:
PyTorch 是一个开源库,主要由 Facebook 的人工智能研究小组作为 Torch 的 Python 版本开发。
笔记
Torch 是一个开源的科学计算框架,支持多种机器学习算法。
PyTorch 于 2017 年 1 月首次向公众发布。它利用GPU的强大功能来加速张量的计算,从而加快复杂模型的训练时间。
该库有一个 C++ 后端,结合了 Torch 的深度学习框架,这使得计算速度比具有许多深度学习功能的原生 Python 库快得多。前端是用 Python 编写的,这有助于它获得普及,使新加入该库的数据科学家能够构建复杂的神经网络。可以将 PyTorch 与其他流行的 Python 包一起使用。
尽管 PyTorch 相当新,但由于它是根据该领域许多专家的反馈开发的,因此迅速流行起来。这导致 PyTorch 成为对用户有用的库。
GPU 最初是为了加速图形渲染中的计算而开发的,特别是对于视频游戏等。然而,由于它们能够帮助加速任何领域的计算,包括深度学习计算,它们最近变得越来越流行。
有几种平台允许将变量分配给机器的 GPU,其中计算统一设备架构( CUDA ) 是最常用的平台之一。CUDA 是由 Nvidia 开发的计算平台,由于使用 GPU 执行计算,它可以加速计算密集型程序。
在 PyTorch 中,可以通过使用torch.cuda包来为 CUDA 分配变量,如以下代码片段所示:
x = torch.Tensor(10).random_(0, 10)
x.to("cuda")
此处,第一行代码创建了一个张量,其中填充了随机整数(介于 0 和 10 之间)。第二行代码将该张量分配给 CUDA,以便所有涉及该张量的计算都由 GPU 而不是 CPU 处理。要将变量分配回 CPU,请使用以下代码片段:
x.to("cpu")
在 CUDA 中,解决深度学习数据问题时,最好分配包含网络架构的模型以及输入数据。这将确保在训练过程中执行的所有计算都由 GPU 处理。
然而,只有在你的机器有可用的 GPU 并且你已经安装了带有 CUDA 包的 PyTorch 的情况下才能完成此分配。要验证您是否能够在 CUDA 中分配变量,请使用以下代码片段:
torch.cuda.is_available()
如果前一行代码的输出为True,则您已准备就绪,可以开始在 CUDA 中分配变量。
笔记
要将 PyTorch 与 CUDA 包一起安装,请访问 PyTorch 的网站并确保选择包含 CUDA(任一版本)的选项:https ://pytorch.org/get-started/locally/ 。
与 NumPy 类似,PyTorch 使用张量来表示数据。张量是n维的类矩阵结构,不同之处在于 PyTorch 张量可以在 GPU 上运行(而 NumPy 张量不能),这有助于加速数值计算。对于张量,维度也称为等级。下图显示了不同维度张量的直观表示:
图 1.2:不同维度张量的可视化表示
与矩阵相反,张量是包含在可以与其他数学实体相互作用的结构中的数学实体。当一个张量变换另一个张量时,前者也进行了自己的变换。
这意味着张量不仅仅是数据结构,而是容器,当输入一些数据时,它可以以多线性方式映射到其他张量。
与 NumPy 数组或任何其他类似矩阵的结构类似,PyTorch 张量可以具有任意多的维度。可以使用以下代码片段在 PyTorch 中定义一维张量 ( tensor_1 ) 和二维张量 ( tensor_2 ):
tensor_1 = torch.tensor([1,1,0,2])
tensor_2 = torch.tensor([[0,0,2,1,2],[1,0,2,2,0]])
请注意,前面代码片段中的数字没有意义。重要的是不同维度的定义,其中填充了随机数。从前面的代码片段中,第一个张量的一个维度大小为 4,而第二个张量的每个维度大小为 5,这可以通过使用张量变量的形状属性来验证,如下所示:
tensor_1.shape
输出是torch.Size([4])。
tensor_2.shape
输出为torch.Size([2],[5])。
当使用支持 GPU 的机器时,实现以下修改来定义张量:
tensor = torch.tensor([1,1,0,2]).cuda()
使用 PyTorch 张量创建虚拟数据非常简单,类似于您在 NumPy 中所做的。例如,torch.randn()返回一个张量,其中填充了括号内指定维度的随机数,而torch.randint()返回一个填充了括号内定义的维度的整数(可以定义最小值和最大值)的张量括号:
笔记
此处显示的代码片段使用反斜杠 ( \ ) 将逻辑拆分为多行。当代码执行时,Python 会忽略反斜杠,将下一行的代码视为当前行的直接延续。
example_1 = torch.randn(3,3)
example_2 = torch.randint(low=0, high=2, \
size=(3,3)).type(torch.FloatTensor)
可以看出,example_1是一个用随机数填充的二维张量,每个维度的size都等于3,而example_2是一个用0和1填充的二维张量(high参数是上界独占),每个维度的大小等于 3。
任何用整数填充的张量都必须转换为浮点数,以便我们可以将其提供给任何 PyTorch 模型。
在在本练习中,我们将使用 PyTorch 库创建一阶、二阶和三阶张量。执行以下步骤来完成本练习:
笔记
对于本章中的练习和活动,您需要安装 Python 3.7、Jupyter 6.0、Matplotlib 3.1 和 PyTorch 1.3+(最好是 PyTorch 1.4,带或不带 CUDA)(如前言中所述)。它们将主要在 Jupyter Notebook 中开发,建议您为不同的作业保留一个单独的笔记本,除非被告知不要这样做。
import torch
使用0到1之间的值来填充张量。如果正确创建了等级,则可以根据需要定义张量的大小:
tensor_1 = torch.tensor([0.1,1,0.9,0.7,0.3])
tensor_2 = torch.tensor([[0,0.2,0.4,0.6],[1,0.8,0.6,0.4]])
tensor_3 = torch.tensor([[[0.3,0.6],[1,0]], \
[[0.3,0.6],[0,1]]])
如果您的机器有可用的 GPU,您可以使用 GPU 语法创建等效的张量:
tensor_1 = torch.tensor([0.1,1,0.9,0.7,0.3]).cuda()
tensor_2 = torch.tensor([[0,0.2,0.4,0.6], \
[1,0.8,0.6,0.4]]).cuda()
tensor_3 = torch.tensor([[[0.3,0.6],[1,0]], \
[[0.3,0.6],[0,1]]]).cuda()
print(tensor_1.shape)
print(tensor_2.shape)
print(tensor_3.shape)
打印语句的输出应如下所示,考虑到张量的每个维度的大小可能会根据您的选择而有所不同:
torch.Size([5])
torch.Size([2, 4])
torch.Size([2, 2, 2])
在下一节中,我们将讨论使用 PyTorch 的优缺点。
现在有几个库可用于开发深度学习解决方案,那么为什么要使用 PyTorch?答案是 PyTorch 是一个动态库,允许其用户非常灵活地开发可适应特定数据问题的复杂架构。
PyTorch 已被许多研究人员和人工智能开发人员采用,这使其成为机器学习工程师工具包中的重要工具。
需要强调的关键方面如下:
尽管优点巨大而且很多,但仍有一些缺点需要考虑,这里解释一下:
与任何其他库一样,PyTorch 具有用于开发不同功能的各种模块、库和包。在本节中,将解释构建深度神经网络的三个最常用的元素,以及一个简单的语法示例。
autograd库包含一种称为自动微分的技术。其目的是在数值上计算函数的导数。这对于我们将在下一章中学习的概念至关重要,称为反向传播,它是在训练神经网络时执行的。
元素的导数(也称为梯度)是指该元素在给定时间步长内的变化率。在深度学习中,梯度是指在训练步骤中必须更新神经网络参数的维度和大小,以最小化损失函数。这一概念将在下一章进一步探讨。
笔记
神经网络的详细解释和训练模型所采取的不同步骤将在后续部分中给出。
要计算梯度,只需调用backward()函数,如下所示:
a = torch.tensor([5.0, 3.0], requires_grad=True)
b = torch.tensor([1.0, 4.0])
ab = ((a + b) ** 2).sum()
ab.backward()
在前面的代码中,创建了两个张量。我们在这里使用requires_grad参数来告诉 PyTorch 计算该张量的梯度。但是,在构建神经网络时,不需要此参数。
接下来,使用两个张量的值定义了一个函数。最后,使用 backward()函数计算梯度。
通过打印a和b的梯度,可以确认它们只是针对第一个变量 ( a ) 计算的,而对于第二个变量 ( b ),它会抛出错误:
print(a.grad.data)
输出为张量([12., 14.])。
print(b.grad.data)
输出如下:
AttributeError: 'NoneType' object has no attribute 'data'
考虑到棘手的部分(梯度计算)已经处理完毕,仅autograd库就可以用来构建简单的神经网络。然而,这种方法可能很麻烦,因此引入了nn 模块。
nn模块是一个完整的PyTorch 模块,用于创建和训练神经网络,通过使用不同的元素,可以进行简单和复杂的开发。例如,Sequential()容器允许轻松创建遵循一系列预定义模块(或层)的网络架构,而不需要太多关于定义网络架构的知识。
笔记
可用于每个神经网络架构的不同层将在后续章节中进一步解释。
该模块还能够定义损失函数来评估模型以及本书将讨论的许多高级功能。
将神经网络架构构建为一系列预定义模块的过程只需几行即可实现,如下所示:
import torch.nn as nn
model = nn.Sequential(nn.Linear(input_units, hidden_units), \
nn.ReLU(), \
nn.Linear(hidden_units, output_units), \
nn.Sigmoid())
loss_funct = nn.MSELoss()
首先,导入模块。然后,定义模型架构。input_units是指输入数据包含的特征个数,hidden_units是指隐藏层的节点个数,output_units是指输出层的节点个数。
从上面的代码可以看出,网络的架构包含一个隐藏层,后面是一个 ReLU 激活函数和一个输出层,然后是一个 sigmoid 激活函数,使其成为一个两层网络。
最后,损失函数定义为均方误差( MSE )。
笔记
将解释针对不同数据问题的最流行的损失函数。
要创建不遵循现有模块序列的模型,可以使用自定义 nn模块。我们将后面介绍这些。
在本练习中,我们将使用 PyTorch 的nn模块为单层神经网络定义模型,并定义损失函数来评估模型。这将是一个起点,以便您能够构建更复杂的网络架构来解决现实生活中的数据问题。执行以下步骤来完成本练习:
import torch
import torch.nn as nn
input_units = 10
output_units = 1
model = nn.Sequential(nn.Linear(input_units, output_units), \
nn.Sigmoid())
print(model)
使用前面的代码片段运行将显示以下输出:
Sequential(
(0): Linear(in_features=10, out_features=1, bias=True)
(1): Sigmoid()
)
loss_funct = nn.MSELoss()
print(loss_funct)
运行前面的代码片段将显示以下输出:
MSELoss()
您已成功定义单层网络架构。
optim包用于定义优化器,该优化器将用于使用autograd模块计算的梯度在每次迭代中更新参数(将在以下章节中进一步说明) 。在这里,可以从可用的不同优化算法中进行选择,例如Adam、随机梯度下降( SGD ) 和均方根传播( RMSprop ) 等。
笔记
最流行的优化算法将在后续章节中进行解释。
要设置要使用的优化器,导入包后,以下代码行就足够了:
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
在这里,model.parameters()参数指的是先前创建的模型的权重和偏差,而lr指的是学习率,它被设置为0.01。
权重是用于确定一般上下文中一些信息的重要性级别的值。这意味着对于网络中的每个神经元,每一位信息都具有相应的权重。此外,偏差类似于添加到线性函数的截距元素,用于调整给定神经元相关性计算的输出。
学习率是一个运行参数,在优化过程中使用它来确定为最小化损失函数而采取的步骤的范围。
接下来,这里显示了运行优化 100 次迭代的过程,如您所见,它使用了nn模块创建的模型和autograd库计算的梯度:
笔记
下面代码片段中的#符号表示代码注释。注释被添加到代码中以帮助解释特定的逻辑位。下面代码片段中显示的三引号 ( """ ) 用于表示多行代码注释的起点和终点。注释被添加到代码中以帮助解释特定的逻辑位。
for i in range(100):
# 调用模型进行预测
y_pred = model(x)
# 根据y_pred和y计算损失函数
loss = loss_funct(y_pred, y)
# 将梯度归零,这样之前的梯度就不会累积
optimizer.zero_grad()
# 计算损失函数的梯度
loss.backward()
"""
调用优化器执行更新
的参数
"""
optimizer.step()
对于每次迭代,都会调用模型以获得预测 ( y_pred )。该预测和真实值 ( y ) 被馈送到损失函数以确定模型逼近真实值的能力。
接下来,将梯度归零,并使用backward()函数计算损失函数的梯度。
最后,调用step()函数根据优化算法和之前计算的梯度更新权重和偏差。
笔记
对于本练习,使用与上一个练习(练习 1.02,定义单层架构)相同的 Jupyter Notebook 。
在本练习中,我们将学习如何使用 PyTorch 的optim包来训练上一个练习中的单层网络。考虑到我们将使用虚拟数据作为输入,训练网络不会解决数据问题,但它将用于学习目的。执行以下步骤来完成本练习:
import torch
import torch.optim as optim
import matplotlib.pyplot as plt
x = torch.randn(20,10)
y = torch.randint(0,2, (20,1)).type(torch.FloatTensor)
optimizer = optim.Adam(model.parameters(), lr=0.01)
losses = []
for i in range(20):
y_pred = model(x)
loss = loss_funct(y_pred, y)
losses.append(loss.item())
optimizer.zero_grad()
loss.backward()
optimizer.step()
if i%5 == 0:
print(i, loss.item())
输出应如下所示:
0 0.25244325399398804
5 0.23448510468006134
10 0.21932794153690338
15 0.20741790533065796
前面的输出显示了纪元编号,以及损失函数的值,可以看出,损失函数正在减小。这意味着训练过程正在最小化损失函数,这意味着模型能够理解输入特征与目标之间的关系。
plt.plot(range(0,20), losses)
plt.show()
输出应如下所示:
图 1.3:损失函数被最小化
如您所见,损失函数正在最小化。
这样,您就成功训练了一个单层神经网络。
对于此活动,我们将创建一个单层神经网络,这将是我们在未来活动中创建深度神经网络的起点。让我们看看下面的场景。
您是萨默维尔市长的助理,人力资源部门要求您构建一个模型,该模型能够根据人们对城市服务的满意度来预测他们是否对当前政府感到满意。为此,您决定使用 PyTorch 构建单层神经网络,并使用之前调查的响应。执行以下步骤以完成此活动:
笔记
用于此活动的数据集取自 UC Irvine 机器学习存储库,可以使用以下 URL 从数据文件夹超链接下载:UCI Machine Learning Repository: Somerville Happiness Survey Data Set。它也可以在本书的 GitHub 存储库中找到:https ://packt.live/38gzpr5 。
笔记
推荐使用 pandas 的read_csv函数来加载 CSV 文件。要了解有关此功能的更多信息,请访问pandas.read_csv — pandas 1.5.2 documentation。
笔记
要对 pandas DataFrame 进行切片,请使用 pandas 的iloc方法。要了解有关此方法的更多信息,请访问pandas.DataFrame.iloc — pandas 1.5.2 documentation。
笔记
可以通过此链接找到此活动的解决方案。
深度学习是机器学习的一个子集,其灵感来自于人类大脑的生物结构。它使用深度神经网络通过使用大量数据来解决复杂的数据问题。尽管该理论是几十年前提出的,但由于硬件和软件的进步使我们能够收集和处理数百万条数据,它最近才得到使用。
随着深度学习解决方案的普及,许多深度学习库被开发出来。其中,最近的一个是 PyTorch。PyTorch 使用 C++ 后端,这有助于加快计算速度,同时具有 Python 前端以保持库易于使用。
它使用张量来存储数据,这些数据是可以在 GPU 上运行以加速处理的 n 级矩阵结构。它提供了三个主要元素,这些元素对于轻松创建复杂的神经网络架构非常有用。
autograd库可以计算函数的导数,用作梯度来优化模型的权重和偏差。此外,nn模块可帮助您轻松地将模型的架构定义为一系列预定义模块,以及确定用于衡量模型的损失函数。最后,考虑到先前计算的梯度, optim包用于选择用于更新参数的优化算法。
在下一章中,我们将了解神经网络的构建块。我们将涵盖三种类型的学习过程,以及三种最常见的神经网络类型。对于每个神经网络,我们将了解网络架构的结构以及训练过程的工作原理。最后,我们将了解数据准备的重要性并解决回归数据问题。