PyTorch深度学习实战(2)——PyTorch基础

news2024/11/29 5:27:23

PyTorch深度学习实战(2)——PyTorch基础

    • 0. 前言
    • 1. 搭建 PyTorch 环境
    • 2. PyTorch 张量
      • 2.1 张量初始化
      • 2.2 张量运算
      • 2.3 张量对象的自动梯度计算
    • 3. PyTorch 张量相对于 NumPy 数组的优势
    • 小结
    • 系列链接

0. 前言

PyTorch 是广泛应用于机器学习领域中的强大开源框架,因其易用性和高效性备受青睐。在本节中,将介绍使用 PyTorch 构建神经网络的基础知识。首先了解 PyTorch 的核心数据类型——张量对象。然后,我们将深入研究用于张量对象的各种操作。PyTorch 提供了许多帮助构建神经网络的高级方法及组件,并提供了利用 GPU 更快地训练神经网络的张量对象。

1. 搭建 PyTorch 环境

关于 Python 的安装和配置,在此不再赘述。由于深度学习中模型的训练需要大量时间,因此通常使用 GPU加速计算,在安装 PyTorch 之前需要根据选用的 PyTorch 版本和显卡安装 CUDAcudnn,关于 CUDAcudnn 的安装和配置可以参考官方文档,建议在安装之前根据自己的操作系统认真查看官方的安装文档,可以避免踩不必要的坑。如果计算机中含有 NVIDIA 显卡作为硬件组件,建议安装 CUDA 驱动程序,该驱动程序可将深度学习训练速度提高几个数量级。
然后,在 PyTorch 官方网页,根据自己实际的环境,进行相应的选择,在 Run this Command 栏中将给出安装 PyTorch 的命令:

Run this Command

在此,我们以 LinuxpipPythonCUDA10.2 为例,复制并在终端执行安装命令:

pip3 install torch torchvision torchaudio

为了确认 PyTorch 已正确安装,可以在 Python shell 中运行以下代码:

>>> import torch
>>> test = torch.empty(2,2)
>>> print(test)
tensor([[2.9685e-26, 4.5722e-41],
        [2.9685e-26, 4.5722e-41]])

如果能够正确调用 PyTorch 相关函数,表明 PyTorch 已正确安装。需要注意的是,以上代码中,使用 torch.emty() 中创建了一个尺寸为 2 x 2 的张量,它是一个空矩阵,这里的“空”并不意味着所有元素的值都为 Null,而是使用一些被认为是占位符的无意义浮点数,需要在之后进行赋值,这与 NumPy 中的空数组类似。

2. PyTorch 张量

张量 (Tensors) 是 PyTorch 的基本数据类型,张量是类似于 NumPy 中的多维矩阵 ndarrays

  • 标量可以表示为零维张量
  • 向量可以表示为一维张量
  • 二维矩阵可以表示为二维张量
  • 多维矩阵可以表示为多维张量

张量表示如下图所示:

张量示例

例如,我们可以将彩色图像视为像素值的三维张量,因为彩色图像由 h x w x 3 个像素组成,其中,hw 分别表示图像的高和宽,三个通道对应于 RGB 通道。类似地,灰度图像可以表示为 2 维张量,因为它由 h x w 个像素组成。

2.1 张量初始化

张量除了可以用作图像的基本数据结构外,另一种常见用途是利用张量来初始化连接神经网络不同层的权重。在本节中,我们将学习初始化张量对象的不同方法。

(1) 导入 PyTorch 并通过在列表上调用 torch.tensor 来初始化张量:

import torch
x = torch.tensor([[1,2]])
y = torch.tensor([[1],[2]])

(2) 获取张量对象的形状和数据类型:

print(x.shape)
# torch.Size([1,2]) # one entity of two items
print(y.shape)
# torch.Size([2,1]) # two entities of one item each
print(x.dtype)
# torch.int64

