• pytroch

张量维度变化

view函数

  • .view()函数简介
    PyTorch中的.view()函数是一个用于改变张量形状的方法。它类似于NumPy中的.reshape()函数,可以通过重新排列张量的维度来改变其形状,而不改变张量的数据。
    在深度学习中,.view()函数常用于调整输入数据的形状以适应模型的输入要求,或者在网络层之间传递数据时进行形状的转换。
    .view()函数的语法如下,shape是一个整数元组,用于指定新的张量形状,新形状的元素个数必须与原形状的元素个数相同。函数返回一个具有指定形状的新张量,但与原始张量共享数据存储,因此它们指向相同的内存区域。:
    New_Tensor = Tensor.view(*shape)

  • .view()相当于reshape、resize,重新调整Tensor的形状。

1
2
3
4
5
6
7
8
9
10
11
import torch
a1 = torch.arange(0,16)
print(a1)
a2 = a1.view(8, 2)
a3 = a1.view(2, 8)
a4 = a1.view(4, 4)

print(a2)
print(a3)
print(a4)

  • tensor([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15])
    tensor([[ 0,  1],
            [ 2,  3],
            [ 4,  5],
            [ 6,  7],
            [ 8,  9],
            [10, 11],
            [12, 13],
            [14, 15]])
    tensor([[ 0,  1,  2,  3,  4,  5,  6,  7],
            [ 8,  9, 10, 11, 12, 13, 14, 15]])
    tensor([[ 0,  1,  2,  3],
            [ 4,  5,  6,  7],
            [ 8,  9, 10, 11],
            [12, 13, 14, 15]])
    
    
    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

    - view中一个参数定为-1,代表自动调整这个维度上的元素个数,以保证元素的总数不变。

    ```python
    import torch
    a1 = torch.arange(0,16)
    print(a1)

    a2 = a1.view(-1, 16)
    a3 = a1.view(-1, 8)
    a4 = a1.view(-1, 4)
    a5 = a1.view(-1, 2)
    a6 = a1.view(4*4, -1)
    a7 = a1.view(1*4, -1)
    a8 = a1.view(2*4, -1)
    a9 = a1.view(-1) # 展平为一维
    print(a2)
    print(a3)
    print(a4)
    print(a5)
    print(a6)
    print(a7)
    print(a8)


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
43
44
tensor([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15])
tensor([[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]])
tensor([[ 0, 1, 2, 3, 4, 5, 6, 7],
[ 8, 9, 10, 11, 12, 13, 14, 15]])
tensor([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15]])
tensor([[ 0, 1],
[ 2, 3],
[ 4, 5],
[ 6, 7],
[ 8, 9],
[10, 11],
[12, 13],
[14, 15]])
tensor([[ 0],
[ 1],
[ 2],
[ 3],
[ 4],
[ 5],
[ 6],
[ 7],
[ 8],
[ 9],
[10],
[11],
[12],
[13],
[14],
[15]])
tensor([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15]])
tensor([[ 0, 1],
[ 2, 3],
[ 4, 5],
[ 6, 7],
[ 8, 9],
[10, 11],
[12, 13],
[14, 15]])

torch.where()

  • torch.where(condition, x, y) → Tensor
    返回一个新的张量,其中的元素是从 x 或 y 中选择的元素,取决于 condition 中的元素是 True 还是 False。
    如果 condition 中的元素是 True,则输出中的对应元素取自 x,否则取自 y。
    参数:
    • condition (BoolTensor) – 一个包含布尔值的张量。
    • x (Tensor) – 一个包含要选择的元素的张量。
    • y (Tensor) – 一个包含要选择的元素的张量。
      返回:
    • 一个张量,包含从 x 或 y 中选择的元素。
  • 要求:x 和 y 的形状必须相同,或者可以广播到相同的形状。condition 的形状必须与 x 和 y 的形状广播后的形状相同。
1
2
3
4
5
6
7
import torch
a = torch.randn(3, 3)
b = torch.randn(3, 3)
print(a)
print(b)
c = torch.where(a > 0, a, b)
print(c)
        tensor([[-0.0048, -0.7391,  0.0659],
                [ 0.5881,  0.2028, -0.7898],
                [ 0.9274,  0.0735, -1.4954]])
        tensor([[ 1.1377, -0.6713, -1.5883],
                [ 0.4658, -0.7398,  0.3812],
                [ 0.8525,  0.5940, -1.3472]])
        tensor([[ 1.1377, -0.6713,  0.0659],
                [ 0.5881,  0.2028,  0.3812],
                [ 0.9274,  0.0735, -1.3472]])
  

model.train() 和 model.eval()

pytorch可以给我们提供两种方式来切换训练和评估(推断)的模式,分别是:model.train()model.eval()

一般用法是:在训练开始之前写上 model.trian() ,在测试时写上 model.eval() 。

1. model.train()

在使用 pytorch 构建神经网络的时候,训练过程中会在程序上方添加一句model.train(),作用是 启用 batch normalization 和 dropout

如果模型中有BN层(Batch Normalization)和 Dropout ,需要在 训练时 添加 model.train()。

model.train() 是保证 BN 层能够用到 每一批数据 的均值和方差。对于 Dropout,model.train() 是 随机取一部分 网络连接来训练更新参数。

2. model.eval()

model.eval()的作用是 不启用 Batch Normalization 和 Dropout

如果模型中有 BN 层(Batch Normalization)和 Dropout,在 测试时 添加 model.eval()。

model.eval() 是保证 BN 层能够用 全部训练数据 的均值和方差,即测试过程中要保证 BN 层的均值和方差不变。对于 Dropout,model.eval() 是利用到了 所有 网络连接,即不进行随机舍弃神经元。

为什么测试时要用 model.eval() ?

训练完 train 样本后,生成的模型 model 要用来测试样本了。在 model(test) 之前,需要加上model.eval(),否则的话,有输入数据,即使不训练,它也会改变权值。这是 model 中含有 BN 层和 Dropout 所带来的的性质。

eval() 时,pytorch 会自动把 BN 和 DropOut 固定住,不会取平均,而是用训练好的值。
不然的话,一旦 test 的 batch_size 过小,很容易就会被 BN 层导致生成图片颜色失真极大。
eval() 在非训练的时候是需要加的,没有这句代码,一些网络层的值会发生变动,不会固定,你神经网络每一次生成的结果也是不固定的,生成质量可能好也可能不好。

也就是说,测试过程中使用model.eval(),这时神经网络沿用 batch normalization 的值,而并 不使用 dropout

3. 总结与对比

如果模型中有 BN 层(Batch Normalization)和 Dropout,需要在训练时添加 model.train(),在测试时添加 model.eval()。

其中 model.train() 是保证 BN 层用每一批数据的均值和方差,而 model.eval() 是保证 BN 用全部训练数据的均值和方差;而对于 Dropout,model.train() 是随机取一部分网络连接来训练更新参数,而 model.eval() 是利用到了所有网络连接。

model.eval()
不启用 BatchNormalization 和 Dropout,保证BN和dropout不发生变化,pytorch框架会自动把BN和Dropout固定住,不会取平均,而是用训练好的值,不然的话,一旦test的batch_size过小,很容易就会被BN层影响结果。

Batch Normalization

其作用对网络中间的每层进行归一化处理,并且使用变换重构(Batch Normalization Transform)保证每层提取的特征分布不会被破坏。训练时是针对每个mini-batch的,但是测试是针对单张图片的,即不存在batch的概念。由于网络训练完成后参数是固定的,每个batch的均值和方差是不变的,因此直接结算所有batch的均值和方差。所有Batch Normalization的训练和测试时的操作不同。

Dropout

其作用克服Overfitting,在每个训练批次中,通过忽略一半的特征检测器,可以明显的减少过拟合现象。

参考

  1. python pytorch中 .view()函数讲解_pytorch .view-CSDN博客
  2. 【PyTorch】PyTroch中.view()函数的详细使用方法_pytorch view_静深松里热开水的博客-CSDN博客
  3. pytorch张量维度变换详解:view、squeeze、transpose_智慧医疗探索者的博客-CSDN博客
  4. 【Pytorch】model.train() 和 model.eval() 原理与用法_python_想变厉害的大白菜-华为云开发者联盟 (csdn.net)