一、什么是张量?张量的基本介绍。
二、pytorch中几种创建张量的方式。
1.直接创建、
2.依据数值创建、
3.依据概率创建。
三、张量的基本操作。
1.张量的拼接、
2.张量的切分、
3.张量的索引、
4.张量的变换、
5.张量的数学运算。
tensor(张量)是深度学习框架中常用的数据形式,虽然在生活中并不常见,但并不难理解,在数学概念中张量就是一个多维数组,是标量、向量、矩阵的高维扩展。如下图:
标量、向量、矩阵和张量之间的关系当张量维度为0时,在含义上对应于标量;当张量维度为1时,在含义上对应于向量;当张量维度为2时,在含义上对应于矩阵。如果在维度上继续拓展,这样的数学表现形式我们统称为标量。例如彩色图像就是一个三维张量(例如3*256*832),在维度上分别表示为色彩(RGB)、图像的高和图像的宽。
在深度学习框架中,张量除了存储数据外,还被赋予了其他的属性,正是因为拥有这些属性,使得张量可以实现自动求导的功能(张量在数据的基础上进行抽象,成为一个数据类)。在Pytorch中张量常用的属性有以下几种:
tensor的几种属性其中:
data:存储的数据即n维数组;
dtype:data存储数据的数据类型(int、float等等);
shape:data的数据大小(例如3*256*832);
device:tensor存储在哪个设备上(cuda or cpu);
requires_grad: 布尔类型,表示该tensor是否需要计算梯度(True or False);
grad:data的梯度;
grad_fn: 创建tensor时所用到的function(例如加法或者乘法等),是自动求导的关键;
is_lead: 该tensor是否为计算图中的叶子节点。
1.直接创建:
① torch.tensor( data, dtype=None, device=None, requires_grad=False, pin_memory=False)
其中data就是张量中存储的数据,可以是list,numpy;dtype数据类型默认和data一致;device所在设备(cuda or cpu);requires_grad是否需要计算梯度;pin__memory是否存于锁页内存。代码实现如下:
import torch
import numpy as np
# 创建numpy数据
arry = np.ones((3,3))
print("array的数据类型:",arry.dtype)
# 创建tensor
t = torch.tensor(arry)
print(t)
② torch.from_numpy(ndarray)
其中ndarray即为numpy数据,需要注意的一点是通过此种方法创建,tensor和ndarray是共享内存的,当修改一个数据时另一个数据也会随之改变。代码实现如下:
import torch
import numpy as np
# 创建numpy数据
arry = np.array([[1,2,3],[4,5,6]])
print("numpy:",arry)
# 创建tensor
t = torch.from_numpy(arry)
print("tensor:",t)
# 测试共享内存
arry[0][0] = 10
print("numpy:",arry)
print("tensor:",t)
2.依据数值创建:
① torch.zeros(size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
功能:创建全为0的张量。
· size: 张量的形状,如(3,3)、(3、256、832);
· out: 输出的张量(即该张量的名字,赋值语句时可忽略);
· layout: 内存中的布局形式,有strided,sparse_coo等;
· requires_grad :是否需要梯度。
代码实现如下:
import torch
t = torch.zeros((3,3))
print(t)
② torch.zeros_like(input, dtpye-None, layout=None, device=None, requires_grad=False)
功能:创建和input一样大小的全0张量。
· input: 创建与input同大小的全0张量;
· dtype: 数据类型;
· layout: 内存中的布局形式。
代码实现如下:
import torch
a= torch.tensor([[1,2,3],[4,5,6]])
t = torch.zeros_like(a)
print(t)
③ torch.ones()、torch.ones_like()
功能:同上所述,创建全1张量。
④ torch.full(size, fill_value, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
torch.full_like(tensor, fill_value)
功能:创建全”full_value“张量。
· size: 张量的形状;
· fill_value: 所需填充的值。
代码实现如下:
import torch
t = torch.full((3,3), 10, dtype = int)
print(t)
t_like = torch.full_like(t, 9)
print(t_like)
⑤ torch.arange (start=0, end, step=1, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
功能:创建等差的一维张量,数值区间为[ start, end ) 。
· start: 数列起始值;
· end: 数列结束值;
· step: 数列公差,默认为1。
代码实现:
import torch
t=torch.arange(start=1, end=9, step=2)
print(t)
⑥ torch.linspace(start, end, steps=100, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
功能:创建均分的一维张量,数值区间为[start, end]。
· start:数列起始值;
· end: 数列结束值;
· step:数列长度。
代码实现如下:
import torch
t=torch.linspace(start=1, end=10, steps=100)
print(t, t.shape)
⑦ torch.eye(n, m=None, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
功能:创建单位对角矩阵(二维张量),默认为方阵。
· n:矩阵行数;
· m: 矩阵列数。
代码实现:
import torch
t=torch.eye(3)
print(t)
3. 依概率分布创建张量
① torch.normal( mean, std, out=None)
功能: 生成正态分布(高斯分布)。
· mean:均值;
· std:标准差。
根据均值和方差的数据形式不同,该函数有四种不同的模式:
1) mean为标量,std为标量(此时需要指定张量的大小,所以多了一个参数size)。
import torch
t=torch.normal(0,1,size=(4,))
print(t)
2)mean为标量,std为张量。
import torch
mean = torch.arange(1, 5, dtype=torch.float)
std = 1
# mean=[1,2,3,4]
print(mean)
# std=1
print(std)
t = torch.normal(mean, std)
# t=[0.0661, 1.3460, 4.5023, 3.4130]
# t中的四个数值是由四个不同的分布的来的,其中-0.0661是均值为1,标准差为1的正态分布采样而来,
# 1.3460是均值为2,标准差为1的正态分布采样而来。
print(t)
3)mean为张量,std为标量。
import torch
mean = 1
std = torch.arange(1, 5, dtype=torch.float)
# mean=1
print(mean)
# std=[1,2,3,4]
print(std)
t = torch.normal(mean, std)
# t=[0.0661, 1.3460, 4.5023, 3.4130]
# t中的四个数值是由四个不同的分布的来的,其中第一个元素是均值为1,标准差为1的正态分布采样而来,
# 第二个元素是均值为1,标准差为2的正态分布采样而来。
print(t)
4)mean为张量,std为张量。
代码实现:
import torch
mean = torch.arange(1, 5, dtype=torch.float)
std = torch.arange(1, 5, dtype=torch.float)
# mean=[1,2,3,4]
print(mean)
# std=[1,2,3,4]
print(std)
t = torch.normal(mean, std)
# t=[-0.4884,3.3864,5.4408,7.5843]
# t中的四个数值是由四个不同的分布的来的,其中-0.4884是均值为1,标准差为1的正态分布采样而来,
# -3.3864是均值为2,标准差为2的正态分布采样而来。
print(t)
② torch.randn(*size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
torch.randn_like()
功能:生成标准正态分布。
· size: 张量的形状。
代码实现:
import torch
t=torch.randn((3,3))
print(t)
③ torch.rand(*size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
torch.rand_like()
功能:在区间[0,1)上生成均匀分布。
代码实现:
import torch
t=torch.rand((3,3))
print(t)
④ torch.randint(low=0, high, size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
torch.randint_like()
功能:在区间[low,high)生成整数均匀分布。
· size: 张量的形状。
代码实现:
import torch
t=torch.randint(1,9,(1,9))
print(t)
⑤ torch.randperm(n, out=None, dtype=torch.int64, layout=torch.strided, device=None, requires_grad=False)
功能:生成从0到n-1的随机排列。
· n: 张量的长度
代码实现:
import torch
t=torch.randperm(6)
print(t)
1.张量的拼接:
① torch.cat(tensors,dim=0,out=None)
功能:将张量按维度dim进行拼接(不会改变张量的维度)。
· tensors:张量序列;
· dim:要拼接的维度。
import torch
t=torch.ones((2,6))
t_cat=torch.cat([t,t], dim=0)
# t.shape=[2,6],t_car.shape=[4,6],在0维度上进行了拼接。
print(t.shape,t_cat.shape)
② torch.stack(tensors,dim=0,out=None)
功能: 在新创建的维度dim上进行拼接(会改变张量的维度,维度+1)。
· tensors:张量序列;
· dim:要拼接的维度。
import torch
t=torch.ones((1,6))
t_cat=torch.stack([t,t], dim=0)
# t.shape=[1,6],t_cat=[2,1,6],在创建一个新的维度,在新的维度上进行拼接。
print(t.shape,t_cat.shape)
2.张量的切分:
① torch.chunk(input, chunks, dim=0)
功能:将张量按维度dim进行平均切分。
返回值:张量列表(若不能整除,最后一份张量小于其他张量)。
· input:要切分的张量;
· chunks: 要切分的份数;
· dim:要切分的维度。
代码实现:
import torch
t=torch.ones((4,6))
# t_chunks是一个列表,存储切分后的张量
t_chunks=torch.chunk(t, chunks=2, dim=0)
for id, tensor in enumerate(t_chunks):
print("切分后第{}个张量的shape为:{}".format(id, tensor.shape))
# 切分后第0个张量的shape为:torch.Size([2, 6]),切分后第1个张量的shape为:torch.Size([2, 6])。
# 即在第0维度上进行平均切分。
② torch.split(tensor, split_size_or_sections, dim=0)
功能:将张量按维度dim进行切分。
返回值:张量列表。
·tensor: 要切分的张量;
·split_size_or_sections:为int时表示每一份的长度;为list时,按list元素进行切分list中每个 元素表示每一份的长度;
·dim:要切分的维度。
代码实现:
import torch
t=torch.ones((4,6))
# 当split_size_or_sections为int时
t_chunks=torch.split(t, 1, dim=0)
for id, tensor in enumerate(t_chunks):
print("切分后第{}个张量的shape为:{}".format(id, tensor.shape))
print('n')
# 当split_size_or_sections为list时
ls=[1,1,2]
t_chunks=torch.split(t, ls, dim=0)
for id, tensor in enumerate(t_chunks):
print("切分后第{}个张量的shape为:{}".format(id, tensor.shape))
3. 张量索引:
① torch.index_select(input, dim, index, out=None)
功能:在dim维度上,按index索引数据。
返回值:依index索引的数据最后拼接在一起。
· input:要索引的张量;
·dim:要索引的维度;
·index:要索引数据的序号。
代码实现:
import torch
t=torch.randn((4,6))
ls=torch.tensor([0,2])
# 取出t中0维度上索引为0和2的两组数据,所以最终得到的张量在0维度上大小为2
t_select_idx=torch.index_select(t,dim=0,index=ls)
print(t_select_idx.shape)
② torch.masked_select(input, mask, out=None)
功能:按mask中的对应位置是否为True进行索引。
返回值:一维张量。
· input:要索引的张量;
· mask:与input同形状的布尔类型的张量。
代码实现:
import torch
t=torch.randint(0,9,size=(3,3))
# 生成mask,ge:元素大于等于5时,mask中同位置值为True
mask=t.ge(5)
t_select=torch.masked_select(t,mask)
print(t,t_select)
4. 张量的变换:
① torch.reshape(input,shape)
功能:变换张量的形状。
注意事项:当张量在内存中是连续时,新张量与input共享数据内存。
· input:要变换的张量;
·shape:新张量的形状。
代码实现:
import torch
t=torch.ones((8))
t_reshape=torch.reshape(t,(2,4))
print(t_reshape.shape)
② torch.transpose(input, dim0, dim1)
功能:交换变量的两个维度。
· input:要变换的张量;
· dim0:要交换的维度;
· dim1:要交换的维度。
代码实现:
import torch
t=torch.rand((2,3,4))
t_transpose=torch.transpose(t,1,2)
print(t.shape,t_transpose.shape)
③ torch.t(input)
功能:将二维矩阵进行转置,等价于torch.transpose(input,0,1)
④ torch.squeeze(input, dim=None, out=None)
功能:压缩长度为1的维度,例如将(1,256,832)=> (256,832)
·dim:若不指定维度,移除所有长度为1的轴;若指定维度,当且仅当该轴长度为1时,可以被移除。
⑤ torch.unsqueeze(input, dim, out=None)
功能:在dim上扩展维度例如将(256,832)=> (3,256,832)
· dim:扩展的维度。
5.张量的数学运算:
① 加减乘除:
1)加法操作:torch.add(input, alpha=1, other) => input + alpha* other
·input:作加运算的一个张量;
·alpha:乘项因子,实现先乘后加的功能;
·other:作加运算的另一个张量。
代码实现:
import torch
t1 = torch.ones((3, 3))
t2 = torch.ones((3, 3))
t_add = torch.add(t1, t2)
print(t_add)
2)乘法操作:点乘(elsement-wise)=> torch.mul(input, other) 等价于 ”*“
矩阵乘法 => torch.mm(input, other)
3)减法操作:torch.neg(input) => 功能:按元素取负。
torch.sub(input, other)
4) 除法操作:torch.div(input, other) => 功能: 按元素相除。
② 其他数学操作:
x.item() => 1*1元素取当前值。
x.view(size) => 改变tensor的大小,x.view(-1,8) 。
x[:,1] => 索引操作,取第1列的所有数据。
len(x) => 返回x第一维的个数。
torch.flatten(input, start_dim=0, end_dim=-1)
功能:只输入input时将input拉成一维向量。
例如input.shape=(2,4,3,5,6), start_dim=1, end_dim=3,则 flatten之后
shape为(2,60,6)