同一张量中的所有元素的数据类型相同,这意味着如果张量包含不同数据类型的数据(例如布尔、整数和浮点数),则整个张量将被强制转换为最通用的数据类型:

x = torch.tensor([False, 1, 2.0])
print(x)
# tensor([0., 1., 2.])

在以上输出结果中可以看到,布尔值 False 和整数 1 被转换为浮点数。
类似于 NumPy,我们也可以使用内置函数初始化张量对象,以便用于神经网络的权重初始化。

(3) 生成一个 34 列用 0 填充的张量对象:

a = torch.zeros((3, 4))
print(a)
"""
tensor([[0., 0., 0., 0.],
        [0., 0., 0., 0.],
        [0., 0., 0., 0.]])
"""

(4) 生成一个 34 列用 1填充的张量对象:

b = torch.ones((3, 4))
print(b)
"""
tensor([[1., 1., 1., 1.],
        [1., 1., 1., 1.],
        [1., 1., 1., 1.]])
"""

(5) 生成 34 列的张量对象,其中每个元素为 010 之间的随机整数值:

c = torch.randint(low=0, high=10, size=(3,4))
print(c)
"""
tensor([[8, 5, 5, 5],
        [1, 5, 4, 5],
        [6, 2, 9, 4]])
"""

(6) 生成 34 列的张量对象,其中每个元素为 01 之间的随机浮点值:

d = torch.rand(3, 4)
print(d)
"""
tensor([[0.4568, 0.8829, 0.8788, 0.2159],
        [0.8409, 0.9374, 0.6409, 0.2946],
        [0.7399, 0.4378, 0.8857, 0.2846]])
"""

(7) 生成 34 列的张量对象,其中每个元素服从正态分布:

e = torch.randn((3,4))
print(e)
"""
tensor([[ 0.3995,  1.1180, -0.0466,  0.9838],
        [-0.2359,  0.8302, -0.1792, -1.5365],
        [ 0.0842,  0.5544,  0.9606, -1.0090]])
"""

(8) 也可以使用 torch.tensor(<numpy-array>) 直接将 NumPy 数组转换为 Torch 张量:

import numpy as np
x = np.array([[10,20,30],[2,3,4]])
y = torch.tensor(x)
print(type(x), type(y))
# <class 'numpy.ndarray'> <class 'torch.Tensor'>

2.2 张量运算

NumPy 类似,张量对象同样可以执行各种基本运算,神经网络中的常见运算包括输入与权重的矩阵相乘、添加偏置项、以及在需要时整形 (reshape) 输入或权重值。

(1)x 中所有元素乘以 10

import torch
x = torch.tensor([[1,2,3,4], [5,6,7,8]]) 
print(x * 10)
"""
tensor([[10, 20, 30, 40],
[50, 60, 70, 80]])
"""

(2)x 中所有元素增加 10,并将结果张量存储在 y 中:

x = torch.tensor([[1,2,3,4], [5,6,7,8]]) 
y = x.add(10)
print(y)
"""
tensor([[11, 12, 13, 14],
[15, 16, 17, 18]])
"""

(3) 使用 view() 方法对张量进行整形:

y = torch.tensor([2, 3, 1, 0]) # y.shape == (4)
y = y.view(4,1)                # y.shape == (4, 1)

整形张量的另一种方法是使用 squeeze 方法,需要提供要删除的轴索引,需要注意的是,这仅适用于要删除的轴在该维度中只有一项时:

x = torch.randn(10,1,10)
z1 = torch.squeeze(x, 1) 
z2 = x.squeeze(1)
assert torch.all(z1 == z2) 
print('Squeeze:\n', x.shape, z1.shape)
"""
Squeeze:
torch.Size([10, 1, 10]) torch.Size([10, 10])
"""

(4)squeeze 相反的操作是 unsqueeze,即向矩阵添加一个新维度:

