0%

Something about PyTorch

Something about PyTorch

  • torchvision.transfroms.Compose(trandforms)

    将多个transform组合起来使用

    例子:

    1
    2
    3
    4
    transforms.Compose([
    transfroms.CenterCrop(10),
    transforms.ToTensor(),
    ])
  • OrderedDict

    是dict的子类,其最大特征是,它可以“维护”添加key-value对的额顺序。简单的来说,就是先添加的key-value对排在前面,后添加的key-value对排在后面

    由于OrderedDict能维护key-value对的添加顺序,因此即使两个OrderedDict照中的key-value对完全相同,但只要他们的顺序不同,程序在判断他们是否相等时也依然会返回false。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from collections import OrderedDict
dx = OrderedDict(b=5, c=2, a=7)
print(dx)
d = OrderedDict()
d['Python'] = 89
d['Swift'] = 92
d['Kotlin'] = 97
d['Go'] = 87
print(d)
for k,v in d.items():
print(k, v)
"""
output:
OrderedDict([('b', 5), ('c', 2), ('a', 7)])
OrderedDict([('Python', 89), ('Swift', 92), ('Kotlin', 97), ('Go', 87)])
Python 89
Swift 92
Kotlin 97
Go 87
"""
  • nn.LeakyReLU(inplace=True)

    inplace=True的意思是进行原地操作,例如x=x+5对于x就是一个原地操作,y=x+5; x=y完成了与x=x+5同样的功能但不是原地操作,与上面的inplace=True的含义是一样的,是对于Conv2d这样的上层网络传递下来的tensor直接进行修改,好处就是可以节省运算内存

  • batch normalization层的实现机理:

    假设我们在网络中间经过某些卷积操作之后输出的feature map的尺寸为4 * 3 * 2 * 2

    4为batch的大小, 3为channel的数目,2 * 2为feature map的长宽

    1565911499478

    所以对于一个batch Normalization层而言,去求均值与方差是对于所有batch中的同一个channel进行求取,batch normalization中的batch体现在这个地方

    batch normalization层能够学习到的参数,对于一个特定的channel而言实际上是两个参数,gamma与beta,对于total的channel而言实际上是channel数目的两倍

  • meshgrid()

    引入创建网格点的矩阵

    示例一:创建一个2行3列的网格点矩阵。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    import numpy as np 
    import matplotlib.pyplot as plt

    X = np.array([[0, 0.5, 1], [0, 0.5, 1]])
    print("X的维度: {}, shape: {}".format(X.ndim, X.shape))
    Y = np.array([[0, 0, 0], [1, 1, 1]])
    print("Y的维度: {}, shape: {}".format(Y.ndim, Y.shape))

    plt.plot(X, Y, 'o--')
    plt.grid(True)
    plt.show()

    1566006916935

      当要描绘的 矩阵网格点的数据量小的时候,可以用上述方法构造网格点坐标数据;
    

但是如果是一个(256, 100)的整数矩阵网格,要怎样构造数据呢?
方法1:将x轴上的100个整数点组成的行向量,重复256次,构成shape(256,100)的X矩阵;将y轴上的256个整数点组成列向量,重复100次构成shape(256,100)的Y矩阵
显然方法1的数据构造过程很繁琐,也不方便调用,那么有没有更好的办法呢?of course!!!
那么meshgrid()就显示出它的作用了
使用meshgrid方法,你只需要构造一个表示x轴上的坐标的向量和一个表示y轴上的坐标的向量;然后作为参数给到meshgrid(),该函数就会返回相应维度的两个矩阵;
例如,你想构造一个2行3列的矩阵网格点,那么x生成一个shape(3,)的向量,y生成一个shape(2,)的向量,将x,y传入meshgrid(),最后返回的X,Y矩阵的shape(2,3)

示例二:使用meshgrid()生成示例一种的网格点矩阵

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import numpy as np 
import matplotlib.pyplot as plt

x = np.array([0, 0.5, 1])
y = np.array([0, 1])

xv, yv = np.meshgrid(x, y)
print("xv的维度: {}, shape: {}".format(xv.ndim, xv.shape))
print("yv的维度: {}, shape: {}".format(yv.ndim, yv.shape))

