Pytorch
Tensor
张量可以视为一个多维数组,支持加速计算的操作。
重要属性
- dimension:维度,0维标量,1维向量,2维矩阵,...
- shape:形状
- Dtype:数据类型
创建
python
import torch
# 第一种,自生成
torch.zeros() # 指定形状的全0向量
torch.ones() # 指定形状的全1向量
torch.rand() # 指定形状的随机向量,(0,1)内均匀分布
torch.randn() # 指定形状的随机值向量,标准正态分布
torch.empty() # 指定形状的未初始化向量,创建快,值不可预测
torch.arange() # 创建一个一维序列状的tensor,用法就是range的用法
torch.eye(size) # 单位矩阵
# 与numpy互相转换
a = torch.rand(2,3) # tensor
b = a.numpy() # numpy array
c = torch.from_numpy(b) # tensor
# 自定义
torch.tensor([[1,2],[3,4]])
具名参数
python
# 直接指定
torch.randn([1,2], device="cuda")
# 通过传入torch.device实例对象
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
torch.randn(2, 3, device=device)
python
# 创建一个空张量
out_tensor = torch.empty(2, 3)
# 使用 out 参数将随机值存储到 out_tensor 中,避免创建新的张量
torch.rand(2, 3, out=out_tensor)
python
# 设置数据类型
x = torch.rand(2, 3, dtype=torch.float64)
print(x.dtype) # 输出: torch.float64
python
# 指定生成的张量是否需要计算梯度。
# 如果张量用于神经网络的权重或需要参与梯度计算,则应设置为 True。
# 如果仅用于数据存储或中间计算,则保持默认值 False。
x = torch.rand(2, 3, requires_grad=True)
print(x.requires_grad) # 输出: True
操作
python
a = torch.rand(1,2)
b = torch.rand(1,2, requires_grad=True)
a + b
a * b # 逐个相乘
a.dot(b) # 需要a,b都为1维向量
a.matmul(b) # 矩阵乘法
a.max(), a.min()
a.argmax(), a.argmax(dim=1) # 返回最大值的index
a.sum()
a.mean()
# more...
a.t(), a.T # 转置,适用于2维tensor
a.transpose(0,1) # 交换指定的两个维度的排列,(0,1)就是转置
a.shape, a.size() # 获取形状
a.dtype # 获取数据类型
a.device # 获取存储设备
a.dim() # 获取维度
a.item() # !!! 只能获取单元素张量的值
a.numel() # 获取元素总数
a_gpu = a.to("cuda") # 生成对应的gpu tensor
a.view()
# 要求张量是连续的。如果张量经过某些操作后变得不连续,需要先调用
a.contiguous() # 方法使其连续。
is_contiguous() # 检查连续
a.reshape()
# 不要求张量是连续的,因此它在更多情况下可以直接使用。
# 共同点,改变后的返回值都共享数据内存
梯度与自动微分
python
b = torch.rand(1,2, requires_grad=True)
tmp = b*2
res = tmp.sum() # 转化为标量
res.backward()
b.grad # 获取b对于res的梯度
res2 = (b*3).sum()
res2.backward() # b.grad会累积
b.grad = None # 清除grad可避免累积
# 除了requires_grad=False,也可以通过with资源语句禁用
with torch.no_grad():
res3 = b**2
神经网络(nn.Module)
- 前馈神经网络
- 卷积神经网络(CNN)
- 循环神经网络(RNN)
- 长短期记忆网络(LSTM)
在训练过程中,所有张量和模型都应该移到同一个设备上
python
import torch
import torch.nn as nn
import torch.optim as optim
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
class MyNet(nn.Module):
def __init__(self):
super().__init__()
self.layer_1 = nn.Linear(4,2)
self.layer_2 = nn.Linear(2,1)
def forward(self, x):
x = torch.relu(self.layer_1(x))
x = torch.relu(self.layer_2(x))
return x
model = MyNet().to(device) # 保证设备一致
optimizer = optim.Adam(model.parameters(), lr=0.005) # 优化器/参数梯度管理和更新器
criterion = nn.MSELoss() # 损失评测函数
x = torch.randn(1,4, device=device)
target = torch.randn(1,1, device=device)
for t in range(100):
y = model(x)
loss = criterion(y, target)
if t % 5 == 0:
print(loss)
optimizer.zero_grad()
loss.backward()
optimizer.step() # update parameters