x = torch.randn(10,10)
print(x.shape)
# torch.size(10,10)
z1 = x.unsqueeze(0)
print(z1.shape)
# torch.size(1,10,10)
x = torch.randn(10,10)
z2, z3, z4 = x[None], x[:,None], x[:,:,None]
print(z2.shape, z3.shape, z4.shape)
# torch.Size([1, 10, 10]) torch.Size([10, 1, 10]) torch.Size([10, 10, 1])

使用 None 进行索引是一种重要的解压方式,通常用于创建新通道/维度。

(5) 执行两个不同张量的矩阵乘法:

x = torch.tensor([[1,2,3,4], [5,6,7,8]])
print(torch.matmul(x, y))
'''
tensor([[11],
        [35]])
'''

矩阵乘法也可以通过使用 @ 运算符来执行:

print(x@y)
'''
tensor([[11],
        [35]])
'''

(6)NumPy 中的连接操作 (concatenate) 类似,可以使用 cat 方法执行张量连接:

import torch
x = torch.randn(10,10,10)
z = torch.cat([x,x], axis=0) # np.concatenate()
print('Cat axis 0:', x.shape, z.shape)
# Cat axis 0:  torch.Size([10, 10, 10]) torch.Size([20, 10, 10])
z = torch.cat([x,x], axis=1) # np.concatenate()
print('Cat axis 1:', x.shape, z.shape)
# Cat axis 1: torch.Size([10, 10, 10]) torch.Size([10, 20, 10])

(7) 提取张量中最大值:

x = torch.arange(25).reshape(5,5)
print('Max:', x.shape, x.max()) 
# Max: torch.Size([5, 5]) tensor(24)

提取最大值以及存在最大值的行索引:

x.max(dim=0)
'''
torch.return_types.max(
values=tensor([20, 21, 22, 23, 24]),
indices=tensor([4, 4, 4, 4, 4]))
'''

需要注意的是,在以上输出中,我们获得了维度 0 上的最大值,这在此张量中表示行。因此,所有行的最大值是第 4 个索引中存在的值,因此索引输出也是 4。此外,max() 方法可以返回最大值和最大值的位置 (argmax)。

类似的,跨列取最大值时的输出如下:

m, argm = x.max(dim=1) 
print('Max in axis 1:\n', m, argm) 
'''
Max in axis 1:
 tensor([ 4,  9, 14, 19, 24]) tensor([4, 4, 4, 4, 4])
'''

min 操作与 max 完全相同,其返回最小值和最小值的位置 (argmin)。

(8) 重排 (permute) 张量对象的维度,当我们在原始张量之上执行 permute 时,张量的形状会发生变化:

x = torch.randn(10,20,30)
z = x.permute(2,0,1) # np.permute()
print('Permute dimensions:', x.shape, z.shape)
# Permute dimensions: torch.Size([10, 20, 30]) torch.Size([30, 10, 20])

避免使用 tensor.view 张量交换对象维度,即使 PyTorch 不会抛出错误,但这会在训练期间产生无法预料的结果,如果需要交换维度,推荐使用 permute

基本上,我们可以在 PyTorch 中使用与 NumPy 几乎相同的语法来执行几乎所有 NumPy 标准数学运算,例如 absaddargsortceilfloorsincostancumsumcumproddiageigexploglog2log10meanmedianmoderesizeroundsigmoidsoftmaxsquaresqrtsvdtranspose 等。可以使用 dir(torch.Tensor) 查看 PyTorch 张量的所有可用方法,使用 help(torch.Tensor.<method>) 可以查看该方法的官方帮助文档。

dir(torch.Tensor)
'''
['T',
 '__abs__',
 '__add__',
 '__and__',
 '__array__',
 '__array_priority__',
 '__array_wrap__',
 '__bool__',
 ...
]
'''

help(torch.Tensor.view)
'''
Help on method_descriptor:

view(...)
    view(*shape) -> Tensor
    
    Returns a new tensor with the same data as the :attr:`self` tensor but of a
    different :attr:`shape`.
    ...
'''

2.3 张量对象的自动梯度计算