plt.plot(xv, yv, 'o--')
plt.grid(True)
plt.show()
"""
output:
xv的维度: 2, shape: (2, 3)
yv的维度: 2, shape: (2, 3)
"""

示例三:生成20行30列的网格点矩阵

只需要改变:

1
2
x = np.linspace(0, 500, 30)
y = np.linspace(0, 500, 20)

1566007285866

  • repeat()expand()的区别

torch.Tensor是包含一种数据类型元素的多维矩阵,torch.Tensor有两个实例方法可以用来扩展某维的数据的尺寸,分别是repeat()expand()

expand()

返回当前张量在某维扩展更大后的张量, 扩展(expand)张量不会分配新的内存,只是在存在的张量上创建一个新的视图(view),一个大小(size)等于1的维度扩展到更大的尺寸。示例:

1
2
3
4
5
6
7
8
9
10
import torch 

x = torch.tensor([1, 2, 3])
x = x.expand(2, 3)
print(x)
"""
output:
tensor([[1, 2, 3],
[1, 2, 3]])
"""
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
28
29
30
31
import torch 

x = torch.randn(2, 1, 1, 4)
print(x)
x = x.expand(-1, 2, 3, -1)
print(x.size())
print(x)
"""
output:
tensor([[[[ 0.6288, -0.3688, 1.0322, 0.8450]]],


[[[-1.5189, -0.6984, -1.0931, 0.0894]]]])
torch.Size([2, 2, 3, 4])
tensor([[[[ 0.6288, -0.3688, 1.0322, 0.8450],
[ 0.6288, -0.3688, 1.0322, 0.8450],
[ 0.6288, -0.3688, 1.0322, 0.8450]],

[[ 0.6288, -0.3688, 1.0322, 0.8450],
[ 0.6288, -0.3688, 1.0322, 0.8450],
[ 0.6288, -0.3688, 1.0322, 0.8450]]],


[[[-1.5189, -0.6984, -1.0931, 0.0894],
[-1.5189, -0.6984, -1.0931, 0.0894],
[-1.5189, -0.6984, -1.0931, 0.0894]],

[[-1.5189, -0.6984, -1.0931, 0.0894],
[-1.5189, -0.6984, -1.0931, 0.0894],
[-1.5189, -0.6984, -1.0931, 0.0894]]]])
"""

repeat()

沿着特定的维度重复这个张量,和expand()不同的是,这个函数拷贝张量的数据。

1
2
3
4
5
6
7
8
9
10
import torch 
x = torch.tensor([1, 2, 3])
x = x.repeat(3, 2)
print(x)
"""
output:
tensor([[1, 2, 3, 1, 2, 3],
[1, 2, 3, 1, 2, 3],
[1, 2, 3, 1, 2, 3]])
"""
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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import torch
x = torch.randn(2, 3, 4)
print(x)
x = x.repeat(2, 1, 3)
print(x)
"""
output:
tensor([[[-0.6915, -2.3975, 1.2687, -1.1976],
[ 0.5424, 0.9949, 0.8677, -0.2078],
[-1.5410, -0.0281, 1.4717, -0.7021]],

[[ 1.3378, -2.0375, 0.2226, 0.8865],
[ 0.0319, 0.2902, 0.0647, 0.5396],
[-1.0962, -2.3473, -0.2049, -0.2524]]])
tensor([[[-0.6915, -2.3975, 1.2687, -1.1976, -0.6915, -2.3975, 1.2687,
-1.1976, -0.6915, -2.3975, 1.2687, -1.1976],
[ 0.5424, 0.9949, 0.8677, -0.2078, 0.5424, 0.9949, 0.8677,
-0.2078, 0.5424, 0.9949, 0.8677, -0.2078],
[-1.5410, -0.0281, 1.4717, -0.7021, -1.5410, -0.0281, 1.4717,
-0.7021, -1.5410, -0.0281, 1.4717, -0.7021]],

[[ 1.3378, -2.0375, 0.2226, 0.8865, 1.3378, -2.0375, 0.2226,
0.8865, 1.3378, -2.0375, 0.2226, 0.8865],
[ 0.0319, 0.2902, 0.0647, 0.5396, 0.0319, 0.2902, 0.0647,
0.5396, 0.0319, 0.2902, 0.0647, 0.5396],
[-1.0962, -2.3473, -0.2049, -0.2524, -1.0962, -2.3473, -0.2049,
-0.2524, -1.0962, -2.3473, -0.2049, -0.2524]],

[[-0.6915, -2.3975, 1.2687, -1.1976, -0.6915, -2.3975, 1.2687,
-1.1976, -0.6915, -2.3975, 1.2687, -1.1976],
[ 0.5424, 0.9949, 0.8677, -0.2078, 0.5424, 0.9949, 0.8677,
-0.2078, 0.5424, 0.9949, 0.8677, -0.2078],
[-1.5410, -0.0281, 1.4717, -0.7021, -1.5410, -0.0281, 1.4717,
-0.7021, -1.5410, -0.0281, 1.4717, -0.7021]],

[[ 1.3378, -2.0375, 0.2226, 0.8865, 1.3378, -2.0375, 0.2226,
0.8865, 1.3378, -2.0375, 0.2226, 0.8865],
[ 0.0319, 0.2902, 0.0647, 0.5396, 0.0319, 0.2902, 0.0647,
0.5396, 0.0319, 0.2902, 0.0647, 0.5396],
[-1.0962, -2.3473, -0.2049, -0.2524, -1.0962, -2.3473, -0.2049,
-0.2524, -1.0962, -2.3473, -0.2049, -0.2524]]])
"""
  • squeeze()unsqueeze()

