1. Tensor的概念
\quad \quad Tensor 中文为张量。张量的意思是一个多维数组,它是标量、向量、矩阵的高维扩展。标量可以称为 0 维张量,向量可以称为1维张量,矩阵可以称为2维张量,RGB图像可以表示3维张量。你可以把张量看作多维数组
2. Tensor几种常见的形式有哪些
-
scalar
-
vector
-
matrix
-
n-dimensional tensor
import torch
from torch import tensor
import numpy as np
scalar
标量通常就是一个数值
x=tensor(42.)
x
输出:
tensor(42.)
x.dim()#查看维度
输出:
0
2*x#对数值做计算
输出:
tensor(84.)
x.item()#输出内容
输出:
42.0
vector
例如:[-5.,3.,0.],在深度学习中通常指特征,例如词向量特征,某一维度特征等
v
⃗
=
[
v
1
,
v
2
,
.
.
.
,
v
n
]
\vec{v}=[v_1,v_2,...,v_n]
v=[v1,v2,...,vn]
v=tensor([-1.5,0.5,3])#是一个一维向量
v
输出:
tensor([-1.5000, 0.5000, 3.0000])
v.dim()#输出维度为1维
输出:
1
v.size()
输出:
torch.Size([3])
Mtrix
一般计算的都是矩阵,通常都是多维的
M=tensor([[1.,2.],[3.,4.]])#一个二维矩阵
M
输出:
tensor([[1., 2.],
[3., 4.]])
M.matmul(M)#矩阵自身的平方
输出:
tensor([[ 7., 10.],
[15., 22.]])
tensor([1.,0.]).matmul(M)#向量和矩阵相乘
输出:
tensor([1., 2.])
M*M#矩阵乘法
输出:
tensor([[ 1., 4.],
[ 9., 16.]])
tensor([1.,2.]).matmul(M)#向量和矩阵相乘
输出:
tensor([ 7., 10.])
3. Tensor 与 Variable
\quad
\quad
在 PyTorch 0.4.0之前,torch.autograd
包中存在 Variable 这种数据类型,主要是用于封装 Tensor,进行自动求导。Variable 主要包含下面几种属性。
-
data: 被包装的 Tensor。
-
data 的梯度。
-
fn: 创建 Tensor 所使用的 Function,是自动求导的关键,因为根据所记录的函数才能计算出导数。
-
requires_grad: 指示是否需要梯度,并不是所有的张量都需要计算梯度。
-
is_leaf: 指示是否叶子节点(张量),叶子节点的概念在计算图中会用到。
\quad \quad 在 PyTorch 0.4.0 之后,Variable 并入了 Tensor。在之后版本的 Tensor 中,除了具有上面 Variable 的 5 个属性,还有另外 3 个属性。
-
dtype: 张量的数据类型,如
torch.FloatTensor
,torch.cuda.FloatTensor
。 -
shape: 张量的形状。如 (64, 3, 224, 224)
-
device: 张量所在设备 (CPU/GPU),GPU 是加速计算的关键
\quad
\quad
关于 dtype,PyTorch 提供了 9 种数据类型,共分为 3 大类:float (16-bit, 32-bit, 64-bit)、integer (unsigned-8-bit ,8-bit, 16-bit, 32-bit, 64-bit)、Boolean。
模型参数和数据用的最多的类型是 float-32-bit。label 常用的类型是 integer-64-bit。
4. Tensor 创建的方法
4.1 直接创建 Tensor
torch.tensor()
data=[1.,4.,2.,6.]#此处data为list
torch.tensor(data, dtype=None, device=None, requires_grad=False, pin_memory=False)
输出:
tensor([1., 4., 2., 6.])
-
data: 数据,可以是 list,numpy
-
dtype: 数据类型,默认与 data 的一致
-
device: 所在设备,cuda/cpu
-
requires_grad: 是否需要梯度
-
pin_memory: 是否存于锁页内存
arr = np.ones((3, 3))#给数组取值,函数返回给定形状和数据类型的新数组,其中元素的值设置为1
print("ndarray的数据类型:", arr.dtype)
# 创建存放在 GPU 的数据
# t = torch.tensor(arr, device='cuda')
t= torch.tensor(arr)#由数组创建Tensor,两者不共用内存,修改Tensor原arry不会改变
print(t)
print("\n修改tensor")
t[0, 0] = -1
print("array: ", arr)
print( t)
输出:
ndarray的数据类型: float64
tensor([[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.]], dtype=torch.float64)
修改tensor
array: [[1. 1. 1.]
[1. 1. 1.]
[1. 1. 1.]]
tensor([[-1., 1., 1.],
[ 1., 1., 1.],
[ 1., 1., 1.]], dtype=torch.float64)
4.2 从 numpy 创建 tensor
torch.from_numpy(ndarray)
\quad \quad 利用这个方法创建的 tensor 和原来的 ndarray 共享内存,当修改其中一个数据,另外一个也会被改动。
arr = np.array([[1, 2, 3], [4, 5, 6]])#创建二维数组,nparray格式
t = torch.from_numpy(arr)#从nparray格式创建Tensor,两者共用内存
print("tensor : ",t)
# 修改 array,tensor 也会被修改
# print("\n修改arr")
# arr[0, 0] = 0
# print("numpy array: ", arr)
# print("tensor : ", t)
# 修改 tensor,array 也会被修改
print("\n修改tensor")
t[0, 0] = -1
print("numpy array: ", arr)
print("tensor : ", t)
输出:
tensor : tensor([[1, 2, 3],
[4, 5, 6]], dtype=torch.int32)
修改tensor
numpy array: [[-1 2 3]
[ 4 5 6]]
tensor : tensor([[-1, 2, 3],
[ 4, 5, 6]], dtype=torch.int32)
4.3 根据数值创建 Tensor
torch.zeros()
size=(5,5)
torch.zeros(*size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
#根据 size 创建全 0 张量
输出:
tensor([[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.]])
-
size: 张量的形状
-
out: 输出的张量,如果指定了 out,那么torch.zeros()返回的张量和 out 指向的是同一个地址
-
layout: 内存中布局形式,有 strided,sparse_coo 等。当是稀疏矩阵时,设置为 sparse_coo 可以减少内存占用。
-
device: 所在设备,cuda/cpu
-
requires_grad: 是否需要梯度
out_t = torch.tensor([1])
# 这里制定了 out
t = torch.zeros((3, 3), out=out_t)
print(t, '\n', out_t)
# id 是取内存地址。最终 t 和 out_t 是同一个内存地址
print(id(t), id(out_t), id(t) == id(out_t))
输出:
tensor([[0, 0, 0],
[0, 0, 0],
[0, 0, 0]])
tensor([[0, 0, 0],
[0, 0, 0],
[0, 0, 0]])
2100382536256 2100382536256 True
torch.zeros_like()
input=tensor([[2,5],[3,4]])
torch.zeros_like(input, dtype=None, layout=torch.strided, device=None, requires_grad=False, memory_format=torch.preserve_format)
#根据 input 形状创建全 0 张量
输出:
tensor([[0, 0],
[0, 0]])
-
input: 创建与 input 同形状的全 0 张量
-
dtype: 数据类型
-
layout: 内存中布局形式,有 strided,sparse_coo 等。当是稀疏矩阵时,设置为 sparse_coo 可以减少内存占用。
\quad
\quad
同理还有全1张量的创建方法:torch.ones()
,torch.ones_like()
l=torch.ones(3)#3列的全1一维张量
k=torch.ones_like(l)#创建和l相同尺寸的全1张量
print("张量l",l)
print("张量k",k)
输出:
张量l tensor([1., 1., 1.])
张量k tensor([1., 1., 1.])
torch.full(),torch.full_like()
size=(6,6)
fill_value=8
torch.full(size, fill_value, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
#创建自定义数值的张量
输出:
tensor([[8, 8, 8, 8, 8, 8],
[8, 8, 8, 8, 8, 8],
[8, 8, 8, 8, 8, 8],
[8, 8, 8, 8, 8, 8],
[8, 8, 8, 8, 8, 8],
[8, 8, 8, 8, 8, 8]])
-
size: 张量的形状,如 (3,3)
-
fill_value: 张量中每一个元素的值
torch.arange()
torch.arange(start=0, end=10, step=1, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
#创建等差的 1 维张量。注意区间为[start, end)。
输出:
tensor([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
-
start: 数列起始值
-
end: 数列结束值,开区间,取不到结束值
-
step: 数列公差,默认为 1
t=torch.arange(2,20,2)#示例代码,从2到20,取不到结束值,等差为2
print(t)
输出:
tensor([ 2, 4, 6, 8, 10, 12, 14, 16, 18])
torch.linspace()
start=2
end=100
torch.linspace(start, end, steps=10, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
#创建均分的 1 维张量。数值区间为 [start, end]
输出:
tensor([ 2.0000, 12.8889, 23.7778, 34.6667, 45.5556, 56.4444, 67.3333,
78.2222, 89.1111, 100.0000])
#示例代码
t=torch.linspace(2,10,6)
print(t)
输出:
tensor([ 2.0000, 3.6000, 5.2000, 6.8000, 8.4000, 10.0000])
torch.logspace()
torch.logspace(start, end, steps=100, base=10.0, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
#创建对数均分的1维张量,数值区间为 [start, end],底为 base
输出:
tensor([1.0000e+02, 1.2045e+02, 1.4508e+02, 1.7475e+02, 2.1049e+02, 2.5354e+02,
3.0539e+02, 3.6784e+02, 4.4306e+02, 5.3367e+02, 6.4281e+02, 7.7426e+02,
9.3260e+02, 1.1233e+03, 1.3530e+03, 1.6298e+03, 1.9630e+03, 2.3645e+03,
2.8480e+03, 3.4305e+03, 4.1320e+03, 4.9770e+03, 5.9948e+03, 7.2208e+03,
8.6975e+03, 1.0476e+04, 1.2619e+04, 1.5199e+04, 1.8307e+04, 2.2051e+04,
2.6561e+04, 3.1993e+04, 3.8535e+04, 4.6416e+04, 5.5908e+04, 6.7342e+04,
8.1113e+04, 9.7701e+04, 1.1768e+05, 1.4175e+05, 1.7074e+05, 2.0565e+05,
2.4771e+05, 2.9836e+05, 3.5938e+05, 4.3288e+05, 5.2140e+05, 6.2803e+05,
7.5646e+05, 9.1116e+05, 1.0975e+06, 1.3219e+06, 1.5923e+06, 1.9179e+06,
2.3101e+06, 2.7826e+06, 3.3516e+06, 4.0370e+06, 4.8626e+06, 5.8570e+06,
7.0548e+06, 8.4975e+06, 1.0235e+07, 1.2328e+07, 1.4850e+07, 1.7886e+07,
2.1544e+07, 2.5950e+07, 3.1257e+07, 3.7649e+07, 4.5349e+07, 5.4623e+07,
6.5793e+07, 7.9248e+07, 9.5455e+07, 1.1498e+08, 1.3849e+08, 1.6681e+08,
2.0092e+08, 2.4201e+08, 2.9151e+08, 3.5112e+08, 4.2292e+08, 5.0941e+08,
6.1359e+08, 7.3907e+08, 8.9022e+08, 1.0723e+09, 1.2915e+09, 1.5557e+09,
1.8738e+09, 2.2570e+09, 2.7186e+09, 3.2745e+09, 3.9442e+09, 4.7508e+09,
5.7224e+09, 6.8926e+09, 8.3022e+09, 1.0000e+10])
#示例代码
# t = torch.logspace(2, 10, 5)
t = torch.logspace(2, 10, 6)
print(t)
输出:
tensor([1.0000e+02, 3.9811e+03, 1.5849e+05, 6.3096e+06, 2.5119e+08, 1.0000e+10])
torch.eye()
n=10
m=10
torch.eye(n, m, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
#创建单位对角矩阵( 2 维张量),默认为方阵
#n: 矩阵行数,通常只设置 n,为方阵
#m: 矩阵列数
输出:
tensor([[1., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 1., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 1., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 1., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 1., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 1., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 1., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 1., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 1., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 1.]])
4.4 根据概率创建 Tensor
torch.normal()
torch.normal(mean, std, *, generator=None, out=None)
#生成正态分布 (高斯分布)
#mean: 均值
#std: 标准差
有 4 种模式:
4.4.1 mean:标量 std: 标量
代码示例:
这时需要设置 size:
size t_normal = torch.normal(0., 1., size=(4,))
print(t_normal)
输出为:
tensor([0.6614, 0.2669, 0.0617, 0.6213])
4.4.2 mean:标量 std: 张量
4.4.3 mean 为张量,std 为标量
代码示例:
mean = torch.arange(1, 5, dtype=torch.float)
std = 1
t_normal = torch.normal(mean, std)
print("mean:{}\nstd:{}".format(mean, std))
print(t_normal)
输出为:
mean:tensor([1., 2., 3., 4.])
std:1
tensor([1.6614, 2.2669, 3.0617, 4.6213])
这 4 个数采样分布的均值不同,但是方差都是 1。
4.4.4 mean:张量 std: 张量
代码示例:
mean = torch.arange(1, 5, dtype=torch.float)
std = torch.arange(1, 5, dtype=torch.float)
t_normal = torch.normal(mean, std)
print("mean:{}\nstd:{}".format(mean, std))
print(t_normal)
输出为:
mean:tensor([1., 2., 3., 4.])
std:tensor([1., 2., 3., 4.])
tensor([1.6614, 2.5338, 3.1850, 6.4853])
其中 1.6614 是从正态分布 N(1,1) 中采样得到的,其他数字以此类推。
torch.randn() 和 torch.randn_like()
torch.randn(*size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
#生成标准正态分布,size=(6,6)
#size: 张量的形状
输出:
tensor([[ 0.3159, -0.9036, -2.0753, 2.2715, -1.3957, 0.6973],
[-1.3426, -1.2217, -0.8526, -1.6076, 0.8988, -0.4000],
[ 1.3999, -1.3826, 1.3054, -1.7632, -1.2837, 2.1097],
[-0.9141, 0.8459, -0.6407, -1.3526, 1.4692, 0.3685],
[ 0.0314, -0.8719, 0.5718, 0.2308, -1.4231, -0.3337],
[ 0.8347, 1.3863, -0.4610, 1.5216, 0.4646, -0.9474]])
torch.rand() 和 torch.rand_like()
torch.rand(*size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
#在区间 [0, 1) 上生成均匀分布,size=(6,6)
输出:
tensor([[0.1764, 0.0427, 0.3045, 0.5961, 0.2474, 0.2665],
[0.6743, 0.2016, 0.3558, 0.7857, 0.8844, 0.8244],
[0.8130, 0.6973, 0.9521, 0.8566, 0.3872, 0.7078],
[0.8661, 0.8461, 0.9105, 0.9769, 0.3201, 0.7918],
[0.6356, 0.2577, 0.4049, 0.7426, 0.1619, 0.0694],
[0.0270, 0.8482, 0.7088, 0.5964, 0.2905, 0.0267]])
torch.randint() 和 torch.randint_like()
torch.randint(low=0,high,size,*,generator=None,
out=None,dtype=None,layout=torch.strided, device=None, requires_grad=False)
#在区间 $[low, high)$ 上生成整数均匀分布,size=(6,6)
torch.randperm()
n=10
torch.randperm(n, out=None, dtype=torch.int64, layout=torch.strided, device=None, requires_grad=False)
#生成从 0 到 n-1 的随机排列。常用于生成索引。
#n: 张量的长度
输出:
tensor([5, 1, 6, 4, 8, 9, 7, 3, 2, 0])
torch.bernoulli()
torch.bernoulli(input,*,generator=None, out=None)
#以 input 为概率,生成伯努利分布 (0-1 分布,两点分布)
#input: 概率值