pytorch学习笔记(1)
学习教程:《动手学深度学习 PYTORCH 版(DEMO)》
Tensor
首先导入pytorch
import torch
利用torch.empty()函数创建一个未被初始化的张量
x = torch.empty(5, 3, dtype=torch.float, device=GPU, requires_grad=Ture )
# dtype:数据类型,device:cpu还是gpu,requires_grad:是否要追踪梯度
print (x)
输出:
创建张量还有torch.ones()
torch.rand()
等很多不同的函数。
通过shape
来获取张量的形状
print(x.shape)
#输出:torch.Size([5, 3])
常用创建tensor的函数
函数 | 功能 |
---|---|
Tensor(*sizes) | 基础构造函数 |
tensor(data,) | 类似np.array的构造函数 |
ones(*sizes) | 全1Tensor |
zeros(*sizes) | 全0Tensor |
eye(*sizes) | 对⻆角线为1,其他为0 |
arange(s,e,step) | 从s到e,步⻓长为step |
inspace(s,e,steps) | 从s到e,均匀切分成steps份 |
rand/randn(*sizes) | 均匀/标准分布 |
normal(mean,std)/uniform(from,to) | 正态分布/均匀分布 |
randperm(m) | 随机排列 |
对张量进行操作
用view()
改变tensor的形状
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仅仅是改变了了对这个张量量的观察⻆角度)
Pytorch还提供了了⼀一个reshape()
可 以 改 变 形 状 , 但 是 此 函 数 并 不不 能 保 证 返 回 的 是 其 拷 ⻉贝 , 所 以 不 推 荐 使 用 。 推 荐 先⽤用clone
创造一个副本然后再使⽤view
。
x_cp = x.clone().view(15)
x -= 1
print(x)
print(x_cp)
# 输出:
# tensor([[ 0.6035, 0.8110, -0.0451],
# [ 0.8797, 1.0482, -0.0445],
# [-0.7229, 2.8663, -0.5655],
# [ 0.1604, -0.0254, 1.0739],
# [ 2.2628, -0.9175, -0.2251]])
# tensor([1.6035, 1.8110, 0.9549, 1.8797, 2.0482, 0.9555, 0.2771,3.8663, 0.4345, 1.1604, 0.9746, 2.0739, 3.2628, 0.0825, 0.7749])
使⽤用clone
还有⼀一个好处是会被记录在计算图中,即梯度回传到副本时也会传到源Tensor。
线性代数
常用函数直接上图:
tensor on gpu
用方法to()
可以将Tensor在CPU和GPU(需要硬件⽀支持)之间相互移动。
# 以下代码只有在PyTorch GPU版本上才会执行
iftorch.cuda.is_available():device = torch.device("cuda") #GPU
GPUy = torch.ones_like(x, device=device) # 直接创建⼀一个在GPU上的
Tensorx = x.to(device) # 等价于 .to("cuda")
z = x+yprint(z)print(z.to("cpu", torch.double)) # to()还可以同时更更改数据类型
自动求梯度
如果将.requires_grad
设 置 为True
,计算机将自动追踪在这个tensor上的所有操作。完成计算后可用.backward()
完成梯度计算,这个tensor的梯度将积累在.grad
属性中。
在y.backward()
时,如果y是标量,则不需要为backward()
传入任何参数;否则,需要传入一个与y同型的tensor。
## 自动求梯度
x = torch.rand(2, 2, requires_grad=True) #开启自动求梯度
print(x)
print(x.grad_fn) # 指向Function对象(用于反向传播),在这x没有对象
y = x + 2
print('y = ',y)
print('y.grad_fn = ',y.grad_fn)
print(x.is_leaf, y.is_leaf) # x和y是否是叶子节点
z = y * y * 3
out = z.mean()
print(z, out)
out.backward() # 等价于 out.backward(torch.tensor(1.))。用backward完成梯度计算
print(x.grad)
注意:每次反向传播都会累加之前的梯度,一般在反向传播之前把梯度清零
注意:在x.backward()时,如果y是张量,backward需要传入一个与y同型的参数
例:
x = torch.tensor([1, 2, 3, 4], requires_grad = True, dtype=torch.float64)
y = 2 * x
z = y.view(2, 2)
v = torch.tensor([[1, 0.1],[0.01, 0.001]], dtype=torch.float64)
z.backward(v)
print(x.grad) # 注意x.grad是一个与x同型的张量
输出: