Pytorch 张量
该笔记从02开始后面是pytorch官网上的60分钟入门篇,我自己翻译的,翻译的不太好,凑活看哈哈哈。。。
标量(0D)
只包含一个元素的张量为标量。类型通常为FloatTensor或LongTensor
import torch
x = torch.rand(10)
x.size()
向量(1D)
import torch
x = torch.FloatTensor([1.0,2.0,3.0,4.0])
out:
torch.Size([4])
矩阵(2D)
x = torch.FloatTensor([[1,2],[3,4]])
print(x.size())
out:
torch.Size([2, 2])
三维向量
多个矩阵累加在一起。比如一张图片,有三个通道,每个通道都有一个矩阵。此处的pic2.jpg是一个28x28x3的图片。
import numpy as np
import torch
import cv2 as cv
src = cv.imread('../pic2.jpg')
matrix = np.array(src)
tensor = torch.from_numpy(matrix)
print(tensor.size())
out:
torch.Size([28, 28, 3])
切片张量
这里和python的用法一样
sales = torch.FloatTensor([1.0,2.0,3.0,4.0,5.0])
print(sales[:2])
out:
tensor([1., 2.])
对于前面的如果需要其中一个通道。一种用切片向量,一种用opencv的split方法。
import numpy as np
import torch
import cv2 as cv
src = cv.imread('../pic2.jpg')
matrix = np.array(src)
tensor = torch.from_numpy(matrix)
#切片
qp_tensor = tensor[:,:,0]
print(qp_tensor.size)
#opencv方法
b,g,r = cv.split(src)
4维张量
对于多张图片,批处理那种
5维张量
视频数据。
GPU上的张量
import torch
import time
a = torch.rand(10000,10000)
b = torch.rand(10000,10000)
cpustart = time.time()
a.matmul(b)
cpuEnd = time.time()
#将张量转移到GPU
a = a.cuda()
b = b.cuda()
gpustart = time.time()
a.matmul(b)
gpuEnd = time.time()
print("CPU cost: " + str(cpuEnd - cpustart))
print("GPU cost: " + str(gpuEnd - gpustart))
out:
CPU cost: 7.888931035995483
GPU cost: 0.1765275001525879
常见的方法
判断GPU是否可用
if torch.cuda.is_available():
tensor = tensor.to('cuda')
print(f"device tensor is stored on: {tensor.device}")
生成空矩阵
没有初始化
import torch
# 构造一个5 x 3的矩阵,没有初始化
x = torch.empty(5,3)
print(x)
out:
tensor([[9.3673e-39, 9.5511e-39, 1.0194e-38],
[4.2246e-39, 1.0286e-38, 1.0653e-38],
[1.0194e-38, 8.4490e-39, 1.0469e-38],
[9.3674e-39, 9.9184e-39, 8.7245e-39],
[9.2755e-39, 8.9082e-39, 9.9184e-39]])
随机初始化
# 构造一个随机初始化的矩阵
x1 = torch.rand(5,3)
out:
tensor([[0.4749, 0.0095, 0.4786],
[0.5207, 0.4228, 0.0364],
[0.8313, 0.9352, 0.6975],
[0.2701, 0.5206, 0.8709],
[0.3670, 0.3378, 0.9704]])
创建零矩阵
# 构造一个矩阵全为0,数据类型是long类型的
x2 = torch.zeros(5,3,dtype=torch.long)
out:
tensor([[0, 0, 0],
[0, 0, 0],
[0, 0, 0],
[0, 0, 0],
[0, 0, 0]])
构造一个张量
#构造一个张量,直接使用数据
x3 = torch.tensor([5.5,3])
out:
tensor([5.5000, 3.0000])
基于一个已存在的tensor创建一个
# 创建一个tensor基于已经存在的tensor
x4 = x.new_ones(5,3,dtype=torch.double)
#Tensor.new_ones 返回一个与size大小相同的用1填充的张量,
#默认情况下,返回的Tensor具有次张量相同的torch.dtype和torch.device
# randn_like,基于已存在的tensor,创建随机相似的
x5 = torch.randn_like(x4,dtype=torch.float)
print(x4)
print(x5)
out:
tensor([[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.]], dtype=torch.float64)
tensor([[-0.7830, 0.2870, 0.3721],
[ 0.2931, 0.4255, 0.3800],
[-0.1016, 0.6011, -0.7567],
[ 0.4526, -1.0510, -0.4116],
[ 1.4605, 1.4378, 0.4322]])
获取维度信息
#获取维度信息
print(x5.size())
out:
torch.Size([5, 3])
加法
#######################加法####################
y1 = torch.ones(5,3) #创建一个全是1的矩阵
print(x4 + y1)
x6 = torch.add(x4,y1)
torch.add(x4,y1,out=x) #提供输出tensor作为参数
#还可以in-place
y1.add_(x4)
# 任何使张量发生变化的操作都有一个前缀'_'
out:
tensor([[2., 2., 2.],
[2., 2., 2.],
[2., 2., 2.],
[2., 2., 2.],
[2., 2., 2.]])
numpy一样标准的索引和切片
import torch
tensor = torch.ones(4,4)
tensor[:,1] = 0
print(tensor)
out:
tensor([[1., 0., 1., 1.],
[1., 0., 1., 1.],
[1., 0., 1., 1.],
[1., 0., 1., 1.]])
乘法
a = torch.rand(2,2)
b = torch.rand(2,2)
#乘法 对应位置相乘
print(a * b)
print(a.mul(b))
#自身乘法,相当于a = a * b
print(a.mul_(b))
print(a)
矩阵乘法计算,行乘列求和的那种
mul = tensor.matmul(tensor.t())
mul2 = tensor @ tensor.t()
print(mul)
print(mul2)
out:
tensor([[3., 3., 3., 3.],
[3., 3., 3., 3.],
[3., 3., 3., 3.],
[3., 3., 3., 3.]])
tensor([[3., 3., 3., 3.],
[3., 3., 3., 3.],
[3., 3., 3., 3.],
[3., 3., 3., 3.]])
连接张量
连接张量可以使用torch.cat。 将给定维数的张量顺序连接起来,也可以用torch.stack,另一种张量连接,略有不同
t1 = torch.cat([tensor,tensor],dim=1)
print(t1)
out:
tensor(
[[1., 0., 1., 1., 1., 0., 1., 1.],
[1., 0., 1., 1., 1., 0., 1., 1.],
[1., 0., 1., 1., 1., 0., 1., 1.],
[1., 0., 1., 1., 1., 0., 1., 1.]])
改变tensor的形状
#改变tensor大小或形状 torch.view
x7 = torch.randn(4,4)
y = x7.view(16)
z = x7.view(-1,8) #尺寸设为-1,表示自己算这个大小
print(x7.size(),y.size(),z.size())
out:
torch.Size([4, 4]) torch.Size([16]) torch.Size([2, 8])
获取标量的值
#如果只有一个tensor,使用item()可以获得这个value
x8 = torch.tensor([1])
print(x8)
print(x8.item())
out:
tensor([1])
1
numpy和tensor相互转换
numpy转pytorch
import numpy as np
import torch
import cv2 as cv
src = cv.imread('../pic2.jpg')
cv.imshow("hello",src)
matrix = np.array(src)
panda_tensor = torch.from_numpy(matrix)
print(panda_tensor.size())
cv.waitKey(0)
cv.destroyAllWindows()
主要是torch.from_numpy()
pytorch转numpy
tensor = torch_data.numpy()
# torch_data是一个tensor
模型的保存和读取
# 保存
def save():
net1 = torch.nn.Sequential(
torch.nn.Linear(1,10),
torch.nn.ReLU(),
torch.nn.Linear(10,1)
)
optimizer = torch.optim.SGD(net1.parameters(),lr=0.5)
for t in range(100):
prediction = net1(x)
loss = F.mse_loss(prediction,y)
optimizer.zero_grad()
loss.backward()
optimizer.step()
torch.save(net1,'net.pkl') # 方式1: 直接保存当前网络
torch.save(net1.state_dict(),'net_params.pkl') # 方式2: 保存网络中的参数parameters
def restore_net():
net2 = torch.load('net.pkl') # 加载网络
def restore_params():
net3 = torch.nn.Sequential(
torch.nn.Linear(1,10),
torch.nn.ReLU(),
torch.nn.Linear(10,1)
)
# 通过Parameters加载,由于存储的是参数而不是网络,所以这个需要构建一个和保存时候一样的网络,然后加载参数即可。
# 加载参数比直接加载网络要快。
net3.load_state_dict(torch.load('net_params.pkl'))