目录
一、PyTorch——经典的深度学习框架
1、 PyTorch简介
PyTorch是一个基于Python的深度学习框架,它提供了一种灵活、高效、易于学习的方式来实现深度学习模型。
PyTorch使用张量(tensor)来表示数据,可以轻松地处理大规模数据集,且可以在GPU上加速。
PyTorch提供了许多高级功能,如自动微分(automatic differentiation)、自动求导(automatic gradients)等,这些功能可以帮助我们更好地理解模型的训练过程,并提高模型训练效率。
2、其他常见深度学习框架
-
TensorFlow: Google开发,广泛应用于学术界和工业界。TensorFlow提供了灵活的构建、训练和部署功能,并支持分布式计算。
-
Keras: Keras是一个高级神经网络API,已整合到TensorFlow中。
-
PaddlePaddle: PaddlePaddle(飞桨)是百度推出的开源深度学习平台,旨在为开发者提供一个易用、高效的深度学习开发框架。
-
MXNet:由亚马逊开发,具有高效的分布式训练支持和灵活的混合编程模型。
-
Caffe:具有速度快、易用性高的特点,主要用于图像分类和卷积神经网络的相关任务。
-
CNTK :由微软开发的深度学习框架,提供了高效的训练和推理性能。CNTK支持多种语言的接口,包括Python、C++和C#等。
-
Chainer:由Preferred Networks开发的开源深度学习框架,采用动态计算图的方式。
3、安装
1.Anaconda创建虚拟环境:
conda create -n "环境名" python=3.9
2.cuDNN和CUDA
cuDNN(CUDA Deep Neural Network library)和 CUDA(Compute Unified Device Architecture)密切相关,它们共同构成了高性能 GPU 计算的基础,尤其在深度学习领域。
CUDA,统一计算设备架构,是由 NVIDIA 提供的并行计算平台和编程模型。它允许开发者利用 NVIDIA GPU 的强大计算能力进行通用计算,包括科学计算、机器学习、图像处理和视频处理等。CUDA提供了GPU并行计算的底层基础,使GPU能够解决复杂的计算问题。
cuDNN是基于CUDA的深度神经网络加速库,提供了针对深度学习常见操作(如卷积、池化、归一化、激活函数等)的高度优化实现。
-
性能优化:cuDNN 为卷积神经网络等深度学习模型的训练和推理提供了极高的性能优化。它利用 CUDA 在 GPU 上进行加速计算,充分发挥了 GPU 的并行计算能力。
-
易用性:cuDNN 被集成在主流的深度学习框架(如 TensorFlow、PyTorch、MXNet 等)中,用户直接通过框架调用 cuDNN 的功能,无需关心底层实现细节。
依赖和协同
-
依赖:cuDNN是建立在CUDA之上的库,它依赖于 CUDA 提供的基础计算能力。因此,使用 cuDNN 必须先安装 CUDA。
-
协同:在深度学习框架中,CUDA 提供了底层的 GPU 计算能力,而 cuDNN 通过调用 CUDA 来优化和加速深度学习操作。这种协同工作大幅提升了深度学习模型的训练和推理速度。
3.cmd中输入nvidia-smi查看GPU驱动程序版本,以保证选择的CUDA版本号小于等于GPU驱动程序版本。
4.在官方文档里面找到适合自己设备的PyTorch版本及对应的安装指令执行即可:Previous PyTorch Versions | PyTorch
二、Tensor概述
PyTorch会将数据封装成张量(Tensor)进行计算,所谓张量就是元素为相同类型的多维矩阵。
1、张量概念
张量(Tensor)是一个多维数组,可以看作是扩展了标量、向量、矩阵的更高维度的数组。张量的维度决定了它的形状(Shape),例如:
-
标量 是 0 阶张量,只有大小没有方向(温度,高度),如
a = torch.tensor(5)
-
向量 是 1 阶张量,具有大小和方向(加速度,力),如
b = torch.tensor([1, 2, 3])
-
2维矩阵 是 2 阶张量,线性变换(旋转矩阵,位移矩阵),,如
c = torch.tensor([[1, 2], [3, 4]])
-
更高维度的张量,如3维、4维等,通常用于表示图像、视频数据等复杂结构。
特点
动态计算图:PyTorch 支持动态计算图,这意味着在每一次前向传播时,计算图是即时创建的。
GPU 支持:PyTorch 张量可以通过
.to('cuda')
移动到 GPU 上进行加速计算。自动微分:通过
autograd
模块,PyTorch 可以自动计算张量运算的梯度,这对深度学习中的反向传播算法非常重要。
2、数据类型
PyTorch中有3种数据类型:浮点数 float、整数 int、布尔 bool。其中,浮点数和整数又分为8位、16位、32位、64位,加起来共9种。
分位数的原因
场景不同,对数据的精度和速度要求不同。通常,移动或嵌入式设备追求速度,对精度要求相对低一些。精度越高,往往效果也越好,自然硬件开销就比较高。
三、Tensor创建
1、基本创建方式
1.torch.tensor
该API通过根据指定的数据创建张量
import torch
import numpy as np
"""
torch.tensor
函数中有两个参数dtype和device, 分别代表数据类型和计算设备,可以通过属性dtype和device获取
"""
def test01():
# 标量创建张量
x = torch.tensor(5)
print(x, x.shape)
# 使用numpy随机数组创建张量
x1 = np.random.randn(3,4) # 正态分布 randn
x1 = torch.tensor(x1)
print(x1, x1.shape, x1.device)
# 根据list创建
x2 = [[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]
x2 = torch.tensor(x2)
print(x2, x2.shape, x2.dtype)
if __name__ == "__main__":
test01()
2. torch.Tensor
该API可根据形状创建张量,也可以用来创建指定数据的张量
import torch
def test02():
# 根据形状创建张量
x = torch.Tensor(2,3)
print(x)
# 根据具体的值
x1 = torch.Tensor([[1,2,3],[4,5,6]])
print(x1, x1.shape, x1.dtype)
x2 = torch.Tensor([10])
print(x2, x2.shape, x2.dtype)
if __name__ == "__main__":
test02()
3.torch.IntTensor
用于创建指定类型的张量,还有诸如Torch.FloatTensor、 torch.DoubleTensor、 torch.LongTensor......等
如果数据类型不匹配,那么在创建的过程中会进行类型转换,要尽可能避免,防止数据丢失。
import torch
def test03():
# 创建指定类型的张量
x = torch.IntTensor(2,3)
print(x, x.dtype) # int32
x1 = torch.FloatTensor(3,3)
print(x1, x1.dtype) # float32
x2 = torch.DoubleTensor(3,3)
print(x2, x2.dtype) # float64
x3 = torch.LongTensor(3,3)
print(x3, x3.dtype) # int64
x4 = torch.ShortTensor(3,3)
print(x4, x4.dtype) # int16
if __name__ == '__main__':
test03()
2、创建线性和随机张量
1.使用torch.arange 和 torch.linspace 创建线性张量
import torch
# 关闭科学计数法的显示
# torch.set_printoptions(sci_mode=False)
"""
使用torch.arange 和 torch.linspace 创建线性张量
"""
def test04():
# 1. 创建线性张量 按步长生成张量:等差 [start,end)
x = torch.arange(1,10,2) # 从1开始,到10结束(不包含10),步长为2
print(x.dtype, x)
# 2. 在指定空间按照元素个数生成张量:等差 间隔=(start-end)/(steps-1)
x1 = torch.linspace(1,10,4)# 从1开始,到10结束(包含10),取4个元素并形成相同间隔
print(x1.dtype, x1)
# 3. 在指定空间按照元素个数生成张量:等比 [start,end]
x2 = torch.logspace(1,10,3, base=2)# 从2的1次方开始,到2的10次方结束(包含10),均匀生成3个数
print(x2.dtype,x2)
2.使用 torch.rand和torch.randn 创建随机张量
import torch
def test05():
# 随机数种子
torch.manual_seed(666)
# 获取当前随机数种子
print(torch.initial_seed())
# 生成随机张量
x = torch.rand(3,3) # np.random.rand(3,3) 目的一致
print(x)
# 标准正态分布随机张量
x1 = torch.randn(3,3)
print(x1)
# 自行配置均值和方差的正态分布的随机张量
x2 = torch.normal(mean=2,std=3,size=(3,3)) # 均值为2 方差为3
print(x2)
if __name__ == '__main__':
test05()
3、创建全0、全1张量
1.使用torch.zeros 和 torch.zeros_like 创建全0张量
import torch
import numpy as np
"""
torch.zeros 和 torch.zeros_like 创建全0张量
"""
# 创建指定形状的张量 用0填充
x = torch.zeros(2,3)
print(x)
# torch.zeros_like 传入的数据容器只能是tensor 不能是列表或数组
# 解决方案
# x = torch.tensor(np.array[1,2,3])
x1 = torch.tensor([[1,2,3],[4,5,6]])
x2 = torch.zeros_like(x1)
print(x1)
print(x2)
2.使用torch.ones 和 torch.ones_like 创建全1张量
import torch
# 创建指定形状的张量 用1填充
x = torch.ones(2,3)
print(x)
x1 = torch.tensor([[1,2,3],
[4,5,6]])
x2 = torch.ones_like(x1)# 根据x1创建全1张量
print(x1)
print(x2)
4、创建指定值张量
使用torch.full 和 torch.full_like 创建全为指定值张量
import torch
# 创建指定形状的张量 用66填充
x = torch.full((3,2),66)
print(x)
x1 = torch.tensor(np.zeros((3,4)))
x2 = torch.full_like(x1,99)# 根据x1创建全99张量
print(x2)
5、创建单位张量
4.使用eye创建对角线上为1的单位张量
import torch
x = torch.eye(3) # 创建3*3的单位矩阵
print(x)
四、Tensor常见属性
1、获取属性
import torch
x = torch.tensor([1,2,3])
print(x.dtype)# tensor中数据的类型 默认是float32
print(x.device)# tensor在哪个设备运行 默认是cpu
# 可以在创建时指定设备
x1 = torch.tensor([1,2,4],device='cuda')
print(x1.device)
print(x.shape)# 获取张量的形状
"""
[] 0阶张量标量
[3] 1阶张量有3个数据
[3,4] 2阶张量 3行四列
[3,4,512,512] 4阶张量 第一层有四个每个中有两个512*512的矩阵
"""
2、设备切换
不同设备上的tensor之间不能直接进行运算。
import torch
# 01 创建时切换
x = torch.tensor([1,2,3], device='cuda')
print(x)
# 02 创建后切换
x1 = torch.tensor([1,2,3])
x2 = x1.to('cuda:0') # to()会返回一个新的x 新x在cuda上
print(x2)
# 通过api获取当前设备中是否有cuda
re = torch.cuda.is_available()
print(re) # 若没有cuda则返回False
x1.to('cuda' if torch.cuda.is_available else 'cpu')
# 03 把创建的tensor移动到cuda上
x3 = torch.tensor([11,21,31])
x4 = x3.cuda() # 会返回一个新的x 原变量的值仍在在cpu上
x4 = x3.cuda() if torch.cuda.is_available() else x3
3、类型转换
import torch
# 01 创建时指定类型
x = torch.tensor([10,20,30],dtype=torch.float16)
print(x.dtype) # float16
# 02 创建后转换类型 type()不会修改原数据 返回新数据
x1 = x.type(torch.int8)
print(x1.dtype) # int8
print(x.dtype) # float16
# 03 更多转换
x2 = x.float()
print(x2.dtype) # float32
x3 = x.half()
print(x3.dtype) # float16
x4 = x.double()
print(x4.dtype) # float64
x5 = x.long()
print(x5.dtype) # int64
五、Tensor数据转换
1、Tensor与Numpy
1.Tensor转换为Numpy
"""
浅拷贝转换
numpy()
"""
x = torch.tensor([1,2,3])
# tensor转换成numpy
x = x.numpy()
print(type(x1)) # <class 'numpy.ndarray'>
# x和x1是两个不同的对象 但数据共享
x1[0] = 100
print(x) # tensor([100, 2, 3])
"""
深拷贝转换
numpy().copy()
"""
x = torch.tensor([1,2,3])
x1 = x.numpy().copy() # numpy的copy方法
x1[0] = 66
print(x) # tensor([1, 2, 3])
2.Numpy转换为Tensor
x = np.array([1,2,3])
# 01 numpy转换成tensor 深拷贝torch.tensor()
x1 = torch.tensor(x) # 不共用内存
x[0] = 1000
print(x)
print(x1)
# 02 numpy转换成tensor 浅拷贝 torch.from_numpy()
x2 = np.array([1,2,3])
x3 = torch.from_numpy(x2)# 会共用内存
x2[0] = 66
print(x2)
print(x3)
2、Tensor与图像
1.图像转Tensor
import cv2
import torch
from PIL import Image
from torchvision import trasnforms
"""
图像转tensor
"""
# 01 cv2库导入图像
def test01():
img = cv2.imread(r"./data/1.png")
print(img)
print(type(img)) # <class 'numpy.ndarray'>
img = torch.from_numpy(img)
print(img)
# 02 PIL库 transforms.ToTensor()将图片转换为张量
def test02():
path = r"./data/1.png"
img = Image.open(path)
print(img)
transfer = transforms.ToTensor()
img_tensor = transfer(img)
print(img_tensor) # 维度:[[808*576],[808*576],[808*576],[808*576]]
print(img_tensor.shape) # torch.Size([4, 808, 576])
2.Tensor转图像
def test03():
img_tensor = torch.rand(4,315,315)
print(img_tensor)
print(img_tensor.shape)
# tensor转换PIL对象
transfer = transforms.ToPILImage()
img_pil = transfer(img_tensor)
img_pil.show()