微分和计算梯度在更新神经网络的权重中起着至关重要的作用,PyTorch 的张量对象内置梯度计算函数。在本节中,我们将了解如何使用 PyTorch 计算张量对象的梯度。

(1) 定义一个张量对象,同时指定它需要计算梯度:

import numpy as np
import torch
x = torch.tensor([[2., -1.], [1., 1.]], requires_grad=True)
print(x)
'''
tensor([[ 2., -1.],
        [ 1.,  1.]], requires_grad=True)
'''

在以上代码中, requires_grad 参数指定要为张量对象计算梯度。

(2) 定义计算输出的方法,计算所有输入的平方和:

out = x.pow(2).sum()

我们知道以上函数的梯度是 2*x,使用 PyTorch 提供的内置函数进行验证。

(3) 通过对该值调用 backward() 方法来计算该值的梯度:

out.backward()

(4) 计算得到 out 关于 x 的梯度,如下所示:

print(x.grad)

输出结果如下所示:

'''
tensor([[ 4., -2.],
        [ 2.,  2.]])
'''

获得的梯度与数学上的梯度值(2*x)相匹配。到目前为止,我们已经了解了在张量对象的初始化、基本运算和梯度计算——它们共同构成了神经网络的基本组件。

3. PyTorch 张量相对于 NumPy 数组的优势

在计算最佳权重值时,会对每个权重进行微量修改,并观察它对降低损失值的影响。需要注意的是,一个权重更新的损失计算不影响同一迭代中其他权重更新的损失计算。因此,每个权重更新可以由不同的核心并行进行,而非顺序更新权重,在这种情况下,GPUCPU 相比更具优势,因为 GPU 通常包含数千个核心。
NumPy 相比,PyTorch 张量对象经过优化以配合 GPU 使用。接下来,我们比较使用 NumPy 数组 (ndarray) 和 Tensor 张量 (tensor) 执行矩阵乘法所花费的时间。

(1) 生成两个不同的 torch 对象:

import torch
import time
x = torch.rand(1, 6400)
y = torch.rand(6400, 5000)

(2) 定义用于存储张量对象的设备:

device = 'cuda' if torch.cuda.is_available() else 'cpu'
assert device == 'cuda', "This exercise is on a GPU machine"

(3) 将步骤 1 中创建的张量对象注册到设备中,注册张量对象意味着将信息存储在指定设备中:

x, y = x.to(device), y.to(device)

(4) 执行 Torch 对象的矩阵乘法,并对其计时,并比较在 NumPy 数组上执行矩阵乘法的速度:

start = time.time()
for i in range(100):
    z=(x@y)
end = time.time()
print('Computation with GPU: ', format((end-start)/100, '.8f'))
# Computation with GPU:  0.00001792

(5)cpu 上执行相同的张量矩阵乘法:

x, y = x.cpu(), y.cpu()
start = time.time()
for i in range(100):
    z=(x@y)
end = time.time()
print('Computation with CPU: ', format((end-start)/100, '.8f'))
# Computation with CPU:  0.00665767

(6) 在 NumPy 数组上执行相同的矩阵乘法:

import numpy as np
x = np.random.random((1, 6400))
y = np.random.random((6400, 5000))
start = time.time()
for i in range(100):
    z = np.matmul(x,y)
end = time.time()
print('Computation with NumPy: ', format((end-start)/100, '.8f'))
# Computation with NumPy:  0.01121808

GPU 上对 Torch 对象执行的矩阵乘法比在 CPU 上的 Torch 对象快约 18 倍,比在 NumPy 数组上执行矩阵乘法快约 40 倍。一般来说,在 CPU 上使用 Torch 张量的矩阵乘法同样比 NumPy 更快。

小结

在本节中,我们学习了如何使用 PyTorch 的张量对象实现神经网络的基本组件,包括张量对象的初始化 (torch.tensor)、基本运算 (viewmaxmin、和 squeeze 等) 和梯度计算 (通过 requires_grad 参数指定要为张量对象计算梯度),并且对比了 PyTorch 张量相对于 NumPy 数组的优势。

