torch.Tensor是存储与变换数据的主要工具。Tensor(张量)是一个多维数组,标量可以看作是0维张量,向量可以看作是1维张量,矩阵可以看作是2维张量。
这部分属实很枯燥
注:dtype是自定义数据类型
函数(生成矩阵的) | 实现功能 |
---|---|
torch.empty(m,n) | 创建一个未初始化的m行n列的张量 |
torch.tensor([需要创建的数据]) | 直接创建一个值为 ”需要创建的数据“ 的张量 |
torch.randn(m,n) | 创建一个满足正态分布(0,1)的张量 |
torch.rand(m,n) | 随机生成在(0,1)一个m行n列的张量 |
torch.ones(m,n) | 创建一个全1的m行n列的张量 |
torch.zeros(m,n,dtype=张量类型) | 创建一个符合张量类型的全0m行n列的张量 |
torch.eye(m,n) | 生成一个m行n列的对角线为1,其他为0的张量 |
函数(生成行向量的) | 实现功能 |
---|---|
torch.linspace(s,e,steps) | 生成一个从s到e,均匀切成steps份的向量 |
torch.arange(s,e,steps) | 生成一个从s到e,步长为steps的向量 |
torch.randperm(m) | 生成一个有m个数的随机向量 |
有超过一百种的Tensor的运算操作。
获取Tensor的行数与列数 | 实现功能 |
---|---|
name.size() | 获取张量的行数和列数,返回一个元组(m,n) |
name.shape() | 同上 |
加法运算 | 注释 |
---|---|
name1+name2 | 直接将两个张量进行相加 |
torch.add(x,y) | |
y.add_(x) |
使用索引访问Tensor:索引出来的结果与元数据共享内存,改变索引的结果也会改变原数据 。
索引使用 | 功能说明 |
---|---|
name[n,m] | 提取出name这个Tensor中的n行m列这个数,注意:索引是从0开始的 |
name[n,:] | 提取出name这个Tensor中的n行的这个向量 |
用view()改变Tensor的形状
函数 | 功能 |
---|---|
torch.is_tensor(obj) | 如果obj是tensor,则返回True |
torch.is_storage(obj) | 如果obj是存储图像,则返回True |
torch.isfloatingpoint(输入) | 如果输入的是浮点数据类型,则返回True |
函数 | 功能 |
---|---|
torch.setdefaultdtype(d) | 设置数据类型 |
torch.getdefaultdtype() | 读取数据类型 |
这个view()调用出来的数据和源数据共享,改变一个,另一个也会被一起改变。
函数 | 功能 |
---|---|
name.view(-1,m) | 将name这个Tensor转换为m列的张量,行数根据列数自动确定,-1是一种标志 |
name.view(n,-1) | 将name这个Tensor转换为n行的张量,列数根据行数自动确定,-1是一种标志 |
name.view(x,y) | 将name这个m行n列的张量转换为x行y列的张量 |
因为上面的原因,所以可以用clone克隆一个副本,然后对副本进行变换。
import torch
x = torch.tensor(1.123456)
y = x.item()
print(x) #tensor(2.2469)
print(y) #2.2469120025634766
这部分也是对Tensor进行操作。
函数 | 功能 |
---|---|
name1 = torch.trace(name) | 求name这个张量的对角线元素之和,然后存储到name1中 |
name1 = torch.diag(name) | 将name这个张量的对角线元素提取出来,然后存储到name1这个行向量中 |
torch.triu(name,n) | 矩阵上三角,只保留上三角的值,其余为0;n的作用是指定向上偏移量,如n=1,则为0的对角线向上平移1一个对角线 |
torch.tril(name,m) | 矩阵下三角,只保留下三角的值,其余为0;n的作用是指定向下偏移量,如n=1,则为0的对角线向下平移1一个对角线 |
torch.mm(name,name1) | 矩阵乘法 |
name1 = torch.t(name) | 对name转置 |
name1 = torch.inverse(name) | 对name求逆矩阵 |
name1 = torch.svd(name) | 对name求奇异值分解 |
前面的运算都是针对形状相同的Tensor,但当两个形状不同的Tensor进行运算时,会触发广播( broadcasting )机制。
广播机制:先适当复制元素使这两个 Tensor
形状相同后再按元素运算。(前提是两个Tensor要满足可以通过复制某些行或列会变成一样形状的;如:[2,4]和[1,4]可以实现广播机制;但[2,3]和[1,4]无法实现)
小注释:
如果想指定结果到某一特定地址可以通过:
torch.add(x,y,out=y)
也可以通过这种方法来实现上述功能y+=x,y.add_(x)
也可以如此实现。通过numpy()和from_numpy()实现将Tensor和NumPy中的数组相互转换。
注意:这两个函数产生的数组共享相同内存,改变其中一个另一个也会转变。
还可以通过 torch.tensor()
实现转换,但这种方法会进行数据复制,所以他们不共享内存,改变一个另一个不会改变。
函数 | 功能 |
---|---|
name1 = name.numpy() | 将name转换为numpy数组并存储到name1中 |
name1 = torch.from_numpy(name) | 将name转换为Tensor数组并存储到name1中 |
动手学习深度学习,2.3
2020.1.28,好久没学习,今天开始学习。
深度学习过程中,常需要对函数进行求梯度,PyTorch提供的autograd包能够根据输入和前向传播过程自动构建计算图,并执行反向传播。
### 使用方法
如果被计算对象是标量(只包含一个元素的数据),则不需要为backward()这个函数传入任何参数;否则,需要传入一个与被计算对象同形的Tensor
import torch
x = torch.ones(2,2,requires_grad = True) #创建一个张量,将属性 .requires_grad 设置为True
print(x) #打印x
print(x.grad_fn) #打印x的 .grad_fn 属性
输出结果
tensor([[1., 1.], [1., 1.]], requires_grad=True) #可以看到整个属性被设置为True
None #因为x没有进行任何计算,所以grad_fn的值为None
叶子节点:如x这种直接创建的变量被称为叶子节点,并可以通过 变量名 .is_leaf 来判断是否为叶子节点
import torchx = torch.ones(2,2,requires_grad = True) #创建一个张量,将属性 .requires_grad 设置为True
y = x + 2
print(y) #打印y
print(y.grad_fn) #打印y的 .grad_fn 属性
print(x.is_leaf,y.is_leaf) #判断变量是否为叶子节点
输出结果
tensor([[3., 3.], [3., 3.]], grad_fn=<AddBackward0>) #可以看到属性.grad_fn的值为 AddBackward0<AddBackward0 object at 0x00000214C9878748> #这是该变量的内存位置
import torchx = torch.ones(2,2,requires_grad = True)
y = x + 2
z = y*y*3out = z.mean()print(z,out)
输出结果
tensor([[27., 27.], [27., 27.]], grad_fn=<MulBackward0>) #可以看到z的grad_fn的值为MulBackward0tensor(27., grad_fn=<MeanBackward0>) #可以看到z的grad_fn的值为MeanBackward0
这个他娘的傻逼求梯度的原理就是求导,我没看懂。只知道使用,使锤子吧,不学造轮子了。
不需要传入张量。
import torchx = torch.ones(2,2,requires_grad = True)
y = x + 2
z = y * y * 3
out = z.mean() #求取均值
out.backward() #用来设置下面的被求导对象(即:设置out为被求导对象)
print(x.grad) #返回设置的计算结果对x的梯度向量(即:out对x的梯度向量)
输出结果
tensor([[4.5000, 4.5000], [4.5000, 4.5000]]) #可以见到,求导的结果是与输入张量同形的
需要传入一个与结果同形的权重张量。
值得注意的是:输出的结果(x.grad)最后是与输入的值(x)相同的。
import torch
x = torch.tensor([1.0,2.0,3.0,4.0],requires_grad = True)y = x * 2z = y.view(2,2) #对x进行变换形状
v = torch.tensor([[1.0,0.1],[0.01,0.001]],dtype = torch.float) #创建一个与结果同形的权重张量。
z.backward(v) #传入这个权重张量。print(x.grad)
输出结果
tensor([2.0000, 0.2000, 0.0200, 0.0020]) #求导的结果也是与输入张量同形的
通过 with语句+torch.no_grad()
import torch
x = torch.tensor(1.0,requires_grad = True)
y1 = x**2
with torch.no_grad(): #对下面语句进行中断梯度追踪 y2 = x**3
y3 = y1+y2
print(x.requires_grad) print(y1.requires_grad)print(y2.requires_grad)print(y3.requires_grad) #对四个变量进行判断是否要求梯度
输出
TrueTrueFlaseTrue #可以见到被隔离的y2变量不需要进行求梯度
被隔离的变量,不能调用 .backward(),否则会报错。
使用x.data之后,对变量进行任何更改都不会被autograd记录。