一.Tensor概述
Pytorch,TensorFlow会把数据封装为tensor(张量)(MXNet为ndarry)
转换成张量因为可以在GPU上加速,同时可以自动微分
1. 概念
张量是一个多维数组,张量的维度决定它的形状
0维是标量,例如 data=torch.tensor(0),1维是向量,例如data=torch.tensor([9,8,9])
2维是矩阵,例如data=torch.tensor([7,4,2],[9,4,5])
(这个地方我自己常常怀疑自己[4,5,6],是一个一维向量,一个点,三维空间里的一个点)
2. 特点
-
动态计算图:PyTorch 支持动态计算图,在每一次前向传播时,计算图是即时创建的。
-
GPU 支持:PyTorch 张量可以通过
.
移动到 toGPU 上进行加速计算。 -
自动微分:通过autograd模块,PyTorch 可以自动计算张量运算的梯度,这对深度学习中的反向传播算法非常重要。
3. 数据类型
PyTorch中有3种数据类型:浮点数、整数、布尔。其中,浮点数和整数又分为8位、16位、32位、64位,加起来共9种。(一般32位就够了)
二.Tensor的创建
1. 基本创建方式
1.1 torch.tensor与torch.Tensor
torch.tensor用于将数据转换为张量 torch.Tensor用于创建张量类型的数据,也可转换
import torch
import numpy as np
def test001():
tensor1=torch.tensor(50)
tensor2=torch.tensor([1,2,3])
tensor3=torch.tensor(np.random.randn(5,6))
tensor4=torch.Tensor(3,4)
tensor5=torch.Tensor([1,2,3])
tensor6=torch.Tensor(np.random.randn(5,6))
print(tensor1,tensor2,tensor3,tensor4,tensor5,tensor6)
pass
if __name__ == "__main__":
test001()
就是一些numpy,列表可以通过torch.tensor转换为张量,直接的torch,Tensor很少使用,Tensor直接创建的就是空张量(也未被初始化)
1.2 torch.IntTensor
用于创建指定类型的张量(很有用,一般Float32即可,节省储存空间与运算空间)
2. 创建线性和随机张量
2.1线性张量 (展示创建线性张量的功能)
import torch
import numpy as np
def test003():
tensor1 = torch.arange(0, 10, 2)
tensor2 = torch.linspace(3, 10, 10)
tensor3 = torch.logspace(3, 10, 5, base=2)
print(tensor1,tensor2,tensor3)
if __name__ == "__main__":
test003()
2.2随机张量
主要就是随机数种子
import torch
import numpy as np
def test004():
torch.manual_seed(4)
print(torch.rand(3,3))
print(torch.normal(0,1,(3,3)))
if __name__ == "__main__":
test004()
保证模型可以复现,随机数种子代码可以敲得熟一点
3. 创建01张量与指定张量
直接调用API与简单的语法,创建全01的张量和用666填充张量空间
import torch
import numpy as np
def test005():
data1=torch.zeros(3,4)
mask=np.ones((1,2))
data2=torch.zeros_like(torch.tensor(mask))
data3 = torch.ones(2, 3)
data4 = torch.ones_like(torch.tensor(mask))
data5 = torch.full((2, 3), 666.0)
data6 = torch.full_like(torch.tensor(mask), 666.0)
print(data1,data2,data3,data4,data5,data6)
pass
if __name__ == "__main__":
test005()
4.创建单位矩张量
调用torch.eye(n) 创建n维的单位矩张量
import torch
import numpy as np
def test006():
data = torch.eye(5)
print(data)
if __name__ == "__main__":
test006()
5.获取tensor张量,进行Cpu,Gpu切换,进行张量类型转换
import torch
def test007():
print(torch.cuda.is_available())
data = torch.tensor([1,2,3])
print(data.dtype,data.shape,data.device)
data=data.type(torch.float32)
device="cuda" if torch.cuda.is_available() else "cpu"
data = data.to(device)
print(data.device,data.dtype)
pass
if __name__ == "__main__":
test007()
tensor有三个属性,分别是dtype类型,shape形状,device运行设备,通过if语句进行Cpu,Gpu的转换,同时张量的转换,float32是很合适的类型,存储,计算成本都不高
注意事项:
调用numpy()方法可以把Tensor转换为Numpy,内存是共享的,使用copy()方法可以避免内存共享
import torch
import numpy as np
def test008():
tensor1=torch.tensor([[1,2,3],[4,5,6]]).float()
tensor2=tensor1.numpy()
print(tensor1.dtype,tensor2.dtype)
tensor2[0,0]=100
print(tensor1,tensor2)
data_tensor = torch.tensor([[1, 2, 3], [4, 5, 6]])
data_numpy = data_tensor.numpy().copy()
print(type(data_tensor), type(data_numpy))
data_numpy[0, 0] = 100
print(data_tensor, data_numpy)
pass
if __name__ == "__main__":
test008()
数据转换的时候是共享的,不共享可以copy一份副本,其实为了简化存储空间,可以用切片法生成将值直接指向原来的存储空间,在花书第二章解读的时候会详细讲解
6.图像与张量相互转换
import torch
from PIL import Image
from torchvision import transforms
def test001():
imgpath = "cat.jpg"
img = Image.open(imgpath)
transform = transfo zrms.ToTensor()
img_tensor = transform(img)
print(img_tensor)
if __name__ == "__main__":
test001()
PIL是python图像处理库,也可以用OpenCV处理,正常的创建图像转换为张量或者张量转图片
import torch
from PIL import Image
from torchvision import transforms
def test002():
img_tensor = torch.randn(3, 224, 224)
transform = transforms.ToPILImage()
img = transform(img_tensor)
img.show()
img.save("./test.jpg")
if __name__ == "__main__":
test002()
图形与张量相关的实例分析
import torch
from PIL import Image
from torchvision import transforms
def test003():
# 指定读取的文件路径
imgpath = r"./105429.jpg"
# 加载图片
img = Image.open(imgpath)
# 图像转为Tensor
transform = transforms.ToTensor()
img_tensor = transform(img)
# 去掉透明度值
print(img_tensor.shape)
# 检查CUDA是否可用并将tensor移至CUDA
if torch.cuda.is_available():
img_tensor = img_tensor.cuda()
print(img_tensor.device)
# 修改每个像素值
img_tensor += 0.2
# 将tensor移回CPU并转换回PIL图像
img_tensor = img_tensor.cpu()
transform = transforms.ToPILImage()
img = transform(img_tensor)
# 保存图像
img.save("./ok.png")
if __name__ == "__main__":
test003()
三.Tensor的常见操作
1. 获取元素值
import torch
def test002():
data = torch.tensor([18])
print(data.item())
pass
if __name__ == "__main__":
test002()
把单个元素tensor转换为Python数值
2. 元素值运算
import torch
def test001():
data = torch.randint(0, 10, (2, 3))
print(data)
print(data.add(1))
print(data.sub(1))
print(data.mul(2))
print(data.div(3))
print(data.pow(2))
data = data.float()
data.add_(1)
data.sub_(1)
data.mul_(2)
data.div_(3.0)
data.pow_(2)
print(data)
if __name__ == "__main__":
test001()
常见的加减乘除次方取反开方等各种操作,带有_的方法则会替换原始值。
3. 阿达玛积
阿达玛积指的是矩阵对应位置的元素相乘,可以使用mul函数或者*来实现;
import torch
def test001():
data1 = torch.tensor([[1, 2, 3], [4, 5, 6]])
data2 = torch.tensor([[2, 3, 4], [2, 2, 3]])
print(data1 * data2)
def test002():
data1 = torch.tensor([[1, 2, 3], [4, 5, 6]])
data2 = torch.tensor([[2, 3, 4], [2, 2, 3]])
print(data1.mul(data2))
if __name__ == "__main__":
test001()
test002()
4. Tensor相乘
点积运算将两个向量映射为一个标量,是向量之间的基本操作。
点积运算要求如果第一个矩阵的shape是 (N, M),那么第二个矩阵 shape必须是 (M, P),最后两个矩阵点积运算的shape为 (N, P)。
使用@或者matmul完成Tensor的乘法
import torch
def test006():
data1 = torch.tensor([
[1, 2, 3],
[4, 5, 6]
])
data2 = torch.tensor([
[3, 2],
[2, 3],
[5, 3]
])
print(data1 @ data2)
print(data1.matmul(data2))
if __name__ == "__main__":
test006()