Tensor(张量)是神经网络框架中重要的基础数据类型,可以简单理解为N维数组的容器对象。Tensor之间的通过运算进行连接,从而形成计算图。几乎所有的深度学习框架都是基于张量和计算图的,PyTorch也不例外。
一、创建Tensor
在PyTorch里创建Tensor的方法很多。
方法名 | 说明 |
---|---|
Tensor(*sizes) | 基础构造函数 |
ones(*sizes) | 全1的Tensor |
zeros(*sizes) | 全0的Tensor |
rand/randn(*sizes) | 均匀/标准分布 |
eye(*sizes) | 对角线为1,其他为0 |
arange(s,e,sep) | 从s到e,步长为step |
linspace(s,e,count) | 从s到e,均匀切分成count份 |
import torch as t
# 使用基础构造函数
a = t.Tensor(2,3)
b = t.Tensor([[1,2,3], [4,5,6]])
print(a)
print(b)
print(b.shape)
print(b.numel()) # b中元素总个数
# 使用全1构造函数
c = t.ones(3,3)
print(c)
# 使用全0构造函数
d = t.zeros(3,3)
print(d)
# 用均匀分布、标准分布构造函数
e = t.randn(3,2)
f = t.randn(3,2)
print(e)
print(f)
# 使用单位矩阵构造函数
g = t.eye(3,4)
print(g)
# 用步长和区间构造函数
h = t.arange(1, 6, 2)
print(h)
# 用个数和区间构造函数
i = t.linspace(1, 6, 2)
print(i)
二、常用Tensor操作
1、改变形状
通过tensor.view方法可以调整tensor的形状,但是必须保证调整前后元素总数一致。
import torch as t
a = t.arange(0, 6)
a.view(-1, 2)
print(a)
通过tensor.resize_方法也可以调整tensor的形状,与view不同的是它可以修改tensor的元素总数。
import torch as t
a = t.arange(0, 6)
a.resize_(2, 3)
print(a)
a.resize_(1, 10)
print(a)
2、分割与合并
import torch as t
a = t.arange(0, 9).view(3, 3)
b = t.arange(0, 9).view(3, 3)
# 按照横向分割成3个
print(t.chunk(a, 3, 0))
# 按照纵向分割成3个
print(t.chunk(a, 3, 1))
# 横向堆叠
print(t.cat([a, b], 0))
# 纵向堆叠
print(t.cat([a, b], 1))
3、逐元素操作
这部分操作会对tensor的每一个元素进行操作,此类操作的输入和输出形状一致。
方法名 | 说明 |
---|---|
add/sub/mul/div | 加/减/乘/除 |
abs/reciprocal/neg | 绝对值/倒数/相反数 |
sqrt/pow/fmod | 平方根/求幂/求余 |
cos/sin/tan/acos/asin/atan | 三角函数 |
ceil/round/floor/trunc/frac | 上取整/四舍五入/下取整/只保留整数部分/只保留小数部分 |
clamp(input,min,max) | 超过min和max的部分截断 |
import torch as t
a = t.arange(0, 6).view(2, 3).float()
# 算术运算
print(t.add(a, 2))
print(t.sub(a, 2))
print(t.mul(a, 2))
print(t.div(a, 2))
print(t.abs(a))
print(t.reciprocal(a))
print(t.neg(a))
print(t.pow(a, 2))
print(t.sqrt(a))
print(t.fmod(a, 3))
# 三角函数
print(t.cos(a))
print(t.sin(a))
print(t.tan(a))
print(t.acos(a))
print(t.asin(a))
print(t.atan(a))
# 取整运算
print(t.ceil(a))
print(t.round(a))
print(t.floor(a))
print(t.trunc(a))
# 截断
print(t.clamp(a, 2, 4))
4、统计运算
这部分操作会让输出形状小于输入形状,并可以沿着某一维度进行制定操作。
方法名 | 说明 |
---|---|
max/min/mean/sum/median/mode | 最大/最小/均值/求和/中位数/众数 |
norm | 范数 |
std/var | 标准差/方差 |
cumsum/cumprod | 累加和/累乘 |
import torch as t
a = t.arange(0, 9).view(3, 3).float()
print(a)
print(a.max()) # 最大值
print(a.min()) # 最小值
print(a.mean()) # 均值
print(a.mean(0)) # 列均值
print(a.sum(0)) # 列求和
print(a.sum(1)) # 行求和
print(a.median(0)) # 列中位数
print(a.mode(0)) # 列众数
print(a.norm(2)) # a的n阶范数
print(a.std()) # 标准差
print(a.var()) # 方差
print(a.cumsum(0)) # 累加和
print(a.cumprod(0)) # 累乘
5、比较运算
方法名 | 说明 |
---|---|
gt/lt/ge/le/eq/ne | 大于/小于/大于等于/小于等于/等于/不等 |
topk | 最大的k个数 |
sort | 排序 |
import torch as t
a = t.arange(0, 9).view(3, 3).float()
print(a.gt(3))
print(a.eq(3))
print(a.ne(3))
print(a.topk(1, 0)[0]) # 纵向最大的1个
print(a.topk(1, 1)[0]) # 横向最大的1个
print(t.topk(a, 1, 1)[0]) # 横向最大的1个
print(a.sort(0, descending=False)[1]) # descending控制升降
print(a.sort(1, descending=True)[1])
6、线性代数
方法名 | 说明 |
---|---|
diag | 矩阵的对角线元素 |
trace | 矩阵的对角线元素之和(矩阵的迹) |
triu/tril | 矩阵的上三角元素/下三角元素 |
t | 矩阵转置 |
inverse | 求逆矩阵 |
eig | 求方阵的特征值和特征向量 |
svd | 奇异值分解 |
dot | 两个张量的内积 |
mm | 两个矩阵的乘法 |
import torch as t
a = t.arange(1, 10).view(3, 3).float()
print(a)
# 对角线元素
print(t.diag(a))
# 对角线元素之和
print(t.trace(a))
# 矩阵上三角元素
print(t.triu(a))
# 矩阵下三角元素
print(t.tril(a))
# 转置,contiguous()使存储空间连续
print(t.t(a).contiguous())
# 求逆矩阵
print(t.inverse(a))
# 求方阵的特征值和特征向量
print(t.eig(a, eigenvectors=True))
# 奇异值分解
print(t.svd(a))
# 两个张量的点积
print(t.dot(t.Tensor([2, 3]), t.Tensor([2, 1])))
# 两个矩阵的乘法
c = t.randn(3, 3)
d = t.arange(0, 12).view(3, 4).float()
print(t.mm(c, d))
三、Tensor与NumPy的转换
Tensor和NumPy数组之间具有很高的相似性,彼此之间的互操作也非常简单高效。
1、从NumPy转Tensor
import numpy as np
import torch as t
a = np.ones([2, 3])
# 方法一
b1 = t.from_numpy(a)
print(type(b1))
# 方法二
b2 = t.Tensor(a)
print(type(b2))
2、从Tensor转NumPy
import numpy as np
import torch as t
b = t.Tensor([2, 3])
a = b.numpy()
print(type(a))
四、Tensor的持久化
1、使用CPU模式
import torch as t
a = t.Tensor([2, 3])
# 保存
t.save(a, 'a.pth')
# 加载
b = t.load('a.pth')
print(b)
2、使用GPU模式
在保存和加载过程中可以制定具体使用哪个设备。
import torch as t
a = t.Tensor([2, 3])
if t.cuda.is_available():
a = a.cuda(0) # 将a转为GPU0上的tensor
# 保存
t.save(a, 'a.pth')
# 加载为b, b加载进GPU0(因为保存时候tensor就在GPU0上)
b = t.load('a.pth')
# 加载为c, 指定新位置
c = t.load('a.pth', map_location={'cuda:1':'cuda:0'})
print(b)
print(c)