系列链接

PyTorch深度学习实战(1)——神经网络与模型训练过程详解

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/607119.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

AutoHotKey脚本初步:判断和选择

文章目录 脚本基础连击识别setTimer判断和选择 脚本基础 尽管通过窗口识别与按键映射&#xff0c;就可以胜任很多工作了&#xff0c;但AutoHotKey仍提供了一些简单的编程功能&#xff0c;对一些稍微复杂的任务&#xff0c;也可以做到得心应手。但要注意一点&#xff0c;AHK的V…

【操作系统】Linux 中的 Page Cache

【操作系统】Linux 中的 Page Cache 参考资料&#xff1a; 文件 I/O 简明概述 - page cache 进程写文件时&#xff0c;进程发生了崩溃&#xff0c;已写入的数据会丢失吗&#xff1f; Linux Page Cache 调优在 Kafka 中的应用 【操作系统】一文带你深入浅出零拷贝技术 【操作系…

大数据Doris(三十四):Doris配置Spark与Yarn

文章目录 Doris配置Spark与Yarn 一、Doris配置Spark 1、配置 SPARK_HOME 环境变量 2、配置SPARK 依赖包

JavaScript之BOM(八)

JavaScript之BOM 1、BOM中的对象2、window对象2.1、简介2.2、常用的属性与方法2.3、常用的事件2.4、定时器和延时器 3、navigator 常用属性与方法4、history 常用属性与方法5、location 常用属性与方法 BOM&#xff1a;浏览器对象模型&#xff08;Browser Object Model&#xf…

