接下来一段时间要好好学习深度学习 和 Pytorch的基础知识。
今天刚刚了解到这份在线教程,迫不及待的赶紧食用了。
环境配置什么的就不说了,对于Anaconda,Pycharm,Pytorch的安装,以前都学习过也写过相关的博客:
这里贴上链接:
Windows10下Anaconda环境的安装与配置
Windows10系统下Anaconda的虚拟环境的创建与pytorch环境的安装
好了,进入今天的学习内容。
今天学习tensor的数据操作。
创建tensor的方法有很多,Pytorch官方文档里面有详细描述过。
如 torch.ones() 创建一个元素都为1的tensor;
torch.empty() 创建一个未初始化的tensor;
torch.zeros() 创建一个元素值都为0的tensor;
torch.rand()创建一个元素值随机的tensor;
最简单的是通过torch.Tensor()来创建一个tensor;
比如torch.Tensor(3,256,256)就创建了一个3 * 256 * 256 的一个tensor
首先得知道如何获取tensor的形状,也就是size
import torch
x = torch.Tensor(3,256,256)
print(x.size())
print(x.shape)
"""
torch.Size([3, 256, 256])
torch.Size([3, 256, 256])
"""
注意:返回的torch.Size其实就是一个tuple, 支持所有tuple的操作。
知道如何获取tensor的size了,那么如何改变tensor的size呢?
view()和reshape()函数,不过官方不推荐使用reshape函数
import torch
x = torch.Tensor(5, 3)
y = x.view(15)
z = x.view(-1, 5) # -1所指的维度可以根据其他维度的值推出来
print(x.size(), y.size(), z.size())
# torch.Size([5, 3]) torch.Size([15]) torch.Size([3, 5])
注意view()返回的新Tensor与源Tensor虽然可能有不同的size,但是是共享data的,也即更改其中的一个,另外一个也会跟着改变。(顾名思义,view仅仅是改变了对这个张量的观察角度,内部数据并未改变)
两个torch 加减法;
import torch
x = torch.ones(3,2)
y = torch.zeros(3,2)
print(x + y)
"""
tensor([[1., 1.],
[1., 1.],
[1., 1.]])
"""
z = torch.empty(3,2)
torch.add(x,y,out = z)
print(z)
"""
tensor([[1., 1.],
[1., 1.],
[1., 1.]])
"""
x += y
print(x)
"""
tensor([[1., 1.],
[1., 1.],
[1., 1.]])
"""
索引
还可以使用类似NumPy的索引操作来访问Tensor的一部分。
其实在Pytorch代码中,最头疼的就是各种tensor的通过切片索引维度变来变去,每个tensor表达的数据意义得明白。
需要注意的是:索引出来的结果与原数据共享内存,也即修改一个,另一个会跟着修改。
乘法 和除法以后遇到了以后再来补充
pytorch有个重要的广播机制。
很容易用numpy()和from_numpy()将Tensor和NumPy中的数组相互转换。
但是需要注意的一点是: 这两个函数所产生的的Tensor和NumPy中的数组共享相同的内存(所以他们之间的转换很快),改变其中一个时另一个也会改变!!!
import torch
a = torch.ones(5)
b = a.numpy() # 将a 转换成一个对应的numpy数组,b与a共享内存
print(a, b)
a += 1
print(a, b)
b += 1
print(a, b)
"""
tensor([1., 1., 1., 1., 1.]) [1. 1. 1. 1. 1.]
tensor([2., 2., 2., 2., 2.]) [2. 2. 2. 2. 2.]
tensor([3., 3., 3., 3., 3.]) [3. 3. 3. 3. 3.]
"""
import numpy as np
a = np.ones(5)
b = torch.from_numpy(a) # 将一个numpy数组a 转换成对应的tensor,两者共享内存
print(a, b)
a += 1
print(a, b)
b += 1
print(a, b)
"""
[1. 1. 1. 1. 1.] tensor([1., 1., 1., 1., 1.], dtype=torch.float64)
[2. 2. 2. 2. 2.] tensor([2., 2., 2., 2., 2.], dtype=torch.float64)
[3. 3. 3. 3. 3.] tensor([3., 3., 3., 3., 3.], dtype=torch.float64)
"""
还有一个常用的将NumPy中的array转换成Tensor的方法就是torch.tensor(), 需要注意的是,此方法总是会进行数据拷贝(就会消耗更多的时间和空间),所以返回的Tensor和原来的数据不再共享内存。
即
import torch
import numpy as np
a = np.ones(5)
b = torch.Tensor(a)
print(a,b)
# [1. 1. 1. 1. 1.] tensor([1., 1., 1., 1., 1.])
跑深度学习代码中,tensor必须全部加载到GPU中,但是有时候,有些运算又不得不在CPU中运行。
所以tensor在两者中如何转换必须学会。
最简单的操作就是x.to(“cuda”)
x.to(“cpu”)
用方法to()可以将Tensor在CPU和GPU(需要硬件支持)之间相互移动。
# 以下代码只有在PyTorch GPU版本上才会执行
if torch.cuda.is_available():
device = torch.device("cuda") # GPU
y = torch.ones_like(x, device=device) # 直接创建一个在GPU上的Tensor
x = x.to(device) # 等价于 .to("cuda")
z = x + y
print(z)
print(z.to("cpu", torch.double)) # to()还可以同时更改数据类型
Tensor是Pytorch的核心类,如果将其属性.requires_grad设置为True,它将开始追踪(track)在其上的所有操作(这样就可以利用链式法则进行梯度传播了)。完成计算后,可以调用.backward()来完成所有梯度计算。此Tensor的梯度将累积到.grad属性中。
链接:https://tangshusen.me/Dive-into-DL-PyTorch/#/chapter02_prerequisite/2.3_autograd
https://pytorch.org/tutorials/beginner/basics/tensor_tutorial.html