2.1张量
2.1.1张量定义
- 张量是指任何维度的数据结构;
如标量是0维、向量是1维、矩阵是2维、时序数据(股价、单色彩图片数据)是3维的、含色彩的图片是4维的、视频是5维的。
-
张量是pytorch是基本计算单元;
-
pytorch是使用torch.Tensor对张量数据进行存储、变换(和numpy数据转换);
-
Tensor提供GPU计算和自动梯度求导。
2.1.2张量(tensor)的创建
- 将一个向量转换为张量
import torch x=torch.tensor([2 3 4],dtype=float) print(x)
tensor([2 3 4])
- 常见的构造Tensor的方法
- Tensor(sizes): 基础构造函数
- tensor(data): 类似np.array
- ones(sizes): 全1
- zeros(sizes):全0
- eye(sizes):对角为1
- arrange(s,e,step): 从s到e,步长为step,不含e
- linspace(s,e,steps): 从s到e,均匀分为steps份
- rand/randn(sizes): rand是从0到1均匀分布;radn服从N(0,1)正态分布
- normal(mean,std):正态分布(mean是均值,step是方差)
- randperm(m): 随机排列
2.1.3张量操作
-
加法操作
import torch # 方式1 y = torch.rand(4, 3) print(x + y) # 方式2 print(torch.add(x, y)) # 方式3 in-place,原值修改 y.add_(x) print(y)
tensor([[ 2.8977, 0.6581, 0.5856], [-1.3604, 0.1656, -0.0823], [ 2.1387, 1.7959, 1.5275], [ 2.2427, -0.3100, -0.4826]]) tensor([[ 2.8977, 0.6581, 0.5856], [-1.3604, 0.1656, -0.0823], [ 2.1387, 1.7959, 1.5275], [ 2.2427, -0.3100, -0.4826]]) tensor([[ 2.8977, 0.6581, 0.5856], [-1.3604, 0.1656, -0.0823], [ 2.1387, 1.7959, 1.5275], [ 2.2427, -0.3100, -0.4826]])
-
索引操作
import torch x = torch.rand(4,3) # 取第二列 print(x[:, 1])
tensor([-0.0720, 0.0666, 1.0336, -0.6965])
y = x[0,:] y += 1 print(y) print(x[0, :]) # 源tensor也被改了了
tensor([3.7311, 0.9280, 1.2497]) tensor([3.7311, 0.9280, 1.2497])
-
维度变换
常见方法有torch.view()和torch.reshape():
x = torch.randn(4, 4) y = x.view(16) z = x.view(-1, 8) # -1是指这一维的维数由其他维度决定 print(x.size(), y.size(), z.size())
torch.Size([4, 4]) torch.Size([16]) torch.Size([2, 8])
torch.view()返回的新tensor和源tensor是共享内存,源tensor的数据大小(数据size除外)会随着新的改变而改变。
torch,reshape()创建的新tensor不共享内存,但是它拷贝的不一定是源tensor。
推荐先clone()创建张量副本,在torch.view(),clone()会记录在计算图里,梯度回传时会保存在源tensor里。
import torch x = torch.randn(1) print(type(x)) print(type(x.item()))
<class 'torch.Tensor'> <class 'float'>
2.1.4广播机制
广播机制会对两个维度不同的张量进行扩充再运算。
x = torch.arange(1, 3).view(1, 2) print(x) y = torch.arange(1, 4).view(3, 1) print(y) print(x + y)
tensor([[1, 2]])#扩充为[1,2;1,2;1,2] tensor([[1],#扩充为[1,1;2,2;3,3] [2], [3]]) tensor([[2, 3], [3, 4], [4, 5]])
-
2.2自动求导
-
每个tensor都有一个requires_grad属性,该属性为true时才能求梯度,手动创建tensor时,默认是false.
-
每个tensor有一个grad_fn属性,该属性默认是FALSE,当被设为true时,后续
-
tensor.requires_grad()可以更改该属性值;
-
多元函数求梯度涉及到雅克比矩阵和链式法则;
-
梯度的计算是累加的,为了避免累加,每次计算梯度前需要将梯度清零
# 再来反向传播⼀一次,注意grad是累加的 out2 = x.sum() out2.backward() print(x.grad) out3 = x.sum() x.grad.data.zero_() out3.backward() print(x.grad)
tensor([[4., 4.], [4., 4.]]) tensor([[1., 1.], [1., 1.]])
雅克比向量积:
x = torch.randn(3, requires_grad=True) print(x) y = x * 2 i = 0 while y.data.norm() < 1000: y = y * 2 i = i + 1 print(y) print(i)
tensor([-0.9332, 1.9616, 0.1739], requires_grad=True) tensor([-477.7843, 1004.3264, 89.0424], grad_fn=<MulBackward0>) 8
利用tensor.data可以只修改数据大小,不被autograd记录()