pytorch学习笔记二————张量1(基础概念与操作)
张量基本概念
张量可全等于多维数组,他门通常是连续内存块的视图
常用的构造方式如下
import torch
a=torch.ones(3)
points=torch.zeros(3,2)
weights=torch.tensor([0.2126,0.7152,0.0722])
img=torch.randn(3,5,5)
索引张量
列表中的范围索引法同时也适用于张量,如下:
语句 | 含义 |
| |
| 列表中的所有元素 |
| 列表中的第1到3个元素不包含第4个 |
| 列表中从第1个元素到末尾 |
| 列表中开头到第3个元素不包含第4个 |
| 列表中开始到最后一个元素之前的元素 |
| 从第1个元素(包含)到第4个元素(不包含),步长为2 |
相对应即可运用到张量上
语句 | 含义 |
| 第1行之后的所有行,隐含所有列 |
| 第1行之后的所有行,所有列 |
| 第1行之后的所有行,第1列 |
| 增加1个大小的维度,如同unsqueeze() |
张量的广播性质
这真的讲不清楚,还是看视频吧
广播主要是对不同形状的张量之间的运算所产生的性质,很明显他跟矩阵的运算有很大的差距
张量的命名
很明显在经过上述张量的广播性质的洗礼后会发现张量的对齐是一个十分令人头疼的事情尤其是张量的维数特别多的时候,因此对张量进行命名并检查对应的名称是否一致再进行运算是一个很好的习惯
创建时命名
weights_name=torch.tensor([0.2126,0.7152,0.0722],name=['channels'])
创建完成后命名
御用refine_names()
的方法,省略号允许省略任意数量的维度,使用rename()
兄弟方法还可以覆盖或删除(传入None
)现有名称
img_named=img_t.refine_names(...,'channels','rows','columns')
print("img name:",img_named.shape,img_named.names)
两个命名张量的运算
除了常规的维度检查,还会检查张量的名称是否一致,目前没有维度对齐功能,所以需要显式的进行操作.align_as()
方法返回一个张量,其中会添加缺失的张量
接受维度参数的函数,如sum()
,mean()
也接受命名维度
如果想在对命名的张量进行操作的函数之外使用张量,则需要通过将这些张量重命名为None
来删除他们的名称
weight_aligned=weight_named.align_as(img_named)
gray_named=(img_named*weight_aligned).sum('channels')
gray_plain=gray_named.rename(None)
张量的元素类型
使用dtype
来管理张量的元素类型,类似于numpy的参数的值
可能的取值如下:
- torch.float32/torch.float
- torch.float64/torch.double
- torch.float16/torch.half
- 8
- torch.uint8
- 16/torch.short
- 32/
- 64/torch.long
- torch.bool
管理张量的类型
例子如下
import torch
double_points=torch.ones(10,2,dtype=torch.double)
short_points=torch.tensor([[1,2],[3,4]],dype=torch.short)
double_points=torch.zeros(10,2).double()
short_points=torch.ones(10,,2).short()
double_points=torch.zeros(10,2).to(torch.double)
short_points=torch.ones(10,,2).to(dtype=torch.short)
张量的存储
张量的值被分到由torch.Storage
实例所管理的连续内存块中,存储区是由数字数据组成的一维数组,可以对其进行直接的修改
例子如下
import torch
points=torch.tensor([[4.0,1.0],[5.0,3.0],[2.0,1.0]])
points_storage=points.storage()
points_storage[0]=2.0
有少量操作仅作为Tensor对象的方法存在,这些操作以从名称结尾的下划线识别出来,这表面该方法通过修改输入张量,而不是创建一个新的输出张量
张量的大小偏移量与步长
- 大小:一个元组,表示张量在每个维度上有多少个元素
- 偏移量:存储区中的某元素相对张量中的第一个元素的索引
- 步长:存储区中为了获得下一个元素需要跳过的元素数量
例:
import torch
points=torch.tensor([[4.0,1.0],[5.0,3.0],[2.0,1.0]])
second_point=points[1]
print(second_point.storage_offset())
# second_point偏移量为2
print(second_point.shape)
# second_point大小为(2)
print(points.stride())
# points步长为(2,1)
张量复制
修改子张量会对原张量进行修改,所以我们必须把子张量复制成新的张量
second_points=points[1].clone()
无复制转置
t()
方法是用于二维张量转置的transpose()
的简写
import torch
points=torch.tensor([[4.0,1.0],[5.0,3.0],[2.0,1.0]])
points_t=points.t()
高维转置
利用transpose()
方法,它将交换矩阵的两个维度
some_t=torch.ones(3,4,5)
transpose_t=some_t.transpose(0,2)
连续张量
pytorch中的一些操作只对连续张量起作用,所以要求显式的调用contiguous()
的方法,如果张量本身是连续的,则不会产生任何操作
print(points.is_contiguous())
# True
print(points_t.is_contiguous())
# False
points_t_cont=points_t.contiguous()
print(points_t_cont.is_contiguous())
# True
将张量储存到gpu
gpu可以进行大量的并行运算以提高速度
构建时指定或者用to()
方法制定到gpu上
如果有多个gpu也可以用数字来确定存储张量的gpu
也可以用cuda()
或cpu()
的方法代替to()
import torch
points_gpu=torch.tensor([[4.0,1.0],[5.0,3.0],[2.0,1.0]],device='cuda')
points_gpu=points.to(device='cuda')
points_gpu=points.to(device='cuda:0')
points.gpu=points.cuda()#gpu索引默认为0
points.gpu=points.cuda(0)
points_cpu=points_gpu.cpu()
numpy的互操作性
如下:
points=torch.ones(3,4)
points_np=points.numpy()
points=torch.from_numpy(points_np)
存储张量/序列化张量
torch.save(points,'filepath')
with open('filepath','wb') as f:
torch.save(points,f)
points=torch.load('filepath')
with open('filepath','rb') as f:
points=torch.load(f)
用h5py序列化到HDF5
上述方法不能用除pytorch之外的方法读写张量,所以运用h5py库进行读取
将张量转换为numpy数组并传给create_dataset()
函数
import h5py
f=h5py.File('filepath','w')
dset=f.create_dataset('coords',data=points.numpy())
f.close()
coords
为hdf5文件的一个键
假设我们想访问数据集当中的最后两个点,代码如下
f=h5py.File('filepath','r')
dset=f['coords']
last_points=torch.from_numpy(dset[-2:])
f.close()