pytorch入门笔记01

  1. 1. Pytorch 张量
    1. 1.1. 标量(0D)
    2. 1.2. 向量(1D)
    3. 1.3. 矩阵(2D)
    4. 1.4. 三维向量
    5. 1.5. 切片张量
    6. 1.6. 四维张量
    7. 1.7. 五维张量
    8. 1.8. GPU上的张量
  2. 2. 常见的方法
    1. 2.1. 判断GPU是否可用
    2. 2.2. 生成空矩阵
    3. 2.3. 随机初始化
    4. 2.4. 创建零矩阵
    5. 2.5. 构造一个张量
    6. 2.6. 获取维度信息
    7. 2.7. 加法
    8. 2.8. numpy一样标准的索引和切片
    9. 2.9. 乘法
    10. 2.10. 连接张量
    11. 2.11. 改变tensor的形状
    12. 2.12. 获取标量的值
    13. 2.13. numpy和tensor相互转换
    14. 2.14. 模型的保存和读取

Pytorch 张量

标量(0D)

只包含一个元素的张量为标量。类型通常为FloatTensor或LongTensor

1
2
3
import torch
x = torch.rand(10)
x.size()

向量(1D)

1
2
import torch
x = torch.FloatTensor([1.0,2.0,3.0,4.0])

out:

torch.Size([4])

矩阵(2D)

1
2
x = torch.FloatTensor([[1,2],[3,4]])
print(x.size())

out:

torch.Size([2, 2])

三维向量

多个矩阵累加在一起。比如一张图片,有三个通道,每个通道都有一个矩阵。此处的pic2.jpg是一个28x28x3的图片。

1
2
3
4
5
6
7
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的用法一样

1
2
sales = torch.FloatTensor([1.0,2.0,3.0,4.0,5.0])
print(sales[:2])

out:

tensor([1., 2.])

对于前面的如果需要其中一个通道。一种用切片向量,一种用opencv的split方法。

1
2
3
4
5
6
7
8
9
10
11
12
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)

四维张量

对于多张图片,批处理那种

五维张量

视频数据。

GPU上的张量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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是否可用

1
2
3
if torch.cuda.is_available():
tensor = tensor.to('cuda')
print(f"device tensor is stored on: {tensor.device}")

生成空矩阵

没有初始化

1
2
3
4
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]])

随机初始化

1
2
# 构造一个随机初始化的矩阵
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]])

创建零矩阵

1
2
# 构造一个矩阵全为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]])

构造一个张量

1
2
#构造一个张量,直接使用数据
x3 = torch.tensor([5.5,3])

out:

tensor([5.5000, 3.0000])

基于一个已存在的tensor创建一个

1
2
3
4
5
6
7
8
9
# 创建一个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]])

获取维度信息

1
2
#获取维度信息
print(x5.size())

out:

torch.Size([5, 3])

加法

1
2
3
4
5
6
7
8
9
#######################加法####################
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一样标准的索引和切片

1
2
3
4
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.]])

乘法

1
2
3
4
5
6
7
8
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)

矩阵乘法计算,行乘列求和的那种

1
2
3
4
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,另一种张量连接,略有不同

1
2
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的形状

1
2
3
4
5
#改变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])

获取标量的值

1
2
3
4
#如果只有一个tensor,使用item()可以获得这个value
x8 = torch.tensor([1])
print(x8)
print(x8.item())

out:

tensor([1])
1

numpy和tensor相互转换

numpy转pytorch

1
2
3
4
5
6
7
8
9
10
11
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

1
2
tensor = torch_data.numpy()
# torch_data是一个tensor

模型的保存和读取

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 保存
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'))