交直流系统潮流计算及相互关联特性分析(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

chatgpt赋能python:Python取消合并单元格

Python取消合并单元格 在Excel中&#xff0c;合并单元格是一个非常常见的操作&#xff0c;它可以将多个单元格合并成一个单元格。这样可视化效果会更好&#xff0c;但是实际上会影响数据的计算和操作。如果你想取消这个操作&#xff0c;手工操作可能会非常费时间。不过&#x…

chatgpt赋能python:Python变量赋值

Python 变量赋值 在 Python 中&#xff0c;我们可以使用多种符号来给变量赋值。本文将介绍这些符号以及它们在编程中的应用。 等号&#xff08;&#xff09; 在 Python 中&#xff0c;我们最常用的符号是等号&#xff08;&#xff09;&#xff0c;它可以将一个值赋给一个变量…

Image fusion based on generative adversarial network consistent with perception

1.摘要 深度学习是红外和可见光图像融合领域中快速发展的方法。在这个背景下&#xff0c;密集块在深层网络中的使用显著提高了浅层信息的利用率&#xff0c;并且生成对抗网络&#xff08;GAN&#xff09;的组合也提高了两个源图像的融合性能。我们提出了一种基于密集块和GAN的…

“吴军讲ChatGPT“课程的个人总结

人工智能时代, ChatGPT如此火热, 大家恐慌, 焦虑, 大家最关注的是两个问题 我会不会被取代?我有没有机会? 吴军老师(浪潮之巅, 数学之美等), 有门课程, <吴军讲ChatGPT>, 用通俗易懂的语言, 讲解了人工智能的技术原理前世今生,以及当下火热的ChatGPT的可以做什么, 那…

关于windows驱动中断的几个小问题

1. intel 8259芯片中的IRQ2和int2的区别是什么&#xff1f; 答曰&#xff1a;IRQ2是芯片上的引脚&#xff0c;而int2是中断向量表的第2项&#xff0c;两者有很大区别。 Intel8259A芯片的中断引脚分别为&#xff1a; 主片&#xff1a; 0&#xff1a;8254时钟 1&#xff1a;键盘 …

chatgpt赋能python:**Python取余符号:了解%运算符的作用和用法**

Python取余符号&#xff1a;了解%运算符的作用和用法 作为一名有着10年编程经验的工程师&#xff0c;我对Python这门编程语言深有了解。在本文中&#xff0c;我将详细介绍Python的取余符号&#xff0c;即%运算符&#xff0c;其作用和用法。 什么是Python取余符号&#xff1f;…

AIGC技术研究与应用 ---- 下一代人工智能:新范式!新生产力!(2.3-大模型发展历程 之 多模态)

文章大纲 什么是多模态stable diffusion“ CLIP 其他模型”成为通用的做法多模态模态生成&#xff1a;文字生成图像取得突破&#xff0c;其他领域仍有待提升参考文献与学习路径GPT 系列模型解析前序文章模型进化券商研报陆奇演讲多模态 什么是多模态 多模态生成&#xff0c; …

PAT A1164 Good in C

1164 Good in C 分数 20 作者 陈越 单位 浙江大学 When your interviewer asks you to write "Hello World" using C, can you do as the following figure shows? Input Specification: Each input file contains one test case. For each case, the first pa…

信息论与编码 SCUEC DDDD 期末复习

1.证明熵的可加性 2.假设一帧视频图像可以认为是由3*10的五次方个像素组成&#xff08;每像素均独立变化&#xff09;&#xff0c;如果每个像素可取128个不同的等概率亮度表示。请计算出每帧图像含多少信息量&#xff1f;若有一口述者在约12000个汉字的字汇中选400个字来口述此…

计算机网络|第五章:网络层:控制平面

目录 &#x1f4da;概述 &#x1f4da;路由选择算法⭐️ &#x1f407;链路状态路由选择算法 ⭐️Dijkstra算法 &#x1f407;距离向量路由选择算法 ⭐️DV算法 &#x1f407;LS与DV路由选择算法的比较 &#x1f4da;因特网中自洽系统内部的路由&#xff1a;OSPF &…

chatgpt赋能python:Python取消关机:让你摆脱关机的烦恼

Python取消关机&#xff1a;让你摆脱关机的烦恼 作为一名有10年Python编程经验的工程师&#xff0c;我深知电脑在工作中的重要性和关机时带来的不便。有的时候你可能会忘记保存数据&#xff0c;或是需要长时间运行的程序正在进行&#xff0c;而突然被迫关机是非常让人头疼的。…

chatgpt赋能python:Python是炒股的好工具吗?——一个有10年python编程经验的工程师的分析

Python 是炒股的好工具吗&#xff1f;—— 一个有10年python编程经验的工程师的分析 作为一个有10年python编程经验的工程师&#xff0c;我深深地了解了Python的能力和潜力。 它不仅是一种流行的编程语言&#xff0c;还是一个强大的功能开发平台。它包括很多库&#xff0c;如P…

Maven高级——继承与聚合——继承关系实现

将Maven拆分成多个项目之后又会引发新的问题&#xff0c;继承与聚合就是用来解决这些问题。 这里的继承就像java中类和类之间的继承一样&#xff0c;工程之间也是可以实现继承的。 继承解决的问题 在之前拆分的三个模块中每个都配置了一个lombok的依赖&#xff0c;每一个mav…

【ARMv8 SIMD和浮点指令编程】NEON 减法指令——减法也好几种

向量减法包括常见的普通加指令&#xff0c;还包括长减、宽减、半减、饱和减、按对减、按对加并累加、选择高半部分结果加、全部元素加等。 1 SUB 减法&#xff08;向量&#xff09;&#xff0c;该指令从第一个源 SIMD&FP 寄存器中的相应向量元素中减去第二个源 SIMD&…

旧改快讯--宝安又一项目计划失效:有效期内专规未获批

西井工业区城市更新单元计划&#xff08;失效&#xff09;公告 西井工业区城市更新单元原列入了《2019年深圳市宝安区城市更新单元五批计划》&#xff0c;更新单元计划有效期3年9个月&#xff0c;自2019年8月12日起至2023年5月11日止&#xff1b;该项目在计划有效期内更新单元规…