一、python中的view()函数的用法
初学者在使用pytorch框架定义神经网络时,经常会在代码中看到:
这样的用法。
view()的作用相当于numpy中的reshape,重新定义矩阵的形状。
例1 普通用法:
import torch
v1 = torch.range(1, 16)
v2 = v1.view(4, 4)
其中v1为1*16大小的张量,包含16个元素。
v2为4*4大小的张量,同样包含16个元素。注意view前后的元素个数要相同,不然会报错。
例2 参数使用-1
import torch
v1 = torch.range(1, 16)
v2 = v1.view(-1, 4)
和图例中的用法一样,view中一个参数定为-1,代表动态调整这个维度上的元素个数,以保证元素的总数不变。因此两个例子的结果是相同的。
二、python中的shape()函数的用法
shape包含在numpy库,是矩阵(ndarray)的属性,可以获取矩阵的形状(例如二维数组的行列),获取的结果是一个元组,因此相关代码如下:
import numpy as np
x = np.array([[1,2,3,4,5],[6,7,8,9,10],[10,9,8,7,6],[5,4,3]])
#输出数组的行和列数
print (x.shape) #结果: (4, 5)
#只输出行数
print (x.shape[0]) #结果: 4
#只输出列数
print (x.shape[1]) #结果: 5
import torch
input = torch.tensor([[1,2,0,3,1],
[0,1,2,3,1],
[1,2,1,0,0],
[5,2,3,1,1],
[2,1,0,1,1]])
kernel = torch.tensor([[1,2,1],
[0,1,0],
[2,1,0]])
print(input.shape)
print(kernel.shape)
输出结果为:
三、python中的reshape()函数的用法
reshape新生成数组和原数组公用一个内存,不管改变哪个都会互相影响。
import torch
import torch.nn.functional as F
input = torch.tensor([[1,2,0,3,1],
[0,1,2,3,1],
[1,2,1,0,0],
[5,2,3,1,1],
[2,1,0,1,1]])
kernel = torch.tensor([[1,2,1],
[0,1,0],
[2,1,0]])
input = torch.reshape(input, (1,1,5,5)) # 变成batch_size=1,channel=1,高H=5,宽W=5
kernel = torch.reshape(kernel, (1,1,3,3)) # 变成batch_size=1,channel=1,高H=5,宽W=5
print(input.shape)
print(kernel.shape)
运行结果为:
四、view和reshape的区别
torch的view()与reshape()方法都可以用来重塑tensor的shape,区别是使用的条件不一样。view()方法只适用于满足连续性条件的tensor,并且该操作不会开辟新的内存空间,只是产生了对原存储空间的一个新别称和引用,返回值是视图。而reshape()方法的返回值既可以是视图,也可以是副本,当满足连续性条件时返回view,否则返回副本[ 此时等价于先调用contiguous()方法在使用view() ]。因此当不确能否使用view时,可以使用reshape。如果只是想简单地重塑一个tensor的shape,那么就是用reshape,但是如果需要考虑内存的开销而且要确保重塑后的tensor与之前的tensor共享存储空间,那就使用view()。
总之,两者都是用来重塑tensor的shape的。view只适合对满足连续性条件(contiguous)的tensor进行操作,而reshape同时还可以对不满足连续性条件的tensor进行操作,具有更好的鲁棒性。view能干的reshape都能干,如果view不能干就可以用reshape来处理。
view的存在可以显示地表示对这个tensor的操作只能是视图操作而非拷贝操作。这对于代码的可读性以及后续可能的bug的查找比较友好。