unsqueeze()函数

首先初始化一个a

1
2
3
4
5
6
>>> import torch
>>> a = torch.arange(0, 6)
>>> a = a.view(2, 3)
>>> a
tensor([[0, 1, 2],
[3, 4, 5]])

可以看到a的维度是(2, 3)

在第二维增加一个维度,使其维度变为(2, 1, 3)

1
2
3
4
5
>>> a = a.unsqueeze(1)
>>> a
tensor([[[0, 1, 2]],

[[3, 4, 5]]])

可以看到维度已经变为(2, 1, 3)了,同样如果需要在倒数第二个维度上增加一个维度,可以用a.unsqueeze(-2)

squeeze()函数

1
2
3
4
>>> a = a.squeeze(1)
>>> a
tensor([[0, 1, 2],
[3, 4, 5]])

另外,

1
2
3
4
5
6
7
8
9
10
>>> a
tensor([[[[0, 1, 2]]],


[[[3, 4, 5]]]])
>>> a.squeeze(-1)
tensor([[[[0, 1, 2]]],


[[[3, 4, 5]]]])

此时可以看到维度没有发生变化,这是因为只有维度为1时才会去掉

  • permute()

将tensor的维度换位

参数:参数是一系列的整数,代表原来张量的维度

1
2
3
4
5
6
7
8
9
10
11
>>> a = np.array([[[1, 2, 3], [4, 5, 6]]])
>>> a = torch.tensor(a)
>>> a.size()
torch.Size([1, 2, 3])
>>> b = a.permute(2, 0, 1)
>>> b
tensor([[[1, 4]],

[[2, 5]],

[[3, 6]]], dtype=torch.int32)

再比如,图片img的size比如是(28, 28, 3),就可以利用img.permute(2, 0, 1)得到一个size为(3, 28, 28)的tensor

  • contiguous()

在PyTorch中,有一些对Tensor的操作不会真正改变Tensor中的内容,改变的仅仅是Tensor中字节位置的索引。这些操作有:

narrow(), view(), expand(), transpose()

例如在执行view()操作之后,不会开辟新的内存空间才存放处理之后的数据,实际上新数据与原始数据共享同一块内存

而在调用contiguous()之后,PyTorch会开辟出一块新的内存空间存放变换之后的数据,并会真正改变Tensor的内容,按照变换之后的顺序存放数据。

  • grid_sample(input, frig, mode='linear', padding_mode='zeros')

    用于图像的恢复

    input (N, C, H_in, W_in)

    output (N, H_out, W_out, 2)

    grid的索引值(数据坐标)对应output索引值(数据坐标)

    grid中数值对应input的索引值(数据坐标)

    grid(u, v) = x, y

    output(u, v) 数值对应 input(x, y)

示意图:

img

  • nn.Upsample()

所用:上采样

定义:CLASS torch.nn.Upsample(size=None, scale_factor=None, mode='nearest', align_corners=None)

计算shape

在这里插入图片描述