深度学习
一 初识Torch
1基础介绍
PyTorch是一个基于Python的深度学习框架,最初由Facebook开发,广泛用于计算机视觉、自然语言处理、语音识别等领域。用张量(tensor)来表示数据,可以在GPU上加速,处理大规模数据集。提供了诸如自动微分、自动求导等功能。
cuDNN(CUDA Deep Neural Network library)和 CUDA(Compute Unified Device Architecture)密切相关,它们共同构成了高性能 GPU计算的基础
CUDA(Compute Unified Device Architecture),统一计算设备架构,是由 NVIDIA 提供的并行计算平台和编程模型。它允许开发者利用 NVIDIA GPU 的强大计算能力进行通用计算,包括科学计算、机器学习、图像处理和视频处理等。CUDA提供了GPU并行计算的底层基础,使GPU能够解决复杂的计算问题。
cuDNN是基于CUDA的深度神经网络加速库,提供了针对深度学习常见操作(如卷积、池化、归一化、激活函数等)的高度优化实现。它为卷积神经网络等深度学习模型的训练和推理提供了性能优化,被集成在主流的深度学习框架中简单易用。它依赖于CUDA提供的基础计算能力,通过调用CUDA协同来优化和加速深度学习操作。
2 安装
windows+r输入cmd打开命令控制台:
输入nvidia-smi查看GPU驱动程序版本:
CUDA版本号<=GPU驱动程序版本
安装PyTorch:Previous PyTorch Versions | PyTorch中找到适合的PyTorch版本
在Anaconda prompt中输入:conda env list 查看虚拟环境
创建名为torch的虚拟环境:conda create -n torch Python=3.9
激活该虚拟环境:conda activate torch
安装:conda install pytorch==1.13.1 torchvision==0.14.1 torchaudio==0.13.1 pytorch-cuda=11.7 -c pytorch -c nvidia
推荐使用1.13.1版本,比较稳定,但一些新的特性不兼容
如果运行的时候提示numpy版本不对,要先卸载当前numpy版本,再下载新的numpy库
查看当前numpy版本:pip show numpy
卸载numpy:pip unstall numpy
安装numpy:pip install numpy==1.21.2
二 Tensor概述
PyTorch会将数据封装成张量(Tensor)进行计算,所谓张量就是元素为相同类型的多维矩阵。张量可以在 GPU 上加速运行。
1 概念
张量是一个扩展了标量、向量、矩阵的更高维度的数组,张量的维度决定了它的形状。
标量是0阶张量,单一的数值,只有大小没有方向(温度)
向量是1阶张量,一维数组,具有大小和方向(加速度)
2维矩阵是2阶张量,二维数组,可以进行线性变换
更高维度的张量可以表示图像、视频数据等复杂结构
2 特点
动态计算图:即时创建
GPU支持:to("cuda")
自动微分:通过autograd可以自动计算张量运算的梯度
3 数据类型
浮点:float 16,32,64
整数:int 8,16,32,64,uint8(8位无符号整数)
布尔值:True或False
对数据的精度和速度要求不同导致对数据类型的需求不同,精度越高效果往往越好硬件开销也越大。
三 Tensor的创建
1基本创建方式
1.torch.tensor
根据指定的数据创建张量
import torch
import numpy as np
print(torch.__version__)
#一阶张量
def cerate_tensor():
t1=torch.tensor(7)#创建一个一阶张量
print(t1.shape)#形状
print(t1.dtype)#它的类型(它指t1中的数据的类型)
print(type(t1))
#
def cerate_tensor2():
data=np.array([10,20,30,40])
t1=torch.tensor(data)
print(t1.shape)#形状
print(t1.dtype)#它的类型(它指t1中的数据的类型)
print(type(t1))
#列表张量
def cerate_tensor3():
data=np.array[10,20,30,40]#列表
t1=torch.tensor(data)
print(t1.shape)#形状
print(t1.dtype)#它的类型(它指t1中的数据的类型)
print(type(t1))
if __name__=="__main__":
cerate_tensor()
2.torch.Tensor
根据形状创建张量,也可以用来创建指定数据的张量
def cerate_tensor4():
t=torch.Tensor(3,4)
print(t.shape)#np阶段 (3,4)
#torch.Size([3, 4])
def cerate_tensor5():
t=torch.Tensor([10,20,30],[10,20,30])
print(t.shape)#np阶段 (3,4)
print(t.device)#在什么设备上进行运算
if __name__=="__main__":
cerate_tensor4()
3.torch.IntTensor
创建指定类型的张量,如果数据类型不匹配,那么在创建过程中会进行类型转换,但会造成数据丢失
def cerate_tensor6():
t=torch.IntTensor([10,20,30])
t=torch.FloatTensor([10,20,30])#会自动把类型转换为浮点数
t=torch.DoubleTensor([10,20,30])
t=torch.DoubleTensor([10,20,30])
t=torch.LongTensor([10,20,30])
t=torch.HalfTensor([10,20,30])
T=torch.BoolTensor([True,False])
t=torch.tensor([10,20,30],dtype=torch.float64)
t=torch.tensor([10,20,300],dtype=torch.int8,device="cuda")#2^8=256,300%256=44,输出10,20,44;cuda为GPU
print(t.shape)
print(t.dtype)
print(t.device)#在什么设备上进行运算
if __name__=="__main__":
cerate_tensor6()
2 创建线性和随机张量
1.创建线性张量
arange:等差
linspace:等间隔
logspace:等比
import torch
#关闭科学计数法的显示效果
torch.set_printoptions(sci_mode=False)
#线性张量
def test01():
x=torch.arange(1,10,2)#从1开始到10结束(不包含10)[1,10) step=2表示步长,等差数列
print(x)
print(x.dtype,x)
x=torch.linspace(1,10,4)#也是等差数列,[1,10] 取4个数字,这4个数字形成相同的“间隔”
print(x)
print(x.dtype,x)
x=torch.logspace(1,10,3,base=2)#等比数列 base=2表示2的指数 表示[2的1次方,和2的10次方] 一共有3个数字
print(x)
print(x.dtype,x)
if __name__=='__main__':
test01()
2.创建随机张量
rand:随机张量
randn:随机呈标准正态分布的张量
normal:mean(均值)std(方差)size(形状)的正态分布
random seed:随机数种子,用于初始化随机数生成器的数值,使用相同的种子进行初始化,生成器将产生相同的数列
#随机张量
def test02():
#设置随机数种子
torch.manual_seed(666)
#获取当前的随机数种子
r=torch.initial_seed()
print(r)
#生成随机张量
x=torch.rand(10,5)#np.random.rand(10,5)
print(x)
#生成标准正态分布的随机张量
x=torch.randn(1,10)
print(x)
#自己配置方差和均值
x=torch.normal(2,1,(3,3))
print(x)
if __name__=='__main__':
test02()
3.创建01张量
zeros:全0张量
zeros_like:类似于给定数据容器的全0张量
ones:全1张量
ones_like:类似于给定数据容器的全1张量
import torch
import numpy as np
def test01():
x=torch.zeros(4,4)#创建指定形状的张量用0填充
print(x)
x=torch.tensor([[10,20,30],[102,23,0]])
x=torch.rand(3,3)
#传入的数据容器只能是tensor,不能是列表或者数组
#x=[10,20,30]
#x=np.array([10,20,30])#(3,) (2,1) (2,1,4)
#解决方案
x=torch.tensor(np.array([10,20,30]))
x=torch.zeros_like(x)#torch.size([3])
print(x)
def test02():
x=torch.ones(4,4)#创建指定形状的张量用0填充
print(x)
x=torch.tensor([[10,20,30],[102,23,0]])
x=torch.rand(3,3)
#x=torch.tensor(np.array([10,20,30]))
x=torch.ones_like(x)#torch.size([3])
print(x)
if __name__=='__main__':
test01()
4.创建指定值张量
full:创建指定值张量
full_like:类似于给定数据容器的指定值张量
def test03():
x=torch.full((3,2),666)
print(x)
x=torch.full_like(x,2)
print(x)
if __name__=='__main__':
test03()
5.创建单位矩阵张量
eye:创建对角线上全为1的单位张量
def test04():
x=torch.eye(4)
print(x)
if __name__=='__main__':
test04()
四 Tensor常见属性
device:在cuda/cpu设备上运行
dtype:数据类型
shape:形状
1获取属性
import torch
def test01():
#torch.Tensor()
x=torch.tensor([1,2,3],device='cuda')#可以在创建时指定创建到cuda或者cpu
print(x.dtype)#tensor中数据的类型
print(x.device)#tensor在哪个设备上运行,默认创建在cpu上,数据在不同的设备不能运行
print(x.shape)#获取tensor形状
#[]0阶张量标量
#[3]1阶张量,有3个数据
#[3,4]2阶张量,张量有3行4列
#[4,2,512,512],4阶张量,第一层有2个,每个中有2个512*512的矩阵
if __name__=='__main__':
test01()
2切换设备
不同设备上的数据是不能相互运算的
def test02():
#不同设备上的tensor是不能参与运算的
x=torch.tensor([1,20,30],device='cuda')
x2=torch.tensor([1,20,30],device='cpu')
print(x)
print(x2)
print(x+x2)#这里运行会报错
#设备切换1
x=torch.tensor([1,2,3],device="cuda")
print(1,x.device)
#设备切换2
x=torch.tensor([1,2,3])
x.to("cpu")
x=x.to("cuda")#会返回一个新的x,这个新的x在cuda上,原变量的值依然在cpu上
print(2,x.device)
#可以通过api获取当前设备中是否有cuda
res=torch.cuda.is_available()
print(res)#设备上有显卡返回True否则就返回False
# c=1 if 100>10 else 0
# print(c)
x.to("cuda" if torch.cuda.is_available() else "cpu")
print(x.device)
#设备切换3 把创建的tensor移动到cuda上
x=torch.tensor([123,123])
print(x.device)
x=x.cuda()#新的x,这个新的x在cuda上,原变量的值依然在cpu上
print(x.device)
x=x.cuda() if torch.cuda.is_available() else x#如果有gpu则用gpu参与运行,否则用cpu
if __name__=='__main__':
test02()
3类型转换
def test03():
#类型转化1
x=torch.tensor([10,20,30,40],dtype=torch.float16)
print(x.dtype)
#类型转化2
x=x.type(torch.int8)#type函数不会修改原数据,会返回一个新数据
print(x.dtype)
#类型转化3
#浮点数
x=x.half()
print(x.dtype)
x=x.double()
print(x.dtype)
x=x.float()
print(x.dtype)
#整数
x=x.long()
print(x.dtype)
x=x.int()
print(x.dtype)
if __name__=='__main__':
test03()
五 Tensor数据转换
1 Tensor与Numpy
1.张量转Numpy
①浅拷贝
numpy(),此时内存共享
import torch
import numpy as np
def test01():
x=torch.tensor([1,2,3])
print(x)
#把tensor转换成numpy
x2=x.numpy()
print(x2)
print(type(x2))
#x和x2是两个不同的对象,但是他们的数据是共享的
x2[0]=100
print(x)
②深拷贝
copy(),此时内存不共享
def test02():
x=torch.tensor([1,2,3])
x3=x.numpy()
x2=x.numpy().copy()#numpy的copy方法,numpy还有一个方法view
print(x2)
x2[0]=100
print(x)#验证x是否改变
print(x2)
print(x3)#x3没变
x3[0]=666
print(x)
print(x2)
print(x3)
2.Numpy转张量
①浅拷贝
from_numpy:内存共享
②深拷贝
torch.tensor:内存不共享
def test03():
#numpy 转tensor 1
x=np.array([1,2,3])
x2=torch.tensor(x)#numpy转tensor 不共用内存
x[0]=1000
x2[1]=666
print(x)
print(x2)
#numpy转tensor 2
x3=np.array([1,2,3])
x4=torch.from_numpy(x3)#numpy转tensor 共用内存
x3[0]=100
x4[1]=200
print(x3)
print(x4)
if __name__=='__main__':
test03()
2 Tensor与图像
1.图片转Tensor
import cv2
import torch
from PIL import Image
from torchvision import transforms
def test01():
img=cv2.imread("./data/1.png")
print(img)
print(type(img))
img=torch.from_numpy(img)
imshow(img)
def test02():
#图片读取为PIL对象,再用转换器把PIL对象转换为张量
path=r"./data/1.png"#r:不转义
img=Image.open(path)
print(img)
transfer=transforms.ToTensor()
img_tensor=transfer(img)
print(img_tensor)
print(img_tensor.shape)
print(img_tensor[0])#rgb维度、行、列 和opencv不一样,opencv是行列维度
if __name__=='__main__':
test01()
2.Tensor转图片
import cv2
import torch
from PIL import Image
from torchvision import transforms
def test03():
# r=torch.rand(315,315)
# g=torch.rand(315,315)
# b=torch.rand(315,315)
#img_tensor=torch.tensor([r,g,b])
img_tensor=torch.rand(4,315,315)
print(img_tensor)
print(img_tensor.shape)
#tensor转PIL对象
transfer=transforms.ToPILImage()
img_pil=transfer(img_tensor)
print(img_pil)
if __name__=='__main__':
test03()
3 PyTorch图像处理
import cv2
import torch
from PIL import Image
from torchvision import transforms
def test05():
path=r"./data/1.png"
img=Image.open(path)
print(img)
transfer=transforms.ToTensor()
img_tensor=transfer(img)
img_tensor[0]+=100
tensor2pil=transforms.ToPILImage()
img_pil=tensor2pil(img_tensor)
img_pil.show()
img_pil.save("./data/2.png")
if __name__=='__main__':
test05()